Классификация

Все курсы > Вводный курс > Занятие 15

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

По традиции вначале откроем ноутбук к этому занятию

Этап 1. Загрузка данных — классификация опухолей

классификация опухолей на злокачественные и доброкачественные

Возьмем данные из модуля datasets библиотеки Scikit-learn. Вначале загрузим их.

Наш набор данных является объектом Bunch, который в свою очередь, представляет собой подкласс питоновского словаря.

Это значит, что его структуру мы можем увидеть с помощью метода .keys().

В разделе data содержится информация о признаках (независимые переменные). В target содержится целевая (зависимая) переменная, в feature_names — наименование признаков, а DESCR содержит описание датасета.

Компонент target_names содержит названия целевых классов.

Посмотрим на описание этого датасета.

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

  • Для каждой из 10 базовых характеристик опухоли (таких как, радиус, текстура, периметр, площадь и т.д.) рассчитаны три значения (среднее арифметическое, СКО и среднее трёх наибольших значений). Таким образом, получается 30 параметров или признаков.
  • Помимо этого, каждое образование классифицировано как злокачественное или доброкачественное.

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

Преобразуем наши данные в формат датафрейма. Для этого передадим функции pd.DataFrame() массив признаков cancer.data. Название столбцов возьмем из cancer.feature_names. Добавим целевую переменную из cancer.tanget и назовем ее так же, ‘target’.

датафрейм для классификации
На рисунке представлена только часть получившегося датафрейма. Весь датафрейм вы найдете в ноутбуке⧉.

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

Целевая переменная обозначается как ноль и один. Посмотрим, какой цифрой обозначается доброкачественная опухоль, а какой — злокачественная.

Из описания мы знаем, что в датасете 212 злокачественных опухолей и 357 доброкачественных. Получается, что ноль означает злокачественное образование, а единица — доброкачественное.

Изучим тип переменных, с которыми нам предстоит работать.

Все зависимые переменные — количественные. Целевая переменная — категориальная, однако что важно, обозначена числовым значением (0 и 1).

Посмотрим на основные статистические показатели (summary statistics):

применение метода .describe() к датафрейму опухолевых образований
На рисунке представлены статистические показатели опять же только для части признаков. Полный набор показателей приведен в ноутбуке⧉.

Этап 2. Предварительная обработка данных

Пропущенные значения

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

Пропущенных значений нет. Мы также могли видеть это в результате метода .info(), сравнив диапазон значений с количеством значений каждой переменной.

Преобразование категориальных переменных

Как уже было сказано, наша целевая категориальная переменная записана числами. Если бы вместо них стояли, например, слова «Да»/ «Нет», или «Злокачественное»/ «Доброкачественное», нам бы пришлось превратить эти строковые значения в цифры. Делается это из-за того, что модель не умеет оперировать словами. Она просто не сможет подобрать веса.

Нормализация данных

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

Например, мы видим, что mean texture имеет разброс от 9,71 до 39,28. При этом mean area находится в диапазоне от 143,50 до 2501,00. Значит ли это, что mean area важнее для нашей модели? Не обязательно. Однако в силу особенностей алгоритма модель может отдать предпочтение (больший вес) именно этому признаку.

Для того чтобы этого не произошло данные нужно нормализовать или привести к единому масштабу (normalization, feature scaling).

В переменную scaled_data был записан массив Numpy. Его нужно вновь преобразовать в датафрейм.

результат масштабирования данных в датафрейме
основные статистическое показатели данных после масштабирования

Как мы видим, масштаб переменных изменился. Теперь у них у всех одинаковое среднее арифметическое (ноль) и одинаковое СКО (единица).

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

Этап 3. Исследовательский анализ данных

Приступим к исследовательскому анализу данных (Exploratory Data Analysis, EDA). Как уже было сказано на прошлом занятии, от нас требуется выявить взаимосвязь между зависимой и независимыми переменными.

В данном случае речь идет о взаимосвязи количественных и категориальной переменной. Вот какие варианты выявления такой взаимосвязи у нас есть:

  • Мы можем количественно оценить насколько будут отличаться основные статистические показатели (например, среднее арифметическое) для каждой из переменных в зависимости от класса.
  • Мы можем графически построить две гистограммы на одном графике, как мы уже делали раньше.
  • В рамках более продвинутого анализа мы можем оценить статистическую значимость такого различия.

