Цель: сформировать интуитивное представление о том, как «действовать в одиночку» (т. е.: исследовать дистрибутивы, выбирать этапы обработки данных, выбирать модель, настраивать модель и т. д.). Эта статья предназначена для тех, кто только начинает заниматься машинным обучением и хорошо разбирается в различных аспектах, но не в том, как и зачем объединять рабочий процесс. Если это похоже на вас, читайте дальше!

В любой проблеме машинного обучения нужно учитывать многое. С чего начать? Какие преобразования мы должны применить к данным для их обработки? И когда? Откуда мы знаем, какую модель использовать? Существуют десятки возможных алгоритмов модели и еще больше шагов обработки и методов преобразования. Поначалу может быть очень ошеломляюще иметь такую ​​возможность выбора в вашем распоряжении.

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

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

Обзор

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

  1. Предварительный код
  2. ЭДА
  3. Обработка данных
  4. Модель обучения
  5. Оценка модели
  6. Оптимизация

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

Шаг 1: Предварительный код

Если вы похожи на меня, когда мы впервые получаем данные, заманчиво просто погрузиться в них. Чтобы мгновенно запустить среду кодирования и начать исследовательский анализ данных (EDA). Вместо этого я бы рекомендовал открыть какой-нибудь текстовый документ и потратить некоторое время на рассмотрение доступных необработанных данных и проблемы, которую нужно решить. Оба они жизненно важны для определения самой структуры нашего рабочего процесса. Для этого пошагового руководства мы будем использовать набор кредитных данных здесь.

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

Учитывая, что это набор данных по кредитам, наиболее интуитивный рабочий процесс происходит из столбца Loan_Status. Здесь наши данные помечены теми, кому кредит был одобрен (верно), и тем, кто не был одобрен (ложь). Таким образом, один из вариантов — создать модель, которая будет предсказывать, будут ли люди получать кредиты на основе других столбцов или функций. Ярлыки и предсказания означают модель контролируемого обучения. Кроме того, поскольку мы пытаемся предсказать двоичный результат (Да/Нет, Истина/Ложь, 1/0), мы будем использовать модель классификации.

Теперь у нас есть данные, нужный нам тип модели и наша задача: предсказать, получит ли кто-то ссуду, на основе входных функций данных. Пришло время начать кодирование!

Шаг 2: ЭДА

Исследовательский анализ данных или EDA, пожалуй, самый важный шаг в машинном обучении, но его очень легко упустить из виду. Здесь мы получаем почти всю информацию, необходимую для принятия обоснованных решений. Мы можем узнатьо чем говорят наши данные, как их обрабатывать, какую модель выбрать и даже чему учится наша модель. Чем больше времени вы сможете потратить на понимание данных, тем лучше, однако некоторые ключевые аспекты, на которых следует сосредоточиться, включают:

  • Отсутствующие значения
  • Тип данных
  • Корреляция (отношения)
  • Распределение каждой функции
  • Обнаружение выбросов

Еще один важный момент, который я не рассматриваю в этой статье, — это базовая сводная статистическая информация с использованием pandas .describe() для любых числовых переменных. Это не то, что нужно пропустить в реальном рабочем процессе, и это играет важную роль в нашем понимании распределений и обнаружения выбросов. Однако в интересах простоты этого урока и из-за модели, с которой мы будем работать, я пропустил его здесь.

Настройка среды

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

Типы данных и пропущенные значения

Давайте сначала посмотрим на количество пропущенных значений (или NaNs) в нашем наборе данных и с каким типом данных мы работаем с командой .info(). Мы также можем рассчитать процент нулевых значений в каждом столбце.

df.info()

#percentage of nan
print(df_raw.isnull().sum() * 100 / len(df_raw))

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

Типы данных из .info показывают нам как числовые (float/int), так и категориальные (объектные) типы данных. Давайте подробнее рассмотрим категориальные данные:

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

Корреляция

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

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

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

Подводя итог, отношения, на которые мы хотим обратить внимание, включают:

  • высокая корреляция между кредитной историей и кредитным статусом (цель): получают ли люди с более высоким кредитным рейтингом больше кредитов?
  • высокая корреляция между суммой кредита и доходом: получают ли люди с более высокими доходами более высокие кредиты?
  • Пригороды и статус кредита: Получают ли люди в пригородных районах больше кредитов?
  • мужчина и женатый: Женатых мужчин больше, чем женщин?

