Машинное обучение, связанное с диабетом, запрограммировано на Python

Python алгоритм Программа перевода самородков машинное обучение

в соответствии сCenters for Disease Control and Prevention, примерно каждый седьмой взрослый в США в настоящее время болеет диабетом. К 2050 году это соотношение увеличится до одной трети. Имея это в виду, вот что мы собираемся сделать сегодня: научиться использовать машинное обучение, чтобы помочь нам предсказать диабет. Начать сейчас!

данные

Набор данных по диабету взят изUCI Machine Learning Repository,здесьможно скачать.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
diabetes = pd.read_csv('diabetes.csv')
print(diabetes.columns)
Index([‘Pregnancies’, ‘Glucose’, ‘BloodPressure’, ‘SkinThickness’, ‘Insulin’, ‘BMI’, ‘DiabetesPedigreeFunction’, ‘Age’, ‘Outcome’], dtype=’object’)
diabetes.head()

Набор данных по диабету содержит 768 точек данных, каждая из которых содержит 9 признаков:

print("dimension of diabetes data: {}".format(diabetes.shape))

dimension of diabetes data: (768, 9)

«Выход» — это функция, которую мы собираемся предсказать, 0 для недиабетических и 1 для диабетических. Из этих 768 точек данных 500 отмечены как 0, а 268 отмечены как 1:

print(diabetes.groupby('Outcome').size())

import seaborn as sns
sns.countplot(diabetes['Outcome'],label="Count")

Получается следующий рисунок:

diabetes.info()

k ближайших соседей

Алгоритм k-ближайшего соседа, пожалуй, самый простой алгоритм машинного обучения. Он строит модель, содержащую только обучающий набор данных. Чтобы сделать прогноз о новой точке данных, алгоритм найдет ближайшую точку данных в обучающем наборе данных — своего «ближайшего соседа».

Во-первых, нам нужно проверить, можем ли мы подтвердить связь между сложностью модели и точностью:

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(diabetes.loc[:, diabetes.columns != 'Outcome'], diabetes['Outcome'], stratify=diabetes['Outcome'], random_state=66)
from sklearn.neighbors import KNeighborsClassifier
training_accuracy = []
test_accuracy = []
# 从 1 到 10 试验参数 n_neighbors
neighbors_settings = range(1, 11)
for n_neighbors in neighbors_settings:
    # 建立模型
    knn = KNeighborsClassifier(n_neighbors=n_neighbors)
    knn.fit(X_train, y_train)
    # 记录训练集精度
    training_accuracy.append(knn.score(X_train, y_train))
    # 记录测试集精度
    test_accuracy.append(knn.score(X_test, y_test))
plt.plot(neighbors_settings, training_accuracy, label="training accuracy")
plt.plot(neighbors_settings, test_accuracy, label="test accuracy")
plt.ylabel("Accuracy")
plt.xlabel("n_neighbors")
plt.legend()
plt.savefig('knn_compare_model')

Получается следующий рисунок:

Как показано выше, точность обучающего и тестового набора по оси y обратно пропорциональна количеству n ближайших соседей по оси x. Представьте, если бы мы выбрали только одного ближайшего соседа, прогнозы на тренировочном наборе были бы идеальными. Однако при добавлении большего количества соседей точность обучения будет снижаться, а это означает, что модель, полученная путем выбора только одного соседа, слишком сложна. Лучшей практикой является выбор 9 или около того ближайших соседей.

Ссылаясь на рисунок выше, мы должны выбрать n_neighbors=9. Итак, вот оно:

knn = KNeighborsClassifier(n_neighbors=9)
knn.fit(X_train, y_train)
print('Accuracy of K-NN classifier on training set: {:.2f}'.format(knn.score(X_train, y_train)))
print('Accuracy of K-NN classifier on test set: {:.2f}'.format(knn.score(X_test, y_test)))
Accuracy of K-NN classifier on training set: 0.79
Accuracy of K-NN classifier on test set: 0.78

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

Логистическая регрессия является одним из наиболее часто используемых алгоритмов классификации.

from sklearn.linear_model import LogisticRegression
logreg = LogisticRegression().fit(X_train, y_train)
print("Training set score: {:.3f}".format(logreg.score(X_train, y_train)))
print("Test set score: {:.3f}".format(logreg.score(X_test, y_test)))
Training set accuracy: 0.781
Test set accuracy: 0.771

