Нам всем знакомо это чувство, после того как мы заняли десятки миллионов долларов, чтобы начать нашу сеть пятизвездочных отелей и кропотливо создали серию роскошных гостиничных курортов с чрезмерным использованием заемных средств, мы сталкиваемся с большой кахуной: почти половина всех наших бронирований получает отменен.
Это число не уникально: согласно исследованию, проведенному D-edge Hospitality Solutions в 2018 году, почти 40% бронирований отелей по всему миру отменяются. Оставляя менеджеров отелей с огромными альтернативными издержками.
Обычное решение заключалось в слепом избыточном бронировании. К сожалению, это приносит с собой целый ряд новых проблем. Если количество отмен падает лишь незначительно, в отеле может быть больше гостей, чем номеров.
Но что, если бы можно было предсказать, какие гости, скорее всего, отменят бронирование, и соответствующим образом скорректировать ставку перебронирования? Это было бы здорово, не так ли? К счастью для вас, это то, что мы собираемся сделать сегодня, используя магию машинного обучения в Python.
Прежде всего, мы собираемся импортировать наши библиотеки машинного обучения и (ранее очищенный) набор данных:
import pandas as pd from sklearn.preprocessing import StandardScaler from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression from sklearn.neighbors import KNeighborsClassifier from yellowbrick.classifier import ConfusionMatrix from sklearn.metrics import classification_report from sklearn.dummy import DummyClassifier pd.read_csv('cleaned_csv'
Этот набор данных имеет комбинацию категориальных и числовых переменных. Чтобы алгоритм машинного обучения понимал данные, нам нужно фиктивно закодировать категориальные переменные и масштабировать числовые переменные.
Для этого мы определяем имена категориальных и числовых столбцов и запускаем следующий код:
#defining categorical variables: df_cat = df[['hotel','meal','market_segment','distribution_channel',\ 'reserved_room_type','assigned_room_type','deposit_type',\ 'customer_type','reservation_status']] #defining numeric variables: df_num = df[['lead_time','adults','children','babies',\ 'previous_cancellations','previous_bookings_not_canceled',\ 'booking_changes','days_in_waiting_list',\ 'required_car_parking_spaces','total_of_special_requests']] #Dummy encoding categorical data: df_dummies = pd.get_dummies(df_cat,drop_first=True) #Scaling numeric data: ss = StandardScaler() df_num_scaled = pd.DataFrame(ss.fit_transform(df_num), columns = ['lead_time','adults','children','babies','previous_cancellations',\ 'previous_bookings_not_canceled','booking_changes',\ 'days_in_waiting_list',\ 'required_car_parking_spaces','total_of_special_requests']) #concatenating the two dataframes: df_final = pd.concat([df_num_scaled,df_dummies,df['is_canceled']],axis=1) #dropping missing values: df_final = df_final.dropna()
Мы хотим разделить данные на обучающий набор и тестовый набор, чтобы мы могли проверить нашу модель на внешнюю достоверность:
X = df_sample.drop(columns=['is_canceled']) y = df_sample['is_canceled'] X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
Сначала мы подгоним фиктивную модель, которая просто возвращает частоту неотмен в качестве основы для нашей модели классификации:
#Fitting a Dummy Model: dummy = DummyClassifier(strategy='most_frequent') dummy.fit(X_train, y_train) dummy.score(X_test, y_test)
Фиктивная модель возвращает оценку 0,6355, что соответствует результатам исследования, проведенного D-edge Hospitality Solutions.
Теперь мы собираемся использовать модель логистической регрессии в качестве классификатора:
logreg = LogisticRegression() logreg.fit(X_train,y_train) logreg.score(X_train,y_train)
Модель логистической регрессии возвращает оценку 1,0.
Это сразу должно вызвать удивление. Оценка 1,0 по существу означает, что модель точно предсказывает, отменит ли кто-то бронирование, и не делает ошибок. Быстрый взгляд на матрицу путаницы наглядно демонстрирует это:
Скорее всего, есть переменная, которая идеально коррелирует с целевой переменной, которая вызывает это, и, конечно же, после проверки регрессора «reservation_status» мы можем увидеть:
Поэтому мы должны удалить этот столбец из набора данных, чтобы удалить этот источник «утечки» из данных. Мы снова запускаем логистическую модель без этого столбца и получаем гораздо более разумную оценку 0,812.
Давайте посмотрим на новую матрицу путаницы:
Как мы видим, отзыв намного лучше, чем точность. Другими словами, модель намного лучше правильно предсказывает, собирается ли кто-то отменить подписку (истинно положительный результат), чем сводит к минимуму неверные прогнозы, которые люди отменят, но не откажутся (ложный положительный результат). С точки зрения прибыльности гораздо лучше правильно предсказать большинство отмен и соответствующим образом скорректировать избыточное бронирование, чем свести к минимуму несколько ложных срабатываний, с которыми мы столкнемся.