От начала до конца на некоторых данных из открытых источников.

Как учитель, последние полгода мне приходилось полагаться на видеоконференции, но до сих пор я никогда не беспокоился о том, чтобы делиться своими личными проектами или исследованиями через видео. У меня есть плейлист на YouTube, где я расскажу вам о различных аспектах простого проекта машинного обучения. В данном случае это «Прогнозирование диабета на ранней стадии», проект классификации под контролем базовых бинарных результатов, включающий небольшое количество преимущественно категориальных признаков. В этом посте я дам вам обзор типа TL; DR, а также некоторые детали, и вы можете посмотреть мои видео или мою общедоступную записную книжку, чтобы по-настоящему вникнуть в код и идеи.

ДАННЫЕ

набор данных общедоступен здесь как часть репозитория машинного обучения UCI:

Статья озаглавлена ​​Прогнозирование вероятности диабета на ранней стадии с использованием методов интеллектуального анализа данных (Islam et al., 2019) , и вы можете найти его здесь, хотя, к сожалению, он находится за платным доступом. У меня есть это, и я поделюсь некоторыми из них, надеюсь, так, чтобы меня не волновало.

Мой Блокнот Google Colab со всем кодом находится здесь и должен быть общедоступным для чтения:

Моя серия YouTube по этому проекту, на данный момент 8 видеороликов, в которых вы познакомитесь с некоторым кодом, который вы найдете в блокноте Colab выше. Это живой плейлист, а это значит, что я мог бы добавить несколько дополнительных видео по этой теме, особенно если есть запросы или отзывы аудитории. Видео имеют метки 1–8 и также включают подтему, затронутую в видео.

РЕЗУЛЬТАТЫ ОРИГИНАЛЬНОЙ БУМАГИ. Регрессор случайного леса является лучшим и может обеспечить точность 97,4%. Они сравнивают это с деревьями решений и другими учениками. Они используют как 10-кратную перекрестную проверку, так и разделение 80/20.

НАШИ РЕЗУЛЬТАТЫ. Мы подтверждаем, что RF, вероятно, действительно лучший, но мы сравниваем его с более широким кругом учащихся, включая GBDT, такие как CatBoost, LightGBM , XGBoost, а также поддерживает векторные машины и многослойные персептроны. Мы обнаружили, что CatBoost и LightGBM являются вторым и третьим лучшим выбором. В отличие от авторов, мы используем повторяющееся стратифицированное k-кратное пересечение -проверка, чтобы получить более «уверенную» оценку успеваемости учащегося. Кроме того, мы не используем сбалансированную точность или баллы F1 для оценки классификатора. Мы используем коэффициент корреляции Мэтьюза (MCC, подробнее об этом позже). Кроме того, мы предлагаем некоторый анализ важности характеристик, которого нет в исходной статье, с использованием значений SHAP и графиков решений.

ИССЛЕДОВАТЕЛЬСКИЙ АНАЛИЗ ДАННЫХ

Авторы статьи заявляют, что у них было 520 ответов на анкету, но в 20 из них отсутствовали значения, так что в итоге они использовали 500 строк. Вы можете видеть в их результатах, показанных ниже, что у них есть разделение 400/100, когда они выполняют 80/20, и 500, когда они выполняют перекрестную проверку. Однако, когда вы загружаете набор данных из UCI, отсутствующих значений нет вообще. Кажется, есть все 520 значений. Я не уверен, объяснили ли они это где-нибудь, и, честно говоря, для наших целей, которые в основном носят образовательный характер, меня это особо не волнует. Но знайте, что результаты, которыми я делюсь с вами, относятся к 520 записям данных. Вот как выглядят данные

ПОДГОТОВКА ДАННЫХ - БИННИРОВАНИЕ

D.isna().sum() 
#You'll find no NAs even though the authors said there were!!!
#All the features, except age, are categorical. Heck, just make age categorical while we’re at it. How about 5 categories?
D["Age"] = pd.qcut(D["Age"], q = 5).astype("category").cat.codes
#qcut bins the data, 5 equal bins. Convert into category so its clear that this categorical data. 

Целью является последний столбец. Итак, как только вы разделите функции и нацелитесь на X и Y, сделайте следующее:

X1 = X.copy()
Y1 = Y.copy()
for col in catcols:
  X1[col] = X1[col].astype("category")
  X1[col] = X1[col].cat.codes
  Y1 = Y1.astype("category")
  Y1 = Y1.cat.codes
#The cat.codes part will convert the string data {"Yes","No"} or {"Male","Female"} into {0,1}. Everything is 0 and 1 and now, except for the Age category which is {1,2,3,4,5}

