pavanmutha commited on
Commit
43f4c69
·
verified ·
1 Parent(s): ebf5f6d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +203 -84
app.py CHANGED
@@ -16,8 +16,8 @@ import shap
16
  import lime
17
  import lime.lime_tabular
18
  import matplotlib.pyplot as plt
19
- import matplotlib
20
- matplotlib.use('Agg') # For headless environments
21
 
22
  # Authenticate Hugging Face
23
  hf_token = os.getenv("HF_TOKEN")
@@ -35,17 +35,17 @@ def format_analysis_report(raw_output, visuals):
35
  analysis_dict = ast.literal_eval(str(raw_output))
36
  except (SyntaxError, ValueError) as e:
37
  print(f"Error parsing CodeAgent output: {e}")
38
- return str(raw_output), visuals
39
-
40
  report = f"""
41
- <div style='font-family: Arial, sans-serif; padding: 20px; color: #333;'>
42
- <h1 style='color: #2B547E; border-bottom: 2px solid #2B547E; padding-bottom: 10px;'>📊 Data Analysis Report</h1>
43
- <div style='margin-top: 25px; background: #f8f9fa; padding: 20px; border-radius: 8px;'>
44
- <h2 style='color: #2B547E;'>🔍 Key Observations</h2>
45
  {format_observations(analysis_dict.get('observations', {}))}
46
  </div>
47
- <div style='margin-top: 30px;'>
48
- <h2 style='color: #2B547E;'>💡 Insights & Visualizations</h2>
49
  {format_insights(analysis_dict.get('insights', {}), visuals)}
50
  </div>
51
  </div>
@@ -58,9 +58,9 @@ def format_analysis_report(raw_output, visuals):
58
  def format_observations(observations):
59
  return '\n'.join([
60
  f"""
61
- <div style='margin: 15px 0; padding: 15px; background: white; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.05);'>
62
- <h3 style='margin: 0 0 10px 0; color: #4A708B;'>{key.replace('_', ' ').title()}</h3>
63
- <pre style='margin: 0; padding: 10px; background: #f8f9fa; border-radius: 4px;'>{value}</pre>
64
  </div>
65
  """ for key, value in observations.items() if 'proportions' in key
66
  ])
@@ -68,12 +68,12 @@ def format_observations(observations):
68
  def format_insights(insights, visuals):
69
  return '\n'.join([
70
  f"""
71
- <div style='margin: 20px 0; padding: 20px; background: white; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.05);'>
72
- <div style='display: flex; align-items: center; gap: 10px;'>
73
- <div style='background: #2B547E; color: white; width: 30px; height: 30px; border-radius: 50%; display: flex; align-items: center; justify-content: center;'>{idx+1}</div>
74
- <p style='margin: 0; font-size: 16px;'>{insight}</p>
75
  </div>
76
- {f"<img src='/file={visuals[idx]}' style='max-width: 100%; height: auto; margin-top: 10px; border-radius: 6px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);'>" if idx < len(visuals) else ''}
77
  </div>
78
  """ for idx, (key, insight) in enumerate(insights.items())
79
  ])
@@ -82,18 +82,18 @@ def analyze_data(csv_file, additional_notes=""):
82
  start_time = time.time()
83
  process = psutil.Process(os.getpid())
84
  initial_memory = process.memory_info().rss / 1024 ** 2
85
-
86
  if os.path.exists('./figures'):
87
  shutil.rmtree('./figures')
88
  os.makedirs('./figures', exist_ok=True)
89
-
90
  wandb.login(key=os.environ.get('WANDB_API_KEY'))
91
  run = wandb.init(project="huggingface-data-analysis", config={
92
  "model": "mistralai/Mixtral-8x7B-Instruct-v0.1",
93
  "additional_notes": additional_notes,
94
  "source_file": csv_file.name if csv_file else None
95
  })
96
-
97
  agent = CodeAgent(tools=[], model=model, additional_authorized_imports=["numpy", "pandas", "matplotlib.pyplot", "seaborn", "sklearn"])
98
  analysis_result = agent.run("""
99
  You are an expert data analyst. Perform comprehensive analysis including:
