Проект по науке о данных для выявления риска заболеваний у пациентов

Недавно у меня появилась прекрасная возможность сотрудничать с членами сообщества «Clique» и разработать проект по науке о данных о том, как питание и потребление пищи могут помочь нам предсказать вероятность различных заболеваний у пациентов. Этот пост в первую очередь посвящен выявлению сердечно-сосудистых заболеваний (например, ССЗ).

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

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

Оглавление

  1. Выбор набора данных
  2. Предварительная обработка и исследование данных
  3. Выбор функций и моделирование данных
  4. Результаты моделирования и интерпретация
  5. Развертывание с использованием библиотеки Streamlit
  6. Заключение и перспективы

1. Выбор набора данных

В этом проекте я решил работать с данными Национального исследования здоровья и питания (NHANES) (2013–2014 гг.), Состоящими из вопросов о демографии, социоэкономике, рационе питания и состоянии здоровья. Я собрал данные из наборов демографических, диетических, лабораторных и анкетных данных. Целевой переменной для проекта был общий холестерин (LBXTC) в lab.csv. Мой подход заключался в том, чтобы рассматривать это как проблему бинарной классификации.

Если у человека был общий холестерин ≤ 200 мг / дл, это было бы классифицировано как «хорошо», а если общий холестерин ›200 мг / дл , он будет классифицирован как «Риск».

2. Предварительная обработка и исследование данных

В этой части я начал с установки и импорта библиотек и пакетов, необходимых для построения модели. Я использовал библиотеки Sklearn, Shap, и Scipy для построения моделей и интерпретации данных. Из библиотеки sklearn для предварительной обработки и моделирования данных используется довольно много модулей, к которым вы можете обратиться здесь.

#importing libraries
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder, StandardScaler, LabelEncoder
import timeit
import pickle
from sklearn.metrics import confusion_matrix, classification_report, roc_auc_score,precision_recall_curve, roc_curve, accuracy_score
from sklearn.exceptions import NotFittedError
from sklearn.linear_model import LogisticRegression
from xgboost import XGBClassifier
import optuna
from sklearn.ensemble import RandomForestClassifier

Следующим шагом была загрузка данных в записную книжку с помощью read.csv(). После загрузки данных я нашел процент пропущенных значений для каждой переменной в файлах demographic.csv и dietary.csv в порядке возрастания. После этого я установил целевой столбец как «LBXTC» (общий холестерин) из lab.csv и выбрал некоторые важные категориальные переменные, такие как «курение», «диабет» и т. Д. Из файла quesstionare.csv.

#data pre-processing
x =df1.isna().mean().round(3)*100
x =x.sort_values() #sorted values in ascending order

Я удалил все столбцы из диетического.csv с пропущенными значениями ›70%, так как они могут привести к нежелательным результатам. Все четыре набора данных имели один общий идентификатор - SEQN, на основе которого были объединены полные данные. С помощью простой линейной интерполяции были вычислены оставшиеся пропущенные значения.

for c in features:
df[c] = df[c].interpolate(limit_direction ='both')

После этого я отделил категориальные и числовые столбцы от набора данных. Категориальные столбцы в NHANES кодируются числами. В наборе данных было 4 целочисленных значения для категориальных столбцов. Затем я изменил тип данных категориальных столбцов «Пол», «Диетический статус отзыва», «Стенокардия», «Курильщик» и «Диабет» на категорию.

categorical_values = []
for column in final_df.columns:
print(‘==============================’)
print(f”{column} : {final_df[column].unique()}”)
if len(final_df[column].unique()) <= 4:
categorical_values.append(column)
final_df[categorical_values] = final_df[categorical_values].astype('category')

После предварительной обработки данных следующим шагом было выполнение разделения данных. Он был разделен на обучающий и тестовый наборы данных с соотношением 70:30, а целевой столбец - класс. Используя конвейер sklearn, я выполнил StandardScaler с SimpleImputer для числовых столбцов и One Hot Encoding для категориальных столбцов для бинаризации категории и включил его как функцию для обучения модели. Наконец, я применил преобразования с помощью ColumnTransformer, LabelEncoder, подогнал данные с помощью fit_transform и сохранил имена функций в списке.

После разделения были определены различные служебные функции, такие как feature_importance_plot, confusion_plot, roc_plot, precision_recall_plot и т. Д. Для оценки различных классификаторов.

3. Выбор характеристик и моделирование данных

Рекурсивное исключение признаков (RFE) [1] и Прямой выбор - это два метода, которые я использовал на комбинированных диетических и демографических переменных для выбора признаков. .

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

