Машинное обучение

Направление путешествия ✈️ Рекомендация для пользователей Airbnb с XGBoost

Система рекомендаций с использованием Python, Pandas, Plotly, Numpy, Sklearn

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

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

Это то, о чем Airbnb, онлайн-рынок аренды жилья для отпуска, размышлял в 2015 году. В рамках конкурса Kaggle Airbnb запускает задачу, чтобы предсказать первое место для бронирования своих новых пользователей. Пользователи из США. В наборе данных есть 12 возможных мест назначения:

США: США, Франция: Франция, Калифорния: Канада, Великобритания: Великобритания, Испания: Испания, Италия: Италия, PT: Португалия, Голландия: Нидерланды, Германия: Германия, Австралия: Австралия, NDF: пункт назначения не найден.

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

Оглавление

Машинное обучение
EDA
Aibnb_df — наш обучающий набор данных. Это основной набор данных, который мы будем использовать для решения задачи.
Предварительная обработка данных
Обучение моделей
Улучшение модели
K-Fold Cross-Validation
Прогноз
Заключение

ЭДА

Исследование данных — важный шаг в решении этой проблемы. Это расширяет наш уровень понимания данных. Мы начнем с импорта некоторых библиотек.

#dataframe and numerical columns
import pandas as pd
import numpy as np
#Visualization
import matplotlib
import matplotlib.pyplot as plt
import plotly.express as px 
import seaborn as sns

Затем мы прочитаем некоторые кадры данных, которые нам дали.

airbnb_df=pd.read_csv(path)
age_df=pd.read_csv(path1)
country_df=pd.read_csv(path2)
test_df=pd.read_csv(path3)
submission_df=pd.read_csv(path4)
session_df=pd.read_csv(path5)

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

Набор данных содержит 213451 строку и 16 столбцов.

Давайте посмотрим на Columns:

  • ID: идентификатор пользователя
  • Date_account_created: дата создания учетной записи.
  • Timestamp_first_active: временная метка первого действия, обратите внимание, что оно может быть раньше, чем date_account_created или date_first_booking, поскольку пользователь может выполнить поиск перед регистрацией date_first_booking: дата первого бронирования.
  • Пол
  • Возраст
  • Signup_method: веб-сайт Airbnb, Facebook или Google.
  • Signup_flow: страница, с которой пользователь пришел зарегистрироваться.
  • Язык: выбор международного языка.
  • Affiliate_channel: какой платный маркетинг
  • Affiliate_provider: где маркетинг, например. гугл, крейгслист, другое
  • First_affiliate_tracked: с чем первым взаимодействовал пользователь перед регистрацией.
  • Signup_app
  • First_device_type
  • Первый_браузер
  • Country_destination: это целевая переменная для прогнозирования.

Age_df представляет возрастную группу пользователей.

Session_df представляет действия каждого пользователя на веб-сайте.

Country_df представляет координаты стран назначения.

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

Выводы:

  • Date_account_created и date_first_booking экспоненциальны со временем с 2010 по 2014 год. Однако с 2014 по 2015 год количество бронирований уменьшилось.
  • Путешествует больше женщин, чем мужчин. Однако большинство людей не раскрывают свой пол.
  • Средний возраст пользователей составляет от 30 до 34 лет. Как мы предполагаем, у нас большой всплеск в 37 лет.
  • Большинство людей получают доступ и открывают для себя Airbnb через веб-сайт. Facebook — это еще один способ, с помощью которого пользователи регистрируются на веб-сайте.
  • Большинство пользователей в США говорят по-английски
  • Лучшие браузеры для доступа к Airbnb — Chrome, Safari и Firefox.
  • Люди чаще всего используют устройства Mac, Windows Desktop, iPhone.
  • Пункт назначения, куда люди едут, называется «NDF». Во-вторых, большинство американцев путешествуют по своей стране. Зарубежные направления, в которые американцы путешествуют, — это Франция, Канада и Англия. Тем не менее, они все еще малы по сравнению с путешествиями по штатам.

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

Мы выполним некоторую предварительную обработку данных, чтобы подготовить наши данные перед применением какой-либо статистической модели.

Мы начнем с преобразования данных в объект DateTime и извлечения года, месяца и дня в качестве других входных переменных.

for data in [airbnb_df,test_df]:
    data.date_account_created=pd.to_datetime(data['date_account_created'])
    data['account_year']=data.date_account_created.dt.year
    data['account_month']=data.date_account_created.dt.month
    data['account_day']=airbnb_df.date_account_created.dt.day

