Классификация плюс использование методов ансамбля для достижения общей оценки точности ~ 92%

В продолжение моей предыдущей статьи (найденной здесь) здесь я продемонстрирую шаги, которые я предпринял для построения модели классификации с использованием Набор данных о сердечных заболеваниях UCI, а также с использованием ансамблевых методов для достижения более высокой оценки точности.

Создание подходящего алгоритма машинного обучения, который может более точно классифицировать сердечные заболевания, принесет большую пользу организациям здравоохранения, а также пациентам.

Давайте начнем!

Сначала импортировал необходимые библиотеки и прочитал в очищенном .csv файле:

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from collections import Counter
from sklearn.preprocessing import StandardScaler
# data splitting
from sklearn.model_selection import train_test_split, cross_val_score, GridSearchCV
# data modeling
from sklearn.metrics import confusion_matrix,accuracy_score,roc_curve,roc_auc_score,classification_report,f1_score
from sklearn.linear_model import LogisticRegression
from sklearn.naive_bayes import GaussianNB
from xgboost import XGBClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.svm import SVC
#ensembling
from mlxtend.classifier import StackingCVClassifier
import xgboost as xgb
import itertools
from sklearn.dummy import DummyClassifier
from sklearn import metrics
df=pd.read_csv('Data/cleaned_df.csv',index_col=0)

Затем я выполнил разделение на поезд-тест и масштабировал наши данные. Чтобы просмотреть, мы должны обучить-проверить-разделить наши данные, чтобы оценить нашу модель, и масштабирование наших данных нормализует диапазон значений в наших независимых переменных.

y = df["target"]
X = df.drop('target',axis=1)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state = 0)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

Затем я использовал DummyClassifier из sklearn, чтобы определить нашу базовую точность, которой следует ожидать, даже если просто угадать.

dummy_clf = DummyClassifier(strategy="stratified")
dummy_clf.fit(X_train, y_train)
DummyClassifier(strategy='stratified')
dummy_clf.predict(X_test)
dummy_clf.score(X_test, y_test)

Это дало нам точность 49,18%, что полезно для сравнения с нашей моделью.

Затем я взял разные модели машинного обучения, чтобы определить, какой алгоритм имеет лучший показатель точности.

  1. Логистическая регрессия
  2. K-ближайший сосед
  3. Наивный байесовский
  4. Классификатор случайного леса
  5. Экстремальное усиление градиента
  6. Древо решений
  7. Классификатор опорных векторов

Логистическая регрессия

#INSTANTIATE LOGISTIC REGRESSION
logreg = LogisticRegression()
logreg.fit(X_train, y_train)
y_pred_log = logreg.predict(X_test)
lr_acc_score=metrics.accuracy_score(y_test, y_pred_log)
lr_f1_score=metrics.f1_score(y_test, y_pred_log)
lr_conf_matrix = confusion_matrix(y_test, y_pred_log)
# checking accuracy
print('Test Accuracy score: ', lr_acc_score)
print('Test F1 score: ', lr_f1_score)
print("confusion matrix")
print(lr_conf_matrix)
print("\n")
print(classification_report(y_test,y_pred_log))

K-ближайший сосед

#INSTANTIATE KNN MODEL
knn = KNeighborsClassifier()
knn.fit(X_train, y_train)
# make class predictions for the testing set
y_pred_knn = knn.predict(X_test)
knn_acc_score=metrics.accuracy_score(y_test, y_pred_knn)
knn_f1_score=metrics.f1_score(y_test, y_pred_knn)
knn_conf_matrix = confusion_matrix(y_test, y_pred_knn)
# checking accuracy
print('Test Accuracy score: ', knn_acc_score)
print('Test F1 score: ',knn_f1_score )
print("confusion matrix")
print(knn_conf_matrix)
print("\n")
print(classification_report(y_test,y_pred_knn))

Древо решений

# INSATNTIATE DECISION TREE MODEL
tree = DecisionTreeClassifier()
tree.fit(X_train, y_train)
y_pred_tree = tree.predict(X_test)
tree_acc_score=metrics.accuracy_score(y_test, y_pred_tree)
tree_f1_score=metrics.f1_score(y_test, y_pred_tree)
tree_conf_matrix=confusion_matrix(y_test,y_pred_tree)
# checking accuracy
print('Test Accuracy score: ', tree_acc_score)
print('Test F1 score: ', tree_f1_score)
print("confusion matrix")
print(tree_conf_matrix)
print("\n")
print(classification_report(y_test,y_pred_tree))