#RecursiveForwardElimination
rfe = RFE(estimator=DecisionTreeRegressor(), n_features_to_select=30)
model = DecisionTreeRegressor()
pipeline = Pipeline(steps=[('s',rfe),('m',model)])
cv = RepeatedKFold(n_splits=10, n_repeats=3, random_state=1)
n_scores = cross_val_score(pipeline, X, y, scoring='neg_mean_absolute_error', cv=cv, n_jobs=-1, error_score='raise')
print('MAE: %.3f (%.3f)' % (mean(n_scores), std(n_scores)))
#SequentialForwardSelector
sfs1 = sfs(model, k_features=30, forward=True, verbose=2, scoring='neg_mean_squared_error')
sfs1 = sfs1.fit(X, y)
#X and y being features and target df respectively.

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

#Forward Selection
from sklearn.ensemble import RandomForestRegressor
from mlxtend.feature_selection import SequentialFeatureSelector
forward_feature_selector = SequentialFeatureSelector(RandomForestRegressor(n_jobs=-1),
 k_features=30,
 forward=True,
 verbose=2,
 scoring=’neg_root_mean_squared_error’,
 cv=4)
forward_selector = forward_feature_selector.fit(X,y)

После RFE и прямого выбора столбцы объектов из RFE, имеющих ранг ›0,5, и столбцы из прямого выбора были пересечены как один список объектов.

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

#HeatMap
colormap = plt.cm.RdYlGn
plt.figure(figsize=(30,30))
sns.heatmap(new_data.astype(float).corr(), linewidths=0.1, vmax=1.0, square=True, cmap=colormap, annot=True)

Переходя к части выбора модели, я пробовал различные модели в наборе данных, все из которых перечислены ниже:

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

Я использовал логистическую регрессию в качестве базовой модели для обучения. Оценка F1 для класса «Риск» по тестовым данным составила всего 0,16.

F1 - оценка - это способ объединения точности и отзывчивости модели, и он определяется как гармоническое среднее точности модели. и вспомним.

XGBoost

После логистической регрессии XGBoost [2] был реализован с использованием XGBClassifier с параметрами по умолчанию. Показатель F1 улучшился до 0,28 здесь.

Я выполнил настройку гиперпараметров в XGBoost, чтобы получить более оптимальный результат. Для этого использовалась Optuna, которая реализует последовательную оптимизацию на основе модели. Задача и использование модуля пробная версия были определены для настройки следующих гиперпараметров: learning_rate, num_boost_round, max_depth, min_child weight, n_estimators, scale_pos_weight, colsample_bytree и с использованием функции study () и сокращения, модель была оптимизирована. Как видно ниже, показатель F1 увеличился до 0,54.

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

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

4. Результаты моделирования и интерпретация.

Я построил кривую обучения, используя набор инструментов визуализации Yellowbrick. Оценки были от 0,5 до 0,6. Оценка (X_train, Y_train) - это измерение точности модели по сравнению с данными обучения. Модель оказалась подходящей, если учесть, что на графике есть небольшой пробел в обобщении.

Я использовал кривую ROC для визуализации. Кривые ROC используются в бинарной классификации для изучения результатов работы классификатора. Наблюдая roc_curve случайного леса, площадь под кривой (AUC) составляет 0,71 и имеет хорошую крутизну в области истинно положительных показателей (ось Y).

С помощью сводного графика SHAP была нанесена важность характеристики модели. Значения SHAP [3] основаны на значениях Шепли. Это теоретико-игровой подход к объяснению результатов модели.

#shapvalues
explainer = shap.TreeExplainer(random_forest)
shap_values = explainer.shap_values(x_train)
shap.summary_plot(shap_values, x_train, max_display=10, show=False)

По значениям shap мы можем видеть, что демографическая переменная «Пол» была основной характеристикой модели. Интересно отметить, что диета из морепродуктов внесла большой вклад в прогнозирование заболевания. Было одинаковое распределение для обоих классов («Хорошо» и «Риск»).

Общая точность модели составила 62%.

5. Развертывание с использованием Streamlit

Библиотека Streamlit оказалась отличным ресурсом для развертывания модели в виде веб-страницы. Streamlit - это платформа приложений для развертывания приложений машинного обучения, созданных с использованием Python. Я создал репозиторий GitHub и сохранил модель как файл pickle перед окончательным развертыванием.

Посетите: Прогнозная аналитика с использованием панели управления диетами

6. Заключение и перспективы на будущее

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

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

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

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

Использованная литература:

[1] https://www.scikit-yb.org/en/latest/api/model_selection/rfecv.html

[2] https://machinelearningmaster.com/xgboost-for-imbalanced-classification/

[3] https://shap.readthedocs.io/en/latest/index.html