Значение по умолчанию C=1 дает точность 78 % на тренировочном наборе и 77 % на тестовом наборе.

logreg001 = LogisticRegression(C=0.01).fit(X_train, y_train)
print("Training set accuracy: {:.3f}".format(logreg001.score(X_train, y_train)))
print("Test set accuracy: {:.3f}".format(logreg001.score(X_test, y_test)))
Training set accuracy: 0.700
Test set accuracy: 0.703

Использование C = 0,01 приводит к падению точности как на обучающем, так и на тестовом наборах.

logreg100 = LogisticRegression(C=100).fit(X_train, y_train)
print("Training set accuracy: {:.3f}".format(logreg100.score(X_train, y_train)))
print("Test set accuracy: {:.3f}".format(logreg100.score(X_test, y_test)))
Training set accuracy: 0.785
Test set accuracy: 0.766

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

Поэтому мы должны использовать значение по умолчанию C=1.

Давайте визуализируем параметры, полученные путем изучения модели на наборе данных трех разных параметров регуляризации C.

Наборы с более сильной регуляризацией (C=0,001) получают параметры, приближающиеся к нулю. Присмотревшись к графику более внимательно, мы также видим, что для C=100, C=1 и C=0,001 все коэффициенты признака «Функция родословной диабета» положительны. Это означает, что независимо от того, какую модель мы рассматриваем, высокая функция «DiabetesPedigreeFunction» и образцы диабета связаны.

diabetes_features = [x for i,x in enumerate(diabetes.columns) if i!=8]
plt.figure(figsize=(8,6))
plt.plot(logreg.coef_.T, 'o', label="C=1")
plt.plot(logreg100.coef_.T, '^', label="C=100")
plt.plot(logreg001.coef_.T, 'v', label="C=0.001")
plt.xticks(range(diabetes.shape[1]), diabetes_features, rotation=90)
plt.hlines(0, 0, diabetes.shape[1])
plt.ylim(-5, 5)
plt.xlabel("Feature")
plt.ylabel("Coefficient magnitude")
plt.legend()
plt.savefig('log_coef')

Получается следующий рисунок:

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

from sklearn.tree import DecisionTreeClassifier
tree = DecisionTreeClassifier(random_state=0)
tree.fit(X_train, y_train)
print("Accuracy on training set: {:.3f}".format(tree.score(X_train, y_train)))
print("Accuracy on test set: {:.3f}".format(tree.score(X_test, y_test)))
Accuracy on training set: 1.000
Accuracy on test set: 0.714

Точность на тренировочном наборе составляет 100%, но точность на тестовом наборе намного хуже. Это означает, что дерево переобучено, поэтому обобщение на новые данные слабое. Поэтому нам нужно обрезать дерево.

Мы устанавливаем максимальную глубину max_depth=3, ограничивая глубину дерева, чтобы уменьшить переоснащение. Это приведет к падению точности на тренировочном наборе, но результаты на тестовом наборе улучшатся.

tree = DecisionTreeClassifier(max_depth=3, random_state=0)
tree.fit(X_train, y_train)
print("Accuracy on training set: {:.3f}".format(tree.score(X_train, y_train)))
print("Accuracy on test set: {:.3f}".format(tree.score(X_test, y_test)))
Accuracy on training set: 0.773
Accuracy on test set: 0.740

Веса признаков для деревьев решений

Веса признаков определяют важность каждого признака для окончательного решения дерева. Это число от 0 до 1 для каждой функции, где 0 означает «совершенно бесполезно», а 1 означает «идеальный результат прогнозирования». Сумма весов признаков должна быть равна 1.

print("Feature importances:\n{}".format(tree.feature_importances_))
Feature importances: [ 0.04554275 0.6830362 0\. 0\. 0\. 0.27142106 0\. 0\. ]

Затем мы визуализируем веса признаков:

def plot_feature_importances_diabetes(model):
    plt.figure(figsize=(8,6))
    n_features = 8
    plt.barh(range(n_features), model.feature_importances_, align='center')
    plt.yticks(np.arange(n_features), diabetes_features)
    plt.xlabel("Feature importance")
    plt.ylabel("Feature")
    plt.ylim(-1, n_features)
plot_feature_importances_diabetes(tree)
plt.savefig('feature_importance')

