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

Поэтому он пошел к специалисту на обследование. Врач посадил его на велотренажер, подключил к аппарату ЭКГ и сказал, чтобы он начал крутить педали.

Папа позже сказал мне, что едва начал, как доктор крикнул: «Стой! останавливаться!" и сразу вызвали скорую. Он был всего в нескольких днях от сердечного приступа!

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

Но вот вопрос: можем ли мы научить машину делать то же самое?

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

Итак, в этой статье я собираюсь создать приложение C # с ML.NET и NET Core, которое считывает медицинские данные и предсказывает, есть ли у пациента риск сердечных заболеваний. Я покажу вам, как мы можем подражать навыкам доктора моего отца с помощью всего 200 строк кода.

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

А NET Core - это многоплатформенная NET Framework Microsoft, работающая в Windows, OS / X и Linux. Это будущее кроссплатформенной разработки NET.

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

Файл данных тренировки выглядит так:

Это CSV-файл с 14 столбцами информации:

  • Возраст
  • Пол: 1 = мужской, 0 = женский
  • Тип боли в груди: 1 = типичная стенокардия, 2 = атипичная стенокардия, 3 = неангинальная боль, 4 = бессимптомная
  • Артериальное давление в состоянии покоя в мм рт. Ст. При поступлении в больницу
  • Холестерин сыворотки в мг / дл
  • Уровень сахара в крови натощак ›120 мг / дл: 1 = верно; 0 = ложь
  • Результаты ЭКГ в состоянии покоя: 0 = нормальные, 1 = наличие отклонения ST-T, 2 = наличие вероятной или определенной гипертрофии левого желудочка по критериям Эстеса.
  • Достигнута максимальная частота пульса
  • Стенокардия, вызванная физической нагрузкой: 1 = да; 0 = нет
  • Депрессия ST, вызванная упражнениями по сравнению с отдыхом
  • Наклон сегмента ST при пиковой нагрузке: 1 = восходящий, 2 = пологий, 3 = нисходящий
  • Количество крупных сосудов (0–3), окрашенных при рентгеноскопии
  • Результаты сканирования сердца таллием: 3 = нормальный, 6 = фиксированный дефект, 7 = обратимый дефект
  • Диагностика болезни сердца: 0 = сужение диаметра менее 50%, 1 = сужение диаметра более 50%

Первые 13 столбцов представляют собой диагностическую информацию о пациенте, а последний столбец - это диагноз: 0 означает здорового пациента, а 1 означает повышенный риск сердечных заболеваний.

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

Давайте начнем. Вот как настроить новый консольный проект в NET Core:

$ dotnet new console -o Heart
$ cd Heart

Затем мне нужно установить базовый пакет ML.NET:

$ dotnet add package Microsoft.ML

Теперь я готов добавить несколько классов. Один мне понадобится для хранения информации о пациенте, а другой - для хранения прогнозов моей модели.

Я изменю файл Program.cs следующим образом:

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

Я также объявляю класс HeartPrediction, который будет содержать одно предсказание сердечного заболевания.

Теперь я загружу данные тренировки в память:

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

Теперь я готов приступить к построению модели машинного обучения:

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

Мой конвейер состоит из следующих компонентов:

  • Concatenate, который объединяет все столбцы входных данных в один столбец с именем Features. Это обязательный шаг, потому что ML.NET может обучать только один входной столбец.
  • Инструмент классификации FastTree, который обучит модель делать точные прогнозы.

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

Когда конвейер полностью собран, я могу обучить модель с помощью вызова Fit (…).

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

Этот код вызывает Transform (…), чтобы установить диагноз для каждого пациента в наборе, и Evaluate (…), чтобы сравнить эти прогнозы с истинными данными и автоматически вычислить все показатели оценки для меня:

  • Точность: это количество правильных прогнозов, деленное на общее количество прогнозов.
  • AUC: показатель, который показывает, насколько точна модель: 0 = модель всегда неверна, 0,5 = модель производит случайный результат, 1 = модель всегда верна. AUC 0,8 или выше считается хорошим.
  • AUCPRC: альтернативный показатель AUC, который лучше работает для сильно несбалансированных наборов данных с гораздо большим количеством отрицательных результатов, чем положительных.
  • F1Score: это показатель, обеспечивающий баланс между точностью и отзывчивостью. Это полезно для несбалансированных наборов данных с гораздо большим количеством отрицательных результатов, чем положительных.
  • LogLoss: это показатель, который выражает размер ошибки в прогнозах, которые делает модель. Нулевое значение logloss означает, что все прогнозы верны, а величина потерь растет по мере того, как модель делает все больше и больше ошибок.
  • LogLossReduction: этот показатель также называется сокращением получения информации (RIG). Он выражает вероятность того, что прогнозы модели лучше случайного.
  • PositivePrecision: также называется «Точность». Это доля верных положительных прогнозов. Это хороший показатель для использования, когда цена ложноположительного прогноза высока.
  • PositiveRecall: также называется «Отзыв». Это доля положительных прогнозов от всех положительных случаев. Это хороший показатель для использования, когда ложноотрицательные результаты высоки.
  • NegativePrecision: доля верных отрицательных прогнозов.
  • NegativeRecall: доля отрицательных прогнозов от всех отрицательных случаев.

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

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

Набор данных имеет хорошо сбалансированное распределение положительных и отрицательных меток, поэтому нет необходимости использовать показатели AUCPRC или F1Score.

В нашем случае я сосредоточусь на Recall и AUC, чтобы оценить эту модель.

В заключение я собираюсь создать новую карту пациента и попросить модель сделать прогноз:

Я использую метод CreatePredictionEngine для настройки механизма прогнозирования. Два аргумента типа - это класс входных данных и класс для хранения прогноза. И как только мой механизм прогнозирования настроен, я могу просто вызвать Predict (…), чтобы сделать один прогноз.

Я составил историю болезни 36-летнего мужчины с бессимптомной болью в груди и кучу другой медицинской информации. Что будет предсказывать модель?

Вот код, запущенный в отладчике Visual Studio Code на моем Mac:

… И в оболочке zsh:

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

Сделка сделана, да?

Не так быстро. Отзыв составляет 0,86, что означает, что из всех положительных случаев моя модель предсказала только 86% правильных. Остальные 14% - пациенты с высоким риском сердечных заболеваний, которым сказали, что все в порядке и они могут идти домой.

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

У меня AUC составляет 96,43%, что является очень хорошим результатом. Это означает, что эта модель обладает отличной предсказательной способностью.

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

Похоже, мы его вовремя поймали!

Так что ты думаешь?

Готовы ли вы начать писать приложения для машинного обучения C # с помощью ML.NET?

Эта статья основана на домашнем задании из моего курса машинного обучения: Машинное обучение с C # и ML.NET .