Merge pull request 'kurmyza_pavel_lab_5 is ready' (#104) from kurmyza_pavel_lab_5 into main
Reviewed-on: http://student.git.athene.tech/Alexey/IIS_2023_1/pulls/104
This commit is contained in:
commit
02422f4eff
53
kurmyza_pavel_lab_5/README.md
Normal file
53
kurmyza_pavel_lab_5/README.md
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# Лабораторная работа №5
|
||||||
|
|
||||||
|
## ПИбд-41, Курмыза Павел
|
||||||
|
|
||||||
|
Датасет по варианту: https://www.kaggle.com/datasets/jessemostipak/hotel-booking-demand.
|
||||||
|
|
||||||
|
Данный набор данных содержит информацию о бронировании городской и курортной гостиниц и включает в себя такие
|
||||||
|
сведения, как время бронирования, продолжительность пребывания, количество взрослых, детей и/или младенцев, количество
|
||||||
|
свободных парковочных мест и т.д.
|
||||||
|
|
||||||
|
## Как запустить ЛР
|
||||||
|
|
||||||
|
- Запустить файл main.py
|
||||||
|
|
||||||
|
## Используемые технологии
|
||||||
|
|
||||||
|
- Язык программирования Python
|
||||||
|
- Библиотеки: sklearn, numpy, pandas
|
||||||
|
|
||||||
|
## Что делает программа
|
||||||
|
|
||||||
|
Программа решает задачу кластеризации на выбранном датасете: выделение наиболее прибыльных посетителей отелей на основе
|
||||||
|
их времени прибывания и средней цены одной ночи пребывания в отели. Решение достигается в несколько этапов:
|
||||||
|
|
||||||
|
- Предобработка данных
|
||||||
|
- Стандартизация данных и приведение их к виду, удобном для работы с моделями ML
|
||||||
|
- Использование модели кластеризации K-средних
|
||||||
|
- Визуализация полученных результатов и вывод
|
||||||
|
|
||||||
|
## Тестирование
|
||||||
|
|
||||||
|
Теперь мы рассмотрели задачу кластеризации K-средних, и проанализируем результаты каждого
|
||||||
|
кластера, чтобы определить наиболее прибыльных клиентов в нашем наборе данных на основе времени выполнения заказа и ADR.
|
||||||
|
Первая проблема, с которой мы сталкиваемся, когда хотим использовать кластеризацию с помощью K-средних, - это
|
||||||
|
определение оптимального количества кластеров, которые мы хотим получить в качестве результатов. Поэтому сначала для
|
||||||
|
определения количества кластеров мы использовали метод локтя:
|
||||||
|
|
||||||
|
![Кластеры](clusters.jpg)
|
||||||
|
|
||||||
|
Для определения оптимального количества кластеров необходимо выбрать значение k, после которого искажение начинает
|
||||||
|
линейно уменьшаться. Таким образом, мы пришли к выводу, что оптимальное количество кластеров для данных равно 4. Поэтому
|
||||||
|
мы запустили алгоритм K-средних на основе lead_time и ADR с количеством кластеров, равным 4, и вывели центры кластеров:
|
||||||
|
|
||||||
|
![Центры кластеров](centers.jpg)
|
||||||
|
|
||||||
|
## Вывод
|
||||||
|
|
||||||
|
Наиболее прибыльными считаются клиенты с наименьшим временем пребывания и наибольшим ADR, т.е. клиенты, попавшие в
|
||||||
|
зеленый кластер. В то время как красная категория показывает самый низкий ADR и самое высокое (наименее выгодное) время
|
||||||
|
пребывания. В нашем случае после визуализации графика мы можем задать такие вопросы, как: почему у
|
||||||
|
одних клиентов время пребывания меньше, чем у других? и есть ли вероятность, что клиенты в определенных странах
|
||||||
|
соответствуют этому профилю? и т.д. На все эти вопросы алгоритм кластеризации K-средних может и не ответить напрямую,
|
||||||
|
но сведение данных в отдельные кластеры обеспечивает надежную основу для постановки подобных вопросов.
|
BIN
kurmyza_pavel_lab_5/centers.jpg
Normal file
BIN
kurmyza_pavel_lab_5/centers.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 47 KiB |
BIN
kurmyza_pavel_lab_5/clusters.jpg
Normal file
BIN
kurmyza_pavel_lab_5/clusters.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
119391
kurmyza_pavel_lab_5/hotel_bookings.csv
Normal file
119391
kurmyza_pavel_lab_5/hotel_bookings.csv
Normal file
File diff suppressed because it is too large
Load Diff
81
kurmyza_pavel_lab_5/main.py
Normal file
81
kurmyza_pavel_lab_5/main.py
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
import pandas as pd
|
||||||
|
from sklearn.model_selection import train_test_split
|
||||||
|
import datetime as dt
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import seaborn as sns
|
||||||
|
from sklearn.preprocessing import LabelEncoder
|
||||||
|
import sklearn.cluster as cluster
|
||||||
|
|
||||||
|
# Чтение данных датасета
|
||||||
|
df = pd.read_csv('hotel_bookings.csv')
|
||||||
|
|
||||||
|
# Удаление строк, содержащих отсутствующие значения
|
||||||
|
df = df[df['children'].notna()]
|
||||||
|
df = df[df['country'].notna()]
|
||||||
|
|
||||||
|
# Объединение столбцов 'arrival_date_year', 'arrival_date_month', 'arrival date day_of_month' в столбец
|
||||||
|
# 'arrival_date', содержащий день, месяц и год приезда клиента в формате datetime
|
||||||
|
df["arrival_date_month"] = pd.to_datetime(df['arrival_date_month'], format='%B').dt.month
|
||||||
|
df["arrival_date"] = pd.to_datetime({"year": df["arrival_date_year"].values,
|
||||||
|
"month": df["arrival_date_month"].values,
|
||||||
|
"day": df["arrival_date_day_of_month"].values})
|
||||||
|
df = df.drop(columns=['arrival_date_year', 'arrival_date_month', 'arrival_date_day_of_month'])
|
||||||
|
|
||||||
|
# Преобразование типа столбца reservation_status_date в datetime
|
||||||
|
df["reservation_status_date"] = pd.to_datetime(df["reservation_status_date"], format='%Y-%m-%d')
|
||||||
|
|
||||||
|
# Заполнение нулевых значений в столбцах средним значением каждого столбца
|
||||||
|
for column in ['agent', 'company', 'arrival_date']:
|
||||||
|
df[column] = df[column].fillna(df[column].mean())
|
||||||
|
|
||||||
|
# Удаляем повторяющиеся значения
|
||||||
|
df.drop_duplicates(inplace=True)
|
||||||
|
|
||||||
|
# Преобразование категориальных переменных в числовые переменные для того, чтобы модель могла с ними работать
|
||||||
|
categoricalV = ["hotel", "meal", "country", "market_segment", "distribution_channel", "reserved_room_type",
|
||||||
|
"assigned_room_type", "deposit_type", "customer_type"]
|
||||||
|
df[categoricalV[1:11]] = df[categoricalV[1:11]].astype('category')
|
||||||
|
|
||||||
|
df[categoricalV[1:11]] = df[categoricalV[1:11]].apply(lambda x: LabelEncoder().fit_transform(x))
|
||||||
|
|
||||||
|
df['hotel_Num'] = LabelEncoder().fit_transform(df['hotel'])
|
||||||
|
|
||||||
|
df['numerical_larrival_date'] = df['arrival_date'].map(dt.datetime.toordinal)
|
||||||
|
df['numerical_reservation_status_date'] = df['reservation_status_date'].map(dt.datetime.toordinal)
|
||||||
|
|
||||||
|
df["is_canceled"].replace({'not canceled': 0, 'canceled': 1}, inplace=True)
|
||||||
|
df["reservation_status"].replace({'Canceled': 0, 'Check-Out': 1, 'No-Show': 2}, inplace=True)
|
||||||
|
|
||||||
|
# Определение входных и выходных значений
|
||||||
|
usefull_columns = df.columns.difference(['hotel', 'hotel_Num', 'arrival_date', 'reservation_status_date'])
|
||||||
|
X = df[usefull_columns]
|
||||||
|
Y = df["hotel_Num"].astype(int)
|
||||||
|
|
||||||
|
# Деление данных на тестовую и обучающую выборки
|
||||||
|
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.3, random_state=150)
|
||||||
|
|
||||||
|
# Определение оптимального количества кластеров
|
||||||
|
df_Short = df[['lead_time', 'adr']]
|
||||||
|
|
||||||
|
K = range(1, 12)
|
||||||
|
wss = []
|
||||||
|
for k in K:
|
||||||
|
kmeans = cluster.KMeans(n_clusters=k, init="k-means++")
|
||||||
|
kmeans = kmeans.fit(df_Short)
|
||||||
|
wss_iter = kmeans.inertia_
|
||||||
|
wss.append(wss_iter)
|
||||||
|
|
||||||
|
mycenters = pd.DataFrame({'Clusters': K, 'WSS': wss})
|
||||||
|
|
||||||
|
sns.scatterplot(x='Clusters', y='WSS', data=mycenters, marker="+")
|
||||||
|
|
||||||
|
# Решение задачи кластеризации с использованием K-Means
|
||||||
|
kmeans = cluster.KMeans(n_clusters=4, init="k-means++")
|
||||||
|
kmeans = kmeans.fit(df[['lead_time', 'adr']])
|
||||||
|
df['Clusters'] = kmeans.labels_
|
||||||
|
|
||||||
|
# Визуализируем кластеры
|
||||||
|
sns.lmplot(x="lead_time", y="adr", hue='Clusters', data=df)
|
||||||
|
plt.ylim(0, 600)
|
||||||
|
plt.xlim(0, 800)
|
||||||
|
plt.show()
|
Loading…
Reference in New Issue
Block a user