однострочники пайтон. Однострочники Python лаконичный и содержательный код by Кристи. Однострочники
Скачать 4.44 Mb.
|
124 Глава 4. Машинное обучение Рис. 4.3. Три модели (прямые) линейной регрессии, соответствующие различным параметрам (коэффициентам) модели. Каждая из этих прямых отражает взаимосвязь между входной и выходной величинами Пусть в нашем примере с курсами акций обучающие данные представляют собой индексы для трех дней, [0, 1, 2] , соответствующие курсам акций [155, 156, 157] . Другими словами: входной сигнал x = 0 должен приводить к выходному сигналу y = 155 ; входной сигнал x = 1 должен приводить к выходному сигналу y = 156 ; входной сигнал x = 2 должен приводить к выходному сигналу y = 157 Какая же прямая хорошо соответствует нашим обучающим данным? Я ото- бразил обучающие данные на рис. 4.4. Чтобы найти прямую, лучше всего описывающую наши данные, а значит, лучшую и для создания модели линейной регрессии, необходимо определить коэффициенты. Именно для этого и служит машинное обучение. Существует два основных способа определения параметров модели для линейной регрес- сии. Во-первых, можно аналитически вычислить лучше всего подходящую прямую между этими точками (стандартный подход для линейной регрессии). Линейная регрессия 125 Рис. 4.4. Наши обучающие данные с индексом в массиве в качестве координаты x и ценой в качестве координаты y Во-вторых, можно пробовать различные модели, проверяя каждую на мар- кированной выборке данных, и в конце концов найти лучшую. В любом случае «лучшая» модель выбирается путем минимизации погрешности (error minimization), при которой модель минимизирует квадрат разности (выбирает минимизирующие ее коэффициенты) предсказанных моделью значений и идеального выходного сигнала, выбирая модель с самой низкой погрешностью. Для наших данных в итоге получаются коэффициенты a 0 = 155.0 и a 1 = 1.0. Подставляем их в нашу формулу линейной регрессии: y = f(x) = a 0 + a 1 x = 155.0 + 1.0 × x и строим на одном графике прямую и добавляем обучающие данные, как показано на рис. 4.5. Идеально! Квадрат расстояния между прямой (прогнозом модели) и обуча- ющими данными равен нулю — мы нашли модель, которая минимизирует погрешность. С помощью этой модели теперь можно предсказывать курсы 126 Глава 4. Машинное обучение акций для любых значений x. Например, пусть мы хотим предсказать курс акций в день x = 4. Для этого мы просто можем воспользоваться моделью и вычислить f(x) = 155.0 + 1.0 × 4 = 159.0. Итак, предсказанный курс акций на четвертый день равен 159 долларам. Конечно, совсем другое дело, на- сколько хорошо это предсказание отражает реальность. Рис. 4.5. Прямая предсказания на основе нашей модели линейной регрессии Такова общая картина происходящего. Теперь посмотрим на то, как выглядит соответствующий код. Код В листинге 4.1 показано, как создать простую модель линейной регрессии с помощью одной строки кода (возможно, вам нужно будет сначала уста- новить библиотеку scikit-learn путем выполнения в командной оболочке команды pip install sklearn ). Листинг 4.1. Простая модель линейной регрессии from sklearn.linear_model import LinearRegression import numpy as np Линейная регрессия 127 ## Данные (курс акций Apple) apple = np.array([155, 156, 157]) n = len(apple) ## Однострочник model = LinearRegression().fit(np.arange(n).reshape((n,1)), apple) ## Результат print(model.predict([[3],[4]])) Можете ли вы уже угадать, какие результаты вернет этот фрагмент кода? Принцип работы В этом однострочнике используется две библиотеки Python: NumPy и scikit- learn. Первая из них — фактически стандартная библиотека для численных вычислений (например, операций с матрицами). Вторая — самая обширная библиотека для машинного обучения, включающая реализации сотен алго- ритмов и методик машинного обучения. Возможно, вы спросите: «Почему вы используете библиотеки в одно- строчнике Python? Не жульничество ли это?» Хороший вопрос, ответ на который — да. Любая программа на языке Python — с библиотеками или без — использует высокоуровневую функциональность, в основе которой лежат низкоуровневые операции. Нет смысла изобретать колесо, когда можно повторно задействовать уже существующую базу кода (то есть встать на плечи гигантов). Начинающие разработчики часто стремятся ре- ализовать все самостоятельно, что снижает их производительность. В этой книге мы хотели бы не игнорировать широкий спектр функциональности, реализованной лучшими разработчиками и первопроходцами Python, а ис- пользовать во всей полноте. Разработка, оптимизация и шлифовка каждой из этих библиотек заняла у высококвалифицированных разработчиков многие годы. Рассмотрим листинг 4.1 шаг за шагом. Во-первых, мы создали простой набор данных из трех значений и сохранили его длину в отдельной переменной n ради сокращения кода. Наши данные состоят из трех курсов акций Apple за три последовательных дня. Этот набор данных хранится в переменной apple в виде одномерного массива NumPy. Во-вторых, мы создали модель с помощью вызова LinearRegression() . Но ка- кие значения параметров будут у этой модели? Чтобы их найти, мы обучаем 128 Глава 4. Машинное обучение модель с помощью вызова функции fit() . Она принимает два аргумента: входные признаки обучающих данных и желаемые выходные сигналы для этих входных сигналов. Роль желаемых выходных сигналов играют насто- ящие курсы акций Apple. Входные же признаки необходимо передать fit() в виде массива в следующем формате: [<обучающие_данные_1>, <обучающие_данные_2>, --сокращено-- <обучающие_данные_n>] где каждое значение обучающих данных представляет собой последователь- ность значений признаков: <обучающие_данные> = [признак_1, признак_2, ..., признак_k] В нашем случае входной сигнал состоит лишь из одного признака x (текущий день). Более того, предсказание также состоит лишь из одного значения y (текущий курс акций). Чтобы изменить форму входного массива на нуж- ную, необходимо привести его к виду следующей матрицы, выглядящей странновато: [[0], [1], [2]] Матрица из одного столбца называется вектором-столбцом. Для созда- ния последовательности возрастающих значений x мы применим метод np.arange() , а затем воспользуемся reshape((n, 1)) для преобразования одномерного массива NumPy в двумерный, содержащий один столбец и n строк (см. главу 3). Обратите внимание, что scikit-learn допускает одно- мерный массив в качестве выходного сигнала (иначе нам бы пришлось из- менить и форму массива данных apple ). Получив обучающие данные и желаемые выходные сигналы, функция fit() производит минимизацию погрешности: находит такие параметры модели (то есть прямую), что разность между предсказанными моделью значениями и желаемыми выходными сигналами минимальна. Когда функция fit() сочтет, что модель доведена до ума, она возвращает модель, пригодную для предсказания двух новых значений курсов акций Линейная регрессия 129 с помощью функции predict() . Требования к входным данным у функции predict() те же, что и у fit() , поэтому для их удовлетворения мы передаем матрицу из одного столбца с нашими двумя новыми значениями, для кото- рых требуются предсказания: print(model.predict([[3],[4]])) А поскольку минимизированная погрешность равна нулю, то должны получиться идеально линейные результаты: 158 и 159, которые прекрасно соответствуют прямой, построенной выше на рис. 4.5. Но зачастую найти столь прекрасно подходящую линейную модель не получается. Например, если запустить ту же функцию для курсов акций [157, 156, 159] и по- строить соответствующий график, то получится прямая, изображенная на рис. 4.6. Рис. 4.6. Неидеально подогнанная модель линейной регрессии В этом случае функция fit() находит прямую, минимизирующую квадрат погрешности между обучающими данными и предсказаниями, как и упо- миналось ранее. 130 Глава 4. Машинное обучение Резюмируем: линейная регрессия — методика машинного обучения, при которой модель усваивает коэффициенты как параметры модели. Получен- ная в итоге линейная модель (например, прямая в двумерном пространстве) может непосредственно выполнять предсказания на основе новых входных данных. Задача предсказания числовых значений по заданным числовым входным значениям относится к классу задач регрессии. Из следующего раздела вы узнаете еще об одной важной сфере машинного обучения — классификации. Логистическая регрессия в одной строке Логистическая регрессия часто применяется для задач классификации, в которых предсказывается, относится ли конкретный пример данных к конкретной категории (классу). Эта постановка отличается от задач ре- грессии, в которых по заданному примеру данных необходимо предсказать числовое значение, относящееся к непрерывному диапазону. Пример задачи классификации: разбиение пользователей Twitter на мужчин и женщин по заданным различным входным признакам, например частоте отправки ими твитов или количеству ответов на твиты. Модель логистической регрессии относится к наиболее основополагающим моделям машинного обучения. Многие из понятий, с которыми вы познакомитесь в этом разделе, станут основой для более продвинутых методик машинного обучения. Общее описание Чтобы познакомиться с логистической регрессией, кратко рассмотрим, как работает линейная регрессия: по входным данным вычисляется прямая, лучше всего подходящая для этих обучающих данных, и предсказывается выходной сигнал для входного сигнала x. В целом линейная регрессия прекрасно подходит для предсказания непрерывного выходного сигнала, величина которого может принимать бесконечное количество значений. Предсказанные ранее курсы акций, например, могут теоретически принимать любые положительные значения. Но что, если выходной сигнал не непрерывный, а категориальный, то есть принадлежит к ограниченному количеству групп или категорий? Например, пусть мы хотим предсказать правдоподобие рака легких, исходя из коли- чества выкуренных пациентом сигарет. У каждого пациента либо есть рак Логистическая регрессия в одной строке 131 легких, либо нет. В отличие от курсов акций, возможных исходов только два. Предсказание правдоподобия категориальных исходов — основная причина использования логистической регрессии. Сигма-функция Если линейная регрессия подгоняет к обучающим данным прямую, то логи- стическая регрессия подгоняет к ним S-образную кривую — так называемую сигма-функцию (the sigmoid function). S-образная кривая упрощает выбор из двух альтернатив (например, да/нет). Для большинства входных сигналов сигма-функция возвращает значение, очень близкое либо к 0 (одна катего- рия), либо к 1 (другая категория). Неоднозначный результат относительно маловероятен. Отметим, что для конкретных входных значений могут быть сгенерированы и равные 0.5 вероятности, но форма кривой специально вы- брана таким образом, чтобы минимизировать возможность этого на практике (для большинства значений горизонтальной оси координат величина веро- ятности очень близка либо к нулю, либо к единице). На рис. 4.7 приведена кривая логистической регрессии для прогноза рака легких. Рис. 4.7. Кривая логистической регрессии для предсказания рака по количеству выкуриваемых сигарет 132 Глава 4. Машинное обучение ПРИМЕЧАНИЕ Логистическую регрессию можно применять и для полиномиальной клас- сификации (multinomial classification), при которой данные классифици- руются более чем по двум классам. Для этого используется обобщение сигма-функции — так называемая многомерная логистическая функция (softmax function), возвращающая кортеж вероятностей, по одной для каж- дого класса. Сигма-функция же преобразует входной (-ые) признак (-и) в одно значение вероятности. Впрочем, ради простоты и удобочитаемости здесь я сосредоточу свое внимание на биномиальной классификации (binomial classification). Сигма-функция на рис. 4.7 аппроксимирует вероятность наличия у паци- ента рака легких в зависимости от количества выкуриваемых им сигарет. Исходя из этой вероятности, можно четко определить при наличии одной только информации о количестве выкуриваемых пациентом сигарет, есть ли у пациента рак легких. Рис. 4.8. Оценка вероятностей исходов с помощью логистической регрессии Логистическая регрессия в одной строке 133 Взгляните на предсказание на рис. 4.8, на котором представлены два новых пациента (изображены светло-серым цветом внизу графика). Нам ничего о них не известно, кроме количества выкуриваемых ими сигарет. Мы обу- чаем модель логистической регрессии (сигма-функцию), возвращающую вероятность для любого нового входного значения x. Если возвращающая сигма-функцией вероятность выше 50 %, то модель выдает предсказание онкопозитивный, в противном случае — онконегативный. Поиск модели максимального правдоподобия Основной вопрос метода логистической регрессии — как выбрать пра- вильную сигма-функцию, лучше всего соответствующую обучающим дан- ным. Для ответа на него используется такое понятие, как правдоподобие (likelihood) модели: возвращаемая моделью вероятность для наблюдаемых обучающих данных. Желательно выбрать модель с максимальным прав- доподобием. Идея в том, чтобы эта модель лучше всего аппроксимировала реальный процесс, в результате которого были сгенерированы обучающие данные. Рис. 4.9. Поиск максимального правдоподобия путем проверки различных сигма-функций 134 Глава 4. Машинное обучение В целях вычисления правдоподобия заданной модели для заданного на- бора обучающих данных вычисляется правдоподобие для каждой из об- учающих точек данных, и в результате их перемножения получается общее правдоподобие для всего набора обучающих данных. Как же вычислить правдоподобие отдельной обучающей точки данных? Достаточно просто применить к ней сигма-функцию модели, чтобы получить вероятность для указанной точки данных при использовании этой модели. Чтобы выбрать модель максимального правдоподобия для всех точек данных, необходимо повторить это вычисление правдоподобия для различных сигма-функций (выбираемых с небольшим сдвигом), как показано на рис. 4.9. В предыдущем абзаце я описал, как определить сигма-функцию (модель) максимального правдоподобия, которая лучше всего описывает данные, по- этому можно ее использовать для предсказания новых точек данных. С теоретической частью покончено. Теперь посмотрим, как можно реализо- вать логистическую регрессию в виде однострочника Python. Код Мы продемонстрировали пример использования логистической регрессии в сфере здравоохранения (корреляция потребления сигарет с вероятностью рака). Подобное приложение — «виртуальный доктор» — прекрасная идея для мобильного приложения, правда? Создадим ваше первое приложение — «виртуальный доктор» на основе логистической регрессии, как показано в листинге 4.2, с помощью одной строки кода Python! Листинг 4.2. Модель логистической регрессии 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]])) Логистическая регрессия в одной строке 135 Попробуйте догадаться, каковы будут результаты выполнения этого фраг- мента кода. Принцип работы Обучающие данные 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'] Модель предсказывает, что первые три пациента — онконегативны, а по- следние два — онкопозитивны. 136 Глава 4. Машинное обучение Посмотрим подробнее на возвращаемые сигма-функцией вероятности, которые привели к такому предсказанию! Просто выполните следующий фрагмент кода после листинга 4.2: for i in range(20): print("x=" + str(i) + " --> " + str(model.predict_proba([[i]]))) Функция predict_proba() принимает на входе количество сигарет и возвра- щает массив с вероятностями онконегативности (индекс 0) и вероятностями онкопозитивности (индекс 1). При выполнении этого кода вы, вероятно, получите следующее: x=0 --> [[0.67240789 0.32759211]] x=1 --> [[0.65961501 0.34038499]] x=2 --> [[0.64658514 0.35341486]] x=3 --> [[0.63333374 0.36666626]] x=4 --> [[0.61987758 0.38012242]] x=5 --> [[0.60623463 0.39376537]] x=6 --> [[0.59242397 0.40757603]] x=7 --> [[0.57846573 0.42153427]] x=8 --> [[0.56438097 0.43561903]] x=9 --> [[0.55019154 0.44980846]] x=10 --> [[0.53591997 0.46408003]] x=11 --> [[0.52158933 0.47841067]] x=12 --> [[0.50722306 0.49277694]] x=13 --> [[0.49284485 0.50715515]] x=14 --> [[0.47847846 0.52152154]] x=15 --> [[0.46414759 0.53585241]] x=16 --> [[0.44987569 0.55012431]] x=17 --> [[0.43568582 0.56431418]] x=18 --> [[0.42160051 0.57839949]] x=19 --> [[0.40764163 0.59235837]] Если вероятность онконегативности выше вероятности онкопозитивности, то будет возвращено предсказание онконегативный. Последний раз такое встречается при x=12 . Если пациент выкуривает более 12 сигарет, то алгоритм классифицирует его как онкопозитивного. Резюмируя: вы научились легко решать задачи классификации с помощью логистической регрессии с использованием библиотеки scikit-learn. Ос- новная идея логистической регрессии заключается в подгонке к данным S-образной кривой (сигма-функции). Эта функция ставит каждой точке данных и каждому возможному классу в соответствие числовое значение от 0 до 1, которое моделирует вероятность принадлежности этой точки данных заданному классу. Однако на практике часто попадаются обучающие данные |