Эксперименты с алгоритмами машинного обучения на задаче Kaggle — Mercari Price Suggestion Challenge
Это мир, управляемый данными. Тот, у кого больше данных, является здесь пионером. От прокрутки роликов Instagram до поиска этой статьи данные есть везде. Машинное обучение — это игра с этими данными путем экспериментирования с ними различных алгоритмов. Когда вы говорите данных и машинного обучения, неудивительно, что электронная коммерция, одна из самых быстрорастущих тенденций, является одним из лучших мест для игры с данными, потому что данные — это все, что у них есть. Существует множество приложений машинного обучения. в области электронной коммерции одним из них является прогнозирование цены товара. В этой статье мы собираемся предсказать цену товара, используя данные из реального мира. Вы можете найти ссылку на этот конкурс в конце этого блога.
Проблема реального мира
Mercari — это одна из платформ электронной коммерции в Японии, которая включает в себя продажу и покупку подержанных/отремонтированных товаров. Всякий раз, когда продавец хочет продать товар в приложении Mercari, он хочет, чтобы продавец знал, по какой цене стоит этот товар. Это помогает продавцам знать стоимость предмета, который они собираются продать.
Поскольку цена предмета зависит от множества характеристик, таких как марка предмета, состояние предмета… человеку очень сложно подробно описать все это вручную и определить цену предмета. Чтобы автоматизировать этот процесс с помощью машинного обучения, они создали задачу, в которой мы должны предсказать цену товара, который продавец собирается продать. Нам будут предоставлены загруженные продавцом данные, такие как название товара, марка товара, состояние товара и т. д. Относящиеся к этому товару и использующие это данных, мы должны предсказать цену этого предмета с помощью машинного обучения, исключив вмешательство человека.
Моделирование как задача машинного обучения
Имея данные о предмете, мы должны предсказать его цену. Эту проблему можно рассматривать как задачу регрессии, где мы должны найти тенденцию заданной серии точек, используя прошлые данные этих точек, таких как цена в этом случае. Даны характеристики предмета, такие как название предмета, бренд предмета и т. д. мы собираемся предсказать цену товара, которая следует за трендом, основываясь на этих характеристиках.
Ключевой показатель эффективности/метрика эффективности
Чтобы измерить, насколько хороши наши прогнозы цены, нам нужно измерение/метрика. Существует много метрик для оценки проблемы регрессии, например, средняя абсолютная ошибка, среднеквадратическая ошибка и т. д. и метрика/индикатор, который мы здесь используем, — это ошибка среднеквадратичного логарифма (RMSLE).
Ограничения бизнеса
Минимизируйте значение ошибки среднеквадратичного логарифма.
Существующие подходы
Решение 2-го места: Идея заключалась в том, чтобы взять n-граммы текстовых функций и обучить их с помощью модели гребня и двух моделей нейронной сети и предсказать окончательные цены.
conv1d and embeddings: здесь они взяли вложения данного текста и категориальных функций и обучили их с помощью 1D Convolutions.
Зная постановку задачи и бизнес-ограничения, давайте приступим к обзору данных.
Описание данных
Данные можно получить с: https://www.kaggle.com/c/mercari-price-suggestion-challenge/data
Данные предоставляются в формате .7z, мы должны их извлечь. Данные состоят в основном из двух файлов: обучение и тестирование, мы должны обучить нашу модель машинного обучения на данных обучения, а затем выбрать наиболее эффективную модель и предсказать цену данных в тестовый файл.
Загрузка данных
После извлечения данных из файлов .7z я получил файлы .tsv. Я загрузил эти файлы .tsv в фреймы данных pandas для поезда и теста соответственно. Фрагмент данных поезда приведен ниже.
Мы видим, что данные поезда содержат детали почти 1,4 миллиона элементов, каждый элемент имеет следующие переменные/функции:
- train_id — идентификатор предмета
- name — Имя элемента
- item_condition_id — число, указывающее состояние предмета
- category_name — категория, к которой относится товар
- brand_name — Марка товара
- доставка — 1, если цена доставки оплачивается продавцом и 0, если оплачивается покупателем
- item_description — описание предмета
- price — фактическая цена проданного товара. Эта переменная будет отсутствовать в тестовых данных, так как нам нужно предсказать цену.
у нас есть те же функции в тестовом файле, за исключением целевой переменной, которую мы собираемся предсказать, используя данные поезда. Таким образом, наши входные данные для модели будут: эти 7 функций, а выходные данные будут: цена.
Обзор данных
Давайте посмотрим на некоторую основную информацию о данных и проверим наличие отклонений в данных.
На приведенном выше изображении True указывает на наличие нулевых значений или отсутствующих значений в соответствующем признаке. Давайте заменим пустые значения в данных, прежде чем двигаться дальше. Процесс заполнения отсутствующих значений называется вменением, и существует множество способов вменения data. Здесь мы просто заменяем отсутствующие значения любыми новыми значениями. Также обнаружено, что нет повторяющихся деталей элемента, т. Е. Характеристики каждого элемента отличаются от других.
Увидев детали данных о поездах, давайте приступим к анализу этих функций, который даст нам некоторое представление об изменении цены по отношению к каждой переменной.
Исследовательский анализ данных
Имя
На приведенной выше гистограмме показано распределение количества слов в названии элемента. Мы видим, что большинство имен имеют 4 слова, описывающие название элемента. Мы можем использовать это число при обработке имен на более поздних этапах.
Item_Condition_ID
Мы видим, что есть 5 чисел, описывающих состояние предмета, и большинство предметов имеют состояние 1, а предметов с идентификатором состояния 4 и 5 очень меньше по сравнению с остальными. Давайте посмотрим, как цена распределяется с идентификатором состояния предмета.
Предметы с идентификатором состояния 5 имеют максимальные значения, а диапазон предметов с идентификатором условия 2 и 3 одинаков. Мы также можем наблюдать, что, хотя состояние предметов уменьшается с 5 до 1, 75 значений процентиля и максимальные цены увеличиваются. (возможно, эти максимальные цены относятся к некоторым дорогостоящим электронным товарам).
Название_Категории
Название каждой категории имеет формат: Красота/Макияж/Лицо. Похоже, что для каждой категории есть подкатегории, давайте разделим названия этих категорий на основную категорию и подкатегории. После их разделения новые функции выглядят следующим образом:
Давайте проанализируем все три названия категорий один за другим.
Главная категория
Большинство элементов относятся к категории «женщины», а следующей категорией являются «красота» и «дети». Существует еще одна категория с именем «не задано», которую мы назвали при обработке отсутствующих значений, поэтому здесь описываются элементы, имена категорий которых не даются.
Мы видим, что ящичные диаграммы явно отличаются друг от друга, поэтому мы можем сказать, что если мы хорошо обработаем основную категорию в моделировании, это даст хорошие прогнозы цены. Позже мы увидим, как это обрабатывать в моделировании.
Подкатегория 1
Мы видим, что предметы, связанные с одеждой и косметикой, преобладают над всеми данными, и даже аксессуары, такие как украшения, обувь и т. д., которые связаны с модой, более многочисленны.
Кажется, что хотя некоторые подкатегории имеют одинаковые средние цены, большинство из них разные, поэтому средняя цена по подкатегории может внести свой вклад в наш прогноз.
Подкатегория 2
Даже в подкатегории 2 предметов, связанных с модой и одеждой, больше. данные, мы можем моделировать отдельно для каждой категории, если количество элементов в этой категории достаточно велико для хороших прогнозов.
В этой категории есть много подкатегорий, мы можем видеть, что есть некоторые подкатегории, где средняя цена велика, мы можем по-разному относиться к элементам подкатегорий во время моделирования, если это необходимо.
Название бренда
print(“No of unique brands: “,train[‘brand_name’].nunique()) No of unique brands: 4810
Для всех товаров существует 4810 брендов, давайте посмотрим на 10 лучших брендов по количеству товаров.
Неизвестно соответствует товарам, для которых не указано торговое название. Мы видим, что для большинства товаров:
brand_missing = train[train.brand_name=='unknown'].shape[0] print(100.0*brand_missing/train.shape[0]))
т. е. 42,68% от общего количества товаров, торговая марка не указана. Во-вторых, у большинства товаров в названиях торговых марок «Pink» и «Nike». Позже мы попытаемся вычислить эти неизвестные значения, используя методы условного исчисления, и посмотрим, улучшат ли они прогнозы.
Перевозки
Идентификатор доставки: 1, если стоимость доставки оплачивается продавцом и 0 покупателем. Из гистограммы видно, что для меньших цен продавец оплачивает стоимость доставки, и по мере увеличения цены товара покупатель оплачивает доставку, но есть некоторые случаи, когда обратное также верно. поэтому не могу сделать вывод: если покупатель оплачивает стоимость доставки, то цена высока.
описание предмета
word_count = train['item_description'].str.split().apply(len).value_counts() #returns the number of words with the frequency
Из распределения мы видим, что число слов в описании большинства предметов меньше 50. Мы будем использовать это число на более поздних этапах кодирования текста. Давайте посмотрим, какие слова встречаются чаще всего во всех описаниях предметов.
Интерпретация приведенного выше рисунка такова: чем больше размер слова, тем чаще оно встречается в описаниях предметов. Из частотности слов мы можем видеть, что слова «бренд» и «новый» встречаются в описании товара много раз, а это означает, что люди больше думают о бренде и о том, насколько «новый» товар.
Цена
Давайте проанализируем переменную цены в данных поезда. Обратите внимание, что у нас нет цены в тестовых данных, так как мы должны предсказать эту переменную.
for i in range(0, 101, 10): var =train["price"].values print("{} percentile value is {}".format(i,np.percentile(var,i))) 0 percentile value is 0.0 10 percentile value is 7.0 20 percentile value is 10.0 30 percentile value is 12.0 40 percentile value is 14.0 50 percentile value is 17.0 60 percentile value is 20.0 70 percentile value is 26.0 80 percentile value is 34.0 90 percentile value is 51.0 100 percentile value is 2009.0
Мы видим, что 90% товаров имеют цену ниже 51.
Почти все товары (99% товаров) имеют цену ниже 170. Давайте посмотрим на распределение цены.
Мы можем заметить, что цена большинства предметов находится в диапазоне 10–30.
Выполнив анализ всех функций, давайте очистим данные и обработаем их, а также создадим некоторые новые функции на основе функций существующего элемента и результатов анализа.
Предварительная обработка
Предварительная обработка текстовых данных
Название образца: 25 шт. НОВЫЙ 7,5x12
Описание образца: 25 шт. НОВЫЕ почтовые ящики с пузырьками из крафт-бумаги размером 7,5x12. Выровнены пузырчатой пленкой для защиты.
Мы видим, что есть много бесполезных данных, таких как специальные символы, короткие слова, такие слова, как, for и т. д., они будут присутствовать в каждом предложении (так называемые стоп-слова), поэтому они также бесполезны. Давайте удалить их.
Предварительная обработка Категориальных данных
пример подкатегории: Компьютеры и планшеты
Существуют специальные символы, такие как «&», «-». Давайте заменим все пробелы и специальные символы на «_».
Разработка функций
В этом разделе рассматривается извлечение новых функций с использованием атрибутов существующих функций.
Поскольку есть текстовые данные, мы можем извлечь оценки тональности всех описаний элементов. На основании проведенного нами анализа данных мы можем разработать новые функции. Ниже упомянуты некоторые функции, извлеченные из заданных данных, и они добавлены как новые столбцы в нашем фрейме данных.
Мы не можем быть уверены, помогут ли эти недавно добавленные функции в наших прогнозах или нет. Итак, давайте построим матрицу корреляции для всех этих функций с ценой. один другой.
Мы видим, что некоторые из новых функций, таких как mean_brand_cond, median_subcat1_price…, показывают хорошую связь с ценой, поэтому добавление новых функций прошло успешно.
Имея в руках все характеристики элемента, давайте приступим к кодированию характеристик, которое включает преобразование данных в числа, поскольку компьютерные алгоритмы работают только с числами.
Подготовка данных
Разделение данных поезда
После обучения мы не можем быть уверены, что модель будет иметь желаемую точность в производственной среде. Нам нужна какая-то гарантия предсказаний, на основе которых предсказывает наша модель. Для этого нам нужно проверить нашу модель, прежде чем тестировать ее на окончательных данных. Поэтому лучше проверить производительность нашей модели на невидимых данных перед тестированием на невидимых окончательных тестовых данных. Для этой цели мы берем небольшую часть (10%). из наших данных поезда, и после обучения мы проверим модель на этой небольшой части данных. Основываясь на производительности моделей на этой небольшой части невидимых данных, мы можем сказать, является ли наша модель недостаточной / чрезмерной / хорошо обобщенной. небольшая часть данных называется данными перекрестной проверки.
#train and cv split from sklearn.model_selection import train_test_split x_train, x_cv, y_train, y_cv = train_test_split(x, y, test_size=0.1, random_state=33)
Кодирование
Кодирование имеет дело с преобразованием всех наших нечисловых данных в числовые значения.
Категориальные данные:
Давайте сначала закодируем категориальные данные. Существует много подходов к кодированию категориальных данных. Здесь мы будем использовать One Hot Encoding.
Текстовые данные:
Что касается текстовых данных, существует множество методов кодирования текстовых данных в виде чисел, от простого Bag of Words до современных представлений векторов BERT, предварительно обученных. Мы будем использовать кодирование TF-IDF с 1–2 граммами.
Числовые данные:
мы нормализуем/стандартизируем числовые значения столбца. Здесь мы используем стандартный масштабатор.
Объединить все значения
Поскольку мы закодировали все функции, давайте объединим их в одну матрицу X_train и значения, которые мы собираемся предсказать, т. е. цену как y_train.
from scipy.sparse import hstack # stack all categorical and text sparse matrices x_train_sp_tfidf = hstack((x_train_brand_ohe, x_train_cat_ohe, x_train_subcat1_ohe, x_train_subcat2_ohe, \ x_train_dum,x_train_name_tfidf,x_train_text_tfidf)).tocsr() x_cv_sp_tfidf = hstack((x_cv_brand_ohe, x_cv_cat_ohe, x_cv_subcat1_ohe, x_cv_subcat2_ohe, \ x_cv_dum,x_cv_name_tfidf,x_cv_text_tfidf)).tocsr() # stack dense features with sparse matrix of categorical and text vectors #final data sets: X_train = hstack((temp1, x_train_sp_tfidf)).tocsr() X_cv = hstack((temp2, x_cv_sp_tfidf)).tocsr()
У нас есть окончательные данные, приступим к моделированию.
Моделирование
Давайте сначала начнем с классических алгоритмов машинного обучения. Я пробовал регрессию хребта, регрессию машины опорных векторов, регрессию дерева решений и методы ансамбля, такие как регрессия случайного леса и регрессор XGB. Наконец, я смоделировал многослойный модель перцептрона (MLP) и модель на основе рекуррентной нейронной сети (LSTM). Давайте рассмотрим эти модели одну за другой.
Ридж-регрессия
Гребневая регрессия — это линейная регрессия с регуляризацией L2. Производительность модели зависит от гиперпараметра этой модели: альфа, мы должны настроить его, используя данные поезда и протестировав его на данных перекрестной проверки для каждой альфы, и мы должны выбрать лучшее значение альфы, которое ни не соответствует, ни превосходит модель. Код для настройки модели приведен ниже.
Для лучшего значения альфа = 1 мы получили RMSLE для данных cv как: 0,458
SVM-регрессия
Машина опорных векторов пытается найти «лучший» запас, который лучше всего соответствует линии для заданных точек, и это снижает риск ошибки в данных. Мы должны настроить гиперпараметр для получения наилучшего значения.
Для лучшего значения альфа = 10 мы получили RMSLE для данных cv как: 0,466
Регрессия дерева решений
Регрессия дерева решений наблюдает за особенностями объекта и обучает модель в структуре дерева для прогнозирования данных в будущем для получения значимого непрерывного вывода. Здесь есть множество гиперпараметров для настройки, но мы будем настраивать только max_depth, min_Sample_split.
Из тепловой карты видно, что мы получили лучший показатель RMSLE 0,635 для значений max_depth = 10 и min_sample_split = 10.
Случайная лесная регрессия
Это метод ансамбля для уменьшения дисперсии модели. Поскольку наш набор данных велик (около 1 миллиона точек), и поскольку я использую Google Colab, существуют ограничения памяти, поэтому я не могу обучить модель со всеми точками. Следовательно Я взял подмножество заданных данных и обучил модель. Кроме того, я настроил только гиперпараметр max_depth.
Поскольку мы сократили наш набор данных из-за ограничений памяти, модель работает очень плохо, но нам, возможно, придется попробовать с полными данными, чтобы узнать производительность модели случайного леса.
XGBРегрессия
Это также один из методов ансамбля для уменьшения смещения модели. Из-за ограничений памяти в google colab я использовал только подмножество данных поезда для обучения. Я попытался настроить max_depth и n_estimators в качестве гиперпараметров.
С лучшими значениями max_depth=5 и числом оценщиков: 10, регрессор xgb хорошо справляется со значением RMSLE 0,498 по сравнению с некоторыми другими моделями, но мы не можем сделать идеальный вывод, так как мы тренировались с меньшим количеством данных.
Классические модели дают хорошие результаты, мы пробовали Ridge, SVM, DT, Random forest и XGBRegressor. Среди всех, ридж работает хорошо, и при обучении ансамблевых моделей, поскольку мы сократили данные из-за ограничений памяти, мы не можем сделать вывод, что мы получили от них лучшую производительность. Мы также можем заметить, что в нашем модели, поэтому классические модели хорошо справляются со своей задачей. Мы продолжим работу с моделями глубокого обучения и посмотрим, сможем ли мы улучшить оценку.
Модель МЛП
Давайте смоделируем простую модель многослойного персептрона (MLP) с нашими окончательными данными и посмотрим, улучшат ли нейронные сети прогнозы. Ниже приведена архитектура, которую я использовал для создания этой модели.
С размером пакета 512 и оптимизатором как Адам (со скоростью обучения: 0,001) мы получили лучший показатель RMSLE 0,402, что лучше, чем у всех моделей. Но, глядя на графики, мы видим, что модель переоснащается, что приводит к дисперсии модели. .
LSTM-модель
Поскольку у нас есть текстовые данные, а текст представляет собой последовательность, в которой следующее слово в предложении зависит от предыдущих слов, мы можем попробовать Рекуррентную нейронную сеть (RNN), потому что они хорошо запоминают поток последовательности. Сеть терминальной памяти (LSTM) здесь. Но эти сети требуют, чтобы данные были в определенном формате, поэтому мы должны предварительно обработать данные соответствующим образом. Ниже приведена архитектура, которую я использовал для построения этой модели.
Обучение модели
Текстовые данные: сначала мы объединяем все текстовые данные и генерируем токены и векторы заполнения для текстовых данных. Здесь я использовал предварительно обученные векторы Glove word2vec в качестве вложений для слоя встраивания, и эти вложения отправляются на слой LSTM.
Категориальные данные: возьмите категориальные данные и передайте их через слой встраивания, эти вложения изучаются во время обучения.
Числовые данные: Возьмите числовые данные и пропустите их через плотный слой.
Теперь объедините все входные данные и пройдите через плотные слои с отсевами и пакетной нормализацией по мере необходимости между слоями.
С использованием слоя LSTM для текстовых данных и внедрения слоев для категориальных переменных мы получили RMSLE 0,461, что лучше, чем у большинства классических алгоритмов. Мы только что запустили 15 эпох, и я также пробовал с 40 эпохами, но модель становится переобученной. , поэтому избегали использования большого количества эпох.
Сводка моделей
Ниже приводится сводка обученных моделей и оценка RMSLE, которую мы получили для соответствующих моделей.
Представление Kaggle
Окончательное представление kaggle включает в себя взвешенную сумму прогнозов лучших моделей. Я взял модель Ridge, модели MLP и LSTM и настроил веса, которые должны быть присвоены им, чтобы получить окончательные прогнозы, и окончательная модель, отправленная на kaggle: w1 * хребет+w2*mlp+w3*lstm.
Я получил оценку RMSLE по окончательным невидимым тестовым данным как 0,398, что составляет 1% лучших в таблице лидеров этой проблемы.
Улучшения существующих подходов
Я извлек новые функции, такие как median_brand_price,mean_subact1_price.., которые повысили производительность модели. В большинстве подходов, которые я видел, они не пытались использовать предварительно обученные векторы BERT, я пробовал их, но из-за ограничений памяти google colab, не могу использовать их в окончательном моделировании. Я пробовал разные кодировки текста и категориальные функции, немногие из них работали, и они были добавлены в окончательное моделирование.
Техники, которые я пробовал
- Пробовал предварительно обученную модель BERT для встраивания предложений, но из-за ограничений памяти в colab сеанс был прерван. Даже увеличение максимальной длины предложений на входе до 30 было неудачным, и если мы еще больше уменьшим максимальную длину, это будет бесполезно, поскольку мы теряют много текстовых данных.
- Пытались использовать предварительно обученные векторы Word2Vec с помощью перчатки, но по тем же причинам мы пропустили это. Даже после попытки с уменьшенными размерами и меньшим объемом данных проблема с памятью все еще существовала, и если мы еще больше уменьшим размеры и данные, модель не будет работать хорошо, поскольку у нас меньше измерений, не хватает контекстной информации.
- Поскольку использование ценовой переменной не дает хороших результатов, из некоторых ссылок на аналогичные проблемы мы взяли логарифмическое преобразование цены, и производительность модели значительно улучшилась, это делает вывод, что связь между данными характеристиками и ценой не является линейной и близка к экспоненциальный тренд.
Будущая работа
- Для лучшего кодирования текстовых данных мы можем попробовать использовать предварительно обученные вложения предложений BERT или аналогичные современные методы, поскольку они хорошо улавливают контекстное значение данного текста.
- Поскольку модели глубокого обучения дают хорошие результаты, мы можем попробовать некоторые сложные модели, включающие свертки текстовых данных.
- Мы можем попробовать использовать библиотеку Hyperas для тонкой настройки гиперпараметров в архитектурах нейронных сетей.
- Мы можем попытаться заменить недостающие значения с помощью библиотеки datawig и посмотреть, улучшится ли производительность.
Вывод
Основная цель этого тематического исследования — поэкспериментировать с различными алгоритмами машинного обучения на большом наборе данных. Это хорошая проблема kaggle для работы, так как она имеет большие данные и данные разных типов, такие как текстовые, категориальные и числовые. Существует много возможностей для разработки функций, мы можем попробовать множество методов. Надеюсь, я рассмотрел большое количество алгоритмы в этом примере. Вы можете обратиться к моему репозиторию GitHub за всеми фрагментами кода.
Я хотел бы услышать ваши отзывы, предложения или вопросы.
Вы можете связаться со мной в LinkedIn.
использованная литература
- https://www.kaggle.com/c/mercari-price-suggestion-challenge/обзор
- https://www.appliedaicourse.com/course/11/Applied-Machine-learning-course
- https://www.kaggle.com/lopuhin/mercari-golf-0-3875-cv-in-75-loc-1900-s
- https://www.kaggle.com/c/mercari-price-suggestion-challenge/discussion/50499
- https://www.kaggle.com/c/mercari-price-suggestion-challenge/discussion/50256