# Логистическая регрессия для предсказания категорий ![Инфографика: Логистическая vs. линейная регрессия](../../../../2-Regression/4-Logistic/images/linear-vs-logistic.png) ## [Тест перед лекцией](https://ff-quizzes.netlify.app/en/ml/) > ### [Этот урок доступен на R!](../../../../2-Regression/4-Logistic/solution/R/lesson_4.html) ## Введение В этом заключительном уроке о регрессии, одной из базовых _классических_ техник машинного обучения, мы рассмотрим логистическую регрессию. Этот метод используется для выявления закономерностей и предсказания бинарных категорий. Это конфета с шоколадом или без? Это заболевание заразное или нет? Выберет ли клиент этот продукт или нет? В этом уроке вы узнаете: - О новой библиотеке для визуализации данных - О техниках логистической регрессии ✅ Углубите свои знания о работе с этим типом регрессии в [модуле обучения](https://docs.microsoft.com/learn/modules/train-evaluate-classification-models?WT.mc_id=academic-77952-leestott) ## Предварительные знания Работая с данными о тыквах, мы уже достаточно с ними знакомы, чтобы понять, что есть одна бинарная категория, с которой мы можем работать: `Color`. Давайте построим модель логистической регрессии, чтобы предсказать, _какого цвета, скорее всего, будет данная тыква_ (оранжевая 🎃 или белая 👻), основываясь на некоторых переменных. > Почему мы говорим о бинарной классификации в уроке, посвященном регрессии? Это сделано исключительно для удобства, так как логистическая регрессия [на самом деле является методом классификации](https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression), хотя и основанным на линейных принципах. Узнайте о других способах классификации данных в следующей группе уроков. ## Определение вопроса Для наших целей мы выразим это как бинарный выбор: "Белая" или "Не белая". В нашем наборе данных также есть категория "полосатая", но таких случаев мало, поэтому мы не будем ее использовать. Она все равно исчезает, когда мы удаляем пропущенные значения из набора данных. > 🎃 Забавный факт: белые тыквы иногда называют "призрачными" тыквами. Их не так просто вырезать, поэтому они не так популярны, как оранжевые, но выглядят они круто! Таким образом, мы могли бы переформулировать наш вопрос как: "Призрак" или "Не призрак". 👻 ## О логистической регрессии Логистическая регрессия отличается от линейной регрессии, с которой вы уже знакомы, несколькими важными аспектами. [![Машинное обучение для начинающих - Понимание логистической регрессии для классификации](https://img.youtube.com/vi/KpeCT6nEpBY/0.jpg)](https://youtu.be/KpeCT6nEpBY "Машинное обучение для начинающих - Понимание логистической регрессии для классификации") > 🎥 Нажмите на изображение выше, чтобы посмотреть короткое видео о логистической регрессии. ### Бинарная классификация Логистическая регрессия не предоставляет тех же возможностей, что и линейная регрессия. Первая предсказывает бинарную категорию ("белая или не белая"), тогда как вторая способна предсказывать непрерывные значения, например, исходя из происхождения тыквы и времени сбора урожая, _насколько вырастет ее цена_. ![Модель классификации тыкв](../../../../2-Regression/4-Logistic/images/pumpkin-classifier.png) > Инфографика от [Dasani Madipalli](https://twitter.com/dasani_decoded) ### Другие классификации Существуют и другие типы логистической регрессии, включая мультиномиальную и порядковую: - **Мультиномиальная**, которая включает более одной категории - "Оранжевая, Белая и Полосатая". - **Порядковая**, которая включает упорядоченные категории, полезные, если мы хотим логически упорядочить результаты, например, наши тыквы, упорядоченные по конечному числу размеров (мини, маленькая, средняя, большая, очень большая, гигантская). ![Мультиномиальная vs порядковая регрессия](../../../../2-Regression/4-Logistic/images/multinomial-vs-ordinal.png) ### Переменные НЕ обязаны коррелировать Помните, как линейная регрессия работала лучше с более коррелированными переменными? Логистическая регрессия — наоборот: переменные не обязаны быть согласованными. Это подходит для наших данных, где корреляции довольно слабые. ### Вам нужно много чистых данных Логистическая регрессия дает более точные результаты, если использовать больше данных; наш небольшой набор данных не является оптимальным для этой задачи, так что имейте это в виду. [![Машинное обучение для начинающих - Анализ и подготовка данных для логистической регрессии](https://img.youtube.com/vi/B2X4H9vcXTs/0.jpg)](https://youtu.be/B2X4H9vcXTs "Машинное обучение для начинающих - Анализ и подготовка данных для логистической регрессии") ✅ Подумайте о типах данных, которые хорошо подходят для логистической регрессии. ## Упражнение - очистка данных Сначала немного очистим данные, удалив пропущенные значения и выбрав только некоторые столбцы: 1. Добавьте следующий код: ```python columns_to_select = ['City Name','Package','Variety', 'Origin','Item Size', 'Color'] pumpkins = full_pumpkins.loc[:, columns_to_select] pumpkins.dropna(inplace=True) ``` Вы всегда можете заглянуть в ваш новый датафрейм: ```python pumpkins.info ``` ### Визуализация - категориальный график На данный момент вы загрузили [начальный ноутбук](../../../../2-Regression/4-Logistic/notebook.ipynb) с данными о тыквах и очистили его, чтобы сохранить набор данных, содержащий несколько переменных, включая `Color`. Давайте визуализируем датафрейм в ноутбуке, используя другую библиотеку: [Seaborn](https://seaborn.pydata.org/index.html), которая построена на основе Matplotlib, использованной ранее. Seaborn предлагает интересные способы визуализации данных. Например, вы можете сравнить распределения данных для каждой `Variety` и `Color` в категориальном графике. 1. Создайте такой график, используя функцию `catplot`, данные о тыквах `pumpkins` и указав цветовую схему для каждой категории тыкв (оранжевая или белая): ```python import seaborn as sns palette = { 'ORANGE': 'orange', 'WHITE': 'wheat', } sns.catplot( data=pumpkins, y="Variety", hue="Color", kind="count", palette=palette, ) ``` ![Сетка визуализированных данных](../../../../2-Regression/4-Logistic/images/pumpkins_catplot_1.png) Наблюдая за данными, вы можете увидеть, как данные о цвете соотносятся с сортами. ✅ Учитывая этот категориальный график, какие интересные исследования вы можете себе представить? ### Предобработка данных: кодирование признаков и меток Наш набор данных о тыквах содержит строковые значения для всех столбцов. Работа с категориальными данными интуитивно понятна для людей, но не для машин. Алгоритмы машинного обучения лучше работают с числами. Поэтому кодирование — это очень важный этап предобработки данных, который позволяет преобразовать категориальные данные в числовые, не теряя информации. Хорошее кодирование способствует созданию хорошей модели. Для кодирования признаков существуют два основных типа кодировщиков: 1. Ordinal encoder: подходит для порядковых переменных, которые являются категориальными переменными с логическим порядком, например, столбец `Item Size` в нашем наборе данных. Он создает отображение, где каждая категория представлена числом, соответствующим порядку категории в столбце. ```python from sklearn.preprocessing import OrdinalEncoder item_size_categories = [['sml', 'med', 'med-lge', 'lge', 'xlge', 'jbo', 'exjbo']] ordinal_features = ['Item Size'] ordinal_encoder = OrdinalEncoder(categories=item_size_categories) ``` 2. Categorical encoder: подходит для номинальных переменных, которые являются категориальными переменными без логического порядка, например, все признаки, кроме `Item Size`, в нашем наборе данных. Это кодирование "one-hot", где каждая категория представлена бинарным столбцом: закодированная переменная равна 1, если тыква принадлежит этому сорту, и 0 в противном случае. ```python from sklearn.preprocessing import OneHotEncoder categorical_features = ['City Name', 'Package', 'Variety', 'Origin'] categorical_encoder = OneHotEncoder(sparse_output=False) ``` Затем `ColumnTransformer` используется для объединения нескольких кодировщиков в один шаг и их применения к соответствующим столбцам. ```python from sklearn.compose import ColumnTransformer ct = ColumnTransformer(transformers=[ ('ord', ordinal_encoder, ordinal_features), ('cat', categorical_encoder, categorical_features) ]) ct.set_output(transform='pandas') encoded_features = ct.fit_transform(pumpkins) ``` Для кодирования метки мы используем класс `LabelEncoder` из scikit-learn, который помогает нормализовать метки, чтобы они содержали только значения от 0 до n_classes-1 (в данном случае 0 и 1). ```python from sklearn.preprocessing import LabelEncoder label_encoder = LabelEncoder() encoded_label = label_encoder.fit_transform(pumpkins['Color']) ``` После кодирования признаков и метки мы можем объединить их в новый датафрейм `encoded_pumpkins`. ```python encoded_pumpkins = encoded_features.assign(Color=encoded_label) ``` ✅ Каковы преимущества использования ordinal encoder для столбца `Item Size`? ### Анализ взаимосвязей между переменными Теперь, когда мы предобработали данные, мы можем проанализировать взаимосвязи между признаками и меткой, чтобы понять, насколько хорошо модель сможет предсказывать метку на основе признаков. Лучший способ провести такой анализ — это построить графики. Мы снова будем использовать функцию `catplot` из Seaborn, чтобы визуализировать взаимосвязи между `Item Size`, `Variety` и `Color` в категориальном графике. Для лучшей визуализации данных мы будем использовать закодированный столбец `Item Size` и некодированный столбец `Variety`. ```python palette = { 'ORANGE': 'orange', 'WHITE': 'wheat', } pumpkins['Item Size'] = encoded_pumpkins['ord__Item Size'] g = sns.catplot( data=pumpkins, x="Item Size", y="Color", row='Variety', kind="box", orient="h", sharex=False, margin_titles=True, height=1.8, aspect=4, palette=palette, ) g.set(xlabel="Item Size", ylabel="").set(xlim=(0,6)) g.set_titles(row_template="{row_name}") ``` ![Категориальный график визуализированных данных](../../../../2-Regression/4-Logistic/images/pumpkins_catplot_2.png) ### Использование swarm plot Поскольку `Color` — это бинарная категория (Белая или Не белая), для ее визуализации требуется "[специализированный подход](https://seaborn.pydata.org/tutorial/categorical.html?highlight=bar)". Существуют и другие способы визуализации взаимосвязи этой категории с другими переменными. Вы можете визуализировать переменные бок о бок с помощью графиков Seaborn. 1. Попробуйте построить график типа "swarm", чтобы показать распределение значений: ```python palette = { 0: 'orange', 1: 'wheat' } sns.swarmplot(x="Color", y="ord__Item Size", data=encoded_pumpkins, palette=palette) ``` ![Swarm-график визуализированных данных](../../../../2-Regression/4-Logistic/images/swarm_2.png) **Обратите внимание**: приведенный выше код может вызвать предупреждение, так как Seaborn может не справиться с отображением такого количества точек на swarm-графике. Возможное решение — уменьшить размер маркера, используя параметр `size`. Однако имейте в виду, что это может повлиять на читаемость графика. > **🧮 Покажите математику** > > Логистическая регрессия основывается на концепции "максимального правдоподобия", используя [сигмоидные функции](https://wikipedia.org/wiki/Sigmoid_function). График сигмоидной функции имеет форму буквы "S". Она принимает значение и отображает его в диапазоне от 0 до 1. Ее кривая также называется "логистической кривой". Формула выглядит так: > > ![логистическая функция](../../../../2-Regression/4-Logistic/images/sigmoid.png) > > где середина сигмоида находится в точке 0 по оси x, L — максимальное значение кривой, а k — крутизна кривой. Если результат функции больше 0.5, метке присваивается класс "1" из бинарного выбора. В противном случае она классифицируется как "0". ## Построение модели Построение модели для нахождения бинарной классификации удивительно просто в Scikit-learn. [![Машинное обучение для начинающих - Логистическая регрессия для классификации данных](https://img.youtube.com/vi/MmZS2otPrQ8/0.jpg)](https://youtu.be/MmZS2otPrQ8 "Машинное обучение для начинающих - Логистическая регрессия для классификации данных") > 🎥 Нажмите на изображение выше, чтобы посмотреть короткое видео о построении модели линейной регрессии. 1. Выберите переменные, которые вы хотите использовать в своей модели классификации, и разделите данные на обучающую и тестовую выборки, вызвав `train_test_split()`: ```python from sklearn.model_selection import train_test_split X = encoded_pumpkins[encoded_pumpkins.columns.difference(['Color'])] y = encoded_pumpkins['Color'] X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0) ``` 2. Теперь вы можете обучить свою модель, вызвав `fit()` с вашими обучающими данными, и вывести результат: ```python from sklearn.metrics import f1_score, classification_report from sklearn.linear_model import LogisticRegression model = LogisticRegression() model.fit(X_train, y_train) predictions = model.predict(X_test) print(classification_report(y_test, predictions)) print('Predicted labels: ', predictions) print('F1-score: ', f1_score(y_test, predictions)) ``` Посмотрите на отчет вашей модели. Это неплохо, учитывая, что у вас всего около 1000 строк данных: ```output precision recall f1-score support 0 0.94 0.98 0.96 166 1 0.85 0.67 0.75 33 accuracy 0.92 199 macro avg 0.89 0.82 0.85 199 weighted avg 0.92 0.92 0.92 199 Predicted labels: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 0 0 0 0 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 1 1] F1-score: 0.7457627118644068 ``` ## Лучшая интерпретация с помощью матрицы ошибок Хотя вы можете получить отчет о результатах модели, напечатав приведенные выше элементы, вы можете лучше понять свою модель, используя [матрицу ошибок](https://scikit-learn.org/stable/modules/model_evaluation.html#confusion-matrix), чтобы понять, как модель работает. > 🎓 "[Матрица ошибок](https://wikipedia.org/wiki/Confusion_matrix)" (или "матрица путаницы") — это таблица, которая показывает истинные и ложные положительные и отрицательные результаты вашей модели, оценивая точность предсказаний. 1. Чтобы использовать матрицу ошибок, вызовите `confusion_matrix()`: ```python from sklearn.metrics import confusion_matrix confusion_matrix(y_test, predictions) ``` Посмотрите на матрицу ошибок вашей модели: ```output array([[162, 4], [ 11, 22]]) ``` В Scikit-learn строки (ось 0) представляют собой фактические метки, а столбцы (ось 1) — предсказанные метки. | | 0 | 1 | | :---: | :---: | :---: | | 0 | TN | FP | | 1 | FN | TP | Что здесь происходит? Допустим, наша модель классифицирует тыквы между двумя бинарными категориями: "белая" и "не белая". - Если модель предсказывает, что тыква не белая, и она действительно относится к категории "не белая", это называется истинно отрицательным результатом (TN), показанным в верхнем левом углу. - Если модель предсказывает, что тыква белая, но она на самом деле относится к категории "не белая", это называется ложным отрицательным результатом (FN), показанным в нижнем левом углу. - Если модель предсказывает, что тыква не белая, но она на самом деле относится к категории "белая", это называется ложным положительным результатом (FP), показанным в верхнем правом углу. - Если модель предсказывает, что тыква белая, и она действительно относится к категории "белая", это называется истинно положительным результатом (TP), показанным в нижнем правом углу. Как вы могли догадаться, предпочтительно иметь больше истинно положительных и истинно отрицательных результатов и меньше ложных положительных и ложных отрицательных, что указывает на лучшее качество работы модели. Как связаны матрица ошибок, точность и полнота? Помните, что отчет о классификации, напечатанный выше, показал точность (0.85) и полноту (0.67). Точность = tp / (tp + fp) = 22 / (22 + 4) = 0.8461538461538461 Полнота = tp / (tp + fn) = 22 / (22 + 11) = 0.6666666666666666 ✅ В: Как модель справилась, согласно матрице ошибок? О: Неплохо; есть хорошее количество истинных отрицательных, но также несколько ложных отрицательных. Давайте снова рассмотрим термины, которые мы видели ранее, с помощью отображения TP/TN и FP/FN в матрице ошибок: 🎓 Точность: TP/(TP + FP) Доля релевантных экземпляров среди извлеченных (например, какие метки были правильно определены). 🎓 Полнота: TP/(TP + FN) Доля релевантных экземпляров, которые были извлечены, независимо от того, правильно ли они определены. 🎓 f1-оценка: (2 * точность * полнота)/(точность + полнота) Взвешенное среднее точности и полноты, где лучший результат — 1, а худший — 0. 🎓 Поддержка: Количество случаев для каждой извлеченной метки. 🎓 Точность (Accuracy): (TP + TN)/(TP + TN + FP + FN) Процент меток, предсказанных правильно для выборки. 🎓 Среднее по меткам (Macro Avg): Расчет невзвешенного среднего показателей для каждой метки, без учета дисбаланса меток. 🎓 Взвешенное среднее (Weighted Avg): Расчет среднего показателей для каждой метки с учетом дисбаланса меток путем их взвешивания по поддержке (количество истинных случаев для каждой метки). ✅ Можете ли вы подумать, какой показатель следует отслеживать, если вы хотите уменьшить количество ложных отрицательных? ## Визуализация ROC-кривой этой модели [![ML для начинающих - Анализ производительности логистической регрессии с помощью ROC-кривых](https://img.youtube.com/vi/GApO575jTA0/0.jpg)](https://youtu.be/GApO575jTA0 "ML для начинающих - Анализ производительности логистической регрессии с помощью ROC-кривых") > 🎥 Нажмите на изображение выше, чтобы посмотреть короткий видеообзор ROC-кривых. Давайте сделаем еще одну визуализацию, чтобы увидеть так называемую 'ROC'-кривую: ```python from sklearn.metrics import roc_curve, roc_auc_score import matplotlib import matplotlib.pyplot as plt %matplotlib inline y_scores = model.predict_proba(X_test) fpr, tpr, thresholds = roc_curve(y_test, y_scores[:,1]) fig = plt.figure(figsize=(6, 6)) plt.plot([0, 1], [0, 1], 'k--') plt.plot(fpr, tpr) plt.xlabel('False Positive Rate') plt.ylabel('True Positive Rate') plt.title('ROC Curve') plt.show() ``` Используя Matplotlib, постройте [Receiving Operating Characteristic](https://scikit-learn.org/stable/auto_examples/model_selection/plot_roc.html?highlight=roc) или ROC-кривую модели. ROC-кривые часто используются для анализа работы классификатора с точки зрения истинных и ложных положительных результатов. "ROC-кривые обычно отображают долю истинных положительных на оси Y и долю ложных положительных на оси X." Таким образом, важны крутизна кривой и пространство между линией середины и кривой: вы хотите, чтобы кривая быстро поднималась вверх и уходила от линии. В нашем случае сначала есть ложные положительные, а затем линия правильно поднимается вверх и уходит. ![ROC](../../../../2-Regression/4-Logistic/images/ROC_2.png) Наконец, используйте API [`roc_auc_score`](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.roc_auc_score.html?highlight=roc_auc#sklearn.metrics.roc_auc_score) из Scikit-learn, чтобы вычислить фактическую 'Площадь под кривой' (AUC): ```python auc = roc_auc_score(y_test,y_scores[:,1]) print(auc) ``` Результат: `0.9749908725812341`. Учитывая, что AUC варьируется от 0 до 1, вы хотите получить высокий результат, так как модель, которая на 100% правильна в своих предсказаниях, будет иметь AUC, равный 1; в данном случае модель _довольно хороша_. В будущих уроках по классификации вы узнаете, как улучшить показатели вашей модели. А пока поздравляем! Вы завершили эти уроки по регрессии! --- ## 🚀Задание Логистическая регрессия — это обширная тема! Но лучший способ учиться — это экспериментировать. Найдите набор данных, подходящий для такого типа анализа, и создайте модель на его основе. Что вы узнаете? совет: попробуйте [Kaggle](https://www.kaggle.com/search?q=logistic+regression+datasets) для интересных наборов данных. ## [Тест после лекции](https://ff-quizzes.netlify.app/en/ml/) ## Обзор и самостоятельное изучение Прочитайте первые несколько страниц [этой статьи из Стэнфорда](https://web.stanford.edu/~jurafsky/slp3/5.pdf) о практическом применении логистической регрессии. Подумайте о задачах, которые лучше подходят для одного или другого типа регрессии, которые мы изучали до сих пор. Что будет работать лучше? ## Задание [Повторное выполнение этой регрессии](assignment.md) --- **Отказ от ответственности**: Этот документ был переведен с помощью сервиса автоматического перевода [Co-op Translator](https://github.com/Azure/co-op-translator). Хотя мы стремимся к точности, пожалуйста, учитывайте, что автоматические переводы могут содержать ошибки или неточности. Оригинальный документ на его исходном языке следует считать авторитетным источником. Для получения критически важной информации рекомендуется профессиональный перевод человеком. Мы не несем ответственности за любые недоразумения или неправильные интерпретации, возникшие в результате использования данного перевода.