Идем глубже

С помощью этих простых визуализаций мы узнаем несколько очень важных вещей.

  1. Данные несбалансированы. Как по целевой переменной, так и по характеристикам:
    • Очень мало женщин
    • Очень мало не имеющих высшего образования
    • Очень мало без кредитной истории
    • Мало незамужних
    • Несколько не одобрено (наша цель)
  2. Ни одна кредитная история не была очень мало принята
  3. Пригородные районы имели наибольшую долю одобрения
  4. Доход и сумма кластеризуются в более низких значениях, а выбросы находятся в очень высоких значениях.

Последним шагом к EDA является визуализация числовых распределений. В этом наборе данных у нас есть только четыре: Coapplicant Income, Applicant Income, Loan Amount и Loan Term. Наша предыдущая визуализация уже дала нам подсказку о том, как могут выглядеть эти распределения, но более понятным вариантом является использование гистограммы.

Теперь у нас есть последняя важная часть информации о данных: числовые данные не распределены нормально.

Давайте подытожим, что мы узнали из нашего EDA.

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

Кое-что из того, что мы узнали, — это образы в данных. Это включает в себя информацию о том, какие признаки получают кредит (т. е. имеют кредитную историю, живут в пригороде) и как признаки в наборе данных связаны друг с другом (брак и принадлежность к мужчине). Эти шаблоны должны способствовать нашему мышлению и пониманию данных, но они ничего не изменят в нашем текущем подходе к рабочему процессу. Наша модель должна якобы изучать любые шаблоны, важные для прогнозирования, самостоятельно. Что нам нужно сделать, так это логически и на основе исследований рассмотреть, имеют ли эти закономерности смысл в реальном мире или они связаны с ограничениями данных, также известными как предвзятость в наборе данных. Это уже может дать нам некоторое представление о том, насколько точной будет модель для каких приложений. Например, из моего EDA я знаю, что количество реальных женщин в обучающей выборке невелико, поэтому, как бы мы ни преобразовывали наши данные, модель будет менее точной с прогнозами для женщин.

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

Распределение. Каждая модель делает определенные предположения о распределении данных. Например, линейная или логистическая регрессия предполагает нормальное распределение, и модель может легко искажаться выбросами. Вы всегда можете погуглить «предположения распределения модели», чтобы получить представление о конкретных предположениях, которые делает модель, и, следовательно, о том, как должны быть подготовлены данные. Для простоты в этом обзоре я выбрал модель случайного леса. Модели случайного леса полезны по множеству причин, но по своей сути они непараметрические, то есть не делают формальных предположений о распределении входных данных.

Тип данных. Это вторая причина выбора Random Forest для этих конкретных данных. Они также могут обрабатывать категориальные (порядковые или нет) и числовые данные. На самом деле в R реализациях случайного леса категориальные переменные могут быть переданы прямо в модель без преобразования в числовые!

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

Шаг 3: Обработка

Разделение тестов на поезд

Если вы познакомились с концепциями машинного обучения, вы, вероятно, знаете разделение Train-Test. Полностью подробную статью об этом можно найти здесь. Что-то, что может быть неинтуитивным при первом запуске, — это когда реализовать это разделение. Если вы уже чувствуете, что у вас есть хорошее понимание, не стесняйтесь пропустить этот раздел, однако сначала я боролся с этим, поэтому я хотел потратить на это некоторое время.

Поскольку все данные должны быть обработаны одинаково, чтобы их можно было понять моделью, кажется наиболее эффективным сделать это после этапа обработки. Однако этот вывод исходит из непонимания того, как ведут себя этапы предварительной обработки и зачем необходимо разбиение обучающих тестов. Во-первых, некоторые преобразования предварительной обработки применяются к данным в целом. Другими словами: преобразование, применяемое к каждой точке данных, основано на общем распределении всего набора данных, переданного в преобразование. Это легче понять на примере с использованием кода sk-learn:

Мы видим, что результат наших обучающих данных при подаче через разделение после предварительной обработки отличается, чем при разделении до этого. Это связано с тем, что мы обсуждали ранее: Imputer() — это преобразование предварительной обработки, которое основывается на полноте переданного ему набора данных. Это также может относиться к преобразованиям, отличным от skit-learning. Например, применение log() преобразует распределение в нормальное, поэтому применяемое преобразование зависит от полного распределения входных данных и будет различным для разных наборов данных.