На сегодняшнем занятии займемся первым и вторым пунктами.

средние значения признаков в зависимости от класса целевой переменной

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

разница средних 10 признаков

Эту разницу в средних значениях и в целом в распределении переменной мы можем также увидеть на совмещенных гистограммах. Давайте построим такие гистограммы для признака с наибольшей разницей средних worst concave points.

две гистограммы на одном графике иллюстрируют разницу распределений

Как мы видим, распределение признака отличается для злокачественных и доброкачественных образований.

Этап 4. Отбор и выделение признаков

На основе проведенного EDA, давайте возьмем десять признаков в наибольшими отличиями среднего арифметического в зависимости от значения целевой переменной. Таким образом, в нашу модель войдут: worst concave points, worst perimeter, mean concave points, worst radius, mean perimeter, worst area, mean radius, mean area, mean concavity, worst concavity.

Давайте поместим наши признаки в переменную X, а классы в переменную y. Для этого возьмем названия признаков из индекса нашего вспомогательного датафрейма data, преобразуем их в список и сделаем срез по первым 10 значениям (и все это для того, чтобы не набирать названия столбцов вручную).

Результат запишем в переменную features.

Теперь отфильтруем исходный датафрейм по этим признакам. Переменная features и будет нашим фильтром.

В переменную y запишем классы.

Разумеется задачи отбора и выделения признаков (feature selection and feature extraction) и конструирования признаков (feature engineering) намного шире и сложнее. Пока мы только начинаем знакомиться с этими инструментами.

Этап 5. Обучение и оценка качества модели

Разделение на обучающую и тестовую выборки

Прежде всего разобьем наши данные на обучающую и тестовую выборки.

Обучение модели и прогноз

Задача классификации решается с помощью множества различных алгоритмов. Сегодня мы будем использовать логистическую регрессию (logistic regression). Во многом принцип ее работы был описан еще на втором занятии, когда мы изучали принцип машинного обучения.

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

Оценка качества модели

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

Вначале построим матрицу ошибок (confusion matrix). Она в целом покажет, сколько наблюдений были правильно и неправильно классифицированы как злокачественные, и сколько — как доброкачественные. Схематично это выглядит так:

матрица ошибок

Теперь построим такую матрицу на основе прогнозных значений нашей модели.

матрица ошибок в задаче рака груди

Мы сделали злокачественные опухоли положительным классом (единица), потому что обычно в медицине под положительным результатом подразумевается выявление заболевания.

матрица ошибок в задаче рака груди (с подписями строк и столбцов)

Как мы видим, модель допустила шесть ошибок:

  • Две опухоли она классифицировала как доброкачественные, хотя на самом деле это не так
  • Кроме того, четыре доброкачественные опухоли были помечены как злокачественные
  • Остальные значения предсказаны верно

Доля правильно предсказанных значений называется accuracy. Чтобы ее посчитать, мы берем те значения, которые предсказаны верно (TP + TN) и делим на общее количество прогнозов.

$$ accuracy = \frac{TP + TN}{TP + TN + FP + FN} $$

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

Мы также можем воспользоваться встроенной в sklearn метрикой.

Итак, наша модель предсказывает верный результат в 96% случаев. Кажется, что это очень хорошо. Однако, есть одна проблема. С точки зрения медицины и здравого смысла мы больше всего боимся того, что модель не сможет распознать злокачественное образование, и нас прежде всего интересует минимизация ложноотрицательныго результата, когда пациенту с онкологией мы говорим, что не стоит волноваться. Показатель accuracy не дает этой информации.

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

Подведем итог

Мы проделали большую работу.

  1. После загрузки данных мы создали датафрейм, изучили переменные, а также посмотрели на основные статистические показатели.
  2. Обработка данных предполагала изучение пропущенных значений, кодировку категориальных переменных и нормализацию данных.
  3. Исследовательcкий анализ данных позволил выявить взаимосвязь нескольких независимых переменных и целевых классов.
  4. В рамках отбора и выделения признаков мы взяли 10 наиболее значимых признаков.
  5. Затем мы разделили выборку на обучающую и тестовую, обучили модель логистической регрессии и сделали прогноз. При оценке результата мы столкнулись с тем, что в случае задачи классификации доля правильных прогнозов не всегда отражает качество модели.