Случайный лес

#INSTANTIATE RANDOM FOREST MODEL
rfc = RandomForestClassifier()
rfc.fit(X_train, y_train)
y_pred_forest = rfc.predict(X_test)
rfc_acc_score=metrics.accuracy_score(y_test, y_pred_forest)
rfc_f1_score = metrics.f1_score(y_test, y_pred_forest)
rfc_conf_matrix=confusion_matrix(y_test,y_pred_forest)
# checking accuracy
print('Test Accuracy score: ', rfc_acc_score)
print('Test F1 score: ', rfc_f1_score)
print("confusion matrix")
print(rfc_conf_matrix)
print("\n")
print(classification_report(y_test,y_pred_forest))

Экстремальное усиление градиента

# Instantiate the XGBClassifier: xg_cl
xg_cl = xgb.XGBClassifier(learning_rate=0.01, n_estimators=10, seed=25)
# Fit the classifier to the training set
xg_cl.fit(X_train,y_train)
# Predict the labels of the test set: preds
y_pred_xgb = xg_cl.predict(X_test)
xgb_acc_score=metrics.accuracy_score(y_test, y_pred_xgb)
xgb_f1_score = metrics.f1_score(y_test, y_pred_xgb)
xgb_conf_matrix=confusion_matrix(y_test,y_pred_xgb)
# Compute the accuracy: accuracy
# checking accuracy
print('Test Accuracy score: ',xgb_acc_score)
print('Test F1 score: ', xgb_f1_score)
print("confusion matrix")
print(xgb_conf_matrix)
print("\n")
print(classification_report(y_test,y_pred_xgb))

Наивный байесовский

nb = GaussianNB()
nb.fit(X_train,y_train)
y_pred_nb = nb.predict(X_test)
nb_conf_matrix = confusion_matrix(y_test,y_pred_nb)
nb_acc_score = metrics.accuracy_score(y_test, y_pred_nb)
nb_f1_score=metrics.f1_score(y_test, y_pred_nb)
print('Test Accuracy score: ',nb_acc_score)
print('Test F1 score: ', nb_f1_score)
print("confusion matrix")
print(nb_conf_matrix)
print("\n")
print(classification_report(y_test,y_pred_nb))

Классификатор опорных векторов

svc =  SVC(kernel='rbf', C=2)
svc.fit(X_train, y_train)
y_pred_svc = svc.predict(X_test)
svc_conf_matrix = confusion_matrix(y_test, y_pred_svc)
svc_acc_score = metrics.accuracy_score(y_test, y_pred_svc)
svc_f1_score = metrics.f1_score(y_test, y_pred_svc)
print('Test Accuracy score: ',svc_acc_score)
print('Test F1 score: ', svc_f1_score)
print("confusion matrix")
print(svc_conf_matrix)
print("\n")
print("Accuracy of Support Vector Classifier:",svc_acc_score,'\n')
print(classification_report(y_test,y_pred_svc))

Как вы можете видеть выше, я распечатал оценки точности и оценки F1 для каждой из моделей. Это произошло из-за моей неуверенности в том, какой показатель лучше всего подходит для моего бизнес-кейса. Прочитав эту замечательную статью Purva, я решил использовать точность в качестве метрики классификации, потому что нет большой разницы в распределении классов и потому, что при определении того, у кого есть или нет сердечное заболевание, важны истинные положительные и истинно отрицательные результаты.

Кроме того, мы видим, что указанные выше показатели точности варьируются от 70 до 80, как мы можем улучшить этот показатель точности? Мы можем использовать ансамблевые методы! Ансамблевые методы - это методы, которые создают несколько моделей и комбинируют их для получения улучшенных результатов. Ансамблевые методы обычно работают лучше по сравнению с единственной моделью. Существуют различные типы ансамблевых методов, которые можно использовать, для получения дополнительной информации о ансамблевых методах см. Эту статью Джозефа Рокка.



В текущем проекте я использовал укладывающийся классификатор cv, который объединяет несколько моделей классификации с помощью метаклассификатора и использует перекрестную проверку для подготовки входных данных для классификатора уровня 2. Для классификатора я проверил оценки точности для каждой модели:

model_ev = pd.DataFrame({'Model': ['Logistic Regression','Random Forest','Extreme Gradient Boost',
                    'K-Nearest Neighbour','Decision Tree','Naive Bayes', 'Support Vector Classifier'], 'Accuracy': [lr_acc_score,
                    rfc_acc_score,xgb_acc_score,knn_acc_score,tree_acc_score,nb_acc_score, svc_acc_score]})
model_ev

Затем я выбрал 3 самые эффективные модели и ввел их в классификатор cv:

scv=StackingCVClassifier(classifiers=[logreg,nb,svc],meta_classifier=nb,random_state=22)
scv.fit(X_train,y_train)
scv_predicted = scv.predict(X_test)
scv_conf_matrix = confusion_matrix(y_test, scv_predicted)
scv_acc_score = accuracy_score(y_test, scv_predicted)
scv_f1_score = f1_score(y_test, scv_predicted)
print("confusion matrix")
print(scv_conf_matrix)
print("\n")
print("Accuracy of StackingCVClassifier:",scv_acc_score*100,'\n')
print(classification_report(y_test,scv_predicted))

Как видно выше, мы достигли показателя точности ~ 92%, используя классификатор cv с накоплением.

Давайте лучше рассмотрим матрицу путаницы для нашей модели ансамбля.

Как мы видим, ансамблевая модель немного переоценивает недоминантный класс.

Затем давайте построим кривые ROC для всех моделей.

# Generate ROC curve values: fpr, tpr, thresholds
fpr_log, tpr_log, thresholds_log = roc_curve(y_test, y_pred_log)
fpr_knn, tpr_knn, thresholds_knn = roc_curve(y_test, y_pred_knn)
fpr_tree, tpr_tree, thresholds_tree = roc_curve(y_test, y_pred_tree)
fpr_rfc, tpr_rfc, thresholds_rfc = roc_curve(y_test, y_pred_forest)
fpr_xgb, tpr_xgb, thresholds_log = roc_curve(y_test, y_pred_xgb)
fpr_nb, tpr_nb, thresholds_log = roc_curve(y_test, y_pred_nb)
fpr_svc, tpr_svc, thresholds_log = roc_curve(y_test, y_pred_svc)
fpr_ens, tpr_ens, thresholds_ens = roc_curve(y_test, scv_predicted)
# Plot ROC curve
plt.plot([0, 1], [0, 1], 'k--')
plt.plot(fpr_log, tpr_log,label = 'Logistic')
plt.plot(fpr_knn, tpr_knn,label = 'KNN')
plt.plot(fpr_tree, tpr_tree,label = 'Decision Tree')
plt.plot(fpr_rfc, tpr_rfc,label = 'Random Forest')
plt.plot(fpr_xgb,tpr_xgb,label= 'XGB')
plt.plot(fpr_nb,tpr_nb,label= 'Naive Bayes')
plt.plot(fpr_svc,tpr_svc,label= 'Support Vector Classifier')
plt.plot(fpr_ens, tpr_ens,label = 'Ensemble')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.legend()
plt.title('ROC Curve no GridSearch')
plt.show()

Из нашей визуализации мы ясно видим, что ансамблевая модель показала лучшие результаты из всех протестированных нами моделей.

Наконец, я вычислил важность функции, которая присваивает оценки независимым переменным в зависимости от того, насколько они полезны для прогнозирования целевой переменной.

feature_importance = abs(logreg.coef_[0])
feature_importance = 100.0 * (feature_importance / feature_importance.max())
sorted_idx = np.argsort(feature_importance)
pos = np.arange(sorted_idx.shape[0]) + .5
featfig = plt.figure()
featax = featfig.add_subplot(1, 1, 1)
featax.barh(pos, feature_importance[sorted_idx], align='center')
featax.set_yticks(pos)
featax.set_yticklabels(np.array(X.columns)[sorted_idx], fontsize=10)
featax.set_xlabel('Relative Feature Importance')
plt.tight_layout()   
plt.show()

Как видно из приведенного выше графика, переменная ca оказала наибольшее влияние на прогнозирование наличия у человека сердечного заболевания. Переменная ca относилась к количеству крупных сосудов (0–3), окрашенных флурозопией. Чем меньше количество крупных кровеносных сосудов, тем меньше кровь, притекающая к сердцу, что увеличивает риск сердечных заболеваний.

Резюме

Из этого проекта классификации мы видим, что использование классификатора cv с накоплением повышает общую точность по сравнению с использованием отдельных моделей классификации. Наша базовая модель работала с точностью ~ 49%, а наша ансамблевая модель - с точностью ~ 92%. Я также пытался использовать методы поиска по сетке для улучшения отдельных моделей и использовать классификатор cv с накоплением, но мне удалось достичь только той же точности, что и текущая модель ансамбля.

Спасибо, что прочитали :) Весь код доступен на моем GitHub!