ЭКСПЕРИМЕНТЫ

ВЫБОР МОДЕЛИ

Первым, что я выбрал при разработке этих экспериментов, была мера ошибки: Коэффициент корреляции Мэтьюза. Почему ? Что ж, это сбалансированная мера, в отличие от точности или F1, точности или отзыва, на которые может влиять порог (например, значение логита выше 0,5 или меньше), а также (не) баланс классов, где большие классы оказывают непропорциональное влияние на показатели ошибок, тем самым заставляя их казаться лучше, чем они есть на самом деле. Конечно, варианты некоторых показателей можно сделать более сбалансированными, но для простоты я придерживаюсь одного, который, как мы знаем, предлагает сбалансированное представление о производительности. Для заинтересованного читателя есть статья, в которой утверждается, что MCC должен быть предпочтительной мерой ошибки, когда дело доходит до двоичной классификации.

Мы хотим использовать перекрестную проверку, чтобы лучше понять, насколько обобщаемы наши модели, то есть насколько хорошо они обрабатывают невидимые данные. Мы используем схему перекрестной проверки RepeatedStratifiedKFold библиотеки sklearn, чтобы помочь нам получить более реалистичное представление о том, как наши модели работают с невидимыми или очень разнообразными данными. Мы будем использовать 10 разделений данных (отчасти потому, что это сделали и авторы оригинальной статьи) и 5 ​​повторов эксперимента (потому что у меня нет терпения на 100, тем более 1000 испытаний).

rs = np.random.randint(1000) ; print("Seed", rs)
rskf = RepeatedStratifiedKFold(n_splits = 10, n_repeats = 5, random_state = rs)

Авторы статьи использовали логистическую регрессию, дерево решений J48, случайные леса и наивный байесовский классификатор. С другой стороны, для этого проекта мы используем классификатор стохастического градиентного спуска, многослойный классификатор персептронов, деревья решений, случайный лес, XGBoost, LightGBM, CatBoost, логистическую регрессию, классификатор гребней, классификатор ближайших соседей и машину опорных векторов.

Я хотел бы начать с проб, когда каждый учащийся обучается со своими значениями по умолчанию. На картинке ниже - отрывок из этого кода. Чтобы оценить эти модели, я создал серию пустых списков, по одному для каждой модели / учащегося, потому что функция cross_val_score в sklearn, которая выполняет резюме и оценку, возвращает список оценок из каждой складки - но я бы предпочел использовать среднее значение этих баллов, чтобы получить только один общий балл. Этот фрагмент кода ниже включает всего 3 учащихся (для экономии места), но вы можете увидеть весь код в моей записной книжке Colab. Посмотрим, кто сделает ставку.

rfscores = [] 
xgbscores = []
lrscores = []
reg = RandomForestClassifier(verbose = 0,random_state = rs)
reg.fit(X1,Y1)
rfscores.append(cross_val_score(reg, X1, Y1, scoring = mcc, cv = rskf))
reg = XGBClassifier(random_state = rs)
reg.fit(X1,Y1)
xgbscores.append(cross_val_score(reg, X1, Y1, scoring = mcc, cv = rskf))
reg = LogisticRegressionCV(cv = 5, refit = True, random_state = rs, max_iter = 500)
reg.fit(X1,Y1)
lrscores.append(cross_val_score(reg, X1, Y1, scoring = mcc, cv = rskf))

Теперь мы находим средние баллы по каждому списку баллов CV, а затем сравниваем:

Мы видим, даже без какой-либо настройки, что лучше всего работают древовидные алгоритмы. Случайный лес кажется на голову выше остальных, что согласуется с результатами из оригинальной статьи. Однако стоит отметить, что MLP тоже не так уж плох и может даже удивить нас, если мы потратим время на настройку гиперпараметров. Я не буду здесь утверждать, что мое тестирование было исчерпывающим, но я могу сказать с некоторой долей уверенности, что машина опорных векторов (SVM), которая обычно может быть устранена с учетом указанной выше производительности, на самом деле может оказаться в пробеге для лучшая модель - все дело в тюнинге, дружище.

НАСТРОЙКА ГИПЕРПАРАМЕТРОВ

