mlforgex 1.0.2__tar.gz → 1.0.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mlforgex
3
- Version: 1.0.2
3
+ Version: 1.0.3
4
4
  Summary: Lightweight ML utility for automated training, evaluation, and prediction with CLI and Python API support
5
5
  Home-page: https://github.com/yourusername/mlforge
6
6
  Author: Priyanshu Mathur
@@ -38,7 +38,7 @@ def train_model(data_path, dependent_feature,rmse_prob,f1_prob,n_jobs=-1,n_iter=
38
38
  # os.remove(data_path)
39
39
  df.head()
40
40
  print("Data loaded successfully")
41
-
41
+ df.replace(["", "NA", "na", "N/A", "n/a", "?", "--"], np.nan, inplace=True)
42
42
  for i in df.columns:
43
43
  if df[i].dtype=="object":
44
44
  df[i] = df[i].fillna(df[i].mode()[0])
@@ -117,6 +117,8 @@ def train_model(data_path, dependent_feature,rmse_prob,f1_prob,n_jobs=-1,n_iter=
117
117
  print("Categorical features : ",cat_features)
118
118
  print("Numerical features : ",num_features)
119
119
  if classification:
120
+ is_multiclass = len(set(y_train)) > 2
121
+ average_type = "weighted" if is_multiclass else "binary"
120
122
  print("Balancing the dataset...")
121
123
  if mild :
122
124
  from imblearn.under_sampling import RandomUnderSampler
@@ -245,7 +247,7 @@ def train_model(data_path, dependent_feature,rmse_prob,f1_prob,n_jobs=-1,n_iter=
245
247
  "AdaBoostClassifier":AdaBoostClassifier(),
246
248
  "XGBClassifier":XGBClassifier(),
247
249
  "KNeighborsClassifier":KNeighborsClassifier(),
248
- "SVC":SVC()
250
+ "SVC":SVC(probability=True)
249
251
  }
250
252
 
251
253
  for i in range(len(list(models))):
@@ -258,15 +260,26 @@ def train_model(data_path, dependent_feature,rmse_prob,f1_prob,n_jobs=-1,n_iter=
258
260
 
259
261
  # Training set performance
260
262
  model_train_accuracy = accuracy_score(y_train, y_train_pred) # Calculate Accuracy
261
- model_train_f1 = f1_score(y_train, y_train_pred, average='weighted') # Calculate F1-score
262
- model_train_precision = precision_score(y_train, y_train_pred) # Calculate Precision
263
- model_train_recall = recall_score(y_train, y_train_pred) # Calculate Recall
264
- model_train_rocauc_score = roc_auc_score(y_train, y_train_pred)
263
+ model_train_f1 = f1_score(y_train, y_train_pred, average=average_type) # Calculate F1-score
264
+ model_train_precision = precision_score(y_train, y_train_pred, average=average_type) # Calculate Precision
265
+ model_train_recall = recall_score(y_train, y_train_pred, average=average_type) # Calculate Recall
266
+ if average_type == "binary":
267
+ y_train_prob = model.predict_proba(x_train)[:,1]
268
+ model_train_rocauc_score = roc_auc_score(y_train, y_train_prob)
269
+ else:
270
+ y_train_prob=model.predict_proba(x_train)
271
+ model_train_rocauc_score = roc_auc_score(y_train, y_train_prob,multi_class='ovr',average=average_type) #Calculate Roc Auc Score
265
272
  # Test set performance
266
273
  model_test_accuracy = accuracy_score(y_test, y_test_pred) # Calculate Accuracy
267
- model_test_f1 = f1_score(y_test, y_test_pred, average='weighted') # Calculate F1-score
268
- model_test_precision = precision_score(y_test, y_test_pred) # Calculate Precision
269
- model_test_recall = recall_score(y_test, y_test_pred) # Calculate Recal
274
+ model_test_f1 = f1_score(y_test, y_test_pred, average=average_type) # Calculate F1-score
275
+ model_test_precision = precision_score(y_test, y_test_pred, average=average_type) # Calculate Precision
276
+ model_test_recall = recall_score(y_test, y_test_pred, average=average_type) # Calculate Recall
277
+ if average_type == "binary":
278
+ y_test_prob = model.predict_proba(x_test)[:,1]
279
+ model_test_rocauc_score = roc_auc_score(y_test, y_test_prob)
280
+ else:
281
+ y_test_prob=model.predict_proba(x_test)
282
+ model_test_rocauc_score = roc_auc_score(y_test, y_test_prob,multi_class='ovr',average=average_type) #Calculate Roc Auc Score
270
283
 
271
284
  model_dict.append({
272
285
  "model":list(models.keys())[i],
@@ -276,7 +289,6 @@ def train_model(data_path, dependent_feature,rmse_prob,f1_prob,n_jobs=-1,n_iter=
276
289
  "test_f1": model_test_f1,
277
290
  "tuned":False
278
291
  })
279
- model_test_rocauc_score = roc_auc_score(y_test, y_test_pred) #Calculate Roc
280
292
 
281
293
 
282
294
  # print(list(models.keys())[i])
@@ -447,7 +459,7 @@ def train_model(data_path, dependent_feature,rmse_prob,f1_prob,n_jobs=-1,n_iter=
447
459
  ["LogisticRegression", {
448
460
  'penalty': ['l1', 'l2', 'elasticnet', 'none'],
449
461
  'C': np.logspace(-4, 4, 20),
450
- 'solver': ['newton-cg', 'lbfgs', 'liblinear', 'sag', 'saga'],
462
+ 'solver': ['lbfgs', 'liblinear', 'saga'],
451
463
  'max_iter': [100, 200, 500, 1000],
452
464
  'class_weight': [None, 'balanced'],
453
465
  'l1_ratio': [0, 0.25, 0.5, 0.75, 1] # For elasticnet
@@ -597,7 +609,6 @@ def train_model(data_path, dependent_feature,rmse_prob,f1_prob,n_jobs=-1,n_iter=
597
609
  for i in range(len(list(models))):
598
610
  model = list(models.values())[i]
599
611
  model.fit(x_train, y_train) # Train model
600
-
601
612
  # Make predictions
602
613
  y_train_pred = model.predict(x_train)
603
614
  y_test_pred = model.predict(x_test)
@@ -658,22 +669,38 @@ def train_model(data_path, dependent_feature,rmse_prob,f1_prob,n_jobs=-1,n_iter=
658
669
 
659
670
  # Training set performance
660
671
  model_train_accuracy = accuracy_score(y_train, y_train_pred) # Calculate Accuracy
661
- model_train_f1 = f1_score(y_train, y_train_pred, average='weighted') # Calculate F1-score
662
- model_train_precision = precision_score(y_train, y_train_pred) # Calculate Precision
663
- model_train_recall = recall_score(y_train, y_train_pred) # Calculate Recall
664
- model_train_rocauc_score = roc_auc_score(y_train, y_train_pred)
672
+ model_train_f1 = f1_score(y_train, y_train_pred, average=average_type) # Calculate F1-score
673
+ model_train_precision = precision_score(y_train, y_train_pred,average=average_type) # Calculate Precision
674
+ model_train_recall = recall_score(y_train, y_train_pred,average=average_type) # Calculate Recall
675
+ if average_type == "binary":
676
+ y_train_prob = model.predict_proba(x_train)[:,1]
677
+ model_train_rocauc_score = roc_auc_score(y_train, y_train_prob)
678
+ else:
679
+ y_train_prob=model.predict_proba(x_train)
680
+ model_train_rocauc_score = roc_auc_score(y_train, y_train_prob, multi_class='ovr', average=average_type)
665
681
  # Test set performance
666
682
  model_test_accuracy = accuracy_score(y_test, y_test_pred) # Calculate Accuracy
667
- model_test_f1 = f1_score(y_test, y_test_pred, average='weighted') # Calculate F1-score
668
- model_test_precision = precision_score(y_test, y_test_pred) # Calculate Precision
669
- model_test_recall = recall_score(y_test, y_test_pred) # Calculate Recal
670
-
683
+ model_test_f1 = f1_score(y_test, y_test_pred, average=average_type) # Calculate F1-score
684
+ model_test_precision = precision_score(y_test, y_test_pred,average=average_type) # Calculate Precision
685
+ model_test_recall = recall_score(y_test, y_test_pred,average=average_type) # Calculate Recall
686
+ if average_type == "binary":
687
+ y_test_prob = model.predict_proba(x_test)[:,1]
688
+ model_test_rocauc_score = roc_auc_score(y_test, y_test_prob)
689
+ else:
690
+ y_test_prob=model.predict_proba(x_test)
691
+ model_test_rocauc_score = roc_auc_score(y_test, y_test_prob, multi_class='ovr', average=average_type)
671
692
  model_dict={
672
693
  "model":list(models.keys())[i],
673
694
  "train_accuracy": model_train_accuracy,
674
695
  "train_f1": model_train_f1,
696
+ "train_precision": model_train_precision,
697
+ "train_recall": model_train_recall,
698
+ "train_rocauc": model_train_rocauc_score,
675
699
  "test_accuracy": model_test_accuracy,
676
700
  "test_f1": model_test_f1,
701
+ "test_precision": model_test_precision,
702
+ "test_recall": model_test_recall,
703
+ "test_rocauc": model_test_rocauc_score,
677
704
  "tuned":True
678
705
  }
679
706
  best_models_copy = pd.concat(
@@ -727,7 +754,7 @@ def train_model(data_path, dependent_feature,rmse_prob,f1_prob,n_jobs=-1,n_iter=
727
754
  if classification:
728
755
  combined_score_ranking=combined_score_ranking[combined_score_ranking["train_f1"]-combined_score_ranking["test_f1"]<0.15]
729
756
  # print("====="*35)
730
- print(combined_score_ranking.iloc[0:1,:])
757
+ # print(combined_score_ranking.iloc[0:1,:])
731
758
  best_model_name = combined_score_ranking.iloc[0]["model"]
732
759
  best_param_dict = None
733
760
  for name, params in best_params:
@@ -742,7 +769,6 @@ def train_model(data_path, dependent_feature,rmse_prob,f1_prob,n_jobs=-1,n_iter=
742
769
  print("Saving the model and preprocessor...")
743
770
  model_path = os.path.join(artifacts_path, "model.pkl")
744
771
  preprocessor_path = os.path.join(artifacts_path, "preprocessor.pkl")
745
- encoder_path = os.path.join(artifacts_path, "encoder.pkl")
746
772
 
747
773
  with open(model_path, "wb") as f:
748
774
  pickle.dump(model, f)
@@ -751,27 +777,39 @@ def train_model(data_path, dependent_feature,rmse_prob,f1_prob,n_jobs=-1,n_iter=
751
777
  pickle.dump(preprocessor, f)
752
778
 
753
779
  if classification:
780
+ encoder_path = os.path.join(artifacts_path, "encoder.pkl")
754
781
  with open(encoder_path, "wb") as f:
755
782
  pickle.dump(le, f)
756
783
  response = {
757
- "message": "Training completed successfully",
784
+ "Message": "Training completed successfully",
758
785
  "Problem_type":"Classification",
759
- "model_metrics": {
760
786
  "Model": combined_score_ranking.iloc[0]["model"],
761
787
  "Train_accuracy": float(combined_score_ranking.iloc[0]["train_accuracy"]),
762
788
  "Train_f1": float(combined_score_ranking.iloc[0]["train_f1"]),
789
+ "Train_precision": float(combined_score_ranking.iloc[0]["train_precision"]),
790
+ "Train_recall": float(combined_score_ranking.iloc[0]["train_recall"]),
791
+ "Train_rocauc": float(combined_score_ranking.iloc[0]["train_rocauc"]),
763
792
  "Test_accuracy": float(combined_score_ranking.iloc[0]["test_accuracy"]),
764
793
  "Test_f1": float(combined_score_ranking.iloc[0]["test_f1"]),
794
+ "Test_precision": float(combined_score_ranking.iloc[0]["test_precision"]),
795
+ "Test_recall": float(combined_score_ranking.iloc[0]["test_recall"]),
796
+ "Test_rocauc": float(combined_score_ranking.iloc[0]["test_rocauc"]),
765
797
  "Hyper_tuned": bool(combined_score_ranking.iloc[0]["tuned"]),
766
798
  "Dropped_Columns":list(dropcorr)
767
- }
768
799
  }
769
- plot_classification_metrics(model,x_train, y_train, x_test, y_test, class_names=['No', 'Yes'],plot_path=plot_path)
800
+ if(response["Hyper_tuned"]):
801
+ response["Best_Params"] = best_param_dict
802
+ print("\n")
803
+ print("="*55)
804
+ for key, value in response.items():
805
+ print(f"{key}: {value}")
806
+ print("="*55)
807
+ print("\n")
808
+ plot_classification_metrics(model,x_train, y_train, x_test, y_test,plot_path=plot_path)
770
809
  else:
771
810
  response={
772
- "message": "Training completed successfully",
773
- "Problem_type":"Regression",
774
- "model_metrics": {
811
+ "Message": "Training completed successfully",
812
+ "Problem_type":"Regression",
775
813
  "Model": combined_score_ranking.iloc[0]["model"],
776
814
  "Train_R2": float(combined_score_ranking.iloc[0]["train_r2"]),
777
815
  "Train_RMSE": float(combined_score_ranking.iloc[0]["train_rmse"]),
@@ -779,10 +817,17 @@ def train_model(data_path, dependent_feature,rmse_prob,f1_prob,n_jobs=-1,n_iter=
779
817
  "Test_RMSE": float(combined_score_ranking.iloc[0]["test_rmse"]),
780
818
  "Hyper_tuned": bool(combined_score_ranking.iloc[0]["tuned"]),
781
819
  "Dropped_Columns":list(dropcorr)
782
- }
783
820
  }
821
+ if(response["Hyper_tuned"]):
822
+ response["Best_Params"] = best_param_dict
823
+ print("\n")
824
+ print("="*55)
825
+ for i in response:
826
+ print(f"{i}: {response[i]}")
827
+ print("="*55)
828
+ print("\n")
784
829
  plot_regression_metrics(model, x_train, y_train, x_test, y_test,feature_names,plot_path=plot_path)
785
- print(response)
830
+
786
831
  print("artifacts_path:", artifacts_path)
787
832
  print("model_path:", model_path)
788
833
  print("preprocessor_path:", preprocessor_path)
@@ -794,10 +839,10 @@ def plot_classification_metrics(model, X_train, y_train, X_test, y_test, plot_pa
794
839
  # Predict
795
840
  y_pred = model.predict(X_test)
796
841
  y_proba = model.predict_proba(X_test)[:, 1] if hasattr(model, "predict_proba") else None
797
-
842
+ unique_classes = model.classes_
798
843
  # Confusion Matrix
799
844
  cm = confusion_matrix(y_test, y_pred)
800
- disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=class_names)
845
+ disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=unique_classes)
801
846
  disp.plot(cmap="Blues")
802
847
  plt.title("Confusion Matrix")
803
848
  plt.savefig(os.path.join(plot_path,"confusion_matrix.png"), bbox_inches='tight')
@@ -810,14 +855,15 @@ def plot_classification_metrics(model, X_train, y_train, X_test, y_test, plot_pa
810
855
  plt.savefig(os.path.join(plot_path,"roc_curve.png"), bbox_inches='tight')
811
856
  plt.close()
812
857
  # Precision-Recall Curve
813
- if y_proba is not None:
858
+ if y_proba is not None and unique_classes.shape[0] == 2:
814
859
  precision, recall, _ = precision_recall_curve(y_test, y_proba)
815
860
  PrecisionRecallDisplay(precision=precision, recall=recall).plot()
816
861
  plt.title("Precision-Recall Curve")
817
862
  plt.savefig(os.path.join(plot_path,"precision_recall_curve.png"), bbox_inches='tight')
818
863
  plt.close()
819
864
  # Learning Curve
820
- train_sizes, train_scores, val_scores = learning_curve(model, X_train, y_train, cv=5, scoring='accuracy')
865
+ cv = min(5, np.min(np.bincount(y_train)))
866
+ train_sizes, train_scores, val_scores = learning_curve(model, X_train, y_train, cv=cv, scoring='accuracy')
821
867
  plt.plot(train_sizes, np.mean(train_scores, axis=1), label="Train")
822
868
  plt.plot(train_sizes, np.mean(val_scores, axis=1), label="Validation")
823
869
  plt.title("Learning Curve (Accuracy)")
@@ -835,6 +881,9 @@ def plot_classification_metrics(model, X_train, y_train, X_test, y_test, plot_pa
835
881
  ax[1].set_title("Testing Class Distribution")
836
882
  plt.savefig(os.path.join(plot_path,"class_distribution.png"), bbox_inches='tight')
837
883
  plt.close()
884
+
885
+
886
+
838
887
  def plot_regression_metrics(model, X_train, y_train, X_test, y_test,feature_names,plot_path):
839
888
  y_pred = model.predict(X_test)
840
889
  residuals = y_test - y_pred
@@ -885,4 +934,3 @@ def main():
885
934
  parser.add_argument("--cv", default=3, type=int)
886
935
  args = parser.parse_args()
887
936
  print(train_model(args.data_path, args.dependent_feature, rmse_prob=args.rmse_prob, f1_prob=args.f1_prob, n_jobs=args.n_jobs, n_iter=args.n_iter, cv=args.cv))
888
-
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mlforgex
3
- Version: 1.0.2
3
+ Version: 1.0.3
4
4
  Summary: Lightweight ML utility for automated training, evaluation, and prediction with CLI and Python API support
5
5
  Home-page: https://github.com/yourusername/mlforge
6
6
  Author: Priyanshu Mathur
@@ -5,7 +5,7 @@ this_directory = Path(__file__).parent
5
5
  long_description = (this_directory / "README.md").read_text()
6
6
  setup(
7
7
  name="mlforgex",
8
- version="1.0.2",
8
+ version="1.0.3",
9
9
  packages=find_packages(),
10
10
  install_requires = [
11
11
  "pandas",
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes