Данные гостиничного рынка и сравнительные данные компании STR и Google, опубликовавшие отчет, показывают, что отслеживание результатов поиска отелей может быть надежной оценкой бронирования отелей. Итак, наша цель сегодня - попытаться построить модель машинного обучения для прогнозирования результата события (бронирование или просто щелчок) для пользовательского события на основе их поиска и других атрибутов, связанных с этим пользовательским событием.
Данные
Данные общедоступны, их можно скачать с Kaggle. мы используем только обучающую выборку. В таблице ниже представлена схема набора данных.
import datetime import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns %matplotlib inline from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.decomposition import PCA from sklearn.metrics import classification_report from sklearn.metrics import confusion_matrix from sklearn.metrics import accuracy_score df = pd.read_csv('train.csv.gz', sep=',').dropna() df = df.sample(frac=0.01, random_state=99)
Чтобы иметь возможность обрабатывать локально, мы будем использовать 1% данных. После этого у нас все еще есть большое количество - 241 179 записей.
df.shape
(241179, 24)
count_classes = pd.value_counts(df['is_booking'], sort = True).sort_index() count_classes.plot(kind = 'bar') plt.title("Booking or Not booking") plt.xlabel("Class") plt.ylabel("Frequency")
Очевидно, что наши данные очень несбалансированы. Нам придется с этим разобраться.
Разработка функций
Процесс включает создание новых столбцов, таких как год, месяц, время планирования и количество ночей в отеле. И удалите столбцы, которые нам больше не нужны.
df["date_time"] = pd.to_datetime(df["date_time"]) df["year"] = df["date_time"].dt.year df["month"] = df["date_time"].dt.month df['srch_ci']=pd.to_datetime(df['srch_ci'],infer_datetime_format = True,errors='coerce') df['srch_co']=pd.to_datetime(df['srch_co'],infer_datetime_format = True,errors='coerce') df['plan_time'] = ((df['srch_ci']-df['date_time'])/np.timedelta64(1,'D')).astype(float) df['hotel_nights']=((df['srch_co']-df['srch_ci'])/np.timedelta64(1,'D')).astype(float) cols_to_drop = ['date_time', 'srch_ci', 'srch_co', 'user_id'] df.drop(cols_to_drop, axis=1, inplace=True)
Постройте корреляционную матрицу, используя тепловую карту, чтобы изучить корреляцию между функциями.
correlation = df.corr() plt.figure(figsize=(18, 18)) sns.heatmap(correlation, vmax=1, square=True,annot=True,cmap='viridis') plt.title('Correlation between different fearures')
Мы не видим, чтобы какие-либо две переменные очень сильно коррелировали.
Работа с несбалансированными данными
Я буду использовать метод недостаточной выборки для создания кадра данных с повторной выборкой.
booking_indices = df[df.is_booking == 1].index random_indices = np.random.choice(booking_indices, len(df.loc[df.is_booking == 1]), replace=False) booking_sample = df.loc[random_indices] not_booking = df[df.is_booking == 0].index random_indices = np.random.choice(not_booking, sum(df['is_booking']), replace=False) not_booking_sample = df.loc[random_indices] df_new = pd.concat([not_booking_sample, booking_sample], axis=0) print("Percentage of not booking clicks: ", len(df_new[df_new.is_booking == 0])/len(df_new)) print("Percentage of booking clicks: ", len(df_new[df_new.is_booking == 1])/len(df_new)) print("Total number of records in resampled data: ", len(df_new))
Перемешайте повторно выбранный фрейм данных.
df_new = df_new.sample(frac=1).reset_index(drop=True)
Назначьте функции и ярлык для нового фрейма данных.
X = df_new.loc[:, df_new.columns != 'is_booking'] y = df_new.loc[:, df_new.columns == 'is_booking']
PCA
Анализ главных компонентов, или PCA, представляет собой статистический метод преобразования данных большой размерности в данные низкой размерности путем выбора наиболее важных функций, которые собирают максимум информации о наборе данных. Мы надеемся, что PCA поможет нам найти компоненты с максимальной вариативностью.
Стандартизируйте набор данных.
scaler = StandardScaler() X=scaler.fit_transform(X) X
Применить PCA. В наших данных 23 функции.
pca = PCA(n_components=23) pca.fit(X)
Вычислить собственные значения.
var=np.cumsum(np.round(pca.explained_variance_ratio_, decimals=3)*100) var
В приведенном выше массиве мы видим, что первая функция объясняет 9,6% дисперсии в нашем наборе данных, а первые две объясняют 17,8% и так далее. Если мы используем все функции, мы улавливаем 100% дисперсии в наборе данных, таким образом, мы получаем некоторую выгоду, реализуя дополнительную функцию. Нет ни одной выдающейся особенности.
Сортировка и выбор.
plt.ylabel('% Variance Explained') plt.xlabel('# of Features') plt.title('PCA Analysis') plt.style.context('seaborn-whitegrid') plt.plot(var)
Судя по графику выше, мы должны сохранить все 23 функции.
Обучение, прогнозирование и оценка эффективности
Классификатор случайного леса
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=1) pca = PCA() X_train = pca.fit_transform(X_train) X_test = pca.transform(X_test) classifier = RandomForestClassifier(max_depth=2, random_state=0) classifier.fit(X_train, y_train) y_pred = classifier.predict(X_test) cm = confusion_matrix(y_test, y_pred) print(cm) print('Accuracy', accuracy_score(y_test, y_pred))
Логистическая регрессия
from sklearn.linear_model import LogisticRegression from sklearn.pipeline import Pipeline X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=1) pca = PCA(n_components=23) logReg = LogisticRegression() pipe = Pipeline([('pca', pca), ('logistic', logReg)]) pipe.fit(X_train, y_train) y_pred = pipe.predict(X_test) cm = confusion_matrix(y_test, y_pred) print(cm) print('Accuracy', accuracy_score(y_test, y_pred))
Возможно, мы сможем улучшить результаты до 70% с помощью Исчерпывающего поиска по сетке. Но для локального запуска требуется вечность. Я не буду здесь пробовать.
Как видите, прогнозировать количество бронирований отелей на основе имеющихся у нас данных - непростая задача. Нам нужно больше функций, таких как средняя дневная ставка, история предыдущих бронирований пользователей, наличие специальной акции, онлайн-отзывы об отелях и т. Д.
Начало работы со сбором данных перед машинным обучением!
Исходный код можно найти на Github. Наслаждайтесь остатком недели!