#Import Pandas, NumPy, Matplotlib, Seaborn
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
#Import Scikit-Learn and XGBoost
from sklearn.model_selection import train_test_split, KFold, cross_val_score, GridSearchCV
from sklearn.metrics import roc_auc_score, accuracy_score, confusion_matrix, f1_score
from sklearn.preprocessing import MinMaxScaler, StandardScaler
from sklearn.ensemble import RandomForestClassifier
from sklearn.decomposition import PCA
from sklearn.svm import SVC
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.cluster import KMeans
import xgboost as xgb
#Load the Dataset
df = pd.read_csv('SP901_CS_completedata.csv', sep=';', encoding='utf-8')
df
| PatientID | Failure.binary | Entropy_cooc.W.ADC | GLNU_align.H.PET | Min_hist.PET | Max_hist.PET | Mean_hist.PET | Variance_hist.PET | Standard_Deviation_hist.PET | Skewness_hist.PET | ... | LZLGE.W.ADC | LZHGE.W.ADC | GLNU_area.W.ADC | ZSNU.W.ADC | ZSP.W.ADC | GLNU_norm.W.ADC | ZSNU_norm.W.ADC | GLVAR_area.W.ADC | ZSVAR.W.ADC | Entropy_area.W.ADC | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 0 | 12.85352 | 46.256345 | 6.249117 | 17.825541 | 9.783773 | 6.814365 | 2.612479 | 0.688533 | ... | 0.006900 | 6201.93480 | 4.134000 | 239.289380 | 0.979180 | 0.018990 | 0.955860 | 1145.104960 | 0.025860 | 6.286320 |
| 1 | 2 | 1 | 12.21115 | 27.454540 | 11.005214 | 26.469077 | 15.426640 | 12.932074 | 3.598298 | 0.789526 | ... | 0.004230 | 16054.01263 | 8.376270 | 644.737020 | 0.956370 | 0.014610 | 0.932880 | 847.525370 | 0.041530 | 6.778530 |
| 2 | 3 | 0 | 12.75682 | 90.195696 | 2.777718 | 6.877486 | 4.295330 | 0.923425 | 0.962163 | 0.248637 | ... | 0.004530 | 6674.63840 | 13.116860 | 1165.702610 | 0.972680 | 0.025010 | 0.915370 | 1923.857050 | 0.071040 | 7.156850 |
| 3 | 4 | 1 | 13.46730 | 325.643330 | 6.296588 | 22.029843 | 10.334779 | 6.649795 | 2.580759 | 0.832011 | ... | 0.008880 | 17172.90951 | 23.847260 | 2760.412930 | 0.972030 | 0.010690 | 0.946580 | 1329.952900 | 0.038480 | 7.295210 |
| 4 | 5 | 0 | 12.63733 | 89.579042 | 3.583846 | 7.922501 | 4.454175 | 0.572094 | 0.757225 | 1.574845 | ... | 0.004050 | 13231.94294 | 8.144370 | 784.597290 | 0.964690 | 0.025260 | 0.937690 | 1116.386690 | 0.052230 | 7.051490 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 192 | 193 | 0 | 11.95184 | 32.691265 | 12.213982 | 33.473818 | 16.208968 | 5.519894 | 3.300192 | 2.555792 | ... | -0.030152 | 38716.62434 | 29.548066 | 2709.805588 | 1.912158 | -0.011360 | 1.864258 | 1972.882222 | 0.034874 | 13.936042 |
| 193 | 194 | 0 | 9.88702 | 60.481188 | 8.860044 | 21.524942 | 12.410224 | 4.226854 | 2.888088 | 1.822704 | ... | 0.028016 | 32577.07934 | 33.427936 | 4222.228292 | 1.842530 | -0.014724 | 1.847794 | 3482.537034 | 0.055972 | 14.884836 |
| 194 | 195 | 0 | 12.84907 | 82.701566 | 11.543354 | 39.525156 | 18.867790 | 11.240758 | 4.716164 | 1.218402 | ... | -0.031432 | 24264.56392 | 163.442656 | 13608.298890 | 1.854554 | -0.010420 | 1.769414 | 2216.464110 | 0.118514 | 14.217008 |
| 195 | 196 | 0 | 12.44606 | 72.223728 | 14.413852 | 49.234694 | 24.682116 | 25.364880 | 7.097038 | 1.554986 | ... | -0.028798 | 23482.25672 | 77.169252 | 7889.657780 | 1.910132 | -0.011150 | 1.856080 | 1931.545086 | 0.037302 | 14.145064 |
| 196 | 197 | 0 | 12.13425 | 109.304666 | 11.545814 | 39.527616 | 18.870250 | 11.243218 | 4.718624 | 1.220862 | ... | -0.028972 | 24264.56638 | 163.445116 | 13608.301350 | 1.857014 | -0.007960 | 1.771874 | 2216.466570 | 0.120974 | 14.219468 |
197 rows × 430 columns
#Checking if there's null
df['Failure.binary'].info()
<class 'pandas.core.series.Series'> RangeIndex: 197 entries, 0 to 196 Series name: Failure.binary Non-Null Count Dtype -------------- ----- 197 non-null int64 dtypes: int64(1) memory usage: 1.7 KB
#Describe the target column
df['Failure.binary'].describe()
count 197.000000 mean 0.340102 std 0.474950 min 0.000000 25% 0.000000 50% 0.000000 75% 1.000000 max 1.000000 Name: Failure.binary, dtype: float64
#Value counts of the target column
df['Failure.binary'].value_counts()
0 130 1 67 Name: Failure.binary, dtype: int64
# Split the data into features (X) and the target variable (y)
X = df.drop(columns=['PatientID', 'Failure.binary'])
y = df['Failure.binary']
print(X)
print(y)
Entropy_cooc.W.ADC GLNU_align.H.PET Min_hist.PET Max_hist.PET \
0 12.85352 46.256345 6.249117 17.825541
1 12.21115 27.454540 11.005214 26.469077
2 12.75682 90.195696 2.777718 6.877486
3 13.46730 325.643330 6.296588 22.029843
4 12.63733 89.579042 3.583846 7.922501
.. ... ... ... ...
192 11.95184 32.691265 12.213982 33.473818
193 9.88702 60.481188 8.860044 21.524942
194 12.84907 82.701566 11.543354 39.525156
195 12.44606 72.223728 14.413852 49.234694
196 12.13425 109.304666 11.545814 39.527616
Mean_hist.PET Variance_hist.PET Standard_Deviation_hist.PET \
0 9.783773 6.814365 2.612479
1 15.426640 12.932074 3.598298
2 4.295330 0.923425 0.962163
3 10.334779 6.649795 2.580759
4 4.454175 0.572094 0.757225
.. ... ... ...
192 16.208968 5.519894 3.300192
193 12.410224 4.226854 2.888088
194 18.867790 11.240758 4.716164
195 24.682116 25.364880 7.097038
196 18.870250 11.243218 4.718624
Skewness_hist.PET Kurtosis_hist.PET Energy_hist.PET ... LZLGE.W.ADC \
0 0.688533 -0.339727 0.005095 ... 0.006900
1 0.789526 -0.319613 0.006297 ... 0.004230
2 0.248637 -0.944246 0.005015 ... 0.004530
3 0.832011 0.855861 0.003289 ... 0.008880
4 1.574845 3.250288 0.008066 ... 0.004050
.. ... ... ... ... ...
192 2.555792 3.463256 -0.030428 ... -0.030152
193 1.822704 -0.009474 -0.024528 ... 0.028016
194 1.218402 -0.030052 -0.031068 ... -0.031432
195 1.554986 0.320610 -0.027516 ... -0.028798
196 1.220862 -0.027592 -0.028608 ... -0.028972
LZHGE.W.ADC GLNU_area.W.ADC ZSNU.W.ADC ZSP.W.ADC GLNU_norm.W.ADC \
0 6201.93480 4.134000 239.289380 0.979180 0.018990
1 16054.01263 8.376270 644.737020 0.956370 0.014610
2 6674.63840 13.116860 1165.702610 0.972680 0.025010
3 17172.90951 23.847260 2760.412930 0.972030 0.010690
4 13231.94294 8.144370 784.597290 0.964690 0.025260
.. ... ... ... ... ...
192 38716.62434 29.548066 2709.805588 1.912158 -0.011360
193 32577.07934 33.427936 4222.228292 1.842530 -0.014724
194 24264.56392 163.442656 13608.298890 1.854554 -0.010420
195 23482.25672 77.169252 7889.657780 1.910132 -0.011150
196 24264.56638 163.445116 13608.301350 1.857014 -0.007960
ZSNU_norm.W.ADC GLVAR_area.W.ADC ZSVAR.W.ADC Entropy_area.W.ADC
0 0.955860 1145.104960 0.025860 6.286320
1 0.932880 847.525370 0.041530 6.778530
2 0.915370 1923.857050 0.071040 7.156850
3 0.946580 1329.952900 0.038480 7.295210
4 0.937690 1116.386690 0.052230 7.051490
.. ... ... ... ...
192 1.864258 1972.882222 0.034874 13.936042
193 1.847794 3482.537034 0.055972 14.884836
194 1.769414 2216.464110 0.118514 14.217008
195 1.856080 1931.545086 0.037302 14.145064
196 1.771874 2216.466570 0.120974 14.219468
[197 rows x 428 columns]
0 0
1 1
2 0
3 1
4 0
..
192 0
193 0
194 0
195 0
196 0
Name: Failure.binary, Length: 197, dtype: int64
# Scaling the data
scaler = MinMaxScaler()
scaled_data = scaler.fit_transform(X)
# Fit the PCA model
pca = PCA(n_components=2) # Choose the number of principal components
pca_components = pca.fit_transform(scaled_data)
# Analyze the principal components
explained_variance = pca.explained_variance_ratio_
print(explained_variance)
principaldf = pd.DataFrame(data = pca_components, columns=['Principal Component 1','Principal Component 2'])
print("")
print(principaldf)
plt.scatter(pca_components[:, 0], pca_components[:, 1])
plt.xlabel('Principal Component 1')
plt.ylabel('Principal Component 2')
plt.title('Scatter Plot of Principal Components')
plt.show()
# Project the original data onto the principal components
pca_scores = pca.transform(scaled_data)
# Analyze the principal component scores
from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=3)
kmeans_labels = kmeans.fit_predict(pca_scores)
[0.67558736 0.08759435]
Principal Component 1 Principal Component 2
0 -1.999969 -0.662641
1 -1.966676 -0.227635
2 -1.943384 -1.076428
3 -2.022240 -0.109832
4 -2.228796 -1.305999
.. ... ...
192 5.367085 2.374854
193 5.766655 1.646730
194 5.709939 3.576730
195 5.703741 3.448861
196 5.758057 3.472670
[197 rows x 2 columns]
/Users/jr/anaconda3/lib/python3.11/site-packages/sklearn/cluster/_kmeans.py:1412: FutureWarning: The default value of `n_init` will change from 10 to 'auto' in 1.4. Set the value of `n_init` explicitly to suppress the warning super()._check_params_vs_input(X, default_n_init=10)
X = principaldf
X_train, X_temp, y_train, y_temp = train_test_split(X, y, test_size=0.4, random_state=42)
X_val, X_test, y_val, y_test = train_test_split(X_temp, y_temp, test_size=0.5, random_state=42)
# The data is first split into a training set (60%), a temporary set (40%).
# Then the temporary set is further split into validation (20%) and test (20%) sets.
print('Training set size:', len(X_train))
print('Validation set size:', len(X_val))
print('Testing set size:', len(X_test))
Training set size: 118 Validation set size: 39 Testing set size: 40
# Create the Logistic Regression model
model = LogisticRegression()
# Initialize the K-Fold cross-validation iterator with 10 folds
kf = KFold(n_splits=10, shuffle=True, random_state=42)
# Perform 10-fold cross-validation and calculate the accuracy for each fold
accuracies = cross_val_score(model, X, y, cv=kf, scoring='accuracy')
# Print the accuracy for each fold and the mean accuracy
for fold, accuracy in enumerate(accuracies, 1):
print(f"Fold {fold}: Accuracy = {accuracy:.2f}")
mean_accuracy = np.mean(accuracies)
print(f"Mean Accuracy: {mean_accuracy:.2f}")
Fold 1: Accuracy = 0.60 Fold 2: Accuracy = 0.55 Fold 3: Accuracy = 0.65 Fold 4: Accuracy = 0.70 Fold 5: Accuracy = 0.75 Fold 6: Accuracy = 0.70 Fold 7: Accuracy = 0.70 Fold 8: Accuracy = 0.63 Fold 9: Accuracy = 0.74 Fold 10: Accuracy = 0.58 Mean Accuracy: 0.66
param_grid = {
'C': [0.1, 1, 10],
'kernel': ['linear', 'rbf'],
'gamma': [0.001, 0.01, 0.1, 1],
}
# Creates an instance of the model to be used
svm = SVC()
# Creates a GridSearchCV object and specify the model, parameter grid, and the number of cross-validation folds
grid_search = GridSearchCV(svm, param_grid, cv=5)
# Fit the grid search object to your training data
grid_search.fit(X_train, y_train)
# Access the best parameters and the best estimator
best_params = grid_search.best_params_
best_estimator = grid_search.best_estimator_
# Evaluate the best model on your test data
accuracy = best_estimator.score(X_test, y_test)
print(f"Best model accuracy on the test set: {accuracy}")
print("Best parameters:", best_params)
Best model accuracy on the test set: 0.625
Best parameters: {'C': 0.1, 'gamma': 0.001, 'kernel': 'linear'}
# Initialize and train the models
models = {
'Logistic Regression': LogisticRegression(),
'K-Nearest Neighbors': KNeighborsClassifier(n_neighbors=3),
'SVM': SVC(),
'Random Forest': RandomForestClassifier(),
'XGBoost': xgb.XGBClassifier()
}
for model_name, model in models.items():
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f'{model_name} Accuracy: {accuracy:.2f}')
# Create a bar chart
models = list(accuracy_results.keys())
accuracy_values = list(accuracy_results.values())
plt.figure(figsize=(10, 6))
bars = plt.bar(models, accuracy_values, color='lightblue')
plt.ylim(0.1, 0.8)
plt.title('Accuracy of Different Classification Models')
plt.xlabel('Model')
plt.ylabel('Accuracy')
plt.xticks(rotation=45)
#Add data labels to the bars
for bar, accuracy in zip(bars, accuracy_values):
plt.text(bar.get_x() + bar.get_width() / 2, bar.get_height() + 0.005, f'{accuracy:.2f}', ha='center', va='bottom')
plt.show()
Logistic Regression Accuracy: 0.62 K-Nearest Neighbors Accuracy: 0.61 SVM Accuracy: 0.62 Random Forest Accuracy: 0.58 XGBoost Accuracy: 0.52
# Initialize dictionaries to store the evaluation metrics
accuracy_results = {}
f1_results = {}
roc_auc_results = {}
# Train and evaluate the models
models = {
'Logistic Regression': LogisticRegression(),
'K-Nearest Neighbors': KNeighborsClassifier(n_neighbors=3),
'SVM': SVC(probability=True),
'Random Forest': RandomForestClassifier(),
'XGBoost': xgb.XGBClassifier()
}
for model_name, model in models.items():
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred, average='weighted')
if 'SVM' in model_name:
y_score = model.predict_proba(X_test)[:, 1]
else:
y_score = model.decision_function(X_test) if hasattr(model, 'decision_function') else model.predict_proba(X_test)[:, 1]
roc_auc = roc_auc_score(y_test, y_score)
accuracy_results[model_name] = accuracy
f1_results[model_name] = f1
roc_auc_results[model_name] = roc_auc
# Create a bar chart for each evaluation metric
models = list(accuracy_results.keys())
plt.figure(figsize=(12, 6))
# Accuracy bar chart
plt.subplot(131)
accuracy_values = list(accuracy_results.values())
bars = plt.bar(models, accuracy_values, color='skyblue')
plt.ylim(0.1, 1.0)
plt.title('Accuracy')
plt.xticks(rotation=90)
for bar, accuracy in zip(bars, accuracy_values):
plt.text(bar.get_x() + bar.get_width() / 2, bar.get_height() + 0.005, f'{accuracy:.2f}', ha='center', va='bottom')
# F1-score bar chart
plt.subplot(132)
f1_values = list(f1_results.values())
bars = plt.bar(models, f1_values, color='lightcoral')
plt.ylim(0.1, 1.0)
plt.title('F1-Score')
plt.xticks(rotation=90)
for bar, f1 in zip(bars, f1_values):
plt.text(bar.get_x() + bar.get_width() / 2, bar.get_height() + 0.005, f'{f1:.2f}', ha='center', va='bottom')
# ROC-AUC bar chart
plt.subplot(133)
roc_auc_values = list(roc_auc_results.values())
bars = plt.bar(models, roc_auc_values, color='lightgreen')
plt.ylim(0.1, 1.0)
plt.title('ROC-AUC')
plt.xticks(rotation=90)
for bar, roc_auc in zip(bars, roc_auc_values):
plt.text(bar.get_x() + bar.get_width() / 2, bar.get_height() + 0.005, f'{roc_auc:.2f}', ha='center', va='bottom')
plt.tight_layout()
plt.show()