Затем мы проверим, есть ли у нас недостающие данные.

airbnb_df.isna().sum()
timestamp_first_active        0
gender                        0
age                       87990
signup_method                 0
signup_flow                   0
language                      0
affiliate_channel             0
affiliate_provider            0
signup_app                    0
first_device_type             0
first_browser                 0
account_year                  0
account_month                 0
account_day                   0
country_destination           0
dtype: int64

У нас отсутствует 87990 значений. Проблема заключается в распределении возрастной переменной. Мы изменим некоторое значение, которое больше 100 и меньше 18, на значение nan. Затем мы заменим значение nan на средний возраст.

for data in [airbnb_df,test_df]:
    data.age=data.age.apply(lambda x: np.nan if x<18 else x)
    data.age=data.age.apply(lambda x: np.nan if x>100 else x)
#remplace the nan value with the age mean
for data in [airbnb_df,test_df]:
    data.age.fillna(data.age.mean(),inplace=True)

Давайте еще раз проверим, есть ли какая-либо отсутствующая переменная.

airbnb_df.isna().sum()
timestamp_first_active    0
gender                    0
age                       0
signup_method             0
signup_flow               0
language                  0
affiliate_channel         0
affiliate_provider        0
signup_app                0
first_device_type         0
first_browser             0
account_year              0
account_month             0
account_day               0
country_destination       0
dtype: int64

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

def remove_outliers(df,name='feature'):
    #Store the 25th and 75th percentile 
    q25,q75=percentile(df[name],25),percentile(df[name],75)
    #Calculate the Interquartile range
    iqr_cut=1.5*(q75-q25)
    #Create variable of lower and upper cut
    lower,upper=q25-iqr_cut,q75+iqr_cut
    #Remove the outliers
    df=df[(df[name] >= lower) & (df[name] <= upper)]
    return df

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

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

#Normalization
scaler=MinMaxScaler()
inputs[numerical_cols]=scaler.fit_transform(inputs[numerical_cols])

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

#label encoding
encoder=LabelEncoder()
for col in categorical_cols:
    inputs[col]=encoder.fit_transform(inputs[col])

кодировка метки преобразует значение столбца в число.

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

enc_countries={'NDF':0,'US':1,'FR':2,'CA':3,'GB':4,'ES':5,'IT':6,'PT':7,'NL':8,'DE':9,'AU':10,'other':11}
target['country_destination']=target['country_destination'].apply(lambda x:enc_countries[x])

Обучите модели

В этом проекте мы будем использовать 4 модели:

  • Древо решений
  • Случайный лес
  • КНН
  • XGBoost

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

Случайный лес — это модель контролируемого обучения, в которой используется ensemble learning множества деревьев решений, выходные данные которых основаны на среднем значении выходных данных этих деревьев. Ensemble learning — это метод, который объединяет множество моделей для решения проблемы.

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

XGBoost, также известный как Extreme Gradient Boosting, представляет собой алгоритм, в котором используются два метода: градиент и повышение на ансамбле деревьев. Градиент означает, что каждое дерево используется для уменьшения потерь предыдущих итераций. Повышение – это факт обучения новой модели, улучшающей существующую.

#Store results
names,score_train,score_val=[],[],[]
#Evaluate model
models=get_models()
for name,model in models.items():
#     score1,score2=evalutate_model(model,X,y)
    score_train.append(score1)
    score_val.append(score2)
    names.append(name)
    print('{}:\n(train_score): {:.2f}%, (val_score): {:.2f}%\n'.format(name,score_train[0]*100,score_val[0]*100))

Результат:

xgb:
(train_score): 65.19%, (val_score): 65.90%

knn:
(train_score): 69.03%, (val_score): 61.36%
rf:
(train_score): 98.03%, (val_score): 58.84%

tree:
(train_score): 98.01%, (val_score): 52.52%

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

Улучшить модель

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

#XGB Classifier
XGB= XGBClassifier(random_state=3,n_jobs=-1,max_depth=5,use_label_encoder=False)

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

Normalized Discounted Cumulative Gain, также известный как NDCG, является показателем качества ранжирования. Это среднее значение суммы всех релевантных баллов, которые были обесценены путем деления на журнал соответствующих позиций в наборе рекомендаций.

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

Давайте рассмотрим два набора рекомендаций:

Рекомендуемый балл = [3,8,4,2,5]

Идеальный рекомендуемый балл = [8,5,4,3,2]

Соответствующая оценка DCG будет:

DCG=3/ log₂(1+1) +8/ log₂(2+1) + 4/ log₂(3+1) + 2/ log₂(4+1)+ 5/ log₂(5+1) = 12,84

iDCG= 8/ log₂(1+1) +5/ log₂(2+1) + 4/ log₂(3+1) + 3/ log₂(4+1)+ 2/ log₂(5+1) = 15.22

Группа NDCG для рекомендации будет следующей:

NDCG = DCG/iDCG=12,84/15,22=0,84

Мы создадим функцию, которая поможет нам в этом процессе.

def evaluate_model(model,X_train,y_train,X_val,y_val):
    model.fit(X_train,y_train,eval_metric='merror')
    #Predict the probabilities of the train and val target
    xgb_predict=model.predict_proba(X_train)
    xgb_predict_val=model.predict_proba(X_val)
#transform the target into one hot encoder array
    y_train1 = pd.get_dummies(y_train).to_numpy()
    y_val1 = pd.get_dummies(y_val).to_numpy()
#Compute the ndcg_score
    train_score= ndcg_score(y_train1,xgb_predict)
    val_score= ndcg_score(y_val1,xgb_predict_val)
#     print('train_acc: {:2f}%, val_acc: {:2f}%'.format(train_score*100, val_score*100))
    return train_score,val_score,model

K-кратная перекрестная проверка

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

Перекрестная проверка или k-кратная перекрестная проверка — это процедура повторной выборки, используемая для оценки модели машинного обучения. Он принимает один параметр k, который разбивает данные на k групп. Итак, если K равно 5, данные будут разделены 5 раз на 5 раз.

kfold=KFold(5)
t_score,v_score=[],[]
for train_idx,val_idx in kfold.split(X):
    print('First Fold...\n')
    X_train,X_val=X.iloc[train_idx],X.iloc[val_idx]
    y_train,y_val=y.iloc[train_idx],y.iloc[val_idx]
    train_score,val_score,model=evaluate_model(XGB,X_train,y_train,X_val,y_val)
    t_score.append(train_score)
    v_score.append(val_score)
print('mean train_acc: {:2f}%, mean val_acc: {:2f}%'.format(np.mean(t_score), np.mean(v_score)))

В итоге мы получили средний балл 85,62% для нашего набора поездов и 84,14% для нашего набора проверки. Это огромное улучшение по сравнению с нашей первой попыткой.

Мы рассмотрим важность каждой функции в модели.

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

Прогноз

Теперь давайте предскажем тестовый набор. Мы создадим функцию predict_test, которая поможет нам.

def predict_test(df):
    #Normalization
    scaler=MinMaxScaler()
    df[numerical_cols]=scaler.fit_transform(df[numerical_cols])
    #label encoding
    encoder=LabelEncoder()
    for col in categorical_cols:
        df[col]=encoder.fit_transform(df[col])
    #Define X variable
    X=df[numerical_cols + categorical_cols]
    print('Processing Destinations ....\n')
    pred=XGB.predict_proba(X)
    if len(df) == 1:
        print('Country of destination: ',enc_label[np.argsort(pred)[::-1][:5]]) # return the label
    return pred

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

pred1=predict_test(input1)
# predict 5 destination for 5 users
for i in range(len(test_id)):
    idx = test_id[i]
    ids += [idx]*5 
    countries += [enc_label[ar] for ar in np.argsort(pred[i])[::-1]][:5]

После отправки прогноза на Kaggle я получил 85,05% на тестовом наборе.

Заключение

  • Статистические модели, такие как дерево решений, KNN, случайный лес и XGBoost, являются полезными процедурами, которые сопоставляют входные данные с выходными для решения задач классификации.
  • Max Depth, гиперпараметр, управляет количеством обучающих примеров, которые будет использовать модель, и может уменьшить переоснащение.
  • Разработка признаков может улучшить производительность модели.
  • K-fold — это метод повторной выборки, который оценивает навыки модели машинного обучения на невидимых данных и снижает высокую дисперсию.
  • NDCG — это хорошая метрика ранжирования для рекомендательных систем, которые учитывают соответствующую оценку в наборе рекомендаций.

Будущая работа

  • Создание небольшого приложения с использованием Streamlit для развертывания модели.
  • Разверните приложение с помощью Heroku.

Ссылки

coursera: https://www.coursera.org/learn/machine-learning

jovian: https://jovian.ai/learn/machine-learning-with-python-zero-to-gbms

Chandekar: https://towardsdatascience.com/evaluate-your-recommendation-engine-using-ndcg-759a851452d1

Вот ссылка на блокнот.

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