Код, который я использовал для каждого ученика, почти идентичен; просто измените учащегося и гиперпараметры. Если вы не уверены, какие гиперпараметры настраивать, в первую очередь погуглите что-нибудь вроде наиболее важных гиперпараметров xgboost. Из всего, что вы читаете, вы получите представление о том, какие из них являются наиболее важными, и вы поймете, что другие люди использовали в качестве диапазонов значений. Подход, который я использую здесь, - это не поиск по сетке (исчерпывающее тестирование различных комбинаций значений HP, что требует много времени), и не случайный поиск (случайный выбор точек сетки в пространстве HP). Это называется байесовская оптимизация, и вот объяснение из Википедии:

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

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

Я сделал выбор в отношении того, какие гиперпараметры были выбраны для оптимизации, а также диапазоны, некоторые из которых основаны на том, что делают другие, а некоторые из них просто изучены методом проб и ошибок - на этом наборе данных. Не думайте, что значения будут такими же для других наборов данных. Иногда вам следует начать с небольшого диапазона значений по умолчанию, просто чтобы посмотреть, сможете ли вы получить постепенное улучшение. Если вас это не устраивает, я бы расширил диапазон HP, но не обязательно расширять все сразу. Если вы внезапно слишком сильно расширите пространство HP, алгоритм может потеряться, и одно «плохое яблоко» HP испортит производительность учащегося в целом.

Регрессор случайного леса

Алгоритм оптимизации для 2 HP, которые я тестировал здесь, привел к max_depth = 14 и n_estimators = 173. Затем я использовал эти значения и обновил модель для данных, найдя оба показателя MCC на основе CV.

Вы можете видеть, что у него хороший результат CV-MCC - 0,952, и он делает в общей сложности 3 ошибки при обучении на всем наборе. Я считаю, что оценка CV-MCC является лучшей оценкой мощности этой модели. Помните, что значения MCC находятся в диапазоне от -1 до 1, где 1 означает идеальную корреляцию и, следовательно, идеальный классификатор.

Машина опорных векторов

Если гиперпараметр SVM C (стоимость) и гамма (полоса пропускания) настроены правильно, оценка CV-MCC составляет 0,939, что почти так же хорошо, как у случайного леса. Обученный на всем наборе данных, он работает точно так же, как модель RF, допуская 3 ошибки. Во время других прогонов этого эксперимента я видел, что показатели SVM достигают 0,95, что очень близко к модели случайного леса. Тем не менее, есть немного больше различий в оценках SVC, чем в оценках RF, что наводит меня на мысль, что RF может быть лучше с точки зрения согласованности.

LightGBM

LightGBM - это быстрая и эффективная реализация GBDT, и результаты после настройки также выглядят достойно по сравнению с другими методами. Общий балл CV-MCC 0,937 - это совсем не плохо.

CatBoost

CatBoost - еще один быстрый и популярный алгоритм GBDT, который довольно легко обрабатывает категориальные данные (отсюда и название CATboost). Это пригодится, так как все наши возможности категоричны. Вот результаты:

Вы можете видеть, что оценка CV-MCC, равная 0,943, превосходит LightGBM и SVM, но по-прежнему занимает второе место после Random Forest. При обучении на всем наборе данных он делает 3 ошибки, как и другие лучшие ученики.

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

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

АНАЛИЗ ВАЖНОСТИ ФУНКЦИИ

ЗНАЧЕНИЯ SHAP: значения SHAP - это один из способов измерения важности функции. Суть идеи принадлежит теоретику игр Эдварду Шепли, который изучал, как коалиции влияют на исход игр. В контексте машинного обучения мы думаем о каждой функции как о игроке в игре, и определенные группы или совпадения игроков, как правило, дают определенные результаты. Подумайте о перетягивании каната - если вы равны, веревка остается посередине (среднее значение прогнозов / результатов модели); однако, если у вас есть сильный игрок с одной стороны - например, функция Полиурия или функция Пол - модель предсказывает что-то выше или ниже среднего. Конечно, это зависит от того, какой пол появится сегодня в матче по перетягиванию каната. Если в этой игре (т. Е. Единичная точка данных) она равна 1 (в отличие от 0) и объединяется с Polyuria как 1, то вы можете увидеть, что модель более решительно подтянулась к 1 или 0. Есть некоторые хорошие свойства для значений SHAP - например, аддитивность - что означает, что эффекты каждого игрока складываются в результат каждой конкретной игры. Суть всего этого в контексте современного машинного обучения состоит в том, что нам нужно больше интерпретируемых моделей машинного обучения. Мы хотим знать, какие функции действительно важны и почему. Имея это в виду, давайте взглянем на некоторые гистограммы, где мы смотрим на среднее значение SHAP каждой функции по всему набору данных. Помните, что такой игрок, как Полиурия, может иногда иметь большое влияние на модель (может быть, когда он имеет значение 1), а иногда и меньшее влияние. Но мы можем измерить общий размер воздействия, и это то, что делают следующие графики.