@@ -105,114 +105,233 @@ def analyze_data(csv_file, additional_notes=""):
105
  Return the analysis results as a python dictionary that can be parsed by ast.literal_eval().
106
  The dictionary should have the following structure:
107
  {
108
- 'observations': {...},
109
- 'insights': {...}
 
 
 
 
 
 
 
 
110
  }
111
  """, additional_args={"additional_notes": additional_notes, "source_file": csv_file})
112
-
113
  execution_time = time.time() - start_time
114
  final_memory = process.memory_info().rss / 1024 ** 2
115
  memory_usage = final_memory - initial_memory
116
  wandb.log({"execution_time_sec": execution_time, "memory_usage_mb": memory_usage})
117
-
118
  visuals = [os.path.join('./figures', f) for f in os.listdir('./figures') if f.endswith(('.png', '.jpg', '.jpeg'))]
119
  for viz in visuals:
120
  wandb.log({os.path.basename(viz): wandb.Image(viz)})
121
-
122
  run.finish()
123
  return format_analysis_report(analysis_result, visuals)
124
 
125
- def tune_hyperparameters(csv_file, n_trials: int):
126
- df = pd.read_csv(csv_file)
127
- y = df.iloc[:, -1]
128
- X = df.iloc[:, :-1]
129
- X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
130
-
131
- study = optuna.create_study(direction="maximize")
132
- objective_func = lambda trial: objective(trial, X_train, y_train, X_test, y_test)
133
- study.optimize(objective_func, n_trials=n_trials)
134
-
135
- best_params = study.best_params
136
- best_value = study.best_value
137
-
138
- model = RandomForestClassifier(**best_params, random_state=42)
 
 
 
 
 
 
 
 
139
  model.fit(X_train, y_train)
140
  predictions = model.predict(X_test)
141
-
 
142
  accuracy = accuracy_score(y_test, predictions)
143
  precision = precision_score(y_test, predictions, average='weighted', zero_division=0)
144
  recall = recall_score(y_test, predictions, average='weighted', zero_division=0)
145
  f1 = f1_score(y_test, predictions, average='weighted', zero_division=0)
146
-
 
147
  wandb.log({
148
- "best_params": best_params,
149
- "accuracy": accuracy,
150
- "precision": precision,
151
- "recall": recall,
152
- "f1": f1
 
 
 
 
 
 
153
  })
 
 
154
 
155
- shap_explainer = shap.TreeExplainer(model)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
  shap_values = shap_explainer.shap_values(X_test)
157
  shap.summary_plot(shap_values, X_test, show=False)
158
  shap_fig_path = "./figures/shap_summary.png"
159
  plt.savefig(shap_fig_path)
160
- wandb.log({"shap_summary": wandb.Image(shap_fig_path)})
161
  plt.clf()
162
-
163
  lime_explainer = lime.lime_tabular.LimeTabularExplainer(
164
- X_train.values,
165
- feature_names=X_train.columns,
166
- class_names=['target'],
167
  mode='classification'
168
  )
169
- lime_explanation = lime_explainer.explain_instance(X_test.iloc[0].values, model.predict_proba)
 
 
 
170
  lime_fig = lime_explanation.as_pyplot_figure()
171
  lime_fig_path = "./figures/lime_explanation.png"
172
  lime_fig.savefig(lime_fig_path)
173
- wandb.log({"lime_explanation": wandb.Image(lime_fig_path)})
174
  plt.clf()
175
-
176
- # Plot optimization history
177
- fig = optuna.visualization.matplotlib.plot_optimization_history(study)
178
- history_fig_path = "./figures/optuna_history.png"
179
- fig.savefig(history_fig_path)
180
- wandb.log({"optuna_history": wandb.Image(history_fig_path)})
181
- plt.clf()
182
-
183
- df_trials = study.trials_dataframe()
184
- df_html = df_trials.sort_values("value", ascending=False).to_html(classes="table table-striped", index=False)
185
-
186
- summary_html = f"""
187
- <h3>🏆 Best Hyperparameters</h3>
188
- <ul>
189
- {''.join([f'<li><b>{k}</b>: {v}</li>' for k, v in best_params.items()])}
190
- </ul>
191
- <p><b>Accuracy:</b> {accuracy:.4f} &nbsp; <b>Precision:</b> {precision:.4f} &nbsp; <b>Recall:</b> {recall:.4f} &nbsp; <b>F1-score:</b> {f1:.4f}</p>
192
- <hr>
193
- <h3>📋 All Trials Summary</h3>
194
- {df_html}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
195
  """
 
 
 
 
 
 
 
 
 
 
 
196
 
197
- return summary_html, history_fig_path
 
 
 
 
 
 
198
 
199
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
200
- gr.Markdown("## 📊 AI Data Analysis Agent with Hyperparameter Optimization")
201
  with gr.Row():
202
  with gr.Column():
203
  file_input = gr.File(label="Upload CSV Dataset", type="filepath")
204
  notes_input = gr.Textbox(label="Dataset Notes (Optional)", lines=3)
205
  analyze_btn = gr.Button("Analyze", variant="primary")
206
- optuna_trials = gr.Number(label="Number of Hyperparameter Tuning Trials", value=10)
 
 
 
 
 
 
207
  tune_btn = gr.Button("Optimize Hyperparameters", variant="secondary")
208
  with gr.Column():
209
  analysis_output = gr.Markdown("### Analysis results will appear here...")
210
  optuna_output = gr.HTML(label="Hyperparameter Tuning Results")
211
- optuna_plot = gr.Image(label="Optimization History Plot")
212
- gallery = gr.Gallery(label="Data Visualizations", columns=2)
213
-
214
  analyze_btn.click(fn=analyze_data, inputs=[file_input, notes_input], outputs=[analysis_output, gallery])
215
- tune_btn.click(fn=tune_hyperparameters, inputs=[file_input, optuna_trials], outputs=[optuna_output, optuna_plot])
216
 
217
- if __name__ == "__main__":
218
- demo.launch(debug=True)
 
16
  import lime
17
  import lime.lime_tabular
18
  import matplotlib.pyplot as plt
19
+ import numpy as np
20
+ from optuna.visualization import plot_optimization_history, plot_param_importances
21
 
22
  # Authenticate Hugging Face
23
  hf_token = os.getenv("HF_TOKEN")
 
35
  analysis_dict = ast.literal_eval(str(raw_output))
36
  except (SyntaxError, ValueError) as e:
37
  print(f"Error parsing CodeAgent output: {e}")
38
+ return str(raw_output), visuals # Return raw output as string
39
+
40
  report = f"""
41
+ <div style="font-family: Arial, sans-serif; padding: 20px; color: #333;">
42
+ <h1 style="color: #2B547E; border-bottom: 2px solid #2B547E; padding-bottom: 10px;">📊 Data Analysis Report</h1>
43
+ <div style="margin-top: 25px; background: #f8f9fa; padding: 20px; border-radius: 8px;">
44
+ <h2 style="color: #2B547E;">🔍 Key Observations</h2>
45
  {format_observations(analysis_dict.get('observations', {}))}
46
  </div>
47
+ <div style="margin-top: 30px;">
48
+ <h2 style="color: #2B547E;">💡 Insights & Visualizations</h2>
49
  {format_insights(analysis_dict.get('insights', {}), visuals)}
50
  </div>
51
  </div>
 
58
  def format_observations(observations):
59
  return '\n'.join([
60
  f"""
61
+ <div style="margin: 15px 0; padding: 15px; background: white; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.05);">
62
+ <h3 style="margin: 0 0 10px 0; color: #4A708B;">{key.replace('_', ' ').title()}</h3>
63
+ <pre style="margin: 0; padding: 10px; background: #f8f9fa; border-radius: 4px;">{value}</pre>
64
  </div>
65
  """ for key, value in observations.items() if 'proportions' in key
66
  ])
 
68
  def format_insights(insights, visuals):