Это подводит нас ко второму пункту: причина использования разделения поезд-тест. Разделение обучения и тестирования — это способ скрыть информацию от нашей модели, чтобы предоставить ей совершенно новую информацию на этапе оценки. Когда разделение применяется после предварительной обработки, наш объект X был преобразован с использованием всех данных, данные тестирования больше не «скрыты».

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

Вменение и дисбаланс

Когда разделение завершено, остается применить два типа преобразования.

  • замена NaN
  • Устранение дисбаланса

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

Все модели будут бороться с дисбалансом, и если их не устранить, это приведет к совершенно неточным результатам, поэтому очень важно всегда лечить это. Более подробно о дисбалансе, о том, что он делает и как с ним бороться, читайте в этой статье. В этом случае я собираюсь использовать SMOTE() для избыточной выборки данных. Для полного объяснения использования SMOTE() и того, как это работает, я рекомендую эту статью. Изучая SMOTE(), мы замечаем кое-что важное: он не может обрабатывать значения NaN.

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

Что касается последней строки кода, помните о том, о чем мы говорили ранее в разделе «поезд-тест». Хотя мы не хотим, чтобы тестовые данные загрязняли обучающие данные (или наоборот), нам все равно нужно, чтобы обучающие данные также обрабатывались, чтобы модель могла их понять для оценки модели. Помните цель каждого преобразования нашего процесса. Нам все еще нужно заменить NaN в тестовом наборе, чтобы случайный лес понял. Однако мы хотим измерить способность нашей модели справляться с дисбалансом в неизвестных наборах данных, поэтому мы не применяем SMOTE().

Шаг 4: Обучение

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

Шаг 5: Оценка

Важным решением на этапе оценки является выбор **показателя**, который вы будете использовать. Существует много метрик и много объяснений для этих метрик, поэтому я не буду вдаваться в них все, мы сосредоточимся на двух основных метриках *classification*, поскольку это классификация. проблема.

Наиболее классической метрикой является *точность*, которая представляет собой процент правильных прогнозов, сделанных обученной моделью с использованием тестового набора. Это то, что по умолчанию возвращает sklearn.score. Лучшей альтернативой, которая также интуитивно понятна визуально, является использование «матрицы путаницы».

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

Мы можем количественно оценить этот дисбаланс с помощью показателей precision и recall. Самый простой способ получить к ним доступ — через scikit-learn's classification report. Уже много написано об отзыве и точности, а также о том, когда и для чего оптимизировать. В этом случае, поскольку, если мы являемся банком, пытающимся автоматически принимать или отказывать людям, мы больше беспокоимся о ложных срабатываниях, чем о ложноотрицательных срабатываниях, поскольку принятие кредита имеет потенциал затраты. Хорошее объяснение взаимосвязи между точностью, отзывом и стоимостью действий см. в этом ответе на переполнение стека.

Шаг 6: Оптимизация

После обработки оптимизация может показаться следующим действительно важным шагом в принятии решений. За тем, как и почему модель работает так, как она работает, стоят миллионы вариантов и множество интуитивных предположений. В статье, написанной Уиллом Кёрсеном на примере случайного леса, рекомендуется следующий порядок 3 основных подходов:

  1. Используйте больше (высококачественных) данных и разработку функций
  2. Настройте гиперпараметры алгоритма
  3. Попробуйте разные алгоритмы

Очень хорошее пошаговое руководство по первому подходу можно посмотреть в статье Керсена. Стоит отметить, что разработка функций часто приводит к более значительным улучшениям, чем настройка гиперпараметров. В полном рабочем процессе машинного обучения этот этап тестирования модели с различными преобразованиями процессов и выбором функций абсолютно необходим. Работодатели и клиенты хотят знать, что они получают наилучшие возможные результаты, и только потому, что что-то кажется способным дать наилучший возможный результат, не означает, что так оно и будет. Возьмем наше предыдущее вменение неизвестных значений. Если бы это был полноценный проект, стоило бы потратить время на то, чтобы опробовать различные результаты моделирования с другими обработками NaN — например, удалить их или заменить на минимум, медиану или моду.

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

