-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
314 lines (286 loc) · 14.7 KB
/
Copy pathapp.py
File metadata and controls
314 lines (286 loc) · 14.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
import streamlit as st
import pandas as pd
from sklearn.model_selection import train_test_split, GridSearchCV, cross_val_score
from sklearn.metrics import accuracy_score, mean_squared_error, confusion_matrix
from sklearn.ensemble import RandomForestClassifier, RandomForestRegressor, GradientBoostingClassifier, GradientBoostingRegressor
from sklearn.linear_model import LogisticRegression, LinearRegression, Ridge, Lasso
from sklearn.svm import SVC, SVR
from sklearn.tree import DecisionTreeClassifier, DecisionTreeRegressor
from sklearn.neighbors import KNeighborsClassifier, KNeighborsRegressor
from sklearn.naive_bayes import GaussianNB
from sklearn.preprocessing import LabelEncoder
import numpy as np
# Function to handle missing values
def handle_missing_values(df, option):
if option == "Ignore":
return df.dropna()
elif option == "Fill with NaN":
return df.fillna(np.nan)
# Function to get model
def get_model(algorithm_name, task_type, params=None):
if task_type == "classification":
if algorithm_name == "Random Forest":
return RandomForestClassifier(**params) if params else RandomForestClassifier()
elif algorithm_name == "Logistic Regression":
return LogisticRegression(**params) if params else LogisticRegression()
elif algorithm_name == "Support Vector Machine":
return SVC(**params) if params else SVC()
elif algorithm_name == "Decision Tree":
return DecisionTreeClassifier(**params) if params else DecisionTreeClassifier()
elif algorithm_name == "K-Nearest Neighbors":
return KNeighborsClassifier(**params) if params else KNeighborsClassifier()
elif algorithm_name == "Naive Bayes":
return GaussianNB(**params) if params else GaussianNB()
elif algorithm_name == "Gradient Boosting":
return GradientBoostingClassifier(**params) if params else GradientBoostingClassifier()
elif task_type == "regression":
if algorithm_name == "Random Forest":
return RandomForestRegressor(**params) if params else RandomForestRegressor()
elif algorithm_name == "Linear Regression":
return LinearRegression(**params) if params else LinearRegression()
elif algorithm_name == "Support Vector Machine":
return SVR(**params) if params else SVR()
elif algorithm_name == "Decision Tree":
return DecisionTreeRegressor(**params) if params else DecisionTreeRegressor()
elif algorithm_name == "K-Nearest Neighbors":
return KNeighborsRegressor(**params) if params else KNeighborsRegressor()
elif algorithm_name == "Ridge Regression":
return Ridge(**params) if params else Ridge()
elif algorithm_name == "Lasso Regression":
return Lasso(**params) if params else Lasso()
elif algorithm_name == "Gradient Boosting":
return GradientBoostingRegressor(**params) if params else GradientBoostingRegressor()
# Function to display confusion matrix
def display_confusion_matrix(cm, labels, dataset_name):
st.subheader(f"{dataset_name}")
st.write("Confusion Matrix:")
cm_df = pd.DataFrame(cm, index=labels, columns=labels)
cm_df['All'] = cm_df.sum(axis=1)
cm_df.loc['All'] = cm_df.sum()
st.write(cm_df)
# Main Streamlit app
def main():
uploaded_file = st.file_uploader("Upload your CSV file", type=["csv"])
if uploaded_file is not None:
try:
df = pd.read_csv(uploaded_file)
st.write("Data Preview:")
st.write(df.head())
except Exception as e:
st.error(f"Error loading file: {e}")
return
# Handle missing values
try:
missing_value_option = st.radio("How to handle missing values?", ('Ignore', 'Fill with NaN'))
df = handle_missing_values(df, missing_value_option)
except Exception as e:
st.error(f"Error handling missing values: {e}")
return
# Checkbox to select all columns
if st.checkbox("Select all columns for modeling"):
selected_columns = df.columns.tolist()
else:
try:
selected_columns = st.multiselect("Select columns for modeling (at least 2)", df.columns, default=df.columns[:2].tolist())
except Exception as e:
st.error(f"Error selecting columns: {e}")
return
if len(selected_columns) < 2:
st.error("Please select at least two columns.")
return
# Choose target column
try:
target_column = st.selectbox("Select the target column", selected_columns)
except Exception as e:
st.error(f"Error selecting target column: {e}")
return
# Create a dictionary to store LabelEncoders
encoders = {}
# Encode categorical variables
try:
for col in df.select_dtypes(include=['object']).columns:
if col != target_column:
le = LabelEncoder()
df[col] = le.fit_transform(df[col])
encoders[col] = le
except Exception as e:
st.error(f"Error encoding categorical variables: {e}")
return
# Determine if target is categorical or continuous
try:
target = df[target_column]
task_type = "classification" if target.dtype == 'int64' or target.nunique() < 20 else "regression"
except Exception as e:
st.error(f"Error determining task type: {e}")
return
# Select algorithm based on task type
if task_type == "classification":
algorithm_options = ["Random Forest", "Logistic Regression", "Support Vector Machine", "Decision Tree", "K-Nearest Neighbors", "Naive Bayes", "Gradient Boosting"]
else:
algorithm_options = ["Random Forest", "Linear Regression", "Support Vector Machine", "Decision Tree", "K-Nearest Neighbors", "Ridge Regression", "Lasso Regression", "Gradient Boosting"]
try:
algorithm = st.selectbox("Choose an algorithm", algorithm_options)
except Exception as e:
st.error(f"Error selecting algorithm: {e}")
return
# Parameters option
try:
use_best_params = st.radio("Parameters option", ('Choose best parameters', 'Select your own parameters'))
except Exception as e:
st.error(f"Error selecting parameters option: {e}")
return
params = {}
if use_best_params == 'Select your own parameters':
try:
if algorithm == "Random Forest":
if task_type == "classification":
params['n_estimators'] = st.number_input("Number of estimators", min_value=1, value=100)
else:
params['n_estimators'] = st.number_input("Number of estimators", min_value=1, value=100)
elif algorithm == "Logistic Regression":
params['C'] = st.number_input("Inverse of regularization strength (C)", value=1.0)
elif algorithm == "Support Vector Machine":
params['C'] = st.number_input("Regularization parameter (C)", value=1.0)
params['kernel'] = st.selectbox("Kernel", ['linear', 'rbf'])
elif algorithm == "Decision Tree":
params['max_depth'] = st.number_input("Max depth", min_value=1, value=3)
elif algorithm == "K-Nearest Neighbors":
params['n_neighbors'] = st.number_input("Number of neighbors", min_value=1, value=5)
elif algorithm == "Ridge Regression":
params['alpha'] = st.number_input("Regularization strength (alpha)", value=1.0)
elif algorithm == "Lasso Regression":
params['alpha'] = st.number_input("Regularization strength (alpha)", value=1.0)
except Exception as e:
st.error(f"Error setting parameters: {e}")
return
try:
model = get_model(algorithm, task_type, params if use_best_params == 'Select your own parameters' else None)
except Exception as e:
st.error(f"Error getting model: {e}")
return
# Train-test split options
try:
split_option = st.radio("Choose train-test split method", ('Random', 'Shuffle'))
train_size = st.slider("Train size (percentage)", 20, 99, 80) # Ensuring a minimum train size of 70%
test_size = 100 - train_size
train_size = train_size / 100
test_size = test_size / 100
split_ratio = f"Train {train_size * 100:.0f}% / Test {test_size * 100:.0f}%"
st.write(split_ratio)
except Exception as e:
st.error(f"Error selecting train-test split options: {e}")
return
# Split data
try:
X = df[selected_columns].drop(columns=[target_column])
y = df[target_column]
if split_option == 'Random':
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=test_size, random_state=42)
elif split_option == 'Shuffle':
df = df.sample(frac=1).reset_index(drop=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=test_size, random_state=42)
except Exception as e:
st.error(f"Error splitting data: {e}")
return
# Train model
try:
if use_best_params == 'Choose best parameters':
if algorithm == "Random Forest":
param_grid = {'n_estimators': [50, 100, 200]}
elif algorithm == "Logistic Regression":
param_grid = {'C': [0.1, 1.0, 10.0]}
elif algorithm == "Support Vector Machine":
param_grid = {'C': [0.1, 1.0, 10.0], 'kernel': ['linear', 'rbf']}
elif algorithm == "Decision Tree":
param_grid = {'max_depth': [3, 5, 7]}
elif algorithm == "K-Nearest Neighbors":
param_grid = {'n_neighbors': [3, 5, 7]}
elif algorithm == "Gradient Boosting":
param_grid = {'n_estimators': [50, 100, 200]}
else:
param_grid = {}
grid_search = GridSearchCV(model, param_grid, cv=3)
grid_search.fit(X_train, y_train)
model = grid_search.best_estimator_
st.write("Best parameters found:")
st.write(model)
model.fit(X_train, y_train)
except Exception as e:
st.error(f"Error training model: {e}")
return
# Validation accuracy or MSE
try:
y_train_pred = model.predict(X_train)
if task_type == "classification":
train_score = accuracy_score(y_train, y_train_pred)
st.write(f"Validation Accuracy: {train_score:.2f}")
# Display confusion matrix
train_cm = confusion_matrix(y_train, y_train_pred)
display_confusion_matrix(train_cm, np.unique(y_train), "Training Set")
else:
train_score = mean_squared_error(y_train, y_train_pred, squared=False)
st.write(f"Validation RMSE: {train_score:.2f}")
except Exception as e:
st.error(f"Error evaluating model on training data: {e}")
return
# Test accuracy or MSE
try:
if test_size > 0:
y_test_pred = model.predict(X_test)
if task_type == "classification":
test_score = accuracy_score(y_test, y_test_pred)
st.write(f"Test Accuracy: {test_score:.2f}")
# Display confusion matrix
test_cm = confusion_matrix(y_test, y_test_pred)
display_confusion_matrix(test_cm, np.unique(y_test), "Validation Set")
else:
test_score = mean_squared_error(y_test, y_test_pred, squared=False)
st.write(f"Test RMSE: {test_score:.2f}")
except Exception as e:
st.error(f"Error evaluating model on test data: {e}")
return
# Upload a test file for checking testing accuracy
st.header("Upload a test file for checking testing accuracy:")
test_uploaded_file = st.file_uploader("Upload your test CSV file", type=["csv"])
if test_uploaded_file is not None:
try:
test_df = pd.read_csv(test_uploaded_file)
# Ensure the test data only contains the selected columns and the target column
test_df = test_df[selected_columns]
# Apply the same LabelEncoder to the test data
for col in test_df.select_dtypes(include=['object']).columns:
if col in encoders:
test_df[col] = encoders[col].transform(test_df[col])
test_X = test_df.drop(columns=[target_column])
test_y = test_df[target_column]
test_pred = model.predict(test_X)
if task_type == "classification":
test_accuracy = accuracy_score(test_y, test_pred)
st.write(f"Testing Accuracy: {test_accuracy:.2f}")
# Display confusion matrix
test_cm = confusion_matrix(test_y, test_pred)
display_confusion_matrix(test_cm, np.unique(test_y), "Uploaded Test Set")
else:
test_rmse = mean_squared_error(test_y, test_pred, squared=False)
st.write(f"Testing RMSE: {test_rmse:.2f}")
except Exception as e:
st.error(f"Error evaluating model on uploaded test data: {e}")
return
# Cross-validation scores
try:
if task_type == "classification":
cv_scores = cross_val_score(model, X, y, cv=10, scoring='accuracy')
else:
cv_scores = cross_val_score(model, X, y, cv=10, scoring='neg_root_mean_squared_error')
st.subheader("Cross-validation scores: ")
st.write(f"{cv_scores}")
st.subheader("Average cross-validation score: ")
st.write(f"{np.mean(cv_scores)}")
except Exception as e:
st.error(f"Error calculating cross-validation scores: {e}")
return
if __name__ == "__main__":
try:
main()
except:
st.write(f"Something went wrong, please make sure your data is correct and you are selecting the right parameters")