Получается следующий рисунок:

Функция «Глюкоза» в настоящее время является функцией с наибольшим весом местоположений.

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

Давайте применим случайный лес из 100 деревьев к набору данных о диабете:

from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier(n_estimators=100, random_state=0)
rf.fit(X_train, y_train)
print("Accuracy on training set: {:.3f}".format(rf.score(X_train, y_train)))
print("Accuracy on test set: {:.3f}".format(rf.score(X_test, y_test)))
Accuracy on training set: 1.000
Accuracy on test set: 0.786

Случайный лес без какой-либо настройки дал точность 78,6%, что лучше, чем только логистическая регрессия или деревья решений. Однако мы все еще можем настроить параметр max_features и посмотреть, будут ли результаты лучше.

rf1 = RandomForestClassifier(max_depth=3, n_estimators=100, random_state=0)
rf1.fit(X_train, y_train)
print("Accuracy on training set: {:.3f}".format(rf1.score(X_train, y_train)))
print("Accuracy on test set: {:.3f}".format(rf1.score(X_test, y_test)))
Accuracy on training set: 0.800
Accuracy on test set: 0.755

Нет, это значит, что дефолтные параметры случайного леса уже работают.

Веса объектов в случайном лесу

plot_feature_importances_diabetes(rf)

Получается следующий рисунок:

