С набором данных heart
создаются и оцениваются 3 модели машинного обучения для прогнозирования наличия сердечных заболеваний.
В этом посте я собираюсь объяснить, как читать данные и строить 3 модели машинного обучения для обнаружения патологии пациента. Это будут модели бинарной классификации. Мы оценим каждую модель и определим, какая из них лучше. Это модели дерева решений, случайного леса и наивного байесовского алгоритма. Кроме того, я буду сравнивать модели, играя с данными. В конце поста я постараюсь объяснить, как повысить точность моделей. Это сердечная болезнь UCI от Kaggle [1]. Лицензия данных — Условия Reddit API.
Чтобы просмотреть код для лучшей визуализации и понимания, нажмите здесь.
Начиная
Нам нужно загрузить данные. В этой записной книжке мы будем использовать набор данных о сердечных заболеваниях с открытым исходным кодом, опубликованный здесь.
!pip install opendatasets import opendatasets as od od.download("https://www.kaggle.com/ronitf/heart-disease-uci")
Подготовка данных
Этот набор данных имеет следующие столбцы:
Непрерывные числовые столбцы
age
: возраст в годахtrestbps
: артериальное давление в покоеchol
: холестерин сыворотки в мг/длthalach
: достигнута максимальная частота сердечных сокращенийoldpeak
: Депрессия ST, вызванная физической нагрузкой, по сравнению с состоянием покоя
Категорийные столбцы
sex
: 1 = мужчина; 0 = женщинаcp
: тип боли в груди (4 значения)fbs
: уровень сахара в крови натощак > 120 мг/дл. 1 = правда; 0 = ложьrestecg
: результаты электрокардиографии в покое (значения 0,1,2)exang
: стенокардия, вызванная физической нагрузкой, 1 = да; 0 = нетslope
: наклон пикового сегмента ST при нагрузке (3 значения)ca
: количество крупных сосудов (0-3), окрашенных при флюороскопииthal
: талассемия, 1 = норма; 2 = фиксированный дефект; 3 = обратимый дефектtarget
: наличие порока сердца. 0 = положительный, 1 = отрицательный
Этот набор данных содержит столбец target
, который является двоичным флагом, указывающим на наличие болезни сердца. Это целевой столбец, который мы хотим предсказать.
Чтобы увидеть первые и последние пять индексов данных в таблице:
# Reading Data: df=pd.read_csv("/Users/esmasert/Desktop/CODES/Jupyter/DataAssessment/heart-disease-uci/heart.csv") df.head() # Showing the First Five Rows:
Чтобы увидеть имена столбцов и информацию о данных:
df.columns # Column Names df.info() # Data Information
Мы можем увидеть, есть ли пропущенное значение в строках, перебирая все столбцы. И если есть, то какой процент?
for clmn in df.columns: any_missing = df[clmn].isnull().sum() print(f'{clmn} - {any_missing :.1%}')
Здорово! Нет пропущенного значения.
Теперь нам нужно проверить данные, чтобы увидеть, есть ли повторяющиеся строки. Чтобы увидеть это:
df.duplicated().sum() # Counting the duplicated rows
В данных есть повторяющаяся строка. Теперь мы должны справиться с этим, чтобы предотвратить любые негативные побочные эффекты для тренировочной части. Потому что избыточность может отрицательно сказаться на анализе данных, поскольку это значения, которые точно не нужны. Чтобы преодолеть это:
Мы можем транспонировать столбец и индексы для лучшей визуализации.
Теперь, чтобы лучше понять данные, мы можем перечислить уникальные значения каждой функции.
Мы закончили с числовой визуализацией, теперь давайте воспользуемся графиками!
print(f'Number of people identified as sex 0 are {df.sex.value_counts()[0]} and Number of people identified as sex 1 are {df.sex.value_counts()[1]}') plt.figure(figsize=(7,7)) p = sns.set_theme(style="darkgrid") p = sns.countplot(data=df, x="sex", palette='Set3')
Также попробуйте этот код! И вы будете удивлены результатами :)
g = sns.PairGrid(df, hue="target") g.map_diag(sns.histplot) g.map_offdiag(sns.scatterplot) g.add_legend()
Теперь давайте посмотрим, сколько там людей того же возраста и пола.
import seaborn as sns import matplotlib.pyplot as plt plt.figure(figsize=(12,6)) # count plot on two categorical variable sns.countplot(x ='age', hue = "sex", data = df) # Show the plot plt.show()
Как мы видим, у нас гораздо больше информации от самцов в данных. (1 = мужчина; 0 = женщина)
Из графиков видно, что сердечные заболевания чаще встречаются у мужчин. (Цель; 0 = положительный, 1 = отрицательный) (Пол; 1 = мужской; 0 = женский)
В возрасте от 55 до 63 лет риск сердечного приступа гораздо выше. (Цель; наличие болезни сердца. 0 = положительный, 1 = отрицательный)
Еще немного графиков:
Построение моделей
Подготовка данных
Выбор функций
Сначала нам нужно разделить заданные столбцы на два типа переменных; независимые (характеристические переменные) и зависимые (целевая переменные) переменные.
Разделение данных
Затем мы разделим набор данных на обучающий набор и тестовый набор, разделив наши данные на 80% для обучения и 20% для тестирования.
from sklearn.model_selection import train_test_split # to split the data X_train, X_test, y_train, y_test = train_test_split(df.drop('target', 1), df['target'], test_size = .2, random_state=10) #split the data
Классификация дерева решений
Теперь давайте создадим модель дерева решений с помощью Scikit-learn.
import pandas as pd from sklearn.tree import DecisionTreeClassifier # importing Decision Tree Classifier from sklearn import metrics # metrics module for accuracy calculation # Create Decision Tree Classifer object clfDT = DecisionTreeClassifier() # Train Decision Tree Classifer clfDT = clfDT.fit(X_train,y_train) #Predict the response for test dataset y_pred = clfDT.predict(X_test)
Оценка модели
И рисуем дерево решений
Матрица путаницы
# Print Accuracy print("Accuracy:",metrics.accuracy_score(y_test, y_pred)) print('\n') from sklearn.metrics import plot_confusion_matrix fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(15,7)) titles_options = [("Confusion matrix for Decision Tree, without normalization", None, axes.flatten()[0]), ("Normalized confusion matrix for Decision Tree", 'true', axes.flatten()[1])] for title, normalize, ax in titles_options: disp = plot_confusion_matrix(clfDT, X_test, y_test, cmap=plt.cm.Blues, ax=ax, normalize = normalize) disp.ax_.set_title(title) plt.rcParams['axes.grid'] = False print(title) print(disp.confusion_matrix) plt.show()
Давайте нормализуем данные:
b = df.target.values a_data = df.drop(['target'], axis = 1) # Normalize a = (a_data - np.min(a_data)) / (np.max(a_data) - np.min(a_data)).values a_train, a_test, b_train, b_test = train_test_split(a, b, test_size = 0.2, random_state=0) # Create Decision Tree classifer object clfNorm = DecisionTreeClassifier() # Train Decision Tree Classifer clfNorm = clfNorm.fit(a_train,b_train) #Predict the response for test dataset b_pred = clfNorm.predict(a_test)
Здорово! Как вы видите здесь, мы можем повысить точность, нормализовав данные перед обучением.
Случайная классификация леса
Алгоритм случайного леса представляет собой алгоритм усреднения по ансамблю, основанный на рандомизированных деревьях решений.
#Import Random Forest Model from sklearn.ensemble import RandomForestClassifier #Create a Gaussian Classifier clfRF=RandomForestClassifier(n_estimators=100) #Train the model using the training sets y_pred=clf.predict(X_test) clfRF.fit(X_train,y_train) y_pred=clfRF.predict(X_test)
Оценка модели:
Матрица путаницы этой модели.
Если мы обучаем модель с нормализованными данными,
#Create a Gaussian Classifier clfRFNorm=RandomForestClassifier(n_estimators=100) #Train the model using the training sets y_pred=clf.predict(X_test) clfRFNorm.fit(a_train,b_train) b_predNorm=clfRFNorm.predict(a_test)
Здорово! Как вы видите здесь, мы повысили точность, нормализовав данные перед обучением с 0,770 до 0,868.
Поиск важных функций
Мы используем переменную важности функции, чтобы увидеть оценки важности функции. Затем мы визуализируем эти партитуры с помощью библиотеки seaborn.
feature_imp = pd.Series(clfRF.feature_importances_, index=X_train.columns.values.tolist()).sort_values(ascending=False) feature_imp from matplotlib import pyplot # Creating a bar plot fig, ax = pyplot.subplots(figsize=(14, 7)) sns.barplot(x=feature_imp, y=feature_imp.index) # Add labels to your graph plt.xlabel('Feature Importance Score',fontsize=15) plt.ylabel('Features',fontsize=15) plt.title("Visualizing Important Features",fontsize=18) plt.legend() plt.show()
Создание модели на основе выбранных объектов
Здесь мы можем удалить последние 4 признака (fbs,restecg,sex,exang), так как они имеют очень низкую важность, по мнению других, и выбрать остальные оставшиеся признаки.
# Split dataset into features and labels RmX= df[['age','cp','trestbps','chol','thalach','oldpeak','slope','ca','thal']] # Removed feature "sepal length" Rmy= df['target'] # Split dataset into training set and test set RmX_train, RmX_test, Rmy_train, Rmy_test = train_test_split(RmX, Rmy, test_size=0.20, random_state=5) # 80% training and 20% test #Create a Gaussian Classifier Rmclf=RandomForestClassifier(n_estimators=100) #Train the model using the training sets y_pred=clf.predict(X_test) Rmclf.fit(RmX_train,Rmy_train) # prediction on test set Rmy_pred=Rmclf.predict(RmX_test)
Оцените модель:
Отлично!! Точность увеличилась до 0,836 с 0,770.
Вы можете видеть, что после удаления наименее важных функций точность увеличилась. Это потому, что мы удалили вводящие в заблуждение данные и шум. Меньшее количество функций также сокращает время обучения. Поскольку мы удалили функции, которые имеют меньшее влияние, мы уже избавились от ненужных функций. Таким образом, нормализация данных может не работать с этим методом.
Наивная байесовская классификация
#Import Gaussian Naive Bayes model from sklearn.naive_bayes import GaussianNB #Create a Gaussian Classifier NBclf = GaussianNB() # Train the model using the training sets NBclf.fit(X_train,y_train) #Predict Output NBy_pred = NBclf.predict(X_test) # 0:Overcast, 2:Mild
Оценить модель
Матрица путаницы:
Подходя к концу, я создал таблицу, в которой показаны все шаги, чтобы увидеть, как влияет точность модели.
Вывод
Сравнение моделей
Мы можем сравнить модели, просмотрев график,
colors = ['red','plum','slateblue','lavender','mediumaquamarine','silver','khaki','yellowgreen','lightskyblue'] plt.figure(figsize=(14,7)) plt.title("Accuracies of different models") plt.xlabel("Algorithms") plt.ylabel("Accuracy %") plt.bar(results_df['Model'],results_df['Testing Accuracy %'], color = colors) plt.xticks(rotation='vertical') plt.show()
Как мы видим здесь, наиболее эффективным алгоритмом для достижения наивысшей точности является наивный байесовский алгоритм с нормализованными данными для набора данных UCI по сердечно-сосудистым заболеваниям. Даже точность обучения в алгоритме Наивного Байеса ниже, чем у других, результат точности теста, что интересно, является самым высоким.
Опять же, у меня была меньшая точность от наивного байесовского классификатора с FIF и результатом нормализованных данных. Кроме того, поскольку у меня не было более высокого результата для случайного леса с нормализованными данными и FIF, чтобы не усложнять внешний вид, я исключил наивный байесовский классификатор с FIF и результатом нормализованных данных из таблицы.
Как повысить точность
Нормализация данных
Нормализация данных — это тип процесса, при котором данные реорганизуются таким образом, чтобы пользователи могли правильно использовать их для дальнейших запросов и анализа. Цель нормализации — привести значения числовых столбцов в наборе данных к общему масштабу, не искажая различий в диапазонах значений.
Как видите, почти во всех методах метод нормализации оказал огромное влияние на точность. Поэтому использование этого метода будет полезным в большинстве случаев.
Ассемблирование
Для повышения точности модели можно использовать метод ансамбля. Цель методов ансамбля состоит в том, чтобы объединить прогнозы нескольких базовых оценок, построенных с помощью заданного алгоритма обучения, чтобы улучшить обобщаемость/надежность по сравнению с одной оценкой.
Существует два типа методов сборки:
- Методы усреднения. Основной принцип заключается в независимом построении нескольких оценщиков, а затем в усреднении их прогнозов. В среднем комбинированная оценка обычно лучше, чем любая из оценок с одной базой, потому что ее дисперсия уменьшается.
- Методы повышения: базовые оценки строятся последовательно, и каждый пытается уменьшить смещение комбинированной оценки. Мотивация состоит в том, чтобы объединить несколько слабых моделей для создания мощного ансамбля.
Мы уже использовали один метод усреднения по ансамблю, случайный лес. Поэтому продолжим с другими. Но, чтобы доказать положительные эффекты метода ансамбля, мы можем просто проверить результаты алгоритма случайного леса.
Поиск важных функций и удаление наименее важных
Важность признаков относится к классу методов присвоения оценок входным признакам в прогностической модели, которая указывает относительную важность каждого признака при прогнозировании.
Оценки полезны и могут использоваться в ряде ситуаций в задаче прогнозного моделирования, например:
- Лучшее понимание данных.
- Лучшее понимание модели.
- Уменьшение количества входных признаков.
- Сокращение времени обучения, меньшее количество точек данных снижает сложность алгоритма, и алгоритмы обучаются быстрее.
- Сокращение переобучения, меньше избыточных данных означает меньше возможностей принимать решения на основе шума.
- Повышение точности, меньше вводящих в заблуждение данных означает повышение точности моделирования.
Настройка гиперпараметров
Чтобы увидеть эффекты настройки гиперпараметров, мы настроим гиперпараметры модели случайного леса. Гиперпараметры, которые мы будем настраивать, включают max_features и n_estimators.
from sklearn.model_selection import GridSearchCV max_features_range = np.arange(1,6,1) n_estimators_range = np.arange(10,210,10) param_grid = dict(max_features=max_features_range, n_estimators=n_estimators_range) RanFrstCls = RandomForestClassifier() gridSCV = GridSearchCV(estimator=RanFrstCls, param_grid=param_grid, cv=5) gridSCV.fit(X_train, y_train)
Функция GridSearchCV() из scikit-learn используется для настройки гиперпараметров. В частности, функция GridSearchCV() может выполнять типичные функции классификатора, такие как соответствие, оценка и прогнозирование, а также прогнозирование_проблемы, решение_функции, преобразование и обратное_преобразование.
После настройки гиперпараметра для алгоритма случайного леса точность увеличилась до 85,9439 с 80,327869.
Это самая высокая точность среди всех опробованных нами методов классификации случайного леса!
Результаты
Когда мы обучили 3 алгоритма с набором данных UCI по сердечно-сосудистым заболеваниям, мы добились очень разной точности.
Пока мы искали, наилучшей точностью на данный момент является алгоритм наивного байесовского классификатора с нормализованными данными (90,1634).
Второй по точности алгоритм случайного леса с настроенными гиперпараметрами (85,9354).
И третье место по точности — это алгоритм повышения дерева градиентов из методов ансамбля. (85,2459)
Наконец, четвертое место по точности занимает классификатор случайного леса с методом поиска важных признаков. (83,6065)
В этом посте я попытался; поиск важных функций, объединение, настройка гиперпараметров и нормализация данных, чтобы увидеть, как они влияют на точность. Существует множество других методов, с помощью которых мы можем вносить изменения в данные перед обучением или моделями.
Из приведенной выше информации мы можем сделать вывод, что все алгоритмы, которые мы пробовали, достигли более высокой точности с дополнительными алгоритмами и методами. Все эффективности методов и алгоритмов меняются в зависимости от данных и того, на каком классификаторе они построены.
Большое спасибо за чтение!
использованная литература
[1] https://www.kaggle.com/ronitf/heart-disease-uci
[2] https://scikit-learn.org/stable/modules/ensemble.html
[4] https://machinelearningmastery.com/calculate-feature-importance-with-python/
[5] https://github.com/dataprofessor/code/blob/master/python