• Быстро
  • Знания домена не требуются
  • Высокая производительность

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

В машинном обучении / глубоком обучении или любом другом виде задач прогнозного моделирования данные предшествуют алгоритму / методологии. Это основная причина, по которой машинное обучение требует большого количества функций перед определенными задачами, такими как классификация изображений, NLP и многие другие необычные данные, которые нельзя напрямую ввести в логистическую регрессию или модель случайного леса. Напротив, этот тип задач значительно лучше решается с помощью глубокого обучения без каких-либо неприятных и трудоемких разработок функций. В большинстве случаев для этих функций требуются знания предметной области, творческий подход и много проб и ошибок. Конечно, опыт в предметной области и умная разработка функций по-прежнему очень ценны, но методов, которые я буду упоминать в этом посте, будет достаточно, чтобы вы смогли попасть в тройку лучших в конкурсе Kaggle (http://blog.kaggle.com/2016/ 22 января / rossmann-store-sales-winners-посредничество-3-место-cheng-gui / ) без каких-либо предварительных знаний по этому вопросу.

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

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

Ниже приведены данные о продавцах в Интернете: строки - каждая уникальная продажа, а столбцы - описывают конкретные продажи.

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

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

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

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

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

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

«Непрерывный характер нейронных сетей ограничивает их применимость
категориальными переменными. Поэтому наивное применение
нейронных сетей к структурированным данным с целочисленным
представлением для переменных категорий не работает »[1]

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

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

Вложения очень широко используются в НЛП, поскольку каждое слово представлено в виде вектора. Двумя известными примерами встраивания являются Glove и word2vec. Мы можем видеть, насколько сильны вложения из рисунка 4 [2]. Эти векторы легко доступны для вас, чтобы вы могли загрузить их и использовать по своему усмотрению, что на самом деле очень круто, думая об информации, которую они хранят.

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

Вложения сущностей

Несмотря на то, что вложения сущностей имеют другое имя, они не сильно отличаются от варианта использования, который мы видели во встраиваниях слов. В конце концов, единственное, о чем мы заботимся, - это иметь более высокое векторное представление наших сгруппированных данных; это могут быть слова, день недели, страны и многое другое, которое вы можете себе представить. Эта транзакция от встраивания слов к встраиванию метаданных (в нашем случае категориальных) данных позволила Йошуа Бенжио и др. чтобы выиграть соревнование Kaggle (https://www.kaggle.com/c/pkdd-15-predict-taxi-service-trajectory-i) еще в 2015 году с помощью одного простого автоматизированного подхода, что не является обычным случаем для выигрышных решений.

«Чтобы иметь дело с дискретными метаданными, состоящими из идентификатора клиента, идентификатора такси, даты и времени, мы изучаем вложения вместе с моделью для каждой из этих данных. Это вдохновлено подходами к моделированию нейронного языка [2], в которых каждое слово отображается в векторное пространство фиксированного размера (вектор называется вложением слова) »[3].

Шаг за шагом мы рассмотрим, как изучить эти функции в нейронной сети. Определите полностью связанную нейронную сеть, отдельные числовые и категориальные переменные.

Для каждой категориальной переменной:

  1. Инициализировать случайную матрицу вложения как m x D.

m: количество уникальных уровней категориальной переменной (понедельник, вторник,…)

D: желаемое измерение для представления, гиперпараметр, который может находиться в диапазоне от 1 до m-1 (если 1, это будет кодировка метки, если m - горячая кодировка)

2. Затем для каждого прямого прохода через нейронную сеть мы выполняем поиск заданного уровня (например, понедельник для «доу») из матрицы вложения, которая дает нам вектор как 1 x D.

3. Добавьте этот вектор размером 1 x D к нашему входному вектору (числовому вектору). Думайте об этом процессе как о расширении матрицы, где мы добавляем вектор внедрения для каждой категории, которая была внедрена, выполняя поиск для каждой конкретной строки.

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

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

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

Примечание. Практическое правило - выбирать категории с не очень высокой мощностью. Например, если у переменной есть уникальные уровни для 90% наблюдений, тогда она не будет очень предсказательной переменной, и мы вполне можем от нее избавиться.

Хорошие новости

Мы можем очень хорошо реализовать вышеупомянутую архитектуру в нашем любимом фреймворке (желательно динамическом), выполнив поиск и разрешив require_grad = True в наших векторах встраивания и изучив их. Но все эти и другие шаги уже выполнены в Fast.ai. Помимо упрощения структурного глубокого обучения, эта библиотека также предоставляет множество современных функций, таких как дифференцированная скорость обучения, SGDR, циклическая скорость обучения, поиск скорости обучения и так далее. Это все, чем мы хотели бы воспользоваться. Вы можете прочитать больше об этих темах из этих замечательных других сообщений в блоге:

Https://medium.com/@bushaev/improving-the-way-we-work-with-learning-rate-5e99554f163b

Https://medium.com/@surmenok/estimating-optimal-learning-rate-for-a-deep-neural-network-ce32f2556ce0

Https://medium.com/@markkhoffmann/exploring-stochastic-gradient-descent-with-restarts-sgdr-fa206c38a74e



Пройдите с Fast.ai

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

Для этого посмотрим на активный конкурс Kaggle https://www.kaggle.com/c/mercari-price-suggestion-challenge/. В этой задаче мы пытаемся предсказать цену товара, продаваемого онлайн-продавцом. Это очень подходящий пример для встраивания сущностей, поскольку данные в основном категориальные с относительно высокой мощностью (не слишком большой), и больше ничего не остается.

Данные:

~ 1,4 млн рядов

  • item_condition_id: состояние элемента (количество элементов: 5)
  • category_name: название категории (количество элементов: 1287)
  • brand_name: название бренда (количество элементов: 4809).
  • доставка: включена ли доставка в цену (число 2).

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

Шаг 1:

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

train.category_name = train.category_name.fillna('missing').astype('category')
train.brand_name = train.brand_name.fillna('missing').astype('category')
train.item_condition_id = train.item_condition_id.astype('category')
test.category_name = test.category_name.fillna('missing').astype('category')
test.brand_name = test.brand_name.fillna('missing').astype('category')
test.item_condition_id = test.item_condition_id.astype('category')

Шаг 2:

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

Я объединил данные обучения и тестирования, так как мы хотим, чтобы одни и те же уровни имели одинаковые кодировки.

combined_x, combined_y, nas, _ = proc_df(combined, 'price', do_scale=True)

Шаг 3:

Создать объект данных модели. Путь - это место, где Fast.ai хранит модели и активации.

path = '../data/'
md = ColumnarModelData.from_data_frame(path, test_idx, combined_x, combined_y, cat_flds=cats, bs= 128

Шаг 4:

Определите D (размер вложения). cat_sz - это список кортежей (col_name, cardinality + 1) для каждого категориального столбца.

# We said that D (dimension of embedding) is an hyperparameter
# But here is Jeremy Howard's rule of thumb
emb_szs = [(c, min(50, (c+1)//2)) for _,c in cat_sz]
# [(6, 3), (1312, 50), (5291, 50), (3, 2)]

Шаг 5:

Создайте обучаемого, это основной объект библиотеки Fast.ai.

# params: embedding sizes, number of numerical cols, embedding dropout, output, layer sizes, layer dropouts
m = md.get_learner(emb_szs, len(combined_x.columns)-len(cats),
                   0.04, 1, [1000,500], [0.001,0.01], y_range=y_range)

Шаг 6:

Эта часть объясняется более подробно в других сообщениях, о которых я упоминал ранее.

Воспользуйтесь полной радостью Fast.ai.

Мы выбираем нашу скорость обучения с точки до того, как убытки начинают расти ...

# find best lr
m.lr_find()
# find best lr
m.sched.plot()

Соответствовать

we can see that with just 3 epochs we have
lr = 0.0001
m.fit(lr, 3, metrics=[lrmse])

Больше подходить

m.fit(lr, 3, metrics=[lrmse], cycle_len=1)

И еще несколько…

m.fit(lr, 2, metrics=[lrmse], cycle_len=1)

Таким образом, эти краткие, но эффективные шаги помогут вам подняться до ~ 10% без каких-либо дополнительных действий в течение нескольких минут. Если вы действительно хотите достичь высокой цели, я бы посоветовал вам использовать столбец item_description и сделать его несколькими категориальными переменными. Затем оставьте работу по внедрению сущностей, конечно, не забудьте сложить и объединить :)

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

Цените все аплодисменты, которые у вас есть для меня :)

Биография: Я сейчас аспирант программы магистра аналитики USF. Я применяю машинное обучение уже 3 года и сейчас практикую глубокое обучение с Fast.ai.

Linkedin: https://www.linkedin.com/in/kerem-turgutlu-12906b65/en

Ссылки:

[1] Ченг Го, Феликс Беркхан (2016, 22 апреля) Вложения категориальных переменных в сущности. Получено с https://arxiv.org/abs/1604.06737.

[2] Руководства по TensorFlow: https://www.tensorflow.org/tutorials/word2vec

[3] Йошуа Бенжио и др. Применение искусственных нейронных сетей для прогнозирования пункта назначения такси. Получено с https://arxiv.org/pdf/1508.00021.pdf.