![]=(https://datascienceplus.com/wp-content/uploads/2018/03/diabetes_8.png)

Подобно дереву с одним решением, случайный лес также имеет более высокий вес для признака «Глюкоза», но также выбирает «ИМТ» как второй по величине вес среди всех признаков. Случайность при создании случайных лесов требует, чтобы алгоритм рассматривал множество возможных решений, в результате чего случайные леса отражают характеристики данных более полно, чем одно дерево решений.

Повышение градиента

from sklearn.ensemble import GradientBoostingClassifier
gb = GradientBoostingClassifier(random_state=0)
gb.fit(X_train, y_train)
print("Accuracy on training set: {:.3f}".format(gb.score(X_train, y_train)))
print("Accuracy on test set: {:.3f}".format(gb.score(X_test, y_test)))
Accuracy on training set: 0.917
Accuracy on test set: 0.792

Модель может быть переобучена. Чтобы уменьшить переоснащение, мы можем применить более сильную операцию обрезки, чтобы ограничить максимальную глубину или уменьшить скорость обучения:

gb1 = GradientBoostingClassifier(random_state=0, max_depth=1)
gb1.fit(X_train, y_train)
print("Accuracy on training set: {:.3f}".format(gb1.score(X_train, y_train)))
print("Accuracy on test set: {:.3f}".format(gb1.score(X_test, y_test)))
Accuracy on training set: 0.804
Accuracy on test set: 0.781
gb2 = GradientBoostingClassifier(random_state=0, learning_rate=0.01)
gb2.fit(X_train, y_train)
print("Accuracy on training set: {:.3f}".format(gb2.score(X_train, y_train)))
print("Accuracy on test set: {:.3f}".format(gb2.score(X_test, y_test)))
Accuracy on training set: 0.802
Accuracy on test set: 0.776

Оба метода, уменьшающие сложность модели, также снижают точность обучающей выборки, как и ожидалось. Но в этом примере ни один из этих методов не улучшил способность к обобщению на тестовом наборе.

Мы можем визуализировать веса функций, чтобы углубиться в нашу модель, хотя мы не очень довольны этим:

plot_feature_importances_diabetes(gb1)

Получается следующий рисунок:

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

Опорные векторные машины

from sklearn.svm import SVC
svc = SVC()
svc.fit(X_train, y_train)
print("Accuracy on training set: {:.2f}".format(svc.score(X_train, y_train)))
print("Accuracy on test set: {:.2f}".format(svc.score(X_test, y_test)))
Accuracy on training set: 1.00
Accuracy on test set: 0.65

Модель явно переобучена, с отличными результатами на тренировочном наборе, но с точностью всего 65% на тестовом наборе.

SVM (Машина опорных векторов) требует, чтобы все функции были нормализованы. Нам нужно изменить масштаб данных, чтобы все функции были примерно в одном измерении:

from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.fit_transform(X_test)
svc = SVC()
svc.fit(X_train_scaled, y_train)
print("Accuracy on training set: {:.2f}".format(svc.score(X_train_scaled, y_train)))
print("Accuracy on test set: {:.2f}".format(svc.score(X_test_scaled, y_test)))
Accuracy on training set: 0.77
Accuracy on test set: 0.77

Нормализация данных имеет огромное значение! Теперь это на самом деле недостаточно, тренировочные и тестовые наборы работают одинаково, но немного далеки от 100% точности. На этом этапе мы можем попробовать увеличить C или гамму, чтобы создать более сложную модель.

svc = SVC(C=1000)
svc.fit(X_train_scaled, y_train)
print("Accuracy on training set: {:.3f}".format(
    svc.score(X_train_scaled, y_train)))
print("Accuracy on test set: {:.3f}".format(svc.score(X_test_scaled, y_test)))
Accuracy on training set: 0.790
Accuracy on test set: 0.797

Здесь увеличение C оптимизирует модель, так что точность на тестовом наборе становится 79,7%.

глубокое обучение

from sklearn.neural_network import MLPClassifier
mlp = MLPClassifier(random_state=42)
mlp.fit(X_train, y_train)
print("Accuracy on training set: {:.2f}".format(mlp.score(X_train, y_train)))
print("Accuracy on test set: {:.2f}".format(mlp.score(X_test, y_test)))
Accuracy on training set: 0.71
Accuracy on test set: 0.67

Многослойные персептроны гораздо менее точны, чем другие модели, вероятно, из-за размерности данных. Алгоритмы глубокого обучения также хотят, чтобы все входные признаки были нормализованы и предпочтительно имели среднее значение 0 и дисперсию 1. Мы должны изменить масштаб данных, чтобы они соответствовали этим требованиям.

from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.fit_transform(X_test)
mlp = MLPClassifier(random_state=0)
mlp.fit(X_train_scaled, y_train)
print("Accuracy on training set: {:.3f}".format(
    mlp.score(X_train_scaled, y_train)))
print("Accuracy on test set: {:.3f}".format(mlp.score(X_test_scaled, y_test)))
Accuracy on training set: 0.823
Accuracy on test set: 0.802

Увеличим количество итераций:

mlp = MLPClassifier(max_iter=1000, random_state=0)
mlp.fit(X_train_scaled, y_train)
print("Accuracy on training set: {:.3f}".format(
    mlp.score(X_train_scaled, y_train)))
print("Accuracy on test set: {:.3f}".format(mlp.score(X_test_scaled, y_test)))
Accuracy on training set: 0.877
Accuracy on test set: 0.755

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

Увеличим параметр альфа и увеличим регулярность весов:

mlp = MLPClassifier(max_iter=1000, alpha=1, random_state=0)
mlp.fit(X_train_scaled, y_train)
print("Accuracy on training set: {:.3f}".format(
    mlp.score(X_train_scaled, y_train)))
print("Accuracy on test set: {:.3f}".format(mlp.score(X_test_scaled, y_test)))
Accuracy on training set: 0.795
Accuracy on test set: 0.792

Результаты хорошие, но мы не смогли еще больше повысить точность набора тестов.

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

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

plt.figure(figsize=(20, 5))
plt.imshow(mlp.coefs_[0], interpolation='none', cmap='viridis')
plt.yticks(range(8), diabetes_features)
plt.xlabel("Columns in weight matrix")
plt.ylabel("Input feature")
plt.colorbar()

Получается следующий рисунок:

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

Суммировать

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

Мы должны знать, как применять, настраивать и анализировать модели, которые мы тестировали выше. Теперь твоя очередь! попробовать вscikit-learnПримените любой из этих алгоритмов к встроенному набору данных или любому другому набору данных по вашему выбору. Удачного машинного обучения!

Исходный код этого блога можно найти здесь. Буду рад получить ваши отзывы и вопросы по вышеизложенному.

Ссылка на ссылку:Introduction to Machine Learning with Python


Программа перевода самородковэто сообщество, которое переводит высококачественные технические статьи из Интернета сНаггетсДелитесь статьями на английском языке на . Охват контентаAndroid,iOS,внешний интерфейс,задняя часть,блокчейн,продукт,дизайн,искусственный интеллектЕсли вы хотите видеть более качественные переводы, пожалуйста, продолжайте обращать вниманиеПрограмма перевода самородков,официальный Вейбо,Знай колонку.