mlforgex 1.0.0__py3-none-any.whl
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.
- mlforge/__init__.py +4 -0
- mlforge/predict.py +23 -0
- mlforge/train.py +879 -0
- mlforgex-1.0.0.dist-info/METADATA +22 -0
- mlforgex-1.0.0.dist-info/RECORD +9 -0
- mlforgex-1.0.0.dist-info/WHEEL +5 -0
- mlforgex-1.0.0.dist-info/entry_points.txt +3 -0
- mlforgex-1.0.0.dist-info/licenses/LICENSE +21 -0
- mlforgex-1.0.0.dist-info/top_level.txt +1 -0
mlforge/__init__.py
ADDED
mlforge/predict.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
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", required=True)
|
|
18
|
+
parser.add_argument("--input", required=True)
|
|
19
|
+
parser.add_argument("--preprocessor", required=True)
|
|
20
|
+
parser.add_argument("--encoder", required=False)
|
|
21
|
+
args = parser.parse_args()
|
|
22
|
+
print(predict(args.model, args.preprocessor, args.input, args.encoder))
|
|
23
|
+
|
mlforge/train.py
ADDED
|
@@ -0,0 +1,879 @@
|
|
|
1
|
+
import pickle
|
|
2
|
+
import pandas as pd
|
|
3
|
+
import pickle
|
|
4
|
+
import os
|
|
5
|
+
import numpy as np
|
|
6
|
+
import seaborn as sns
|
|
7
|
+
import matplotlib
|
|
8
|
+
import warnings
|
|
9
|
+
warnings.filterwarnings("ignore", category=UserWarning)
|
|
10
|
+
warnings.filterwarnings("ignore", category=FutureWarning)
|
|
11
|
+
matplotlib.use('Agg') # Set backend to Agg to prevent GUI window
|
|
12
|
+
import matplotlib.pyplot as plt
|
|
13
|
+
from sklearn.metrics import (
|
|
14
|
+
confusion_matrix,
|
|
15
|
+
ConfusionMatrixDisplay,
|
|
16
|
+
roc_curve,
|
|
17
|
+
precision_recall_curve,
|
|
18
|
+
RocCurveDisplay,
|
|
19
|
+
PrecisionRecallDisplay,
|
|
20
|
+
mean_squared_error,
|
|
21
|
+
r2_score,
|
|
22
|
+
accuracy_score,
|
|
23
|
+
)
|
|
24
|
+
from sklearn.inspection import permutation_importance
|
|
25
|
+
from sklearn.model_selection import learning_curve
|
|
26
|
+
import warnings
|
|
27
|
+
warnings.filterwarnings("ignore")
|
|
28
|
+
artifacts_path=os.path.join(os.path.dirname(__file__),"artifacts")
|
|
29
|
+
plot_path=os.path.join(artifacts_path,"Plots")
|
|
30
|
+
def train_model(data_path, dependent_feature,rmse_prob,f1_prob,n_jobs=-1,n_iter=100,cv=3):
|
|
31
|
+
os.makedirs(artifacts_path,exist_ok=True)
|
|
32
|
+
print("Getting data from:",data_path)
|
|
33
|
+
data=pd.read_csv(data_path)
|
|
34
|
+
df=pd.DataFrame(data)
|
|
35
|
+
# os.remove(data_path)
|
|
36
|
+
df.head()
|
|
37
|
+
print("Data loaded successfully")
|
|
38
|
+
|
|
39
|
+
for i in df.columns:
|
|
40
|
+
if df[i].dtype=="object":
|
|
41
|
+
df[i] = df[i].fillna(df[i].mode()[0])
|
|
42
|
+
else:
|
|
43
|
+
df[i] = df[i].fillna(df[i].median())
|
|
44
|
+
|
|
45
|
+
mild=False
|
|
46
|
+
moderate=False
|
|
47
|
+
majority=max(df[dependent_feature].value_counts())
|
|
48
|
+
minority=min(df[dependent_feature].value_counts())
|
|
49
|
+
IR = majority/minority
|
|
50
|
+
# print(f"Imbalance Ratio: {IR}")
|
|
51
|
+
if IR <= 3:
|
|
52
|
+
# print("Mild Imbalance")
|
|
53
|
+
mild=True
|
|
54
|
+
elif 3 < IR <= 20:
|
|
55
|
+
# print("Moderate Imbalance")
|
|
56
|
+
moderate=True
|
|
57
|
+
|
|
58
|
+
# feature selection
|
|
59
|
+
# Replace < Dependent feture > and < Independent feature > with actual column names
|
|
60
|
+
x=df.drop(columns=[dependent_feature])
|
|
61
|
+
y=df[dependent_feature]
|
|
62
|
+
# print("Independent Feature:", x)
|
|
63
|
+
# print("Dependent Feature:", y)
|
|
64
|
+
regressor=False
|
|
65
|
+
classification=False
|
|
66
|
+
print("Finding the type of problem...")
|
|
67
|
+
if df[dependent_feature].dtype=="object":
|
|
68
|
+
classification=True
|
|
69
|
+
print("Classification Problem")
|
|
70
|
+
else:
|
|
71
|
+
regressor=True
|
|
72
|
+
print("Regression Problem")
|
|
73
|
+
|
|
74
|
+
from sklearn.model_selection import train_test_split
|
|
75
|
+
# Splitting the dataset into training and testing sets
|
|
76
|
+
print("Splitting the dataset into training and testing sets...")
|
|
77
|
+
if classification:
|
|
78
|
+
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=42,stratify=y)
|
|
79
|
+
else:
|
|
80
|
+
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=42)
|
|
81
|
+
|
|
82
|
+
print("Dataset split successfully")
|
|
83
|
+
|
|
84
|
+
cat_features=[i for i in x_train.columns if x_train[i].dtype=="object" and i!=dependent_feature]
|
|
85
|
+
num_features=[i for i in x_train.columns if x_train[i].dtype!="object" and i!=dependent_feature]
|
|
86
|
+
|
|
87
|
+
plt.figure(figsize=(12, 8))
|
|
88
|
+
sns.heatmap(
|
|
89
|
+
x[num_features].corr(),
|
|
90
|
+
annot=True,
|
|
91
|
+
fmt=".2f",
|
|
92
|
+
cmap="coolwarm",
|
|
93
|
+
annot_kws={"size": 14}
|
|
94
|
+
)
|
|
95
|
+
plt.title("Correlation Heatmap", fontsize=18)
|
|
96
|
+
os.makedirs(plot_path, exist_ok=True)
|
|
97
|
+
plt.savefig(os.path.join(plot_path,"correlation_heatmap.png"), bbox_inches='tight')
|
|
98
|
+
|
|
99
|
+
plt.close()
|
|
100
|
+
def correlation(dataset,threshold):
|
|
101
|
+
corr_thresh=set()
|
|
102
|
+
for i in range(len(dataset.columns)):
|
|
103
|
+
for j in range(i):
|
|
104
|
+
colname=dataset.columns[i]
|
|
105
|
+
if abs(dataset.corr().iloc[i,j])>threshold :
|
|
106
|
+
corr_thresh.add(colname)
|
|
107
|
+
return corr_thresh
|
|
108
|
+
|
|
109
|
+
dropcorr = correlation(x_train[num_features], 0.85)
|
|
110
|
+
x_train.drop([col for col in dropcorr if col in x_train.columns], axis=1, inplace=True)
|
|
111
|
+
x_test.drop([col for col in dropcorr if col in x_test.columns], axis=1, inplace=True)
|
|
112
|
+
cat_features = [i for i in x_train.columns if x_train[i].dtype == "object" and i != dependent_feature]
|
|
113
|
+
num_features = [i for i in x_train.columns if x_train[i].dtype != "object" and i != dependent_feature]
|
|
114
|
+
print("Categorical features : ",cat_features)
|
|
115
|
+
print("Numerical features : ",num_features)
|
|
116
|
+
print("Balancing the dataset...")
|
|
117
|
+
if mild:
|
|
118
|
+
from imblearn.under_sampling import RandomUnderSampler
|
|
119
|
+
undersampler = RandomUnderSampler(random_state=42)
|
|
120
|
+
x_train, y_train = undersampler.fit_resample(x_train, y_train)
|
|
121
|
+
print("Mild Imbalance Resolved")
|
|
122
|
+
if moderate:
|
|
123
|
+
from imblearn.over_sampling import SMOTETomek
|
|
124
|
+
smote_tomek = SMOTETomek(random_state=42)
|
|
125
|
+
x_train, y_train = smote_tomek.fit_resample(x_train, y_train)
|
|
126
|
+
print("Moderate Imbalace Resolved")
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
print("Preprocessing the data...")
|
|
131
|
+
from sklearn.preprocessing import StandardScaler, OneHotEncoder,OrdinalEncoder,LabelEncoder
|
|
132
|
+
from sklearn.compose import ColumnTransformer
|
|
133
|
+
scaler=StandardScaler()
|
|
134
|
+
ohe=OneHotEncoder(drop="first")
|
|
135
|
+
oe=OrdinalEncoder(handle_unknown='use_encoded_value', unknown_value=-1)
|
|
136
|
+
ohe_data=[]
|
|
137
|
+
oe_data=[]
|
|
138
|
+
for i in cat_features:
|
|
139
|
+
if len(x_train[i].unique())>10:
|
|
140
|
+
oe_data.append(i)
|
|
141
|
+
else:
|
|
142
|
+
ohe_data.append(i)
|
|
143
|
+
# print("One Hot Encoding Features:", ohe_data)
|
|
144
|
+
# print("Ordinal Encoding Features:", oe_data)
|
|
145
|
+
preprocessor=ColumnTransformer(
|
|
146
|
+
[("OneHotEncoder",ohe,ohe_data),
|
|
147
|
+
("OrdinalEncoder",oe,oe_data),
|
|
148
|
+
("StandardScaler",scaler,num_features)]
|
|
149
|
+
)
|
|
150
|
+
feature_names=list(x_train.columns)
|
|
151
|
+
x_train=preprocessor.fit_transform(x_train)
|
|
152
|
+
x_test=preprocessor.transform(x_test)
|
|
153
|
+
if classification:
|
|
154
|
+
le=LabelEncoder()
|
|
155
|
+
y_train=le.fit_transform(y_train)
|
|
156
|
+
y_test=le.transform(y_test)
|
|
157
|
+
model_dict=[]
|
|
158
|
+
print("Training the models...")
|
|
159
|
+
if regressor:
|
|
160
|
+
from sklearn.ensemble import RandomForestRegressor,GradientBoostingRegressor,AdaBoostRegressor
|
|
161
|
+
from sklearn.linear_model import LinearRegression,Ridge, Lasso,ElasticNet
|
|
162
|
+
from xgboost import XGBRegressor
|
|
163
|
+
from sklearn.neighbors import KNeighborsRegressor
|
|
164
|
+
from sklearn.tree import DecisionTreeRegressor
|
|
165
|
+
from sklearn.svm import SVR
|
|
166
|
+
from sklearn.metrics import mean_absolute_error,mean_squared_error,r2_score
|
|
167
|
+
models={
|
|
168
|
+
"RandomForestRegressor":RandomForestRegressor(),
|
|
169
|
+
"GradientBoostingRegressor":GradientBoostingRegressor(),
|
|
170
|
+
"AdaBoostRegressor":AdaBoostRegressor(),
|
|
171
|
+
"XGBRegressor":XGBRegressor(),
|
|
172
|
+
"KNeighborsRegressor":KNeighborsRegressor(),
|
|
173
|
+
"LinearRegression":LinearRegression(),
|
|
174
|
+
"Ridge":Ridge(),
|
|
175
|
+
"Lasso":Lasso(),
|
|
176
|
+
"ElasticNet":ElasticNet(),
|
|
177
|
+
"DecisionTreeRegressor":DecisionTreeRegressor(),
|
|
178
|
+
"SVR":SVR()
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
for i in range(len(list(models))):
|
|
182
|
+
model = list(models.values())[i]
|
|
183
|
+
model.fit(x_train, y_train) # Train model
|
|
184
|
+
|
|
185
|
+
# Make predictions
|
|
186
|
+
y_train_pred = model.predict(x_train)
|
|
187
|
+
y_test_pred = model.predict(x_test)
|
|
188
|
+
|
|
189
|
+
model_train_mae = mean_absolute_error(y_train, y_train_pred)
|
|
190
|
+
model_train_mse = mean_squared_error(y_train, y_train_pred)
|
|
191
|
+
model_train_rmse = np.sqrt(model_train_mse)
|
|
192
|
+
model_train_r2 = r2_score(y_train, y_train_pred)
|
|
193
|
+
|
|
194
|
+
model_test_mae = mean_absolute_error(y_test, y_test_pred)
|
|
195
|
+
model_test_mse = mean_squared_error(y_test, y_test_pred)
|
|
196
|
+
model_test_rmse = np.sqrt(model_test_mse)
|
|
197
|
+
model_test_r2 = r2_score(y_test, y_test_pred)
|
|
198
|
+
model_dict.append({
|
|
199
|
+
"model":list(models.keys())[i],
|
|
200
|
+
"train_rmse": model_train_rmse,
|
|
201
|
+
"train_r2": model_train_r2,
|
|
202
|
+
"test_rmse": model_test_rmse,
|
|
203
|
+
"test_r2": model_test_r2,
|
|
204
|
+
"tuned":False
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
# print(list(models.keys())[i])
|
|
208
|
+
|
|
209
|
+
# print('Model performance for Training set')
|
|
210
|
+
# print("- mae: {:.4f}".format(model_train_mae))
|
|
211
|
+
# print('-mse: {:.4f}'.format(model_train_mse))
|
|
212
|
+
# print('- rmse: {:.4f}'.format(model_train_rmse))
|
|
213
|
+
# print('- r2: {:.4f}'.format(model_train_r2))
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
# print('----------------------------------')
|
|
218
|
+
|
|
219
|
+
# print('Model performance for Test set')
|
|
220
|
+
# print('- mae: {:.4f}'.format(model_test_mae))
|
|
221
|
+
# print('- mse: {:.4f}'.format(model_test_mse))
|
|
222
|
+
# print('- rmse: {:.4f}'.format(model_test_rmse))
|
|
223
|
+
# print('- r2: {:.4f}'.format(model_test_r2))
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
# print('='*35)
|
|
227
|
+
# print('\n')
|
|
228
|
+
else:
|
|
229
|
+
from sklearn.ensemble import RandomForestClassifier,GradientBoostingClassifier,AdaBoostClassifier
|
|
230
|
+
from xgboost import XGBClassifier
|
|
231
|
+
from sklearn.neighbors import KNeighborsClassifier
|
|
232
|
+
from sklearn.svm import SVC
|
|
233
|
+
from sklearn.tree import DecisionTreeClassifier
|
|
234
|
+
from sklearn.linear_model import LogisticRegression
|
|
235
|
+
from sklearn.metrics import accuracy_score,confusion_matrix,classification_report,f1_score,roc_auc_score,roc_curve,precision_score,recall_score
|
|
236
|
+
models={
|
|
237
|
+
"LogisticRegression":LogisticRegression(),
|
|
238
|
+
"DecisionTreeClassifier":DecisionTreeClassifier(),
|
|
239
|
+
"RandomForestClassifier":RandomForestClassifier(),
|
|
240
|
+
"GradientBoostingClassifier":GradientBoostingClassifier(),
|
|
241
|
+
"AdaBoostClassifier":AdaBoostClassifier(),
|
|
242
|
+
"XGBClassifier":XGBClassifier(),
|
|
243
|
+
"KNeighborsClassifier":KNeighborsClassifier(),
|
|
244
|
+
"SVC":SVC()
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
for i in range(len(list(models))):
|
|
248
|
+
model = list(models.values())[i]
|
|
249
|
+
model.fit(x_train, y_train) # Train model
|
|
250
|
+
|
|
251
|
+
# Make predictions
|
|
252
|
+
y_train_pred = model.predict(x_train)
|
|
253
|
+
y_test_pred = model.predict(x_test)
|
|
254
|
+
|
|
255
|
+
# Training set performance
|
|
256
|
+
model_train_accuracy = accuracy_score(y_train, y_train_pred) # Calculate Accuracy
|
|
257
|
+
model_train_f1 = f1_score(y_train, y_train_pred, average='weighted') # Calculate F1-score
|
|
258
|
+
model_train_precision = precision_score(y_train, y_train_pred) # Calculate Precision
|
|
259
|
+
model_train_recall = recall_score(y_train, y_train_pred) # Calculate Recall
|
|
260
|
+
model_train_rocauc_score = roc_auc_score(y_train, y_train_pred)
|
|
261
|
+
# Test set performance
|
|
262
|
+
model_test_accuracy = accuracy_score(y_test, y_test_pred) # Calculate Accuracy
|
|
263
|
+
model_test_f1 = f1_score(y_test, y_test_pred, average='weighted') # Calculate F1-score
|
|
264
|
+
model_test_precision = precision_score(y_test, y_test_pred) # Calculate Precision
|
|
265
|
+
model_test_recall = recall_score(y_test, y_test_pred) # Calculate Recal
|
|
266
|
+
|
|
267
|
+
model_dict.append({
|
|
268
|
+
"model":list(models.keys())[i],
|
|
269
|
+
"train_accuracy": model_train_accuracy,
|
|
270
|
+
"train_f1": model_train_f1,
|
|
271
|
+
"test_accuracy": model_test_accuracy,
|
|
272
|
+
"test_f1": model_test_f1,
|
|
273
|
+
"tuned":False
|
|
274
|
+
})
|
|
275
|
+
model_test_rocauc_score = roc_auc_score(y_test, y_test_pred) #Calculate Roc
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
# print(list(models.keys())[i])
|
|
279
|
+
|
|
280
|
+
# print('Model performance for Training set')
|
|
281
|
+
# print("- Accuracy: {:.4f}".format(model_train_accuracy))
|
|
282
|
+
# print('- F1 score: {:.4f}'.format(model_train_f1))
|
|
283
|
+
|
|
284
|
+
# print('- Precision: {:.4f}'.format(model_train_precision))
|
|
285
|
+
# print('- Recall: {:.4f}'.format(model_train_recall))
|
|
286
|
+
# print('- Roc Auc Score: {:.4f}'.format(model_train_rocauc_score))
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
# print('----------------------------------')
|
|
291
|
+
|
|
292
|
+
# print('Model performance for Test set')
|
|
293
|
+
# print('- Accuracy: {:.4f}'.format(model_test_accuracy))
|
|
294
|
+
# print('- F1 score: {:.4f}'.format(model_test_f1))
|
|
295
|
+
# print('- Precision: {:.4f}'.format(model_test_precision))
|
|
296
|
+
# print('- Recall: {:.4f}'.format(model_test_recall))
|
|
297
|
+
# print('- Roc Auc Score: {:.4f}'.format(model_test_rocauc_score))
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
# print('='*35)
|
|
301
|
+
# print('\n')
|
|
302
|
+
print("Finding the best model...")
|
|
303
|
+
if regressor:
|
|
304
|
+
comparison_df=pd.DataFrame(model_dict)
|
|
305
|
+
comparison_df["total_rmse"]=comparison_df["train_rmse"]+comparison_df["test_rmse"]
|
|
306
|
+
comparison_df["total_r2"]=comparison_df["train_r2"]+comparison_df["test_r2"]
|
|
307
|
+
# print(comparison_df)
|
|
308
|
+
comparison_df['Norm RMSE'] = comparison_df["total_rmse"] / comparison_df['total_rmse'].max()
|
|
309
|
+
comparison_df['Norm R2'] = 1 - (comparison_df["total_r2"] / comparison_df['total_r2'].max())
|
|
310
|
+
comparison_df['Combined Score'] = rmse_prob * comparison_df['Norm RMSE'] + (1-rmse_prob)* comparison_df['Norm R2']
|
|
311
|
+
combined_score_ranking = comparison_df.sort_values('Combined Score')
|
|
312
|
+
# print(combined_score_ranking[["train_rmse", "train_r2", "test_rmse", "test_r2","total_rmse","total_r2","Combined Score"]])
|
|
313
|
+
# print("===="*35)
|
|
314
|
+
best_models = comparison_df.nsmallest(3, 'Combined Score')
|
|
315
|
+
|
|
316
|
+
if classification:
|
|
317
|
+
comparison_df=pd.DataFrame(model_dict)
|
|
318
|
+
comparison_df["total_accuracy"]=comparison_df["train_accuracy"]+comparison_df["test_accuracy"]
|
|
319
|
+
comparison_df["total_f1"]=comparison_df["train_f1"]+comparison_df["test_f1"]
|
|
320
|
+
# print(comparison_df)
|
|
321
|
+
comparison_df['Norm F1'] = comparison_df["total_f1"] / comparison_df['total_f1'].max()
|
|
322
|
+
comparison_df['Norm Accuracy'] = comparison_df["total_accuracy"] / comparison_df['total_accuracy'].max()
|
|
323
|
+
comparison_df['Combined Score'] = f1_prob * comparison_df['Norm F1'] + (1-f1_prob)* comparison_df['Norm Accuracy']
|
|
324
|
+
combined_score_ranking = comparison_df.sort_values('Combined Score',ascending=False)
|
|
325
|
+
combined_score_ranking=combined_score_ranking[combined_score_ranking["train_f1"]-combined_score_ranking["test_f1"]<0.15]
|
|
326
|
+
# print(combined_score_ranking[["model","train_accuracy", "train_f1", "test_accuracy", "test_f1","total_accuracy","total_f1","Combined Score"]])
|
|
327
|
+
# print("===="*35)
|
|
328
|
+
best_models = combined_score_ranking.nlargest(3, 'Combined Score')
|
|
329
|
+
|
|
330
|
+
# print("Best Models based on Combined Score:", best_models[["model"]])
|
|
331
|
+
# print("===="*35)
|
|
332
|
+
# print(best_models)
|
|
333
|
+
# print("===="*35)
|
|
334
|
+
top_model=[i for i in best_models["model"] ]
|
|
335
|
+
print("Top Model:",top_model)
|
|
336
|
+
print("Training the best models with enhanced parameters...")
|
|
337
|
+
randomcv_model = []
|
|
338
|
+
if regressor:
|
|
339
|
+
reg_params = [
|
|
340
|
+
["RandomForestRegressor", {
|
|
341
|
+
'n_estimators': [100, 200,300,400],
|
|
342
|
+
'max_depth': [None, 5, 10, 15, 20, 30, 50],
|
|
343
|
+
'min_samples_split': [2, 5, 10, 15],
|
|
344
|
+
'min_samples_leaf': [1, 2, 4, 6],
|
|
345
|
+
'max_features': ['sqrt', 'log2', None, 0.5, 0.7],
|
|
346
|
+
'bootstrap': [True, False],
|
|
347
|
+
'random_state': [42]
|
|
348
|
+
}],
|
|
349
|
+
|
|
350
|
+
["GradientBoostingRegressor", {
|
|
351
|
+
'n_estimators': [100, 200,300,400],
|
|
352
|
+
'learning_rate': [0.001, 0.01, 0.05, 0.1, 0.2],
|
|
353
|
+
'max_depth': [3, 4, 5, 6, 7, 8],
|
|
354
|
+
'min_samples_split': [2, 5, 10],
|
|
355
|
+
'min_samples_leaf': [1, 2, 4],
|
|
356
|
+
'subsample': [0.7, 0.8, 0.9, 1.0],
|
|
357
|
+
'max_features': ['sqrt', 'log2', None],
|
|
358
|
+
'loss': ['squared_error', 'absolute_error', 'huber', 'quantile'],
|
|
359
|
+
'random_state': [42]
|
|
360
|
+
}],
|
|
361
|
+
|
|
362
|
+
["AdaBoostRegressor", {
|
|
363
|
+
'n_estimators': [50, 100, 150, 200, 300],
|
|
364
|
+
'learning_rate': [0.001, 0.01, 0.05, 0.1, 0.5, 1.0],
|
|
365
|
+
'loss': ['linear', 'square', 'exponential'],
|
|
366
|
+
'random_state': [42]
|
|
367
|
+
}],
|
|
368
|
+
|
|
369
|
+
["XGBRegressor", {
|
|
370
|
+
'n_estimators': [100, 200,300,400],
|
|
371
|
+
'learning_rate': [0.001, 0.01, 0.05, 0.1, 0.2],
|
|
372
|
+
'max_depth': [3, 4, 5, 6, 7, 8, 9],
|
|
373
|
+
'min_child_weight': [1, 2, 3, 4],
|
|
374
|
+
'gamma': [0, 0.1, 0.2, 0.3, 0.4],
|
|
375
|
+
'subsample': [0.6, 0.7, 0.8, 0.9, 1.0],
|
|
376
|
+
'colsample_bytree': [0.6, 0.7, 0.8, 0.9, 1.0],
|
|
377
|
+
'reg_alpha': [0, 0.1, 0.5, 1],
|
|
378
|
+
'reg_lambda': [0, 0.1, 1, 10],
|
|
379
|
+
'random_state': [42]
|
|
380
|
+
}],
|
|
381
|
+
|
|
382
|
+
["KNeighborsRegressor", {
|
|
383
|
+
'n_neighbors': [3, 5, 7, 10, 15, 20],
|
|
384
|
+
'weights': ['uniform', 'distance'],
|
|
385
|
+
'algorithm': ['auto', 'ball_tree', 'kd_tree', 'brute'],
|
|
386
|
+
'leaf_size': [10, 20, 30, 40, 50],
|
|
387
|
+
'p': [1, 2, 3]
|
|
388
|
+
}],
|
|
389
|
+
|
|
390
|
+
["LinearRegression", {
|
|
391
|
+
'fit_intercept': [True, False],
|
|
392
|
+
'positive': [True, False],
|
|
393
|
+
'copy_X': [True, False]
|
|
394
|
+
}],
|
|
395
|
+
|
|
396
|
+
["Ridge", {
|
|
397
|
+
'alpha': [0.001, 0.01, 0.1, 1.0, 10.0, 100.0],
|
|
398
|
+
'solver': ['auto', 'svd', 'cholesky', 'lsqr', 'sparse_cg', 'sag', 'saga'],
|
|
399
|
+
'fit_intercept': [True, False],
|
|
400
|
+
'random_state': [42]
|
|
401
|
+
}],
|
|
402
|
+
|
|
403
|
+
["Lasso", {
|
|
404
|
+
'alpha': [0.0001, 0.001, 0.01, 0.1, 1.0],
|
|
405
|
+
'max_iter': [1000, 2000, 5000, 10000],
|
|
406
|
+
'selection': ['cyclic', 'random'],
|
|
407
|
+
'random_state': [42]
|
|
408
|
+
}],
|
|
409
|
+
|
|
410
|
+
["ElasticNet", {
|
|
411
|
+
'alpha': [0.0001, 0.001, 0.01, 0.1, 1.0],
|
|
412
|
+
'l1_ratio': [0.1, 0.3, 0.5, 0.7, 0.9],
|
|
413
|
+
'max_iter': [1000, 5000],
|
|
414
|
+
'selection': ['cyclic', 'random'],
|
|
415
|
+
'random_state': [42]
|
|
416
|
+
}],
|
|
417
|
+
|
|
418
|
+
["DecisionTreeRegressor", {
|
|
419
|
+
'max_depth': [None, 5, 10, 15, 20, 30],
|
|
420
|
+
'min_samples_split': [2, 5, 10, 15],
|
|
421
|
+
'min_samples_leaf': [1, 2, 4, 6, 8],
|
|
422
|
+
'max_features': ['sqrt', 'log2', None, 0.5, 0.7],
|
|
423
|
+
'criterion': ['squared_error', 'friedman_mse', 'absolute_error', 'poisson'],
|
|
424
|
+
'random_state': [42]
|
|
425
|
+
}],
|
|
426
|
+
|
|
427
|
+
["SVR", {
|
|
428
|
+
'kernel': ['rbf', 'linear', 'poly', 'sigmoid'],
|
|
429
|
+
'C': [0.1, 0.5, 1, 5, 10, 50, 100],
|
|
430
|
+
'epsilon': [0.01, 0.1, 0.2, 0.5, 1.0],
|
|
431
|
+
'gamma': ['scale', 'auto'] + [0.001, 0.01, 0.1, 1, 10],
|
|
432
|
+
'degree': [2, 3, 4] # Only for poly kernel
|
|
433
|
+
}]
|
|
434
|
+
]
|
|
435
|
+
|
|
436
|
+
for i in reg_params:
|
|
437
|
+
if i[0] in top_model:
|
|
438
|
+
randomcv_model.append((i[0], models[i[0]], i[1]))
|
|
439
|
+
|
|
440
|
+
# print("Enhanced Random CV Model Parameters:", randomcv_model)
|
|
441
|
+
if classification:
|
|
442
|
+
class_params = [
|
|
443
|
+
["LogisticRegression", {
|
|
444
|
+
'penalty': ['l1', 'l2', 'elasticnet', 'none'],
|
|
445
|
+
'C': np.logspace(-4, 4, 20),
|
|
446
|
+
'solver': ['newton-cg', 'lbfgs', 'liblinear', 'sag', 'saga'],
|
|
447
|
+
'max_iter': [100, 200, 500, 1000],
|
|
448
|
+
'class_weight': [None, 'balanced'],
|
|
449
|
+
'l1_ratio': [0, 0.25, 0.5, 0.75, 1] # For elasticnet
|
|
450
|
+
}],
|
|
451
|
+
|
|
452
|
+
["DecisionTreeClassifier", {
|
|
453
|
+
'criterion': ['gini', 'entropy', 'log_loss'],
|
|
454
|
+
'splitter': ['best', 'random'],
|
|
455
|
+
'max_depth': [None, 5, 10, 15, 20, 30, 50],
|
|
456
|
+
'min_samples_split': [2, 5, 10, 15, 20],
|
|
457
|
+
'min_samples_leaf': [1, 2, 4, 6, 8],
|
|
458
|
+
'max_features': ['sqrt', 'log2', None, 0.3, 0.5, 0.7],
|
|
459
|
+
'class_weight': [None, 'balanced'],
|
|
460
|
+
'random_state': [42]
|
|
461
|
+
}],
|
|
462
|
+
|
|
463
|
+
["RandomForestClassifier", {
|
|
464
|
+
'n_estimators': [100, 200,300,400],
|
|
465
|
+
'criterion': ['gini', 'entropy', 'log_loss'],
|
|
466
|
+
'max_depth': [None, 5, 10, 15, 20, 30, 50],
|
|
467
|
+
'min_samples_split': [2, 5, 10, 15],
|
|
468
|
+
'min_samples_leaf': [1, 2, 4, 6],
|
|
469
|
+
'max_features': ['sqrt', 'log2', None, 0.5, 0.7],
|
|
470
|
+
'bootstrap': [True, False],
|
|
471
|
+
'class_weight': [None, 'balanced', 'balanced_subsample'],
|
|
472
|
+
'random_state': [42]
|
|
473
|
+
}],
|
|
474
|
+
|
|
475
|
+
["GradientBoostingClassifier", {
|
|
476
|
+
'n_estimators': [100, 200,300,400],
|
|
477
|
+
'learning_rate': [0.001, 0.01, 0.05, 0.1, 0.2],
|
|
478
|
+
'loss': ['log_loss', 'exponential'],
|
|
479
|
+
'max_depth': [3, 4, 5, 6, 7, 8],
|
|
480
|
+
'min_samples_split': [2, 5, 10],
|
|
481
|
+
'min_samples_leaf': [1, 2, 4],
|
|
482
|
+
'subsample': [0.7, 0.8, 0.9, 1.0],
|
|
483
|
+
'max_features': ['sqrt', 'log2', None],
|
|
484
|
+
'random_state': [42]
|
|
485
|
+
}],
|
|
486
|
+
|
|
487
|
+
["AdaBoostClassifier", {
|
|
488
|
+
'n_estimators': [50, 100, 150, 200,300,400],
|
|
489
|
+
'learning_rate': [0.001, 0.01, 0.05, 0.1, 0.5, 1.0],
|
|
490
|
+
'random_state': [42]
|
|
491
|
+
}],
|
|
492
|
+
|
|
493
|
+
["XGBClassifier", {
|
|
494
|
+
'n_estimators': [100, 200,300 ,400],
|
|
495
|
+
'learning_rate': [0.001, 0.01, 0.05, 0.1, 0.2],
|
|
496
|
+
'max_depth': [3, 4, 5, 6, 7, 8, 9],
|
|
497
|
+
'min_child_weight': [1, 2, 3, 4],
|
|
498
|
+
'gamma': [0, 0.1, 0.2, 0.3, 0.4],
|
|
499
|
+
'subsample': [0.6, 0.7, 0.8, 0.9, 1.0],
|
|
500
|
+
'colsample_bytree': [0.6, 0.7, 0.8, 0.9, 1.0],
|
|
501
|
+
'reg_alpha': [0, 0.1, 0.5, 1],
|
|
502
|
+
'reg_lambda': [0, 0.1, 1, 10],
|
|
503
|
+
'scale_pos_weight': [1, 5, 10], # For imbalanced classes
|
|
504
|
+
'random_state': [42],
|
|
505
|
+
'use_label_encoder': [False],
|
|
506
|
+
'eval_metric': ['logloss', 'aucpr', 'auc']
|
|
507
|
+
}],
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
["KNeighborsClassifier", {
|
|
512
|
+
'n_neighbors': [3, 5, 7, 10, 15, 20, 25],
|
|
513
|
+
'weights': ['uniform', 'distance'],
|
|
514
|
+
'algorithm': ['auto', 'ball_tree', 'kd_tree', 'brute'],
|
|
515
|
+
'leaf_size': [10, 20, 30, 40, 50],
|
|
516
|
+
'p': [1, 2, 3],
|
|
517
|
+
'metric': ['minkowski', 'euclidean', 'manhattan']
|
|
518
|
+
}],
|
|
519
|
+
|
|
520
|
+
["SVC", {
|
|
521
|
+
'kernel': ['linear', 'rbf', 'poly', 'sigmoid'],
|
|
522
|
+
'C': [0.001, 0.01, 0.1, 1, 5, 10, 50, 100],
|
|
523
|
+
'gamma': ['scale', 'auto'] + [0.001, 0.01, 0.1, 1, 10],
|
|
524
|
+
'degree': [2, 3, 4, 5], # For poly kernel
|
|
525
|
+
'class_weight': [None, 'balanced'],
|
|
526
|
+
'probability': [True], # If you need predict_proba
|
|
527
|
+
'random_state': [42]
|
|
528
|
+
}],
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
]
|
|
532
|
+
|
|
533
|
+
for i in class_params:
|
|
534
|
+
if i[0] in top_model:
|
|
535
|
+
randomcv_model.append((i[0], models[i[0]], i[1]))
|
|
536
|
+
|
|
537
|
+
# print("Enhanced Classification Model Parameters:", randomcv_model)
|
|
538
|
+
|
|
539
|
+
from sklearn.model_selection import RandomizedSearchCV
|
|
540
|
+
|
|
541
|
+
model_param = {}
|
|
542
|
+
for name, model, params in randomcv_model:
|
|
543
|
+
random = RandomizedSearchCV(estimator=model,
|
|
544
|
+
param_distributions=params,
|
|
545
|
+
n_iter=n_iter,
|
|
546
|
+
cv=cv,
|
|
547
|
+
n_jobs=n_jobs)
|
|
548
|
+
random.fit(x_train, y_train)
|
|
549
|
+
model_param[name] = random.best_params_
|
|
550
|
+
|
|
551
|
+
# for model_name in model_param:
|
|
552
|
+
# print(f"---------------- Best Params for {model_name} -------------------")
|
|
553
|
+
# print(model_param[model_name])
|
|
554
|
+
best_params=[]
|
|
555
|
+
if regressor:
|
|
556
|
+
model_cls={
|
|
557
|
+
"RandomForestRegressor":RandomForestRegressor,
|
|
558
|
+
"GradientBoostingRegressor":GradientBoostingRegressor,
|
|
559
|
+
"AdaBoostRegressor":AdaBoostRegressor,
|
|
560
|
+
"XGBRegressor":XGBRegressor,
|
|
561
|
+
"KNeighborsRegressor":KNeighborsRegressor,
|
|
562
|
+
"LinearRegression":LinearRegression,
|
|
563
|
+
"Ridge":Ridge,
|
|
564
|
+
"Lasso":Lasso,
|
|
565
|
+
"ElasticNet":ElasticNet,
|
|
566
|
+
"DecisionTreeRegressor":DecisionTreeRegressor,
|
|
567
|
+
"SVR":SVR
|
|
568
|
+
}
|
|
569
|
+
if classification:
|
|
570
|
+
model_cls={
|
|
571
|
+
"LogisticRegression":LogisticRegression,
|
|
572
|
+
"DecisionTreeClassifier":DecisionTreeClassifier,
|
|
573
|
+
"RandomForestClassifier":RandomForestClassifier,
|
|
574
|
+
"GradientBoostingClassifier":GradientBoostingClassifier,
|
|
575
|
+
"AdaBoostClassifier":AdaBoostClassifier,
|
|
576
|
+
"XGBClassifier":XGBClassifier,
|
|
577
|
+
"KNeighborsClassifier":KNeighborsClassifier,
|
|
578
|
+
"SVC":SVC
|
|
579
|
+
}
|
|
580
|
+
for i in model_param:
|
|
581
|
+
best_params.append([i,model_param[i]])
|
|
582
|
+
# print("Best Params:", best_params)
|
|
583
|
+
|
|
584
|
+
best_models_copy=best_models.copy()
|
|
585
|
+
if regressor:
|
|
586
|
+
best_models_copy.drop(columns=['total_rmse' ,'total_r2' ,'Norm RMSE','Norm R2',"Combined Score"], inplace=True)
|
|
587
|
+
if classification:
|
|
588
|
+
best_models_copy.drop(columns=['total_accuracy' ,'total_f1' ,'Norm F1','Norm Accuracy',"Combined Score"], inplace=True)
|
|
589
|
+
models={}
|
|
590
|
+
for i in best_params:
|
|
591
|
+
models[i[0]]=model_cls[i[0]](**i[1])
|
|
592
|
+
if regressor:
|
|
593
|
+
for i in range(len(list(models))):
|
|
594
|
+
model = list(models.values())[i]
|
|
595
|
+
model.fit(x_train, y_train) # Train model
|
|
596
|
+
|
|
597
|
+
# Make predictions
|
|
598
|
+
y_train_pred = model.predict(x_train)
|
|
599
|
+
y_test_pred = model.predict(x_test)
|
|
600
|
+
|
|
601
|
+
model_train_mae = mean_absolute_error(y_train, y_train_pred)
|
|
602
|
+
model_train_mse = mean_squared_error(y_train, y_train_pred)
|
|
603
|
+
model_train_rmse = np.sqrt(model_train_mse)
|
|
604
|
+
model_train_r2 = r2_score(y_train, y_train_pred)
|
|
605
|
+
|
|
606
|
+
model_test_mae = mean_absolute_error(y_test, y_test_pred)
|
|
607
|
+
model_test_mse = mean_squared_error(y_test, y_test_pred)
|
|
608
|
+
model_test_rmse = np.sqrt(model_test_mse)
|
|
609
|
+
model_test_r2 = r2_score(y_test, y_test_pred)
|
|
610
|
+
|
|
611
|
+
# print(list(models.keys())[i])
|
|
612
|
+
model_dict={
|
|
613
|
+
"model":list(models.keys())[i],
|
|
614
|
+
"train_rmse": model_train_rmse,
|
|
615
|
+
"train_r2": model_train_r2,
|
|
616
|
+
"test_rmse": model_test_rmse,
|
|
617
|
+
"test_r2": model_test_r2,
|
|
618
|
+
"tuned":True}
|
|
619
|
+
best_models_copy = pd.concat(
|
|
620
|
+
[best_models_copy, pd.DataFrame([model_dict])],
|
|
621
|
+
ignore_index=True
|
|
622
|
+
)
|
|
623
|
+
|
|
624
|
+
|
|
625
|
+
# print('Model performance for Training set')
|
|
626
|
+
# print("- mae: {:.4f}".format(model_train_mae))
|
|
627
|
+
# print('-mse: {:.4f}'.format(model_train_mse))
|
|
628
|
+
# print('- rmse: {:.4f}'.format(model_train_rmse))
|
|
629
|
+
# print('- r2: {:.4f}'.format(model_train_r2))
|
|
630
|
+
|
|
631
|
+
|
|
632
|
+
|
|
633
|
+
# print('----------------------------------')
|
|
634
|
+
|
|
635
|
+
# print('Model performance for Test set')
|
|
636
|
+
# print('- mae: {:.4f}'.format(model_test_mae))
|
|
637
|
+
# print('- mse: {:.4f}'.format(model_test_mse))
|
|
638
|
+
# print('- rmse: {:.4f}'.format(model_test_rmse))
|
|
639
|
+
# print('- r2: {:.4f}'.format(model_test_r2))
|
|
640
|
+
|
|
641
|
+
|
|
642
|
+
# print('='*35)
|
|
643
|
+
# print('\n')
|
|
644
|
+
|
|
645
|
+
if classification:
|
|
646
|
+
|
|
647
|
+
for i in range(len(list(models))):
|
|
648
|
+
model = list(models.values())[i]
|
|
649
|
+
model.fit(x_train, y_train) # Train model
|
|
650
|
+
|
|
651
|
+
# Make predictions
|
|
652
|
+
y_train_pred = model.predict(x_train)
|
|
653
|
+
y_test_pred = model.predict(x_test)
|
|
654
|
+
|
|
655
|
+
# Training set performance
|
|
656
|
+
model_train_accuracy = accuracy_score(y_train, y_train_pred) # Calculate Accuracy
|
|
657
|
+
model_train_f1 = f1_score(y_train, y_train_pred, average='weighted') # Calculate F1-score
|
|
658
|
+
model_train_precision = precision_score(y_train, y_train_pred) # Calculate Precision
|
|
659
|
+
model_train_recall = recall_score(y_train, y_train_pred) # Calculate Recall
|
|
660
|
+
model_train_rocauc_score = roc_auc_score(y_train, y_train_pred)
|
|
661
|
+
# Test set performance
|
|
662
|
+
model_test_accuracy = accuracy_score(y_test, y_test_pred) # Calculate Accuracy
|
|
663
|
+
model_test_f1 = f1_score(y_test, y_test_pred, average='weighted') # Calculate F1-score
|
|
664
|
+
model_test_precision = precision_score(y_test, y_test_pred) # Calculate Precision
|
|
665
|
+
model_test_recall = recall_score(y_test, y_test_pred) # Calculate Recal
|
|
666
|
+
|
|
667
|
+
model_dict={
|
|
668
|
+
"model":list(models.keys())[i],
|
|
669
|
+
"train_accuracy": model_train_accuracy,
|
|
670
|
+
"train_f1": model_train_f1,
|
|
671
|
+
"test_accuracy": model_test_accuracy,
|
|
672
|
+
"test_f1": model_test_f1,
|
|
673
|
+
"tuned":True
|
|
674
|
+
}
|
|
675
|
+
best_models_copy = pd.concat(
|
|
676
|
+
[best_models_copy, pd.DataFrame([model_dict])],
|
|
677
|
+
ignore_index=True
|
|
678
|
+
)
|
|
679
|
+
|
|
680
|
+
|
|
681
|
+
|
|
682
|
+
# print(list(models.keys())[i])
|
|
683
|
+
|
|
684
|
+
# print('Model performance for Training set')
|
|
685
|
+
# print("- Accuracy: {:.4f}".format(model_train_accuracy))
|
|
686
|
+
# print('- F1 score: {:.4f}'.format(model_train_f1))
|
|
687
|
+
|
|
688
|
+
# print('- Precision: {:.4f}'.format(model_train_precision))
|
|
689
|
+
# print('- Recall: {:.4f}'.format(model_train_recall))
|
|
690
|
+
# print('- Roc Auc Score: {:.4f}'.format(model_train_rocauc_score))
|
|
691
|
+
|
|
692
|
+
|
|
693
|
+
|
|
694
|
+
# print('----------------------------------')
|
|
695
|
+
|
|
696
|
+
# print('Model performance for Test set')
|
|
697
|
+
# print('- Accuracy: {:.4f}'.format(model_test_accuracy))
|
|
698
|
+
# print('- F1 score: {:.4f}'.format(model_test_f1))
|
|
699
|
+
# print('- Precision: {:.4f}'.format(model_test_precision))
|
|
700
|
+
# print('- Recall: {:.4f}'.format(model_test_recall))
|
|
701
|
+
# print('- Roc Auc Score: {:.4f}'.format(model_test_rocauc_score))
|
|
702
|
+
|
|
703
|
+
|
|
704
|
+
# print('='*35)
|
|
705
|
+
# print('\n')
|
|
706
|
+
best_models_copy
|
|
707
|
+
if regressor:
|
|
708
|
+
best_models_copy["total_rmse"]=best_models_copy["train_rmse"]+best_models_copy["test_rmse"]
|
|
709
|
+
best_models_copy["total_r2"]=best_models_copy["train_r2"]+best_models_copy["test_r2"]
|
|
710
|
+
best_models_copy['Norm RMSE'] = best_models_copy["total_rmse"] / best_models_copy['total_rmse'].max()
|
|
711
|
+
best_models_copy['Norm R2'] = 1 - (best_models_copy["total_r2"] / best_models_copy['total_r2'].max())
|
|
712
|
+
best_models_copy['Combined Score'] = rmse_prob * best_models_copy['Norm RMSE'] + (1-rmse_prob)* best_models_copy['Norm R2']
|
|
713
|
+
combined_score_ranking = best_models_copy.sort_values('Combined Score').reset_index(drop=True)
|
|
714
|
+
if classification:
|
|
715
|
+
best_models_copy["total_accuracy"]=best_models_copy["train_accuracy"]+best_models_copy["test_accuracy"]
|
|
716
|
+
best_models_copy["total_f1"]=best_models_copy["train_f1"]+best_models_copy["test_f1"]
|
|
717
|
+
best_models_copy['Norm F1'] = best_models_copy["total_f1"] / best_models_copy['total_f1'].max()
|
|
718
|
+
best_models_copy['Norm Accuracy'] = best_models_copy["total_accuracy"] / best_models_copy['total_accuracy'].max()
|
|
719
|
+
best_models_copy['Combined Score'] = f1_prob * best_models_copy['Norm F1'] + (1-f1_prob)* best_models_copy['Norm Accuracy']
|
|
720
|
+
combined_score_ranking = best_models_copy.sort_values('Combined Score',ascending=False).reset_index(drop=True)
|
|
721
|
+
# print(combined_score_ranking.iloc[0:1,:]["model"][0])
|
|
722
|
+
# print(combined_score_ranking)
|
|
723
|
+
if classification:
|
|
724
|
+
combined_score_ranking=combined_score_ranking[combined_score_ranking["train_f1"]-combined_score_ranking["test_f1"]<0.15]
|
|
725
|
+
# print("====="*35)
|
|
726
|
+
print(combined_score_ranking.iloc[0:1,:])
|
|
727
|
+
best_model_name = combined_score_ranking.iloc[0]["model"]
|
|
728
|
+
best_param_dict = None
|
|
729
|
+
for name, params in best_params:
|
|
730
|
+
if name == best_model_name:
|
|
731
|
+
best_param_dict = params
|
|
732
|
+
break
|
|
733
|
+
model = model_cls[best_model_name](**best_param_dict)
|
|
734
|
+
# print("Best Model Name:", best_model_name)
|
|
735
|
+
# print("Best Model Parameters:", best_param_dict)
|
|
736
|
+
model.fit(x_train, y_train)
|
|
737
|
+
print("Best Model Trained Successfully")
|
|
738
|
+
print("Saving the model and preprocessor...")
|
|
739
|
+
model_path = os.path.join(artifacts_path, "model.pkl")
|
|
740
|
+
preprocessor_path = os.path.join(artifacts_path, "preprocessor.pkl")
|
|
741
|
+
encoder_path = os.path.join(artifacts_path, "encoder.pkl")
|
|
742
|
+
|
|
743
|
+
with open(model_path, "wb") as f:
|
|
744
|
+
pickle.dump(model, f)
|
|
745
|
+
|
|
746
|
+
with open(preprocessor_path, "wb") as f:
|
|
747
|
+
pickle.dump(preprocessor, f)
|
|
748
|
+
|
|
749
|
+
if classification:
|
|
750
|
+
with open(encoder_path, "wb") as f:
|
|
751
|
+
pickle.dump(le, f)
|
|
752
|
+
response = {
|
|
753
|
+
"message": "Training completed successfully",
|
|
754
|
+
"Problem_type":"Classification",
|
|
755
|
+
"model_metrics": {
|
|
756
|
+
"Model": combined_score_ranking.iloc[0]["model"],
|
|
757
|
+
"Train_accuracy": float(combined_score_ranking.iloc[0]["train_accuracy"]),
|
|
758
|
+
"Train_f1": float(combined_score_ranking.iloc[0]["train_f1"]),
|
|
759
|
+
"Test_accuracy": float(combined_score_ranking.iloc[0]["test_accuracy"]),
|
|
760
|
+
"Test_f1": float(combined_score_ranking.iloc[0]["test_f1"]),
|
|
761
|
+
"Hyper_tuned": bool(combined_score_ranking.iloc[0]["tuned"]),
|
|
762
|
+
"Dropped_Columns":list(dropcorr)
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
plot_classification_metrics(model,x_train, y_train, x_test, y_test, class_names=['No', 'Yes'])
|
|
766
|
+
else:
|
|
767
|
+
response={
|
|
768
|
+
"message": "Training completed successfully",
|
|
769
|
+
"Problem_type":"Regression",
|
|
770
|
+
"model_metrics": {
|
|
771
|
+
"Model": combined_score_ranking.iloc[0]["model"],
|
|
772
|
+
"Train_R2": float(combined_score_ranking.iloc[0]["train_r2"]),
|
|
773
|
+
"Train_RMSE": float(combined_score_ranking.iloc[0]["train_rmse"]),
|
|
774
|
+
"Test_R2": float(combined_score_ranking.iloc[0]["test_r2"]),
|
|
775
|
+
"Test_RMSE": float(combined_score_ranking.iloc[0]["test_rmse"]),
|
|
776
|
+
"Hyper_tuned": bool(combined_score_ranking.iloc[0]["tuned"]),
|
|
777
|
+
"Dropped_Columns":list(dropcorr)
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
plot_regression_metrics(model, x_train, y_train, x_test, y_test,feature_names)
|
|
781
|
+
print(response)
|
|
782
|
+
return {"status": "success", "model": "trained_model.pkl"}
|
|
783
|
+
|
|
784
|
+
def plot_classification_metrics(model, X_train, y_train, X_test, y_test, class_names=None):
|
|
785
|
+
# Predict
|
|
786
|
+
y_pred = model.predict(X_test)
|
|
787
|
+
y_proba = model.predict_proba(X_test)[:, 1] if hasattr(model, "predict_proba") else None
|
|
788
|
+
|
|
789
|
+
# Confusion Matrix
|
|
790
|
+
cm = confusion_matrix(y_test, y_pred)
|
|
791
|
+
disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=class_names)
|
|
792
|
+
disp.plot(cmap="Blues")
|
|
793
|
+
plt.title("Confusion Matrix")
|
|
794
|
+
plt.savefig(os.path.join(plot_path,"confusion_matrix.png"), bbox_inches='tight')
|
|
795
|
+
plt.close()
|
|
796
|
+
# ROC Curve
|
|
797
|
+
if y_proba is not None and len(np.unique(y_test)) == 2:
|
|
798
|
+
fpr, tpr, _ = roc_curve(y_test, y_proba)
|
|
799
|
+
RocCurveDisplay(fpr=fpr, tpr=tpr).plot()
|
|
800
|
+
plt.title("ROC Curve")
|
|
801
|
+
plt.savefig(os.path.join(plot_path,"roc_curve.png"), bbox_inches='tight')
|
|
802
|
+
plt.close()
|
|
803
|
+
# Precision-Recall Curve
|
|
804
|
+
if y_proba is not None:
|
|
805
|
+
precision, recall, _ = precision_recall_curve(y_test, y_proba)
|
|
806
|
+
PrecisionRecallDisplay(precision=precision, recall=recall).plot()
|
|
807
|
+
plt.title("Precision-Recall Curve")
|
|
808
|
+
plt.savefig(os.path.join(plot_path,"precision_recall_curve.png"), bbox_inches='tight')
|
|
809
|
+
plt.close()
|
|
810
|
+
# Learning Curve
|
|
811
|
+
train_sizes, train_scores, val_scores = learning_curve(model, X_train, y_train, cv=5, scoring='accuracy')
|
|
812
|
+
plt.plot(train_sizes, np.mean(train_scores, axis=1), label="Train")
|
|
813
|
+
plt.plot(train_sizes, np.mean(val_scores, axis=1), label="Validation")
|
|
814
|
+
plt.title("Learning Curve (Accuracy)")
|
|
815
|
+
plt.xlabel("Training Set Size")
|
|
816
|
+
plt.ylabel("Accuracy")
|
|
817
|
+
plt.legend()
|
|
818
|
+
plt.savefig(os.path.join(plot_path,"Accuracy_curve.png"), bbox_inches='tight')
|
|
819
|
+
plt.close()
|
|
820
|
+
|
|
821
|
+
# Class Distribution
|
|
822
|
+
fig, ax = plt.subplots(1, 2, figsize=(10, 4))
|
|
823
|
+
sns.countplot(x=y_train, ax=ax[0])
|
|
824
|
+
ax[0].set_title("Training Class Distribution")
|
|
825
|
+
sns.countplot(x=y_test, ax=ax[1])
|
|
826
|
+
ax[1].set_title("Testing Class Distribution")
|
|
827
|
+
plt.savefig(os.path.join(plot_path,"class_distribution.png"), bbox_inches='tight')
|
|
828
|
+
plt.close()
|
|
829
|
+
def plot_regression_metrics(model, X_train, y_train, X_test, y_test,feature_names):
|
|
830
|
+
y_pred = model.predict(X_test)
|
|
831
|
+
residuals = y_test - y_pred
|
|
832
|
+
|
|
833
|
+
# Actual vs. Predicted
|
|
834
|
+
plt.scatter(y_test, y_pred, alpha=0.7)
|
|
835
|
+
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], '--r')
|
|
836
|
+
plt.xlabel("Actual")
|
|
837
|
+
plt.ylabel("Predicted")
|
|
838
|
+
plt.title("Actual vs. Predicted")
|
|
839
|
+
plt.savefig(os.path.join(plot_path,"actual_vs_predictes.png"), bbox_inches='tight')
|
|
840
|
+
plt.close()
|
|
841
|
+
# Residual Plot
|
|
842
|
+
plt.scatter(y_pred, residuals, alpha=0.7)
|
|
843
|
+
plt.axhline(0, color='red', linestyle='--')
|
|
844
|
+
plt.xlabel("Predicted")
|
|
845
|
+
plt.ylabel("Residuals")
|
|
846
|
+
plt.title("Residual Plot")
|
|
847
|
+
plt.savefig(os.path.join(plot_path,"residual.png"), bbox_inches='tight')
|
|
848
|
+
plt.close()
|
|
849
|
+
# Distribution of Residuals
|
|
850
|
+
sns.histplot(residuals, kde=True)
|
|
851
|
+
plt.title("Distribution of Residuals")
|
|
852
|
+
plt.xlabel("Residual")
|
|
853
|
+
plt.savefig(os.path.join(plot_path,"residual_distribution.png"), bbox_inches='tight')
|
|
854
|
+
plt.close()
|
|
855
|
+
# Learning Curve (R² or MSE)
|
|
856
|
+
train_sizes, train_scores, val_scores = learning_curve(model, X_train, y_train, cv=5, scoring='r2')
|
|
857
|
+
plt.plot(train_sizes, np.mean(train_scores, axis=1), label="Train")
|
|
858
|
+
plt.plot(train_sizes, np.mean(val_scores, axis=1), label="Validation")
|
|
859
|
+
plt.title("Learning Curve (R² Score)")
|
|
860
|
+
plt.xlabel("Training Set Size")
|
|
861
|
+
plt.ylabel("R² Score")
|
|
862
|
+
plt.savefig(os.path.join(plot_path,"r2_score.png"), bbox_inches='tight')
|
|
863
|
+
plt.legend()
|
|
864
|
+
plt.close()
|
|
865
|
+
|
|
866
|
+
|
|
867
|
+
def main():
|
|
868
|
+
import argparse
|
|
869
|
+
parser = argparse.ArgumentParser()
|
|
870
|
+
parser.add_argument("--data", required=True)
|
|
871
|
+
parser.add_argument("--target", required=True)
|
|
872
|
+
parser.add_argument("--rmse", required=True)
|
|
873
|
+
parser.add_argument("--f1", required=True)
|
|
874
|
+
parser.add_argument("--n_jobs", default=-1, type=int)
|
|
875
|
+
parser.add_argument("--n_iter", default=100, type=int)
|
|
876
|
+
parser.add_argument("--cv", default=3, type=int)
|
|
877
|
+
args = parser.parse_args()
|
|
878
|
+
print(train_model(args.data, args.target, rmse_prob=args.rmse, f1_prob=args.f1, n_jobs=args.n_jobs, n_iter=args.n_iter, cv=args.cv))
|
|
879
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mlforgex
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: MLForge: Train and evaluate ML models easily
|
|
5
|
+
Home-page: https://github.com/yourusername/mlforge
|
|
6
|
+
Author: Priyanshu Mathur
|
|
7
|
+
Author-email: mathurpriyanshu2006@gmail.com
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Requires-Python: >=3.8
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Dist: pandas
|
|
13
|
+
Requires-Dist: numpy
|
|
14
|
+
Requires-Dist: scikit-learn
|
|
15
|
+
Dynamic: author
|
|
16
|
+
Dynamic: author-email
|
|
17
|
+
Dynamic: classifier
|
|
18
|
+
Dynamic: home-page
|
|
19
|
+
Dynamic: license-file
|
|
20
|
+
Dynamic: requires-dist
|
|
21
|
+
Dynamic: requires-python
|
|
22
|
+
Dynamic: summary
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
mlforge/__init__.py,sha256=KF9-OgHhD_9tvdgekjebdIehH34eCbd7FSb_9YcN0t4,87
|
|
2
|
+
mlforge/predict.py,sha256=zxu6rR-94F1h4k4qasrVSpNVkcSXKcvVTRe4loUibJ0,1040
|
|
3
|
+
mlforge/train.py,sha256=rhzIkJJRfjY_jNbUtUlKMnAIOTq8ZqjTWDoKw82Wwco,39526
|
|
4
|
+
mlforgex-1.0.0.dist-info/licenses/LICENSE,sha256=ajw85KQBQVyhuA7N0vPG92aXWWUanH6aq2wOo6hQNc8,1092
|
|
5
|
+
mlforgex-1.0.0.dist-info/METADATA,sha256=e4xNgkhuT0NivsYw3Xutjw7CSqBh6LXTRrf9CRkGdqw,623
|
|
6
|
+
mlforgex-1.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
7
|
+
mlforgex-1.0.0.dist-info/entry_points.txt,sha256=HxvVbd88ye_YRcZw_Kp_Yn-d-ccyGlfLdqrXcZJnJAE,92
|
|
8
|
+
mlforgex-1.0.0.dist-info/top_level.txt,sha256=Deisw-We6Xoaj6mV5d7DdeuiA7sYl_RXBJh2tAaTdW4,8
|
|
9
|
+
mlforgex-1.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Priyanshu_Mathur
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
mlforge
|