import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import train_test_split

from sklearn.svm import SVC
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.linear_model import LogisticRegression, LogisticRegressionCV

from sklearn.metrics import confusion_matrix, roc_curve, roc_auc_score
from statsmodels.stats.outliers_influence import variance_inflation_factor
"""
# Loading dataset
"""
cancer = pd.read_csv("/kaggle/input/breast-cancer-prediction-dataset/Breast_cancer_data.csv")
cancer.head()
"""
# Check if there is missing data
"""
cancer.describe().T
"""
Clearly, there is no missing data so we can proceed with the next steps:
1. Scaling
2. Visualization
3. Modification (if required)
"""
"""
# Data Scaling
"""
scaler = MinMaxScaler()
cancer = pd.DataFrame(data=scaler.fit_transform(cancer), columns=cancer.columns)
cancer.head()
"""
# Data Visualization
"""
sns.pairplot(data=cancer)
"""
From the above pairplot it is clearly visible that "mean_area", "mean_radius" and "mean_perimeter" are closely related to one another and can thereby be removed to reduce collinearity. Same can be visualized using the heatmap (as shown below)
"""
plt.figure(figsize=(10, 8))
sns.heatmap(cancer.corr(), annot=True)
target = cancer.diagnosis
features = cancer.drop(columns=["diagnosis"])
"""
# Removing multi-colilinearity using VIF
Here we remove the features that increase the multi-collinearity of the data distribution. We do this using variance_inflation_factor
"""
while True:
    temp_var = 0
    temp_col = ""
    for i in range(features.shape[1]):
        if variance_inflation_factor(features.values, i) > temp_var:
            temp_col = features.columns[i]
            temp_var = variance_inflation_factor(features.values, i)
    if temp_var > 5:
        print("Dropping feature '{}' which has a VIF value: {}\n".format(temp_col, temp_var))
        features.drop(columns=[temp_col], inplace=True)
    else:
        break
        
print("Final Features with VIF <=5:")
for i in range(features.shape[1]):
    print(features.columns[i], variance_inflation_factor(features.values, i))
"""
# Splitting data into training and test set
"""
X_train, X_test, y_train, y_test = train_test_split(features, target, random_state=0)
"""
# Using different classification models and selecting the best fit
"""
model_data = []
listOfModels = [LogisticRegression(), LogisticRegressionCV(), KNeighborsClassifier(), SVC(), GradientBoostingClassifier(), DecisionTreeClassifier()]

for model in listOfModels:
    classifier = model
    classifier.fit(X_train, y_train)
    y_pred = classifier.predict(X_test)
    model_data.append([model.__class__.__name__, roc_auc_score(y_test, y_pred)])
    
model_data_frame = pd.DataFrame(columns=["Model", "ROC_Score"], data=model_data)
print(model_data_frame.sort_values("ROC_Score"))
"""
Gradient Boosting Classifier is the best fitting model amongst all. We'll now derive its confusion matrix and plot auc-roc curve
"""
print("Confusion Matrix")
print(pd.DataFrame(data=confusion_matrix(y_test, y_pred), columns=["Predicted True", "Predicted False"], index=["Actual True", "Actual False"]))
falsePositive, truePositive, threshold = roc_curve(y_test, y_pred, pos_label=1)
plt.figure(figsize=(10, 8))
sns.lineplot(falsePositive, truePositive)
plt.title("ROC - AUC Curve")