Итак, ребята, вот еще один из моих самых любимых проектов. В этом блоге мы будем внедрять модель прогнозирования цен на авиабилеты с использованием различных методов, а также будем выполнять очень частую визуализацию данных, чтобы лучше понять наши данные. Это будет большой блог, поэтому, не вдаваясь в подробности, выпейте кофе и начните.
Полную статью с исходным кодом читайте здесь —https://machinelearningprojects.net/flight-price-prediction/
Посмотреть видео можно здесь — https://youtu.be/LFQ2JwEVf6M
Давай сделаем это…
Шаг 1 — Импорт библиотек, необходимых для прогнозирования цен на рейсы.
import pandas as pd import seaborn as sns import numpy as np import matplotlib.pyplot as plt import datetime as dt from sklearn.model_selection import train_test_split, RandomizedSearchCV from sklearn.ensemble import RandomForestRegressor, ExtraTreesRegressor import pickle
Шаг 2 — Чтение обучающих данных.
train_data = pd.read_excel('Flight Dataset/Data_Train.xlsx') train_data.head()
Шаг 3 — Проверка значений в столбце «Назначение».
train_data[‘Destination’].value_counts()
- В нашем наборе данных максимальное количество людей направляется в Кочин, затем в Бангалор, а затем в Дели.
Шаг 3.5 — Слияние Дели и Нью-Дели.
def newd(x): if x=='New Delhi': return 'Delhi' else: return x train_data['Destination'] = train_data['Destination'].apply(newd)
- Как мы видели выше, у нашего пункта назначения были Дели и Нью-Дели, поэтому мы объединили их оба.
Шаг 4 — Проверка информации о наших данных поезда.
train_data.info()
- Мы видим, что остановки Route и Total имеют значения 1 1 NULL каждая.
- Поэтому мы будем отбрасывать значения NULL дальше.
Шаг 5 — Преобразование столбцов дня и месяца в столбцы даты и времени.
train_data['Journey_day'] = pd.to_datetime(train_data['Date_of_Journey'],format='%d/%m/%Y').dt.day train_data['Journey_month'] = pd.to_datetime(train_data['Date_of_Journey'],format='%d/%m/%Y').dt.month train_data.drop('Date_of_Journey',inplace=True,axis=1) train_data.head()
- Мы извлечем день поездки и месяц поездки из даты поездки и создадим для них 2 столбца, как показано ниже.
- А затем мы опустим столбец «Дата поездки».
Шаг 6 — Извлечение часов и минут из времени.
train_data['Dep_hour'] = pd.to_datetime(train_data['Dep_Time']).dt.hour train_data['Dep_min'] = pd.to_datetime(train_data['Dep_Time']).dt.minute train_data.drop('Dep_Time',axis=1,inplace=True) train_data['Arrival_hour'] = pd.to_datetime(train_data['Arrival_Time']).dt.hour train_data['Arrival_min'] = pd.to_datetime(train_data['Arrival_Time']).dt.minute train_data.drop('Arrival_Time',axis=1,inplace=True) train_data.head()
- Как и выше, мы будем извлекать время отправления и минуты отправления из времени отправления.
- И то же самое будет сделано для времени прибытия.
- И после этого мы опустим оба столбца.
Шаг 7 — Проверка значений в столбце «Длительность».
train_data[‘Duration’].value_counts()
- Это продолжительность полетов.
- 550 полетов продолжительностью 2 часа 50 минут и так далее.
Шаг 8 — Удаление столбца «Длительность» и извлечение из него важной информации.
duration = list(train_data['Duration']) for i in range(len(duration)): if len(duration[i].split()) != 2: if 'h' in duration[i]: duration[i] = duration[i] + ' 0m' else: duration[i] = '0h ' + duration[i] duration_hour = [] duration_min = [] for i in duration: h,m = i.split() duration_hour.append(int(h[:-1])) duration_min.append(int(m[:-1])) train_data['Duration_hours'] = duration_hour train_data['Duration_mins'] = duration_min train_data.drop('Duration',axis=1,inplace=True) train_data.head()
Строка 1 — Создание списка всех длительностей, присутствующих в данных.
- Строка 3–8 — мы просто приводим все длительности к одному и тому же формату. Может быть случай, когда некоторая продолжительность полета будет составлять всего 30 м, поэтому мы запишем это как «0 ч 30 м», а также могут быть случаи, такие как 2 ч, поэтому мы запишем это как «2 ч 0 м».
- Строка 13–16 — просто разделите ее на 2 компонента: часы и минуты.
- Строка 18–19. Добавьте два столбца «Duration_hours» и «Duration_mins».
- Строка 21. Удалите исходный столбец «Длительность».
Шаг 9 — График зависимости авиакомпании от цены.
sns.catplot(x=’Airline’,y=’Price’,data=train_data.sort_values(‘Price’,ascending=False),kind=’boxen’,aspect=3,height=6)
- Из приведенного ниже графика мы можем сделать вывод, что бизнес Jet Airways является самым дорогостоящим авиаперевозчиком.
Шаг 10 — Создание фиктивных столбцов из столбца «Авиакомпания».
airline = train_data[['Airline']] airline = pd.get_dummies(airline,drop_first=True)
- Поскольку авиакомпания является категориальным столбцом, мы сделаем из него фиктивные столбцы.
Шаг 11 — Построение графика зависимости источника от цены.
# If we are going from Banglore the prices are slightly higher as compared to other cities sns.catplot(x='Source',y='Price',data=train_data.sort_values('Price',ascending=False),kind='boxen',aspect=3,height=4)
- Сюжет ниже говорит о том, что если вы едете из Бангалора, то куда бы вы ни отправились, вам придется заплатить наибольшую сумму денег.
Шаг 12 — Создание фиктивных столбцов из исходного столбца.
source = train_data[['Source']] source = pd.get_dummies(source,drop_first=True) source.head()
- Поскольку Source является категориальным столбцом, мы сделаем из него фиктивные столбцы.
Шаг 13 — Построение графика зависимости от цены.
# If we are going to New Delhi the prices are slightly higher as compared to other cities sns.catplot(x='Destination',y='Price',data=train_data.sort_values('Price',ascending=False),kind='boxen',aspect=3,height=4)
- Сюжет ниже говорит о том, что если вы едете в Нью-Дели, неважно откуда, вам придется заплатить самую большую сумму денег.
Шаг 14 — Создание фиктивных столбцов из столбца «Назначение».
destination = train_data[['Destination']] destination = pd.get_dummies(destination,drop_first=True) destination.head()
- Поскольку Destination также является категориальным столбцом, мы сделаем из него фиктивные столбцы.
Шаг 15 — Удаление ненужных столбцов.
train_data.drop([‘Route’,’Additional_Info’],inplace=True,axis=1)
Шаг 16 — Проверка значений в столбце Всего остановок.
train_data[‘Total_Stops’].value_counts()
Шаг 17 — Преобразование меток в числа в столбце Total_stops.
# acc to the data, price is directly prop to the no. of stops train_data['Total_Stops'].replace({'non-stop':0,'1 stop':1,'2 stops':2,'3 stops':3,'4 stops':4},inplace=True) train_data.head()
Шаг 18 — Проверка форм наших 4 фреймов данных.
print(airline.shape) print(source.shape) print(destination.shape) print(train_data.shape)
- Как мы видим, все эти 4 фрейма данных имеют одинаковое количество строк, а значит, мы все сделали правильно.
- И теперь мы можем присоединиться к ним.
Шаг 19 — Объедините все 4 фрейма данных.
data_train = pd.concat([train_data,airline,source,destination],axis=1) data_train.drop(['Airline','Source','Destination'],axis=1,inplace=True) data_train.head()
- Соедините все 4 фрейма данных.
- Удалите столбцы «Авиакомпания», «Источник» и «Назначение».
Шаг 20 — Извлечение данных о поездах.
X = data_train.drop('Price',axis=1) X.head()
- Здесь мы берем наши тренировочные данные.
- Мы взяли все столбцы, кроме столбца «Цена», который является нашим целевым столбцом.
Шаг 21 — Извлечение меток данных поезда.
y = data_train['Price'] y.head()
Шаг 22 — Проверка корреляций между столбцами.
plt.figure(figsize=(10,10)) sns.heatmap(train_data.corr(),cmap='viridis',annot=True)
- Просто проверка корреляции между различными характеристиками обучающих данных.
- Мы видим, что Total_stops сильно коррелирует с Duration_hours, что очень очевидно. Если нет. остановок увеличится, увеличится и продолжительность полета в часах.
- Кроме того, цена сильно коррелирует с общим количеством остановок, потому что увеличение количества остановок также потребует большого количества топлива, а это повысит цену.
Шаг 23 — Первое испытание модели ExtraTreesRegressor для прогнозирования цен на рейсы.
reg = ExtraTreesRegressor() reg.fit(X,y) print(reg.feature_importances_)
- Давайте поместим наши данные в ExtraTreeRegressor и проанализируем важность функций.
Шаг 24 — Проверка важности функции, заданной ExtraTreeRegressor.
plt.figure(figsize = (12,8)) feat_importances = pd.Series(reg.feature_importances_, index=X.columns) feat_importances.nlargest(20).plot(kind='barh') plt.show()
- Total_stops — это функция с наибольшей важностью при определении цены, как мы также видели выше.
- После этого день путешествия также играет большую роль в определении цены. В выходные обычно цены выше.
Шаг 25 — Разделение наших данных на данные обучения и тестирования.
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 42)
Шаг 26 — Обучение модели случайного лесного регрессора для прогнозирования цен на рейсы.
# Number of trees in random forest n_estimators = [int(x) for x in np.linspace(start = 100, stop = 1200, num = 12)] # Number of features to consider at every split max_features = ['auto', 'sqrt'] # Maximum number of levels in tree max_depth = [int(x) for x in np.linspace(5, 30, num = 6)] # Minimum number of samples required to split a node min_samples_split = [2, 5, 10, 15, 100] # Minimum number of samples required at each leaf node min_samples_leaf = [1, 2, 5, 10] random_grid = {'n_estimators': n_estimators, 'max_features': max_features, 'max_depth': max_depth, 'min_samples_split': min_samples_split, 'min_samples_leaf': min_samples_leaf} # Random search of parameters, using 5 fold cross validation, search across 100 different combinations rf_random = RandomizedSearchCV(estimator = RandomForestRegressor(), param_distributions = random_grid, scoring='neg_mean_squared_error', n_iter = 10, cv = 5, verbose=1, random_state=42, n_jobs = 1) rf_random.fit(X_train,y_train)
- Здесь мы используем RandomizedSearchCV, который просто случайным образом пробует комбинации и видит, какая из них лучше.
- Мы объявили параметры RandomForestRegressor, которые хотим попробовать.
Шаг 27 — Проверка лучших параметров, которые мы получили с помощью Randomized Search CV.
rf_random.best_params_
Шаг 28 — Делаем прогнозы
# Flight Price Prediction prediction = rf_random.predict(X_test)
Шаг 29 — Построение остатков.
plt.figure(figsize = (8,8)) sns.distplot(y_test-prediction) plt.show()
- Как мы видим, большинство остатков равны 0, что означает, что наша модель хорошо обобщает.
Шаг 30 — График y_test по сравнению с прогнозами.
plt.figure(figsize = (8,8)) plt.scatter(y_test, prediction, alpha = 0.5) plt.xlabel("y_test") plt.ylabel("y_pred") plt.show()
- Просто сопоставьте наши прогнозы с истинными значениями.
- В идеале это должна быть прямая линия.
Шаг 31 — Печать метрик.
print(‘r2 score: ‘, metrics.r2_score(y_test,y_pred))
Шаг 32 — Сохранение нашей модели.
file = open('flight_rf.pkl', 'wb') pickle.dump(rf_random, file)
Окончательные результаты прогнозирования цен на рейсы…
Чтобы узнать больше о машинном обучении, глубоком обучении, компьютерном зрении, НЛП и проектах Flask, посетите мой блог.
Для дальнейшего объяснения кода и исходного кода посетите здесь —
Итак, это все для этого блога, ребята, спасибо за то, что прочитали его, и я надеюсь, что вы возьмете что-то с собой после прочтения этого и до следующего раза 👋…