Важность функции / Случайный лес. Вот гистограмма важности функции для модели случайного леса:

Мы видим, что полиурия (аномально большие объемы разбавленной мочи), полидипсия (аномально сильная жажда) и пол это 3 наиболее важные особенности.

Важность функции / CatBoost

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

Важность функции / SVM

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

ФУНКЦИИ ПРИНЯТИЯ РЕШЕНИЯ

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

Видно, что настоящее «разделение» происходит по 8–10 наиболее важным, наиболее различающим признакам. Степень разделяемости данных на самом деле довольно велика, поскольку здесь не так много «пересечений» - экземпляры, которые могут начинаться снизу, кажущиеся принадлежащими одному классу, только для того, чтобы совершить огромный «скачок», когда они достигнут более важная особенность. Эти два класса действительно «раздвигаются» первыми тремя функциями, что подтверждает наше мнение о том, что они действительно важны для любой хорошей модели, независимо от лежащего в основе алгоритма.

ОСОБЕННОСТИ ВЗАИМОДЕЙСТВИЯ

В GBDT хорошо то, что они предназначены для нелинейных моделей. Теперь вы могли бы моделировать все виды нелинейных взаимодействий и эффектов, если бы вы расширили свои функции, включив, скажем, полиномиальные степени и условия взаимодействия исходных функций. Под этим я подразумеваю, что, возможно, ваша цель Y не является простой линейной функцией X, а является функцией X². Возможно, у вас есть 2 функции, такие как X1 и X2, и термин взаимодействия X1 * X2 важен. Вы можете представить себе что-то вроде Расы * Пол или Возраст * Образование как термины взаимодействия, которые имеют значение в каком-нибудь эконометрическом или социологическом исследовании. Иногда, чтобы добиться большей гауссовости ваших функций, что полезно в традиционных методах регрессии, вы можете захотеть использовать некоторую преобразованную в журнал версию X, такую ​​как log (1 + X). В этом проекте я не использовал ни Box-Cox / Yeo-Johnson, ни какие-либо полиномиальные функции в дополнение к исходному набору функций. Это не потому, что я знаю, что этот подход не работает (я его не тестировал), а ради простоты представления этого проекта. Тем не менее, методы дерева регрессии допускают взаимодействия первого порядка типа X1 * X2, и мы используем библиотеку shap для построения графика, какие взаимодействия действительно важны для модели:

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

ОШИБКИ

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

Итак, мы говорим о возрастной группе, у которой есть 0 для всех возможных характеристик, то есть они не проявляют никаких симптомов, указанных в анкете. Не нужно быть врачом, чтобы классифицировать такого человека как человека, не подверженного риску диабета, и тем не менее эти записи были классифицированы как положительные. Это вызывает такие вопросы, как «являются ли эти данные точными? Или что-то не так с этими тремя записями? " или «какие еще факторы мы могли бы добавить в качестве функций, чтобы лучше различать два класса?»

ВЫВОД

Вот что-то из оригинальной статьи:

Надеюсь, вам понравился этот небольшой тур по проекту, над которым я работал в свободное время. Мне нравится находить (управляемые) наборы данных в Интернете, будь то из UCI, Kaggle или других, а затем запускать различные модели, чтобы увидеть, какой производительности мы можем достичь и что действительно важно для модели. В этом мини-отчете мы обнаружили, что, как и авторы, модель случайного леса хорошо подходит для решения этой проблемы. Кроме того, мы включили различных учащихся GBDT, таких как CatBoost и LightGBM, и обнаружили, что они сопоставимы, как SVM с ядром радиальной базисной функции. Подобные результаты не упоминаются в исходной статье. Наконец, когда мы смотрим на значения SHAP, мы видим, что каждая модель имеет разный рейтинг важности функций, но что полиурия, полидипсия, пол, возраст и другие подобные факторы, как правило, имеют более высокий рейтинг, чем другие. Мы также видели влияние эффектов взаимодействия, особенно с полиурией.

Пожалуйста, посетите мой канал YouTube и мою записную книжку Google Colab для получения более подробной информации. Я приветствую любую критику или предложения, и, кстати, я ищу новую работу, поэтому, если вы считаете, что какие-либо из моих навыков машинного обучения или науки о данных могут быть мне полезны, не стесняйтесь связаться со мной по LinkedIn или прямо здесь, в комментариях. Скоро появятся другие проекты и учебные пособия!