Вопросы для закрепления

Какие три задачи нужно решить при предварительной обработке данных?

Посмотреть правильный ответ

Какая задача решается в рамках исследовательского анализа данных (EDA)?

Посмотреть правильный ответ

Почему accuracy не всегда позволяет адекватно оценить качество модели?

Посмотреть правильный ответ

Дополнительные упражнения⧉ вы найдете в конце ноутбука.

Теперь перейдем к алгоритму кластеризации.


Ответы на вопросы

Вопрос. Почему правильно проводить нормализацию данных после разделения на train и test?

Ответ. При разделении на обучающую (train) и тестовую (test) выборки самое главное — избежать их взаимного влияния друг на друга. В противном случае, мы не сможем объективно оценить качество модели.

Эту проблему также называют проблемой утечки данных (data leakage).

Если говорить про решение этой задачи с помощью библиотеки sklearn, то, например, у класса StandardScaler есть методы .fit(), .transform() и .fit_transform(). Метод .fit() рассчитывает среднее арифметическое и СКО для масштабирования данных, метод .transform() их применяет. Метод .fit_transform() сразу делает и то, и другое.

На практике, мы могли бы (1) применить метод .fit_transform() к обучающей выборке (train dataset). Это даст нам необходимые среднее арифметическое и СКО (метод .fit()), которые затем позволят масштабировать эти данные (метод .transform()). После этого (2) мы можем применить полученные с помощью .fit() параметры для масштабирования уже тестовых данных (test dataset).

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

Приведу пример на Питоне. Предположим, вы уже поместили ваши данные в переменные X и y.


Вопрос. Запутался с терминологией. Встречал в других источниках, что приведение данных к одному масштабу, которое описывается в этой статье, называют стандартизацией или z-преобразованием. А нормализацией — когда данные масштабируются в диапазон от $0$ до $1$.

Есть ли чёткие определения у этих масштабирований в русском языке или, чтобы не путаться, лучше пользоваться оригинальными наименованиями типа StandardScaler, MinMaxScaler и другие?

Ответ. Я думал над этим вопросом. На самом деле есть некоторая путаница в самих источниках. Я руководствовался двумя статьями.

(1) Статья в Википедии⧉, которая, в свою очередь, ссылается на Оксфордский словарь, обозначает нормализацию как наиболее общий термин.

Нормализация же включает:

  • стандартизацию (standartization) или как еще говорят нормализацию по z-оценке (z-score normalization), т.е. изменение данных таким образом, чтобы их среднее (mean) было равно нулю, а СКО (standard deviation) — единице
  • min-max нормализацию, т.е. приведение данных к определенному диапазону; кстати, диапазон не обязательно должен быть от $0$ до $1$, на занятии по нейросетям мы, например, приводим данные к диапазону от $-1$ до $1$ (общая формула приведена ниже)
  • и другие методы

(2) Еще один общий термин — feature scaling⧉ (масштабирование признаков).

Именно эти два понятия (нормализация и масштабирование) я и использовал для первого знакомства с темой преобразования данных.

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

И StandardScaler, разумеется, отвечает за стандартизацию.

Более подробно все эти методы мы рассмотрим на курсе по анализу и обработке данных.

А вот формула для min-max нормализации:

$$ x’ = a + \frac{x-min(x)(b-a)}{max(x)-min(x)} $$

где a и b — это желаемые минимальное и максимальное значения.

UPD: вероятно наиболее общим термином следует считать преобразование количественных переменных (numerical data transformation), которое включает в себя:

  • масштабирование (scaling), т.е. стандартизацию (standartization) и приведение данных к определенному диапазону (min-max scaling)
  • нелинейные преобразования (non-linear transformations)
  • нормализацию (normalization), т.е. приведение отдельных наблюдений к единичной норме (scaling individual samples to have unit norm)