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

  • Обзор
  • Описание данных
  • Исследование данных
  • Подготовка данных
  • Обучение и оценка модели машинного обучения
  • Интерпретация модели машинного обучения
  • Сохранение модели
  • Прогнозы с помощью модели
  • Следующие шаги

Обзор

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

Мы будем использовать Python и некоторые из его популярных пакетов, связанных с наукой о данных. Прежде всего, мы импортируем pandas, чтобы читать наши данные из файла CSV и манипулировать ими для дальнейшего использования. Мы также будем использовать numpy для преобразования данных в формат, подходящий для нашей модели классификации. Мы будем использовать seaborn и matplotlib для визуализации. Затем мы импортируем алгоритм логистической регрессии из sklearn. Этот алгоритм поможет нам построить нашу классификационную модель. Наконец, мы будем использовать joblib, доступный в sklearn, чтобы сохранить нашу модель для будущего использования.

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
% matplotlib inline
from sklearn.linear_model import LogisticRegression
from sklearn.externals import joblib

Описание данных

Наши данные сохранены в файле CSV с именем diabetes.csv. Сначала мы считываем наш набор данных в фрейм данных pandas с именем diabetesDF, а затем используем функцию head(), чтобы показать первые пять записей из нашего набора данных.

diabetesDF = pd.read_csv('diabetes.csv')
print(diabetesDF.head())

Следующие функции были предоставлены, чтобы помочь нам предсказать, болен ли человек диабетом или нет:

  • Беременности: количество беременных.
  • Глюкоза: концентрация глюкозы в плазме в течение 2 часов в пероральном тесте на толерантность к глюкозе.
  • Артериальное давление: диастолическое артериальное давление (мм рт. ст.).
  • Толщина кожи: толщина кожной складки трицепса (мм).
  • Инсулин: 2-часовой сывороточный инсулин (мЕд / мл).
  • ИМТ: индекс массы тела (вес в кг / (рост в м) 2)
  • DiabetesPedigreeFunction: Диабетическая родословная (функция, которая оценивает вероятность диабета на основе семейного анамнеза)
  • Возраст: Возраст (лет)
  • Результат: переменная класса (0, если не диабетик, 1, если диабет)

Давайте также убедимся, что наши данные чистые (не имеют нулевых значений и т. Д.).

diabetesDF.info() # output shown below
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 768 entries, 0 to 767
Data columns (total 9 columns):
Pregnancies                 768 non-null int64
Glucose                     768 non-null int64
BloodPressure               768 non-null int64
SkinThickness               768 non-null int64
Insulin                     768 non-null int64
BMI                         768 non-null float64
DiabetesPedigreeFunction    768 non-null float64
Age                         768 non-null int64
Outcome                     768 non-null int64
dtypes: float64(2), int64(7)
memory usage: 54.1 KB

Обратите внимание, что в данных действительно есть некоторые пропущенные значения (см. Инсулин = 0) в образцах на предыдущем рисунке. В идеале мы могли бы заменить эти 0 значения средним значением для этой функции, но пока мы это пропустим.

Исследование данных

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

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

corr = diabetesDF.corr()
print(corr)
sns.heatmap(corr, 
         xticklabels=corr.columns, 
         yticklabels=corr.columns)

На приведенной выше тепловой карте более яркие цвета указывают на большую корреляцию. Как видно из таблицы и тепловой карты, уровни глюкозы, возраст, ИМТ и количество беременностей имеют значительную корреляцию с переменной результата. Также обратите внимание на корреляцию между парами признаков, такими как возраст и беременность или инсулин и толщина кожи.

Давайте также посмотрим, сколько людей в наборе данных страдают диабетом, а сколько нет. Ниже приведен график того же:

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

Кстати - вкратце - это руководство взято из Курса Data Science на Commonlounge. Курс включает в себя множество практических заданий и проектов. Кроме того, 80% содержания курса доступно бесплатно! Если вы заинтересованы в изучении науки о данных, определенно рекомендую это проверить.

Подготовка набора данных (разделение и нормализация)

При использовании алгоритмов машинного обучения мы всегда должны разделять наши данные на обучающий набор и набор тестов. (Если количество экспериментов, которые мы проводим, велико, тогда мы можем разделить наши данные на 3 части, а именно - обучающий набор, набор для разработки и набор тестов). В нашем случае мы также выделим некоторые данные для ручной перекрестной проверки.

Набор данных состоит из записи всего 767 пациентов. Для обучения нашей модели мы будем использовать 650 записей. Мы будем использовать 100 записей для тестирования и последние 17 записей для перекрестной проверки нашей модели.

dfTrain = diabetesDF[:650]
dfTest = diabetesDF[650:750]
dfCheck = diabetesDF[750:]

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

trainLabel = np.asarray(dfTrain['Outcome'])
trainData = np.asarray(dfTrain.drop('Outcome',1))
testLabel = np.asarray(dfTest['Outcome'])
testData = np.asarray(dfTest.drop('Outcome',1))

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

means = np.mean(trainData, axis=0)
stds = np.std(trainData, axis=0)
trainData = (trainData - means)/stds
testData = (testData - means)/stds
# np.mean(trainData, axis=0) => check that new means equal 0
# np.std(trainData, axis=0) => check that new stds equal 1

