mlforgex 1.0.2__tar.gz → 1.0.4__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,8 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mlforgex
3
- Version: 1.0.2
3
+ Version: 1.0.4
4
4
  Summary: Lightweight ML utility for automated training, evaluation, and prediction with CLI and Python API support
5
- Home-page: https://github.com/yourusername/mlforge
6
5
  Author: Priyanshu Mathur
7
6
  Author-email: mathurpriyanshu2006@gmail.com
8
7
  License: MIT
@@ -24,14 +23,13 @@ Dynamic: author-email
24
23
  Dynamic: classifier
25
24
  Dynamic: description
26
25
  Dynamic: description-content-type
27
- Dynamic: home-page
28
26
  Dynamic: license
29
27
  Dynamic: license-file
30
28
  Dynamic: requires-dist
31
29
  Dynamic: requires-python
32
30
  Dynamic: summary
33
31
 
34
- # mlforgex
32
+ # mlforgex [![PyPI Downloads](https://static.pepy.tech/badge/mlforgex)](https://pepy.tech/projects/mlforgex)
35
33
 
36
34
  **mlforgex** is a Python package that enables easy training, evaluation, and prediction for machine learning models on cleaned dataset. It supports both classification and regression problems, automates preprocessing, model selection, hyperparameter tuning, and generates useful artifacts and plots for analysis.
37
35
 
@@ -1,4 +1,4 @@
1
- # mlforgex
1
+ # mlforgex [![PyPI Downloads](https://static.pepy.tech/badge/mlforgex)](https://pepy.tech/projects/mlforgex)
2
2
 
3
3
  **mlforgex** is a Python package that enables easy training, evaluation, and prediction for machine learning models on cleaned dataset. It supports both classification and regression problems, automates preprocessing, model selection, hyperparameter tuning, and generates useful artifacts and plots for analysis.
4
4
 
@@ -0,0 +1,44 @@
1
+ import pickle;
2
+ import pandas as pd;
3
+ def predict(model_path,preprocessor_path,input_data, encoder_path=None):
4
+ """
5
+ Load a trained model and make predictions on input data.
6
+
7
+ Args:
8
+ model_path (str):
9
+ Path to the serialized trained model file.
10
+ preprocessor_path (str):
11
+ Path to the serialized preprocessor file (used for feature transformation).
12
+ input_data (str):
13
+ Path to the input CSV file containing data for prediction.
14
+ encoder_path (Optional[str], optional):
15
+ Path to the serialized encoder file (for categorical target encoding). Defaults to None.
16
+
17
+ Returns:
18
+ List[Any]:
19
+ List of predictions generated by the model.
20
+
21
+ Examples:
22
+ >>> predict("model.pkl", "preprocessor.pkl", "input.csv")
23
+ [1, 0, 1]
24
+ """
25
+ print("Loading the pickled model and preprocessor...")
26
+ model = pickle.load(open(model_path, 'rb'))
27
+ preprocessor = pickle.load(open(preprocessor_path, 'rb'))
28
+ encoder = pickle.load(open(encoder_path, 'rb')) if encoder_path else None
29
+ df= pd.read_csv(input_data)
30
+ X = preprocessor.transform(df)
31
+ predictions = model.predict(X)
32
+ if encoder_path:
33
+ predictions = encoder.inverse_transform(predictions)
34
+ return {"prediction": predictions.tolist()}
35
+ def main():
36
+ import argparse
37
+ parser = argparse.ArgumentParser()
38
+ parser.add_argument("--model_path", required=True,help="Path to the model file")
39
+ parser.add_argument("--input_data", required=True,help="Path to the input data CSV file")
40
+ parser.add_argument("--preprocessor_path", required=True,help="Path to the preprocessor file")
41
+ parser.add_argument("--encoder_path", required=False,help="Path to the encoder file")
42
+ args = parser.parse_args()
43
+ print(predict(args.model_path, args.preprocessor_path, args.input_data, args.encoder_path))
44
+
@@ -26,6 +26,21 @@ from sklearn.model_selection import learning_curve
26
26
  import warnings
27
27
  warnings.filterwarnings("ignore")
28
28
  def train_model(data_path, dependent_feature,rmse_prob,f1_prob,n_jobs=-1,n_iter=100,cv=3,artifacts_dir=None):