69
  return '\n'.join([
70
  f"""
71
+ <div style="margin: 20px 0; padding: 20px; background: white; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.05);">
72
+ <div style="display: flex; align-items: center; gap: 10px;">
73
+ <div style="background: #2B547E; color: white; width: 30px; height: 30px; border-radius: 50%; display: flex; align-items: center; justify-content: center;">{idx+1}</div>
74
+ <p style="margin: 0; font-size: 16px;">{insight}</p>
75
  </div>
76
+ {f'<img src="/file={visuals[idx]}" style="max-width: 100%; height: auto; margin-top: 10px; border-radius: 6px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">' if idx < len(visuals) else ''}
77
  </div>
78
  """ for idx, (key, insight) in enumerate(insights.items())
79
  ])
 
82
  start_time = time.time()
83
  process = psutil.Process(os.getpid())
84
  initial_memory = process.memory_info().rss / 1024 ** 2
85
+
86
  if os.path.exists('./figures'):
87
  shutil.rmtree('./figures')
88
  os.makedirs('./figures', exist_ok=True)
89
+
90
  wandb.login(key=os.environ.get('WANDB_API_KEY'))
91
  run = wandb.init(project="huggingface-data-analysis", config={
92
  "model": "mistralai/Mixtral-8x7B-Instruct-v0.1",
93
  "additional_notes": additional_notes,
94
  "source_file": csv_file.name if csv_file else None
95
  })
96
+
97
  agent = CodeAgent(tools=[], model=model, additional_authorized_imports=["numpy", "pandas", "matplotlib.pyplot", "seaborn", "sklearn"])
98
  analysis_result = agent.run("""
99
  You are an expert data analyst. Perform comprehensive analysis including:
 
105
  Return the analysis results as a python dictionary that can be parsed by ast.literal_eval().
106
  The dictionary should have the following structure:
107
  {
108
+ 'observations': {
109
+ 'observation_1_key': 'observation_1_value',
110
+ 'observation_2_key': 'observation_2_value',
111
+ ...
112
+ },
113
+ 'insights': {
114
+ 'insight_1_key': 'insight_1_value',
115
+ 'insight_2_key': 'insight_2_value',
116
+ ...
117
+ }
118
  }
119
  """, additional_args={"additional_notes": additional_notes, "source_file": csv_file})
120
+
121
  execution_time = time.time() - start_time
122
  final_memory = process.memory_info().rss / 1024 ** 2
123
  memory_usage = final_memory - initial_memory
124
  wandb.log({"execution_time_sec": execution_time, "memory_usage_mb": memory_usage})
125
+
126
  visuals = [os.path.join('./figures', f) for f in os.listdir('./figures') if f.endswith(('.png', '.jpg', '.jpeg'))]
127
  for viz in visuals:
128
  wandb.log({os.path.basename(viz): wandb.Image(viz)})
129
+
130
  run.finish()
131
  return format_analysis_report(analysis_result, visuals)
132
 
133
+ def objective(trial, X_train, y_train, X_test, y_test):
134
+ # Enhanced hyperparameter space
135
+ n_estimators = trial.suggest_int("n_estimators", 50, 500, step=50)
136
+ max_depth = trial.suggest_int("max_depth", 3, 15)
137
+ min_samples_split = trial.suggest_int("min_samples_split", 2, 10)
138
+ min_samples_leaf = trial.suggest_int("min_samples_leaf", 1, 5)
139
+ max_features = trial.suggest_categorical("max_features", ["sqrt", "log2", None])
140
+ bootstrap = trial.suggest_categorical("bootstrap", [True, False])
141
+ criterion = trial.suggest_categorical("criterion", ["gini", "entropy"])
142
+
143
+ model = RandomForestClassifier(
144
+ n_estimators=n_estimators,
145
+ max_depth=max_depth,
146
+ min_samples_split=min_samples_split,
147
+ min_samples_leaf=min_samples_leaf,
148
+ max_features=max_features,
149
+ bootstrap=bootstrap,
150
+ criterion=criterion,
151
+ random_state=42,
152
+ n_jobs=-1
153
+ )
154
+
155
  model.fit(X_train, y_train)
156
  predictions = model.predict(X_test)
157
+
158
+ # Track multiple metrics
159
  accuracy = accuracy_score(y_test, predictions)
160
  precision = precision_score(y_test, predictions, average='weighted', zero_division=0)
