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

tl; dr: Я самостоятельно свернул трансформатор sklearn, который ничего не делает с входом. Это позволяет мне конкатенировать его (преобразование) самого себя с помощью FeatureUnion sklearn. Это может быть полезно для целей отладки / понимания.

Введение

С тех пор, как я прошел Курс Эндрю Нга по машинному обучению, я начал знакомиться с sklearn Python. Лучший способ понять - это заняться программированием, а что может быть лучше для начала, чем Титанический вызов Kaggle? Самая большая ценность в наборе данных Kaggle - это на самом деле количество описаний, которые были сделаны при работе с набором данных и знакомстве с ним. Два из моих любимых - это Пост Ахмеда Бесбеса и серия постов Ультрафиолетовая аналитика.

Проблема

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

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

Размышляя над тем, как бы я сам реализовать / решить эти проблемы, и просматривая руководство пользователя sklearn (кстати, отличный ресурс, хотя иногда и немного пояснений), я наткнулся на их Pipeline/FeatureUnion концепции.
Это довольно классные инструменты. Они допускают простой декларативный интерфейс, который принимает данные, пропускает их через некоторые четко определенные преобразователи и в конечном итоге пропускает их через классификатор (обычно в любом случае). У него отличный способ объявления параметров, а также простой и понятный способ реализовать поиск по сетке с перекрестной проверкой, например, для настройки гиперпараметров.

Я не буду вдаваться в подробности о том, что это такое и как их использовать. Уже есть несколько хороших сообщений в блогах, в которых это довольно прилично детализируется. Я по-прежнему расскажу об основных вещах, но вместо того, чтобы вдаваться в подробности, я хочу показать, как я использовал Pipeline / FeatureUnion для самостоятельной прокрутки Transformer, который по функциональности эквивалентен матрице идентичности, и показать, почему это может быть полезно. .

Учитесь на практике: трансформация кабины "Титаника"

Лучше всего объяснить все это на примере (опять же, посмотрите блокнот на моем GitHub, если хотите продолжить). В наборе данных Kaggle Titanic есть столбец с именем Cabin. Это беспорядок из пропущенных и переполненных буквенно-цифровых элементов, и наша задача состоит в том, чтобы преобразовать его во что-то машинное. Большинство рецензий будут делать с этим две вещи:

  • Вменять недостающие значения
  • Факторизовать или закодировать в горячем режиме

Интуитивно вы можете увидеть, как здесь появляется конвейер: возьмите данные, пропустите их через «импульсный» преобразователь, а затем через преобразователь «факторизатор / один горячий кодировщик». Однако я хотел сделать что-то необычное для целей отладки и лучше понять, как работает эта борьба с данными. Я хотел сравнить выходы обоих трансформаторов рядом. Однако FeatureUnions в sklearn этого не допускают. Хотя это сложно объяснить, так что держитесь.

Принцип работы конвейеров заключается в том, что они принимают входные данные, каким-то образом их преобразуют и возвращают выходные данные. Иногда вы хотите выполнить разные преобразования с разными входными данными и объединить их позже, чтобы передать их классификатору. Здесь на помощь приходит FeatureUnion, он просто объединяет (по оси = 1) выходные данные разных конвейеров.

Конкатенационные махинации

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

Следовательно, я подумал, что какая-то личность-Transformer может помочь. Его функционирование аналогично единичной матрице (отсюда и ее название): умножение матрицы на нее ничего не дает. Это кажется относительно бессмысленным, но позволяет мне делать следующее:

Это позволяет мне объединять выходные данные, не выполняя одно и то же преобразование дважды! Вот как я написал этот класс очень просто:

from sklearn.base import BaseEstimator, TransformerMixin

class IdentityTransformer(BaseEstimator, TransformerMixin):
    def __init__(self):
        pass
    
    def fit(self, input_array, y=None):
        return self
    
    def transform(self, input_array, y=None):
        return input_array*1

Вот и все! «Магия» происходит в методе transform(): просто умножьте на 1. Похоже, это работает как для строк, так и для (буквенных) чисел. Пропуск этого *1, похоже, вызывает ошибки. Очевидно, что код сам по себе не слишком интересен, но он позволяет мне делать некоторые интересные манипуляции.

Последние мысли:

  • Я не уверен, что это лучший способ сделать это. Помимо того, что мне это показалось крайним случаем, я не тестировал его на других наборах данных. Хотя, похоже, он отлично работает для этого смешанного. Я также не знаю, каковы могут быть последствия для производительности.
  • Перед самокатанием трансформаций влево и вправо обязательно ознакомьтесь с документацией sklearn на трансформаторы. Многие из них уже являются частью пакета, и зачастую они могут уже делать то, что вы хотите, в несколько раз более эффективно / надежно.

Буду рад услышать любые комментарии, если вы действительно дойдете до конца этой публикации.