<jupyter_start><jupyter_text>Описание проектаКомпания «Чётенькое такси» собрала исторические данные о заказах такси в аэропортах. Чтобы привлекать больше водителей в период пиковой нагрузки, нужно спрогнозировать количество заказов такси на следующий час. Постройте модель для такого предсказания.Значение метрики *RMSE* на тестовой выборке должно быть не больше 48. Инструкция по выполнению проекта1. Загрузите данные и выполните их ресемплирование по одному часу.2. Проанализируйте данные.3. Обучите разные модели с различными гиперпараметрами. Сделайте тестовую выборку размером 10% от исходных данных.4. Проверьте данные на тестовой выборке и сделайте выводы. Описание данныхДанные лежат в файле `taxi.csv`. Количество заказов находится в столбце '*num_orders*' (от англ. *number of orders*, «число заказов»).  1. Подготовка<jupyter_code>#Подключим необходимые библиотеки для проекта
import numpy as np
import pandas as pd
import lightgbm as lgb
import seaborn as sns
sns.set_style("darkgrid")
import warnings
warnings.filterwarnings('ignore')
import matplotlib.pyplot as plt
from pylab import rcParams
rcParams['figure.figsize'] = 10, 5
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import mean_absolute_error
from catboost import CatBoostRegressor
from statsmodels.tsa.seasonal import seasonal_decompose
class DataScience:

    def rmse(self,predictions, targets): 
        return np.sqrt(((predictions - targets) ** 2).mean())
    
    
    def plot_feature_importance(self,importance,names,model_type):

        feature_importance = np.array(importance)
        feature_names = np.array(names)

        #Create a DataFrame using a Dictionary
        data={'feature_names':feature_names,'feature_importance':feature_importance}
        fi_df = pd.DataFrame(data)

        #Sort the DataFrame in order decreasing feature importance
        fi_df.sort_values(by=['feature_importance'], ascending=False,inplace=True)

        #Define size of bar plot
        plt.figure(figsize=(10,8))
        #Plot Searborn bar chart
        sns.barplot(x=fi_df['feature_importance'], y=fi_df['feature_names'])
        #Add chart labels
        plt.title(model_type + 'FEATURE IMPORTANCE')
        plt.xlabel('FEATURE IMPORTANCE')
        plt.ylabel('FEATURE NAMES')
        
        
ds = DataScience()
#Откроем файл с данными. 
df = pd.read_csv('/datasets/taxi.csv', index_col=[0], parse_dates=[0])
#выведем первые 5 строк
df.head()
df.info()
#Проверим наличие пустых значений
df.isna().sum()
#Проверим упорядочен ли наш index
print(df.index.is_monotonic)<jupyter_output>True<jupyter_text>2. Анализ<jupyter_code>#Проведем ресемплирование по 1 часу, неделе и месяцу
monthly_stat= df.resample('1M').sum()
weekly_stat = df.resample('1W').sum()
hourly_stat = df.resample('1H').sum()
#Посмотрим на статистику заказов в разбивке по месяцам
sns.lineplot(x=monthly_stat.index,y=monthly_stat['num_orders'])
#Посмотрим на статистику заказов в разбивке по неделям
sns.lineplot(x=weekly_stat.index,y=weekly_stat['num_orders'])
#Посмотрим на скользящее среднее и скользящее стандартное отклонение
hourly_stat['mean'] = hourly_stat['num_orders'].rolling(25).mean()
hourly_stat['std'] = hourly_stat['num_orders'].rolling(25).std()
hourly_stat.plot()
#Сделаем копию датасета чтобы провести анализ
df_copy = df.copy()
df_copy = df_copy.resample('1H').sum()
df_copy['rolling_mean'] = df_copy['num_orders'].shift().rolling(12).mean()
df_copy['std'] = df_copy['num_orders'].rolling(12).std()
df_copy = df_copy.dropna()
#
decomposed_df = seasonal_decompose(df_copy)
decomposed_df.trend.plot(title='Тренд', figsize=(15,4))
decomposed_df.seasonal.tail(24*7).plot(title='Сезонность', figsize=(15,4))
plt.figure(figsize=(15, 4))
decomposed_df.seasonal['2018-05-10':'2018-05-11'].plot(ax=plt.gca(), figsize=(15,4))
plt.title('Сезонность в течении дня')
plt.tight_layout()<jupyter_output><empty_output><jupyter_text>Вывод: - На графике "Тренд" можно увидеть, что количество заказов постепенно увеличивается.- На графике сезонность разбитое на неделю видно, как количество заказов по выходным меньше чем в другие дни- На третьем графике количество заказов к утру намного меньше, чем в другое время  3. Обучение<jupyter_code>#выполним ресемплирование по одному часу
df = df.resample('1H').sum()