161
  recall = recall_score(y_test, predictions, average='weighted', zero_division=0)
162
  f1 = f1_score(y_test, predictions, average='weighted', zero_division=0)
163
+
164
+ # Log metrics to W&B
165
  wandb.log({
166
+ "trial_accuracy": accuracy,
167
+ "trial_precision": precision,
168
+ "trial_recall": recall,
169
+ "trial_f1": f1,
170
+ "n_estimators": n_estimators,
171
+ "max_depth": max_depth,
172
+ "min_samples_split": min_samples_split,
173
+ "min_samples_leaf": min_samples_leaf,
174
+ "max_features": str(max_features),
175
+ "bootstrap": bootstrap,
176
+ "criterion": criterion
177
  })
178
+
179
+ return accuracy
180
 
181
+ def tune_hyperparameters(csv_file, n_trials: int):
182
+ # Initialize W&B run
183
+ wandb.login(key=os.environ.get('WANDB_API_KEY'))
184
+ run = wandb.init(project="hyperparameter-optimization",
185
+ config={"n_trials": n_trials, "model_type": "RandomForest"})
186
+
187
+ df = pd.read_csv(csv_file)
188
+ y = df.iloc[:, -1]
189
+ X = df.iloc[:, :-1]
190
+ X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
191
+
192
+ # Create study with enhanced settings
193
+ study = optuna.create_study(
194
+ direction="maximize",
195
+ sampler=optuna.samplers.TPESampler(),
196
+ pruner=optuna.pruners.MedianPruner(n_warmup_steps=5)
197
+ )
198
+
199
+ # Run optimization
200
+ study.optimize(lambda trial: objective(trial, X_train, y_train, X_test, y_test),
201
+ n_trials=n_trials,
202
+ callbacks=[wandb_callback])
203
+
204
+ # Get best trial results
205
+ best_params = study.best_params
206
+ best_value = study.best_value
207
+
208
+ # Train final model with best parameters
209
+ final_model = RandomForestClassifier(**best_params, random_state=42, n_jobs=-1)
210
+ final_model.fit(X_train, y_train)
211
+ final_predictions = final_model.predict(X_test)
212
+
213
+ # Calculate final metrics
214
+ accuracy = accuracy_score(y_test, final_predictions)
215
+ precision = precision_score(y_test, final_predictions, average='weighted', zero_division=0)
216
+ recall = recall_score(y_test, final_predictions, average='weighted', zero_division=0)
217
+ f1 = f1_score(y_test, final_predictions, average='weighted', zero_division=0)
218
+
219
+ # Generate optimization visualizations
220
+ optimization_history = plot_optimization_history(study)
221
+ param_importance = plot_param_importances(study)
222
+
223
+ # Save visualizations
224
+ os.makedirs('./figures', exist_ok=True)
225
+ history_path = "./figures/optimization_history.png"
226
+ importance_path = "./figures/param_importance.png"
227
+
228
+ optimization_history.figure.savefig(history_path)
229
+ param_importance.figure.savefig(importance_path)
230
+
231
+ # Generate SHAP and LIME explanations
232
+ shap_explainer = shap.TreeExplainer(final_model)
233
  shap_values = shap_explainer.shap_values(X_test)
234
  shap.summary_plot(shap_values, X_test, show=False)
235
  shap_fig_path = "./figures/shap_summary.png"
236
  plt.savefig(shap_fig_path)
 
237
  plt.clf()
238
+
239
  lime_explainer = lime.lime_tabular.LimeTabularExplainer(
240
+ X_train.values,
241
+ feature_names=X_train.columns,
242
+ class_names=['target'],
243
  mode='classification'
244
  )
245
+ lime_explanation = lime_explainer.explain_instance(
246
+ X_test.iloc[0].values,
247
+ final_model.predict_proba
248
+ )
249
  lime_fig = lime_explanation.as_pyplot_figure()
250
  lime_fig_path = "./figures/lime_explanation.png"
251
  lime_fig.savefig(lime_fig_path)
 
252
  plt.clf()
253
+
254
+ # Log everything to W&B
255
+ wandb.log({
256
+ "best_params": best_params,
257
+ "best_accuracy": best_value,
258
+ "final_accuracy": accuracy,
259
+ "final_precision": precision,
260
+ "final_recall": recall,
261
+ "final_f1": f1,
262
+ "optimization_history": wandb.Image(history_path),
263
+ "parameter_importance": wandb.Image(importance_path),
264
+ "shap_summary": wandb.Image(shap_fig_path),
265
+ "lime_explanation": wandb.Image(lime_fig_path)
266
+ })
267
+
268
+ # Generate HTML report
269
+ report = f"""
270
+ <div style="font-family: Arial, sans-serif; padding: 20px; color: #333;">
271
+ <h1 style="color: #2B547E; border-bottom: 2px solid #2B547E; padding-bottom: 10px;">🎯 Hyperparameter Optimization Results</h1>
272
+
273
+ <div style="margin-top: 20px; background: #f8f9fa; padding: 15px; border-radius: 8px;">
274
+ <h2 style="color: #2B547E;">📈 Performance Metrics</h2>
275
+ <p><strong>Best Accuracy:</strong> {best_value:.4f}</p>
276
+ <p><strong>Final Model Accuracy:</strong> {accuracy:.4f}</p>
277
+ <p><strong>Precision:</strong> {precision:.4f}</p>
278
+ <p><strong>Recall:</strong> {recall:.4f}</p>
279
+ <p><strong>F1 Score:</strong> {f1:.4f}</p>
280
+ </div>
281
+
282
+ <div style="margin-top: 25px; background: #f8f9fa; padding: 15px; border-radius: 8px;">
283
+ <h2 style="color: #2B547E;">⚙️ Best Parameters</h2>
284
+ <pre style="background: white; padding: 10px; border-radius: 4px;">{best_params}</pre>
285
+ </div>
286
+
287
+ <div style="margin-top: 25px;">
288
+ <h2 style="color: #2B547E;">📊 Optimization Process</h2>
289
+ <img src="/file={history_path}" style="max-width: 100%; border-radius: 6px; margin-bottom: 15px;">
290
+ <img src="/file={importance_path}" style="max-width: 100%; border-radius: 6px;">
291
+ </div>
292
+ </div>
293
  """
294
+
295
+ # Get visualization paths for gallery
296
+ visuals = [
297
+ history_path,
298
+ importance_path,
299
+ shap_fig_path,
300
+ lime_fig_path
301
+ ]
302
+
303
+ run.finish()
304
+ return report, visuals
305
 
306
+ def wandb_callback(study, trial):
307
+ """Callback to log study information to W&B after each trial"""
308
+ wandb.log({
309
+ "best_accuracy": study.best_value,
310
+ "current_trial": trial.number,
311
+ "current_accuracy": trial.value
312
+ })
313
 
314
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
315
+ gr.Markdown("## 📊 AI Data Analysis Agent with Enhanced Hyperparameter Optimization")
316
  with gr.Row():
317
  with gr.Column():
318
  file_input = gr.File(label="Upload CSV Dataset", type="filepath")
319
  notes_input = gr.Textbox(label="Dataset Notes (Optional)", lines=3)
320
  analyze_btn = gr.Button("Analyze", variant="primary")
321
+ optuna_trials = gr.Number(
322
+ label="Number of Hyperparameter Tuning Trials",
323
+ value=50,
324
+ minimum=10,
325
+ maximum=200,
326
+ step=5
327
+ )
328
  tune_btn = gr.Button("Optimize Hyperparameters", variant="secondary")
329
  with gr.Column():
330
  analysis_output = gr.Markdown("### Analysis results will appear here...")
331
  optuna_output = gr.HTML(label="Hyperparameter Tuning Results")
332
+ gallery = gr.Gallery(label="Optimization Visualizations", columns=2)
333
+
 
334
  analyze_btn.click(fn=analyze_data, inputs=[file_input, notes_input], outputs=[analysis_output, gallery])
335
+ tune_btn.click(fn=tune_hyperparameters, inputs=[file_input, optuna_trials], outputs=[optuna_output, gallery])
336
 
337
+ demo.launch(debug=True)