На этом шаге мы закончим изучение этого вопроса.
Мы продемонстрировали пример использования логистической регрессии в сфере здравоохранения (корреляция потребления сигарет с вероятностью рака). Подобное приложение - "виртуальный доктор" - прекрасная идея для мобильного приложения, правда? Создадим ваше первое приложение - "виртуальный доктор" на основе логистической регрессии, как показано в примере 4.2, с помощью одной строки кода Python!
from sklearn.linear_model import LogisticRegression import numpy as np ## Данные (#сигареты, рак) n = 4 X = np.array([[0, "No"], [10, "No"], [60, "Yes"], [90, "Yes"]]) ## Однострочник model = LogisticRegression().fit(X[:, 0].reshape(n, 1), X[:, 1]) ## Результат print(model.predict([[2], [12], [13], [40], [90]]))
Попробуйте догадаться, каковы будут результаты выполнения этого фрагмента кода.
Обучающие данные X состоят из четырех медицинских карт (строк), включающих два столбца. В первом столбце содержится количество выкуриваемых пациентами сигарет (входной признак), а во втором - метки классов (class labels), отражающие, был ли у них в итоге диагностирован рак легких.
Мы создали модель с помощью вызова конструктора LogisticRegression(), а затем вызвали для этой модели функцию fit(); она принимает два аргумента - входной сигнал (количество выкуриваемых сигарет) и выходные метки классов (рак). Функция fit() ожидает на входе двумерный массив данных, по одной строке на каждый обучающий пример данных и по одному столбцу для каждого признака этого обучающего примера данных. В данном случае у нас только одно значение признака, так что мы преобразуем одномерный входной сигнал в двумерный массив NumPy с помощью операции reshape(). Первый аргумент функции reshape() задает количество строк, а второй - количество столбцов. Нам важно только количество столбцов, равное 1. В качестве желаемого количества строк мы передаем -1, указывая тем самым NumPy определить количество строк автоматически.
Входные обучающие данные после изменения формы будут выглядеть следующим образом (фактически мы просто удалили метки классов, сохранив форму двумерного массива неизменной):
[[0], [10], [60], [90]]
Далее мы предсказываем, есть ли у пациента рак легких по выкуриваемому количеству сигарет: входные данные включают значения 2, 12, 13, 40 и 90 сигарет. На выходе получаем следующее:
# ['No' 'No' 'No' 'Yes' 'Yes']
Модель предсказывает, что первые три пациента - онконегативны, а последние два - онкопозитивны.
Посмотрим подробнее на возвращаемые сигма-функцией вероятности, которые привели к такому предсказанию! Просто выполните следующий фрагмент кода после примера 4.2:
for i in range(50): print("x=" + str(i) + " --> " + str(model.predict_proba([[i]])))
Функция predict_proba() принимает на входе количество сигарет и возвращает массив с вероятностями онконегативности (индекс 0) и вероятностями онкопозитивности (индекс 1). При выполнении этого кода вы, вероятно, получите следующее:
x=0 --> [[9.99568507e-01 4.31492826e-04]] x=1 --> [[9.99462453e-01 5.37546844e-04]] x=2 --> [[9.99330350e-01 6.69649778e-04]] x=3 --> [[9.99165810e-01 8.34190106e-04]] x=4 --> [[0.99896088 0.00103912]] x=5 --> [[0.99870568 0.00129432]] x=6 --> [[0.9983879 0.0016121]] x=7 --> [[0.99799225 0.00200775]] x=8 --> [[0.99749974 0.00250026]] x=9 --> [[0.99688681 0.00311319]] x=10 --> [[0.99612419 0.00387581]] x=11 --> [[0.99517566 0.00482434]] x=12 --> [[0.9939964 0.0060036]] x=13 --> [[0.99253105 0.00746895]] x=14 --> [[0.99071137 0.00928863]] x=15 --> [[0.98845352 0.01154648]] x=16 --> [[0.98565479 0.01434521]] x=17 --> [[0.9821899 0.0178101]] x=18 --> [[0.97790687 0.02209313]] x=19 --> [[0.97262256 0.02737744]] x=20 --> [[0.96611811 0.03388189]] x=21 --> [[0.95813483 0.04186517]] x=22 --> [[0.94837105 0.05162895]] x=23 --> [[0.93648112 0.06351888]] x=24 --> [[0.92207796 0.07792204]] x=25 --> [[0.90474105 0.09525895]] x=26 --> [[0.88403197 0.11596803]] x=27 --> [[0.85951983 0.14048017]] x=28 --> [[0.83081811 0.16918189]] x=29 --> [[0.79763294 0.20236706]] x=30 --> [[0.75982023 0.24017977]] x=31 --> [[0.717445 0.282555]] x=32 --> [[0.67083232 0.32916768]] x=33 --> [[0.62059649 0.37940351]] x=34 --> [[0.5676353 0.4323647]] x=35 --> [[0.51308165 0.48691835]] x=36 --> [[0.45821454 0.54178546]] x=37 --> [[0.40434246 0.59565754]] x=38 --> [[0.35268109 0.64731891]] x=39 --> [[0.30424888 0.69575112]] x=40 --> [[0.25979831 0.74020169]] x=41 --> [[0.2197904 0.7802096]] x=42 --> [[0.18440863 0.81559137]] x=43 --> [[0.15360127 0.84639873]] x=44 --> [[0.1271383 0.8728617]] x=45 --> [[0.10467066 0.89532934]] x=46 --> [[0.08578325 0.91421675]] x=47 --> [[0.0700374 0.9299626]] x=48 --> [[0.05700155 0.94299845]] x=49 --> [[0.0462713 0.9537287]]
Если вероятность онконегативности выше вероятности онкопозитивности, то будет возвращено предсказание онконегативный. Последний раз такое встречается при x=35. Если пациент выкуривает более 35 сигарет, то алгоритм классифицирует его как онкопозитивного.
Резюмируя: вы научились легко решать задачи классификации с помощью логистической регрессии с использованием библиотеки scikit-learn. Основная идея логистической регрессии заключается в подгонке к данным S-образной кривой (сигма-функции). Эта функция ставит каждой точке данных и каждому возможному классу в соответствие числовое значение от 0 до 1, которое моделирует вероятность принадлежности этой точки данных заданному классу. Однако на практике часто попадаются обучающие данные без меток классов. Например, у вас могут быть данные о покупателях (допустим, их возраст и уровень дохода), но никаких меток классов для точек данных. Чтобы извлечь полезную информацию из подобных данных, понадобится еще одна разновидность машинного обучения: машинное обучение без учителя. А точнее, мы научимся искать кластеры схожих точек данных - это важное подмножество машинного обучения без учителя.
На следующем шаге мы рассмотрим кластеризацию методом k-средних в одной строке кода.