Модель обучения и оценки машинного обучения

Теперь мы можем обучить нашу модель классификации. Мы будем использовать простую модель машинного обучения под названием логистическая регрессия. Поскольку модель легко доступна в sklearn, процесс обучения довольно прост, и мы можем сделать это в нескольких строках кода. Сначала мы создаем экземпляр с именем diaCheck, а затем используем функцию соответствия для обучения модели.

diabetesCheck = LogisticRegression()
diabetesCheck.fit(trainData, trainLabel)

Далее мы будем использовать наши тестовые данные, чтобы выяснить точность модели.

accuracy = diabetesCheck.score(testData, testLabel)
print("accuracy = ", accuracy * 100, "%")

Оператор печати напечатает accuracy = 78.0 %.

Интерпретация модели машинного обучения

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

coeff = list(diabetesCheck.coef_[0])
labels = list(trainData.columns)
features = pd.DataFrame()
features['Features'] = labels
features['importance'] = coeff
features.sort_values(by=['importance'], ascending=True, inplace=True)
features['positive'] = features['importance'] > 0
features.set_index('Features', inplace=True)
features.importance.plot(kind='barh', figsize=(11, 6),color = features.positive.map({True: 'blue', False: 'red'}))
plt.xlabel('Importance')

Из приведенного выше рисунка можно сделать следующие выводы.

  1. Уровень глюкозы, ИМТ, беременность и родословная диабета имеют значительное влияние на модель, особенно на уровень глюкозы и ИМТ. Приятно видеть, что наша модель машинного обучения соответствует тому, что мы слышим от врачей всю свою жизнь!
  2. Артериальное давление оказывает негативное влияние на прогноз, т.е. более высокое артериальное давление коррелирует с человеком, не страдающим диабетом. (также обратите внимание, что артериальное давление является более важным параметром, чем возраст, потому что величина выше для артериального давления).
  3. Хотя возраст больше коррелировал, чем ИМТ, с выходными переменными (как мы видели во время исследования данных), модель больше полагается на ИМТ. Это может происходить по нескольким причинам, включая тот факт, что корреляция, фиксируемая по возрасту, также фиксируется некоторыми другими переменными, тогда как информация, фиксируемая ИМТ, не фиксируется другими переменными.

Обратите внимание, что эта интерпретация требует, чтобы наши входные данные были нормализованы. Без этого мы не можем утверждать, что важность пропорциональна весам.

Сохранение модели

Теперь мы сохраним нашу обученную модель для будущего использования с помощью joblib.

joblib.dump([diabetesCheck, means, stds], 'diabeteseModel.pkl')

Чтобы проверить, правильно ли мы сохранили модель или нет, мы будем использовать наши тестовые данные для проверки точности нашей сохраненной модели (мы не должны наблюдать никаких изменений в точности, если мы сохранили ее правильно).

diabetesLoadedModel, means, stds = joblib.load('diabeteseModel.pkl')
accuracyModel = diabetesLoadedModel.score(testData, testLabel)
print("accuracy = ",accuracyModel * 100,"%")

Прогнозы с помощью модели

Теперь мы будем использовать наши неиспользованные данные, чтобы увидеть, как можно делать прогнозы. У нас есть неиспользованные данные в dfCheck.

print(dfCheck.head())

Теперь мы будем использовать первую запись, чтобы сделать наш прогноз.

sampleData = dfCheck[:1]
# prepare sample
sampleDataFeatures = np.asarray(sampleData.drop('Outcome',1))
sampleDataFeatures = (sampleDataFeatures - means)/stds
# predict
predictionProbability = diabetesLoadedModel.predict_proba(sampleDataFeatures)
prediction = diabetesLoadedModel.predict(sampleDataFeatures)
print('Probability:', predictionProbability)
print('prediction:', prediction)

Из приведенного выше кода мы получаем:

Probability: [[ 0.4385153,  0.5614847]]
prediction: [1]

Первый элемент массива predictionProbability 0,438 - это вероятность того, что класс будет 0, а второй элемент 0,561 - это вероятность того, что класс будет 1. Сумма вероятностей равна 1. Поскольку мы видим, что 1 является более вероятным классом, мы получаем [1] в качестве нашего прогноза, что означает, что модель предсказывает, что человек болеет диабетом.

Следующие шаги

Есть много способов улучшить указанную выше модель. Вот несколько идей.

  1. Группирование входных функций должно помочь, т. Е. Создавать новые переменные для артериального давления в определенном диапазоне, уровней глюкозы в определенном диапазоне и т. Д.
  2. Вы также можете улучшить очистку данных, заменив 0 значений средним значением.
  3. Прочтите немного о том, на какие показатели врачи больше всего полагаются при диагностике пациента с диабетом, и соответственно создайте новые функции.

Посмотрите, сможете ли вы достичь точности 85–90%. Для этого урока вы можете начать работу с записной книжкой jupyter: pima_indians.ipynb.

Соавторы Кешав Дхандхания и Бишал Лакха.

Первоначально опубликовано как учебное пособие на сайте www.commonlounge.com в рамках Курса Data Science.