29
+ """
30
+ Trains a machine learning model using the provided dataset and parameters.
31
+
32
+ Args:
33
+ data_path (str): Path to the CSV dataset file.
34
+ dependent_feature (str): The target column (dependent variable) in the dataset.
35
+ rmse_prob (float): Probability threshold for RMSE (used in regression).
36
+ f1_prob (float): Probability threshold for F1 score (used in classification).
37
+ n_jobs (int, optional): Number of parallel jobs to run (-1 uses all CPUs). Default is -1.
38
+ n_iter (int, optional): Number of iterations for parameter search. Default is 100.
39
+ cv (int, optional): Number of cross-validation folds. Default is 3.
40
+
41
+ Returns:
42
+ dict: Model evaluation metrics and trained model object.
43
+ """
29
44
  if artifacts_dir:
30
45
  artifacts_path = os.path.join(artifacts_dir, "artifacts")
31
46
  else:
@@ -38,7 +53,7 @@ def train_model(data_path, dependent_feature,rmse_prob,f1_prob,n_jobs=-1,n_iter=
38
53
  # os.remove(data_path)
39
54
  df.head()
40
55
  print("Data loaded successfully")
41
-
56
+ df.replace(["", "NA", "na", "N/A", "n/a", "?", "--"], np.nan, inplace=True)
42
57
  for i in df.columns:
43
58
  if df[i].dtype=="object":
44
59
  df[i] = df[i].fillna(df[i].mode()[0])
@@ -117,6 +132,8 @@ def train_model(data_path, dependent_feature,rmse_prob,f1_prob,n_jobs=-1,n_iter=
117
132
  print("Categorical features : ",cat_features)
118
133
  print("Numerical features : ",num_features)
119
134
  if classification:
135
+ is_multiclass = len(set(y_train)) > 2
136
+ average_type = "weighted" if is_multiclass else "binary"
120
137
  print("Balancing the dataset...")
121
138
  if mild :
122
139
  from imblearn.under_sampling import RandomUnderSampler
@@ -245,7 +262,7 @@ def train_model(data_path, dependent_feature,rmse_prob,f1_prob,n_jobs=-1,n_iter=
245
262
  "AdaBoostClassifier":AdaBoostClassifier(),
246
263
  "XGBClassifier":XGBClassifier(),
247
264
  "KNeighborsClassifier":KNeighborsClassifier(),
248
- "SVC":SVC()
265
+ "SVC":SVC(probability=True)
249
266
  }
250
267
 
251
268
  for i in range(len(list(models))):
@@ -258,15 +275,26 @@ def train_model(data_path, dependent_feature,rmse_prob,f1_prob,n_jobs=-1,n_iter=
258
275
 
259
276
  # Training set performance
260
277
  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)
278
+ model_train_f1 = f1_score(y_train, y_train_pred, average=average_type) # Calculate F1-score
279
+ model_train_precision = precision_score(y_train, y_train_pred, average=average_type) # Calculate Precision
280
+ model_train_recall = recall_score(y_train, y_train_pred, average=average_type) # Calculate Recall
281
+ if average_type == "binary":
282
+ y_train_prob = model.predict_proba(x_train)[:,1]
283
+ model_train_rocauc_score = roc_auc_score(y_train, y_train_prob)
284
+ else:
285
+ y_train_prob=model.predict_proba(x_train)
286
+ model_train_rocauc_score = roc_auc_score(y_train, y_train_prob,multi_class='ovr',average=average_type) #Calculate Roc Auc Score
265
287
  # Test set performance
266
288
  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
289
+ model_test_f1 = f1_score(y_test, y_test_pred, average=average_type) # Calculate F1-score
290
+ model_test_precision = precision_score(y_test, y_test_pred, average=average_type) # Calculate Precision
291
+ model_test_recall = recall_score(y_test, y_test_pred, average=average_type) # Calculate Recall
292
+ if average_type == "binary":
293
+ y_test_prob = model.predict_proba(x_test)[:,1]
294
+ model_test_rocauc_score = roc_auc_score(y_test, y_test_prob)
295
+ else:
296
+ y_test_prob=model.predict_proba(x_test)
297
+ model_test_rocauc_score = roc_auc_score(y_test, y_test_prob,multi_class='ovr',average=average_type) #Calculate Roc Auc Score
270
298
 
271
299
  model_dict.append({
272
300
  "model":list(models.keys())[i],
@@ -276,7 +304,6 @@ def train_model(data_path, dependent_feature,rmse_prob,f1_prob,n_jobs=-1,n_iter=
276
304
  "test_f1": model_test_f1,
277
305
  "tuned":False
278
306
  })
279
- model_test_rocauc_score = roc_auc_score(y_test, y_test_pred) #Calculate Roc
280
307
 
281
308
 
282
309
  # print(list(models.keys())[i])
@@ -447,7 +474,7 @@ def train_model(data_path, dependent_feature,rmse_prob,f1_prob,n_jobs=-1,n_iter=
447
474
  ["LogisticRegression", {
448
475
  'penalty': ['l1', 'l2', 'elasticnet', 'none'],
449
476
  'C': np.logspace(-4, 4, 20),
450
- 'solver': ['newton-cg', 'lbfgs', 'liblinear', 'sag', 'saga'],
477
+ 'solver': ['lbfgs', 'liblinear', 'saga'],
451
478
  'max_iter': [100, 200, 500, 1000],
452
479
  'class_weight': [None, 'balanced'],
453
480
  'l1_ratio': [0, 0.25, 0.5, 0.75, 1] # For elasticnet
@@ -597,7 +624,6 @@ def train_model(data_path, dependent_feature,rmse_prob,f1_prob,n_jobs=-1,n_iter=
597
624
  for i in range(len(list(models))):
598
625
  model = list(models.values())[i]
599
626
  model.fit(x_train, y_train) # Train model
600
-
601
627
  # Make predictions
602
628
  y_train_pred = model.predict(x_train)
603
629
  y_test_pred = model.predict(x_test)
@@ -658,22 +684,38 @@ def train_model(data_path, dependent_feature,rmse_prob,f1_prob,n_jobs=-1,n_iter=
658
684
 
659
685
  # Training set performance
660
686
  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)
687
+ model_train_f1 = f1_score(y_train, y_train_pred, average=average_type) # Calculate F1-score
688
+ model_train_precision = precision_score(y_train, y_train_pred,average=average_type) # Calculate Precision
689
+ model_train_recall = recall_score(y_train, y_train_pred,average=average_type) # Calculate Recall
690
+ if average_type == "binary":
691
+ y_train_prob = model.predict_proba(x_train)[:,1]
692
+ model_train_rocauc_score = roc_auc_score(y_train, y_train_prob)
693
+ else:
694
+ y_train_prob=model.predict_proba(x_train)
695
+ model_train_rocauc_score = roc_auc_score(y_train, y_train_prob, multi_class='ovr', average=average_type)
665
696
  # Test set performance
666
697
  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
-
698
+ model_test_f1 = f1_score(y_test, y_test_pred, average=average_type) # Calculate F1-score
699
+ model_test_precision = precision_score(y_test, y_test_pred,average=average_type) # Calculate Precision
700
+ model_test_recall = recall_score(y_test, y_test_pred,average=average_type) # Calculate Recall
701
+ if average_type == "binary":
702
+ y_test_prob = model.predict_proba(x_test)[:,1]
703
+ model_test_rocauc_score = roc_auc_score(y_test, y_test_prob)
704
+ else:
705
+ y_test_prob=model.predict_proba(x_test)
706
+ model_test_rocauc_score = roc_auc_score(y_test, y_test_prob, multi_class='ovr', average=average_type)
671
707
  model_dict={
672
708
  "model":list(models.keys())[i],
673
709
  "train_accuracy": model_train_accuracy,
674
710
  "train_f1": model_train_f1,
711
+ "train_precision": model_train_precision,
712
+ "train_recall": model_train_recall,
713
+ "train_rocauc": model_train_rocauc_score,
675
714
  "test_accuracy": model_test_accuracy,
676
715
  "test_f1": model_test_f1,
716
+ "test_precision": model_test_precision,
717
+ "test_recall": model_test_recall,
718
+ "test_rocauc": model_test_rocauc_score,
677
719
  "tuned":True
678
720
  }
679
721
  best_models_copy = pd.concat(
@@ -727,7 +769,7 @@ def train_model(data_path, dependent_feature,rmse_prob,f1_prob,n_jobs=-1,n_iter=
727
769
  if classification:
728
770
  combined_score_ranking=combined_score_ranking[combined_score_ranking["train_f1"]-combined_score_ranking["test_f1"]<0.15]
729
771
  # print("====="*35)
730
- print(combined_score_ranking.iloc[0:1,:])
772
+ # print(combined_score_ranking.iloc[0:1,:])
731
773
  best_model_name = combined_score_ranking.iloc[0]["model"]
732
774
  best_param_dict = None
733
775
  for name, params in best_params:
@@ -742,36 +784,41 @@ def train_model(data_path, dependent_feature,rmse_prob,f1_prob,n_jobs=-1,n_iter=
742
784
  print("Saving the model and preprocessor...")
743
785
  model_path = os.path.join(artifacts_path, "model.pkl")
744
786
  preprocessor_path = os.path.join(artifacts_path, "preprocessor.pkl")
745
- encoder_path = os.path.join(artifacts_path, "encoder.pkl")
746
787
 
747
788
  with open(model_path, "wb") as f:
748
789
  pickle.dump(model, f)
749
790
 
750
791
  with open(preprocessor_path, "wb") as f:
751
792
  pickle.dump(preprocessor, f)
752
-
793
+ encoder_path = None
753
794
  if classification:
795
+ encoder_path = os.path.join(artifacts_path, "encoder.pkl")
754
796
  with open(encoder_path, "wb") as f:
755
797
  pickle.dump(le, f)
756
798
  response = {
757
- "message": "Training completed successfully",
799
+ "Message": "Training completed successfully",
758
800
  "Problem_type":"Classification",
759
- "model_metrics": {
760
801
  "Model": combined_score_ranking.iloc[0]["model"],
761
802
  "Train_accuracy": float(combined_score_ranking.iloc[0]["train_accuracy"]),
762
803
  "Train_f1": float(combined_score_ranking.iloc[0]["train_f1"]),
804
+ "Train_precision": float(combined_score_ranking.iloc[0]["train_precision"]),
805
+ "Train_recall": float(combined_score_ranking.iloc[0]["train_recall"]),
806
+ "Train_rocauc": float(combined_score_ranking.iloc[0]["train_rocauc"]),
763
807
  "Test_accuracy": float(combined_score_ranking.iloc[0]["test_accuracy"]),
764
808
  "Test_f1": float(combined_score_ranking.iloc[0]["test_f1"]),
809
+ "Test_precision": float(combined_score_ranking.iloc[0]["test_precision"]),
810
+ "Test_recall": float(combined_score_ranking.iloc[0]["test_recall"]),
811
+ "Test_rocauc": float(combined_score_ranking.iloc[0]["test_rocauc"]),
765
812
  "Hyper_tuned": bool(combined_score_ranking.iloc[0]["tuned"]),
766
813
  "Dropped_Columns":list(dropcorr)
767
- }
768
814
  }
769
- plot_classification_metrics(model,x_train, y_train, x_test, y_test, class_names=['No', 'Yes'],plot_path=plot_path)
815
+ if(response["Hyper_tuned"]):
816
+ response["Best_Params"] = best_param_dict
817
+ plot_classification_metrics(model,x_train, y_train, x_test, y_test,plot_path=plot_path)
770
818
  else:
771
819
  response={
772
- "message": "Training completed successfully",
773
- "Problem_type":"Regression",
774
- "model_metrics": {
820
+ "Message": "Training completed successfully",
821
+ "Problem_type":"Regression",
775
822
  "Model": combined_score_ranking.iloc[0]["model"],
776
823
  "Train_R2": float(combined_score_ranking.iloc[0]["train_r2"]),
777
824
  "Train_RMSE": float(combined_score_ranking.iloc[0]["train_rmse"]),
@@ -779,10 +826,19 @@ def train_model(data_path, dependent_feature,rmse_prob,f1_prob,n_jobs=-1,n_iter=
779
826
  "Test_RMSE": float(combined_score_ranking.iloc[0]["test_rmse"]),
780
827
  "Hyper_tuned": bool(combined_score_ranking.iloc[0]["tuned"]),
781
828
  "Dropped_Columns":list(dropcorr)
782
- }
783
829
  }
830
+ if(response["Hyper_tuned"]):
831
+ response["Best_Params"] = best_param_dict
784
832
  plot_regression_metrics(model, x_train, y_train, x_test, y_test,feature_names,plot_path=plot_path)
785
- print(response)
833
+ print("\n")
834
+ print("="*55)
835
+ for i in response:
836
+ print(f"{i}: {response[i]}")
837
+ print("="*55)
838
+ print("\n")
839
+ with open(os.path.join(artifacts_path, "metrices.txt"), "w") as f:
840
+ for key, value in response.items():
841
+ f.write(f"{key}: {value}\n")
786
842
  print("artifacts_path:", artifacts_path)
787
843
  print("model_path:", model_path)
788
844
  print("preprocessor_path:", preprocessor_path)
@@ -794,10 +850,10 @@ def plot_classification_metrics(model, X_train, y_train, X_test, y_test, plot_pa
794
850
  # Predict
795
851
  y_pred = model.predict(X_test)
796
852
  y_proba = model.predict_proba(X_test)[:, 1] if hasattr(model, "predict_proba") else None
797
-
853
+ unique_classes = model.classes_
798
854
  # Confusion Matrix
799
855
  cm = confusion_matrix(y_test, y_pred)
800
- disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=class_names)
856
+ disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=unique_classes)
801
857
  disp.plot(cmap="Blues")
802
858
  plt.title("Confusion Matrix")
803
859
  plt.savefig(os.path.join(plot_path,"confusion_matrix.png"), bbox_inches='tight')
@@ -810,14 +866,15 @@ def plot_classification_metrics(model, X_train, y_train, X_test, y_test, plot_pa
810
866
  plt.savefig(os.path.join(plot_path,"roc_curve.png"), bbox_inches='tight')
811
867
  plt.close()
812
868
  # Precision-Recall Curve
813
- if y_proba is not None:
869
+ if y_proba is not None and unique_classes.shape[0] == 2:
814
870
  precision, recall, _ = precision_recall_curve(y_test, y_proba)
815
871
  PrecisionRecallDisplay(precision=precision, recall=recall).plot()
816
872
  plt.title("Precision-Recall Curve")
817
873
  plt.savefig(os.path.join(plot_path,"precision_recall_curve.png"), bbox_inches='tight')
818
874
  plt.close()
819
875
  # Learning Curve
820
- train_sizes, train_scores, val_scores = learning_curve(model, X_train, y_train, cv=5, scoring='accuracy')
876
+ cv = min(5, np.min(np.bincount(y_train)))
877
+ train_sizes, train_scores, val_scores = learning_curve(model, X_train, y_train, cv=cv, scoring='accuracy')
821
878
  plt.plot(train_sizes, np.mean(train_scores, axis=1), label="Train")
822
879
  plt.plot(train_sizes, np.mean(val_scores, axis=1), label="Validation")
823
880
  plt.title("Learning Curve (Accuracy)")
@@ -835,6 +892,9 @@ def plot_classification_metrics(model, X_train, y_train, X_test, y_test, plot_pa
835
892
  ax[1].set_title("Testing Class Distribution")
836
893
  plt.savefig(os.path.join(plot_path,"class_distribution.png"), bbox_inches='tight')
837
894
  plt.close()
895
+
896
+
897
+
838
898
  def plot_regression_metrics(model, X_train, y_train, X_test, y_test,feature_names,plot_path):
839
899
  y_pred = model.predict(X_test)
840
900
  residuals = y_test - y_pred
@@ -876,13 +936,12 @@ def plot_regression_metrics(model, X_train, y_train, X_test, y_test,feature_name
876
936
  def main():
877
937
  import argparse
878
938
  parser = argparse.ArgumentParser()
879
- parser.add_argument("--data_path", required=True)
880
- parser.add_argument("--dependent_feature", required=True)
881
- parser.add_argument("--rmse_prob", required=True)
882
- parser.add_argument("--f1_prob", required=True)
883
- parser.add_argument("--n_jobs", default=-1, type=int)
884
- parser.add_argument("--n_iter", default=100, type=int)
885
- parser.add_argument("--cv", default=3, type=int)
939
+ parser.add_argument("--data_path", required=True,help="Path to the dataset CSV file")
940
+ parser.add_argument("--dependent_feature", required=True,help="Name of the dependent feature (target variable)")
941
+ parser.add_argument("--rmse_prob", required=True,help="RMSE probability threshold")
942
+ parser.add_argument("--f1_prob", required=True,help="F1 score probability threshold")
943
+ parser.add_argument("--n_jobs", default=-1, type=int,help="Number of jobs to run in parallel")
944
+ parser.add_argument("--n_iter", default=100, type=int,help="Number of iterations for hyperparameter tuning")
945
+ parser.add_argument("--cv", default=3, type=int,help="Number of cross-validation folds")
886
946
  args = parser.parse_args()
887
947
  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,8 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mlforgex
3
- Version: 1.0.2
3
+ Version: 1.0.4
4
4
  Summary: Lightweight ML utility for automated training, evaluation, and prediction with CLI and Python API support
5
- Home-page: https://github.com/yourusername/mlforge
6
5
  Author: Priyanshu Mathur
7
6
  Author-email: mathurpriyanshu2006@gmail.com
8
7
  License: MIT
@@ -24,14 +23,13 @@ Dynamic: author-email
24
23
  Dynamic: classifier
25
24
  Dynamic: description
26
25
  Dynamic: description-content-type
27
- Dynamic: home-page
28
26
  Dynamic: license
29
27
  Dynamic: license-file
30
28
  Dynamic: requires-dist
31
29
  Dynamic: requires-python
32
30
  Dynamic: summary
33
31
 
34
- # mlforgex
32
+ # mlforgex [![PyPI Downloads](https://static.pepy.tech/badge/mlforgex)](https://pepy.tech/projects/mlforgex)
35
33
 
36
34
  **mlforgex** is a Python package that enables easy training, evaluation, and prediction for machine learning models on cleaned dataset. It supports both classification and regression problems, automates preprocessing, model selection, hyperparameter tuning, and generates useful artifacts and plots for analysis.
37
35
 
@@ -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.4",
9
9
  packages=find_packages(),
10
10
  install_requires = [
11
11
  "pandas",
@@ -28,7 +28,6 @@ setup(
28
28
  author="Priyanshu Mathur",
29
29
  author_email="mathurpriyanshu2006@gmail.com",
30
30
  description="Lightweight ML utility for automated training, evaluation, and prediction with CLI and Python API support",
31
- url="https://github.com/yourusername/mlforge",
32
31
  license="MIT",
33
32
  classifiers=[
34
33
  "License :: OSI Approved :: MIT License",
@@ -0,0 +1,9 @@
1
+ from mlforge import train_model, predict
2
+
3
+ def test_train_model():
4
+ result = train_model("StudentsPerformance.csv", "math_score", rmse_prob=0.3, f1_prob=0.7, n_jobs=-1)
5
+ assert result["status"] == "success"
6
+
7
+ def test_predict():
8
+ result =predict("artifacts/model.pkl", "artifacts/preprocessor.pkl", "input.csv")
9
+ assert "prediction" in result
@@ -1,23 +0,0 @@
1
- import pickle;
2
- import pandas as pd;
3
- def predict(model_path,preprocessor_path,input_data, encoder_path=None):
4
- print("Loading the pickled model and preprocessor...")
5
- model = pickle.load(open(model_path, 'rb'))
6
- preprocessor = pickle.load(open(preprocessor_path, 'rb'))
7
- encoder = pickle.load(open(encoder_path, 'rb')) if encoder_path else None
8
- df= pd.read_csv(input_data)
9
- X = preprocessor.transform(df)
10
- predictions = model.predict(X)
11
- if encoder_path:
12
- predictions = encoder.inverse_transform(predictions)
13
- return {"prediction": predictions.tolist()}
14
- def main():
15
- import argparse
16
- parser = argparse.ArgumentParser()
17
- parser.add_argument("--model_path", required=True)
18
- parser.add_argument("--input_data", required=True)
19
- parser.add_argument("--preprocessor_path", required=True)
20
- parser.add_argument("--encoder_path", required=False)
21
- args = parser.parse_args()
22
- print(predict(args.model_path, args.preprocessor_path, args.input_data, args.encoder_path))
23
-
@@ -1,9 +0,0 @@
1
- from mlforge import train_model, predict
2
-
3
- def test_train_model():
4
- result = train_model("mlforge/diabetes_cleaned.csv", "Outcome", rmse_prob=0.3, f1_prob=0.7, n_jobs=-1)
5
- assert result["status"] == "success"
6
-
7
- def test_predict():
8
- result =predict("mlforge/artifacts/model.pkl", "mlforge/artifacts/preprocessor.pkl", "mlforge/input.csv", "mlforge/artifacts/encoder.pkl")
9
- assert "prediction" in result
File without changes
File without changes
File without changes
File without changes