plethegenuine1908 commited on
Commit
36f961a
ยท
verified ยท
1 Parent(s): 575169b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +35 -60
app.py CHANGED
@@ -4,12 +4,12 @@ import vlai_template
4
 
5
  # Import Logistic Regression core
6
  try:
7
- from src import logistic_regression
8
  LR_AVAILABLE = True
9
  except ImportError as e:
10
- print(f"โŒ Logistic Regression module failed to load: {str(e)}")
11
  LR_AVAILABLE = False
12
- logistic_regression = None
13
 
14
  vlai_template.configure(
15
  project_name="Softmax Regression Demo",
@@ -41,21 +41,21 @@ def load_sample_data_fallback(dataset_choice="Breast Cancer"):
41
  df["target"] = data.target
42
  return df
43
 
44
- def wine_to_binary_df(wine_data):
45
  df = pd.DataFrame(wine_data.data, columns=wine_data.feature_names)
46
- df["target"] = (wine_data.target == 0).astype(int)
47
  return df
48
 
49
  def synthetic_classification():
50
- X, y = make_classification(n_samples=1000, n_features=20, n_informative=15,
51
- n_redundant=5, n_classes=2, random_state=42)
52
  df = pd.DataFrame(X, columns=[f"feature_{i}" for i in range(X.shape[1])])
53
  df["target"] = y
54
  return df
55
 
56
  datasets = {
57
- "Breast Cancer": lambda: sklearn_to_df(load_breast_cancer()),
58
- "Wine (Binary)": lambda: wine_to_binary_df(load_wine()),
59
  "Synthetic": lambda: synthetic_classification(),
60
  }
61
 
@@ -91,9 +91,9 @@ def create_input_components_fallback(df, target_col):
91
  return components
92
 
93
  SAMPLE_DATA_CONFIG = {
94
- "Breast Cancer": {"target_column": "target", "problem_type": "classification"},
95
- "Wine (Binary)": {"target_column": "target", "problem_type": "classification"},
96
- "Synthetic": {"target_column": "target", "problem_type": "classification"},
97
  }
98
 
99
  force_light_theme_js = """
@@ -112,8 +112,6 @@ def validate_config(df, target_col):
112
 
113
  target_series = df[target_col]
114
  unique_vals = target_series.nunique()
115
-
116
- # For logistic regression, we only support binary classification (2 classes)
117
  problem_type = "classification"
118
 
119
  if target_series.isnull().any():
@@ -122,15 +120,15 @@ def validate_config(df, target_col):
122
  if target_series.dtype == "object":
123
  return False, "โš ๏ธ Target must be numeric for classification. Please select a numeric column.", None
124
 
125
- if unique_vals != 2:
126
- return False, f"โš ๏ธ Target must have exactly 2 unique values for binary classification. Found {unique_vals} unique values.", None
 
 
 
127
 
128
- # Check if values are 0 and 1
129
  unique_values = sorted(target_series.unique())
130
- if set(unique_values) != {0, 1}:
131
- return True, f"\nโœ… Configuration is valid! Target will be mapped to binary (0/1). Original values: {unique_values}", problem_type
132
 
133
- return True, f"\nโœ… Configuration is valid! Ready for binary classification with values {unique_values}.", problem_type
134
 
135
 
136
  def get_status_message(is_sample, dataset_choice, target_col, problem_type, is_valid, validation_msg):
@@ -176,7 +174,7 @@ def load_and_configure_data_simple(dataset_choice="Breast Cancer"):
176
  return [pd.DataFrame(), gr.Dropdown(choices=[], value=None), f"โŒ **Error loading data**: {str(e)} | Please try a different dataset."]
177
 
178
 
179
- def load_and_configure_data(file_obj=None, dataset_choice="Breast Cancer"):
180
  global current_dataframe
181
  try:
182
  if not LR_AVAILABLE:
@@ -356,7 +354,7 @@ def update_configuration(df_preview, target_col):
356
 
357
  # Logistic Regression prediction function
358
 
359
- def execute_prediction(df_preview, target_col, epochs, learning_rate_power, batch_size_power, train_test_split_ratio, threshold, *input_values):
360
  global current_dataframe
361
  df = current_dataframe
362
 
@@ -408,8 +406,8 @@ def execute_prediction(df_preview, target_col, epochs, learning_rate_power, batc
408
  actual_batch_size = 2 ** int(batch_size_power)
409
  batch_size_str = str(actual_batch_size)
410
 
411
- train_loss_fig, val_loss_fig, results_display, prediction = logistic_regression.run_logistic_regression_and_visualize(
412
- df, target_col, new_point_dict, epochs, lr_float, batch_size_str, train_test_split_ratio, threshold
413
  )
414
 
415
  return (train_loss_fig, val_loss_fig, results_display)
@@ -429,11 +427,11 @@ with gr.Blocks(theme="gstaff/sketch", css=vlai_template.custom_css, fill_width=T
429
 
430
  gr.HTML(vlai_template.render_info_card(
431
  icon="๐Ÿ“Š",
432
- title="About this Logistic Regression Demo",
433
- description="Interactive demonstration of Logistic Regression using NumPy and gradient descent. Learn binary classification with sigmoid activation, binary cross-entropy loss, and adjustable prediction threshold. Visualize training metrics and experiment with different threshold values."
434
  ))
435
 
436
- gr.Markdown("### ๐Ÿ“Š **How to Use**: Select binary classification data โ†’ Configure target (must have 2 classes) โ†’ Set training parameters โ†’ Adjust threshold โ†’ Enter feature values โ†’ Run training!")
437
 
438
  with gr.Row(equal_height=False, variant="panel"):
439
  with gr.Column(scale=45):
@@ -479,15 +477,6 @@ with gr.Blocks(theme="gstaff/sketch", css=vlai_template.custom_css, fill_width=T
479
  value=0.8, minimum=0.6, maximum=0.9, step=0.05,
480
  info="Proportion of data used for training (e.g., 0.8 = 80% train, 20% validation)"
481
  )
482
-
483
- gr.Markdown("**๐ŸŽฏ Prediction Threshold Configuration**")
484
- with gr.Row():
485
- threshold = gr.Slider(
486
- label="Classification Threshold",
487
- value=0.5, minimum=0.0, maximum=1.0, step=0.01,
488
- info="Probability threshold for binary classification. Predict class 1 if probability โ‰ฅ threshold, else class 0. Adjust to balance precision/recall."
489
- )
490
- threshold_display = gr.Markdown("**Current Threshold:** 0.50")
491
 
492
  inputs_group = gr.Group(visible=False)
493
  with inputs_group:
@@ -506,16 +495,16 @@ with gr.Blocks(theme="gstaff/sketch", css=vlai_template.custom_css, fill_width=T
506
  run_prediction_btn = gr.Button("๐Ÿ“Š Run Training & Prediction", variant="primary", size="lg")
507
 
508
  with gr.Column(scale=55):
509
- gr.Markdown("### ๐Ÿ“Š **Logistic Regression Results & Visualization**")
510
 
511
  train_loss_chart = gr.Plot(label="Training Loss & Accuracy Over Epochs", visible=True)
512
  val_loss_chart = gr.Plot(label="Validation Loss & Accuracy Over Epochs", visible=True)
513
- results_display = gr.HTML("**๐Ÿ“Š Logistic Regression Results**<br><br>Training details will appear here showing model performance, learned parameters, and predictions with current threshold.", label="๐Ÿ“Š Results & Predictions")
514
 
515
- gr.Markdown("""๐Ÿ“Š **Logistic Regression Guide**:
516
 
517
  **๐Ÿ“ˆ Training Metrics**:
518
- - **Loss (BCE)**: Binary Cross-Entropy loss decreases as model learns. Lower loss indicates better fit.
519
  - **Accuracy**: Classification accuracy improves during training. Monitor both training and validation accuracy.
520
 
521
  **๐Ÿ”ง Training Parameters**:
@@ -524,29 +513,21 @@ with gr.Blocks(theme="gstaff/sketch", css=vlai_template.custom_css, fill_width=T
524
  - **Batch Size**: Samples processed before updating parameters. Powers of 2: 1, 2, 4, 8... or Full Batch. Smaller = faster updates but noisier. Larger = more stable.
525
  - **Train/Validation Split**: Proportion of data for training vs validation. Default 80/20 split.
526
 
527
- **๐ŸŽฏ Threshold Parameter**:
528
- - **Threshold**: Probability cutoff for binary classification. If predicted probability โ‰ฅ threshold โ†’ class 1, else โ†’ class 0.
529
- - **Default**: 0.5 (balanced)
530
- - **Lower threshold** (e.g., 0.3): More predictions of class 1 โ†’ higher recall, lower precision
531
- - **Higher threshold** (e.g., 0.7): Fewer predictions of class 1 โ†’ higher precision, lower recall
532
- - **Experiment**: Adjust threshold to see how predictions and accuracy change!
533
-
534
  **๐Ÿงฎ Algorithm Details**:
535
- - **Sigmoid Activation**: Maps linear output to probability (0-1 range)
536
- - **Binary Cross-Entropy Loss**: Optimized for binary classification tasks
537
- - **Feature Normalization**: Automatic standardization (zero mean, unit variance) for stable training
538
 
539
  **๐Ÿ’ก Tips**:
540
  - Start with default parameters (100 epochs, learning rate 0.01, threshold 0.5)
541
  - Monitor validation metrics to detect overfitting
542
- - Adjust threshold based on your classification goals (precision vs recall)
543
  - Use batch size = Full Batch for most stable training
544
  """)
545
 
546
  vlai_template.create_footer()
547
 
548
  load_evt = demo.load(
549
- fn=lambda: load_and_configure_data(None, "Breast Cancer"),
550
  outputs=[data_preview, target_column, status_message] + input_components + [inputs_group, input_status],
551
  ).then(
552
  fn=update_batch_size_slider,
@@ -562,7 +543,7 @@ with gr.Blocks(theme="gstaff/sketch", css=vlai_template.custom_css, fill_width=T
562
  outputs=[learning_rate_display],
563
  )
564
  upload_evt = file_upload.upload(
565
- fn=lambda file: load_and_configure_data(file, "Breast Cancer"),
566
  inputs=[file_upload],
567
  outputs=[data_preview, target_column, status_message] + input_components + [inputs_group, input_status],
568
  ).then(
@@ -629,15 +610,9 @@ with gr.Blocks(theme="gstaff/sketch", css=vlai_template.custom_css, fill_width=T
629
  outputs=[learning_rate_display],
630
  )
631
 
632
- threshold.change(
633
- fn=lambda t: f"**Current Threshold:** {t:.2f}",
634
- inputs=[threshold],
635
- outputs=[threshold_display],
636
- )
637
-
638
  run_prediction_btn.click(
639
  fn=execute_prediction,
640
- inputs=[data_preview, target_column, epochs, learning_rate_slider, batch_size_slider, train_test_split_ratio, threshold] + input_components,
641
  outputs=[train_loss_chart, val_loss_chart, results_display],
642
  )
643
 
 
4
 
5
  # Import Logistic Regression core
6
  try:
7
+ from src import softmax_regression
8
  LR_AVAILABLE = True
9
  except ImportError as e:
10
+ print(f"โŒ Softmax Regression module failed to load: {str(e)}")
11
  LR_AVAILABLE = False
12
+ softmax_regression = None
13
 
14
  vlai_template.configure(
15
  project_name="Softmax Regression Demo",
 
41
  df["target"] = data.target
42
  return df
43
 
44
+ def wine_to_df(wine_data):
45
  df = pd.DataFrame(wine_data.data, columns=wine_data.feature_names)
46
+ df["target"] = wine_data.target
47
  return df
48
 
49
  def synthetic_classification():
50
+ X, y = make_classification(n_samples=1000, n_features=10, n_informative=8,
51
+ n_redundant=2, n_classes=3, random_state=42)
52
  df = pd.DataFrame(X, columns=[f"feature_{i}" for i in range(X.shape[1])])
53
  df["target"] = y
54
  return df
55
 
56
  datasets = {
57
+ "Iris": lambda: sklearn_to_df(load_iris())),
58
+ "Wine (Binary)": lambda: wine_to_df(load_wine()),
59
  "Synthetic": lambda: synthetic_classification(),
60
  }
61
 
 
91
  return components
92
 
93
  SAMPLE_DATA_CONFIG = {
94
+ "Iris": {"target_column": "target", "problem_type": "classification"},
95
+ "Wine (Multi-class)": {"target_column": "target", "problem_type": "classification"},
96
+ "Synthetic (3-Class)": {"target_column": "target", "problem_type": "classification"},
97
  }
98
 
99
  force_light_theme_js = """
 
112
 
113
  target_series = df[target_col]
114
  unique_vals = target_series.nunique()
 
 
115
  problem_type = "classification"
116
 
117
  if target_series.isnull().any():
 
120
  if target_series.dtype == "object":
121
  return False, "โš ๏ธ Target must be numeric for classification. Please select a numeric column.", None
122
 
123
+ if unique_vals < 2:
124
+ return False, f"โš ๏ธ Target must have at least 2 unique values. Found {unique_vals}.", None
125
+
126
+ if not pd.api.types.is_numeric_dtype(target_series):
127
+ return False, "โš ๏ธ For this demo, target labels must be numeric (e.g., 0, 1, 2). Please encode your labels first.", None
128
 
 
129
  unique_values = sorted(target_series.unique())
 
 
130
 
131
+ return True, f"\nโœ… Ready for Multi-class Softmax Classification! Found {unique_vals} classes: {unique_values}", problem_type
132
 
133
 
134
  def get_status_message(is_sample, dataset_choice, target_col, problem_type, is_valid, validation_msg):
 
174
  return [pd.DataFrame(), gr.Dropdown(choices=[], value=None), f"โŒ **Error loading data**: {str(e)} | Please try a different dataset."]
175
 
176
 
177
+ def load_and_configure_data(file_obj=None, dataset_choice="Iris"):
178
  global current_dataframe
179
  try:
180
  if not LR_AVAILABLE:
 
354
 
355
  # Logistic Regression prediction function
356
 
357
+ def execute_prediction(df_preview, target_col, epochs, learning_rate_power, batch_size_power, train_test_split_ratio, *input_values):
358
  global current_dataframe
359
  df = current_dataframe
360
 
 
406
  actual_batch_size = 2 ** int(batch_size_power)
407
  batch_size_str = str(actual_batch_size)
408
 
409
+ train_loss_fig, val_loss_fig, results_display, prediction = sofmax_regression.run_softmax_regression_and_visualize(
410
+ df, target_col, new_point_dict, epochs, lr_float, batch_size_str, train_test_split_ratio
411
  )
412
 
413
  return (train_loss_fig, val_loss_fig, results_display)
 
427
 
428
  gr.HTML(vlai_template.render_info_card(
429
  icon="๐Ÿ“Š",
430
+ title="About this Softmax Regression Demo",
431
+ description="Interactive demonstration of Softmax Regression for multi-class classification. Learn how it uses the Softmax activation function and Categorical Cross-Entropy loss to predict probabilities across multiple categories."
432
  ))
433
 
434
+ gr.Markdown("### ๐Ÿ“Š **How to Use**: Select multi-class data โ†’ Configure target โ†’ Set training parameters โ†’ Enter feature values โ†’ Run training!")
435
 
436
  with gr.Row(equal_height=False, variant="panel"):
437
  with gr.Column(scale=45):
 
477
  value=0.8, minimum=0.6, maximum=0.9, step=0.05,
478
  info="Proportion of data used for training (e.g., 0.8 = 80% train, 20% validation)"
479
  )
 
 
 
 
 
 
 
 
 
480
 
481
  inputs_group = gr.Group(visible=False)
482
  with inputs_group:
 
495
  run_prediction_btn = gr.Button("๐Ÿ“Š Run Training & Prediction", variant="primary", size="lg")
496
 
497
  with gr.Column(scale=55):
498
+ gr.Markdown("### ๐Ÿ“Š **Softmax Regression Results & Visualization**")
499
 
500
  train_loss_chart = gr.Plot(label="Training Loss & Accuracy Over Epochs", visible=True)
501
  val_loss_chart = gr.Plot(label="Validation Loss & Accuracy Over Epochs", visible=True)
502
+ results_display = gr.HTML("**๐Ÿ“Š Softmax Regression Results**<br><br>Training details will appear here showing model performance, learned parameters, and predictions with current threshold.", label="๐Ÿ“Š Results & Predictions")
503
 
504
+ gr.Markdown("""๐Ÿ“Š **Softmax Regression Guide**:
505
 
506
  **๐Ÿ“ˆ Training Metrics**:
507
+ - **Categorical Cross-Entropy (CCE)**: The loss function used to optimize multi-class models.
508
  - **Accuracy**: Classification accuracy improves during training. Monitor both training and validation accuracy.
509
 
510
  **๐Ÿ”ง Training Parameters**:
 
513
  - **Batch Size**: Samples processed before updating parameters. Powers of 2: 1, 2, 4, 8... or Full Batch. Smaller = faster updates but noisier. Larger = more stable.
514
  - **Train/Validation Split**: Proportion of data for training vs validation. Default 80/20 split.
515
 
 
 
 
 
 
 
 
516
  **๐Ÿงฎ Algorithm Details**:
517
+ - **Softmax Activation**: Converts raw scores (logits) into a probability distribution that sums to 1.0 across all classes.
518
+ - **Categorical Cross-Entropy (CCE)**: The loss function used to optimize multi-class models.
519
+ - **Feature Normalization**: Automatic standardization (zero mean, unit variance) for stable training.
520
 
521
  **๐Ÿ’ก Tips**:
522
  - Start with default parameters (100 epochs, learning rate 0.01, threshold 0.5)
523
  - Monitor validation metrics to detect overfitting
 
524
  - Use batch size = Full Batch for most stable training
525
  """)
526
 
527
  vlai_template.create_footer()
528
 
529
  load_evt = demo.load(
530
+ fn=lambda: load_and_configure_data(None, "Iris"),
531
  outputs=[data_preview, target_column, status_message] + input_components + [inputs_group, input_status],
532
  ).then(
533
  fn=update_batch_size_slider,
 
543
  outputs=[learning_rate_display],
544
  )
545
  upload_evt = file_upload.upload(
546
+ fn=lambda file: load_and_configure_data(file, "Iris"),
547
  inputs=[file_upload],
548
  outputs=[data_preview, target_column, status_message] + input_components + [inputs_group, input_status],
549
  ).then(
 
610
  outputs=[learning_rate_display],
611
  )
612
 
 
 
 
 
 
 
613
  run_prediction_btn.click(
614
  fn=execute_prediction,
615
+ inputs=[data_preview, target_column, epochs, learning_rate_slider, batch_size_slider, train_test_split_ratio] + input_components,
616
  outputs=[train_loss_chart, val_loss_chart, results_display],
617
  )
618