#Создадим признаки
def make_features(data, max_lag, rolling_mean_size):
    data['dayofweek'] = data.index.dayofweek
    data['hour'] = data.index.hour
    
    for lag in range(1, max_lag + 1):
        data['lag_{}'.format(lag)] = data['num_orders'].shift(lag)

    data['rolling_mean'] = data['num_orders'].shift().rolling(rolling_mean_size).mean()

make_features(df, 9, 9)
df.describe()
#Разделим нашу таблилцу на обучающую и тестовую выборки
train, test = train_test_split(df, shuffle=False, test_size=0.1)
train = train.dropna()
#Определим признаки и целевой признак у обучающей и тестовой выборк
X = train.drop(['num_orders'], axis=1)
y = train['num_orders']
X_test = test.drop(['num_orders'],axis=1)
y_test = test['num_orders']
#Проверим правильно ли расположены временные даннные, нельзя допустить в обучающую выборку данные из будущего
display(train.head(3))
display(test.head(3))
#Размеры обучающей и тестовой выборки
print('Размер обучающей выборки: {} объектов, {} признаков'.format(X.shape[0], X.shape[1]))
print('Размер тестовой выборки: {} объектов, {} признаков'.format(X_test.shape[0], X_test.shape[1]))<jupyter_output>Размер обучающей выборки: 3965 объектов, 12 признаков
Размер тестовой выборки: 442 объектов, 12 признаков<jupyter_text>LinearRegression<jupyter_code>from sklearn.linear_model import LinearRegression

lr = LinearRegression(n_jobs=-1)
lr.fit(X,y)
lr_predictions = lr.predict(X_test)
print('RMSE:', ds.rmse(lr_predictions,y_test))
#Попробуем подобрать параметры с помощью цикла
estimators = [50,100,200,300]
forleaves = [2,5,7,12]


for estim, leaves in zip(estimators, forleaves):
    lgb_model = lgb.LGBMRegressor(n_estimators=estim, num_leaves=leaves)
    lgb_model.fit(X,y)
    predictions = lgb_model.predict(X)
    print('RMSE with n_estimators : {} and num_leaves: {} is {}'.format(estim, leaves, ds.rmse(predictions, y)))<jupyter_output>RMSE with n_estimators : 50 and num_leaves: 2 is 29.447685769072727
RMSE with n_estimators : 100 and num_leaves: 5 is 22.159400472645576
RMSE with n_estimators : 200 and num_leaves: 7 is 19.212092776098753
RMSE with n_estimators : 300 and num_leaves: 12 is 14.89407898647034<jupyter_text>LightGBM показал лучший результат на обучающей выборке с ним и будем работать дальше  LightGBMRegressor  4. Тестирование<jupyter_code>model = lgb.LGBMRegressor(
                          n_estimators=300,
                          num_leaves=12,
                          objective='regression'
)

model.fit(X,y)
predictions = model.predict(X_test)
print('RMSE на тестовой выборке:', ds.rmse(predictions,y_test))<jupyter_output>RMSE на тестовой выборке: 43.92340606427539<jupyter_text>Feature Importance<jupyter_code>#Посмотрим feature importance у модели lightgbm
ds.plot_feature_importance(model.feature_importances_,X_test.columns,'LightGBM ')
#выведем на графике реальное количество заказов в день и предсказанное нашей моделью. 
graph = y_test.copy()
predictions_taxi = pd.DataFrame(data = predictions, columns = ['predictions'], index = X_test.index.copy())
df_out = pd.merge(graph, predictions_taxi, how = 'left', left_index = True, right_index = True)
df_out['predictions'] = df_out['predictions'].astype('int64')
df_out['2018-08-15':'2018-08-17'].plot(figsize=(16,5))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11108189825161036, 'fraction_numerical': 0.0307611410542921, 'mean_word_length': 5.679543459174715, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '596550', 'license': 'MIT', 'n_tokens_mistral': 3056, 'n_tokens_neox': 3140, 'n_words': 619, 'path': '12-predicting-taxi-trips/predicting-taxi-trips.ipynb', 'repo_name': 'akylson/yandex-praktikum-projects', 'size': '7607'}