Вы, вероятно, знакомы с концепцией настройки гиперпараметров, но на всякий случай: это процесс настройки доступных входных параметров для модели, чтобы изменить способ обучения или обучения этой модели. Возможно, вы уже сталкивались с Grid Search, методом, позволяющим компьютеру запускать комбинации опций параметров, чтобы избежать многократного повторного кодирования. Поначалу использование поиска по сетке может напоминать съемку в темноте, и это нормально. Невозможно сразу узнать все детали каждой модели, но по мере работы с каждой моделью мы можем интуитивно понять компромиссы, которые мы делаем, когда изменяем гиперпараметры модели.

Важным аспектом гиперпараметров, который необходимо понять, является перекрестная проверка. Если вы сомневаетесь в этой концепции, я рекомендую просмотреть вторую часть статьи Koehrsen’s Random Forest, прежде чем двигаться дальше. К счастью для нас, реализация Grid Search в sklearn автоматически интегрирована с перекрестной проверкой, поэтому, когда мы кодируем, этот процесс для нас объединяется.

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

model.get_params()

Достаточно много! Если мы перейдем к документации skit-learn для RandomForestClassifier и далее в User Guide, то сможем найти более конкретную информацию. В разделе Parameters scikit-learn удобно сообщает нам основные параметры для настройки, n_estimators и max_features. Вот их формальные определения:

  • n_estimator: количество деревьев в лесу
  • max_features: случайное подмножество функций, которые следует учитывать при разделении узла.

Если это имеет смысл, учитывая ваше понимание Random Forest, отлично! Если это немного сбивает с толку, лучше всего рассматривать гиперпараметры с точки зрения того, какие компромиссы они представляют?

  • n_estimator: Оптимизация модели против вычислительной оптимизации. Больше означает лучшую модель (до определенного момента), но увеличивает время вычислений. Другими словами, чем выше, тем лучше, но тем дольше будет работать модель.
  • max_features: Предвзятость против дисперсии. Более низкие значения уменьшают дисперсию, но увеличивают смещение

Если мы еще потратим некоторое время на гугление Random Forest, мы сможем найти инструкции по другим параметрам, например, в этом учебнике, в котором упоминается min_samples_leaf. Как объясняется в статье, меньшее значение более склонно к переоснащению — рекомендуется не менее 50.

Какие разные значения мы пробуем для каждого параметра? Еще раз, нет простого ответа, это в основном зависит от вас. Тем не менее, хорошее эмпирическое правило состоит в том, чтобы поэкспериментировать с включением и исключением значений из исходного (по умолчанию) запуска модели. Также полезно начинать с больших приращений (например: 1, 100, 500, 1000), а затем работать с меньшими (например: 0,1, 0,5, 1, 1,3). В полном рабочем процессе мы хотели бы повторять несколько поисков в сетке, каждый раз становясь более конкретными. В этом пошаговом руководстве мы сделаем это только один раз. Обратитесь к главной странице документации для получения дополнительной информации о значениях, которые принимает каждый гиперпараметр.

Теперь у нас есть хорошее представление о том, с чего начать наш поиск по сетке.

За кулисами я сделал несколько итераций, изменив сетку параметров, чтобы найти оптимальную переменную min_samples_leaf. С помощью вышеуказанного поиска по сетке параметров нам удалось немного повысить точность нашего теста, с 77,8% до 79,5%. Потратив больше времени на настройку различных гиперпараметров и вернувшись к этапам обработки и разработки функций, мы могли бы попытаться улучшить его дальше. Он также, возможно, ограничен небольшим набором данных, поэтому может помочь сбор большего количества данных.

Заключение

Теперь мы прошли контролируемую классификацию от начала до конца! Подводя итоги шагов:

  1. Предварительный код: поймите проблему, которую вы пытаетесь решить
  2. EDA: сосредоточьтесь на распределении данных, корреляциях и типах данных. Используйте их для принятия решений по моделированию и преобразованиям обработки.
  3. Обработка: применить преобразования к обучающим данным и (в зависимости от преобразования) к тестовым данным отдельно
  4. Обучить: так написано на жестяной банке — Обучить базовую модель!
  5. Оценить: используйте различные показатели для оценки вашей модели.
  6. Оптимизируйте: повторяйте столько, сколько сможете! Для настройки гиперпараметров используйте документацию модели и понимание компромиссов различных гиперпараметров.

Надеюсь, теперь вы чувствуете себя лучше подготовленными, чтобы самостоятельно отправиться в путь и решить любую проблему машинного обучения самостоятельно!