Beispiel #1
0
def test_plot_series_uniform_treatment_of_int64_range_index_types():
    """Test that int64 and range indices are treated the same without error."""
    _check_soft_dependencies("matplotlib")
    import matplotlib.pyplot as plt

    y1 = pd.Series(np.arange(10))
    y2 = pd.Series(np.random.normal(size=10))
    y1.index = pd.Int64Index(y1.index)
    y2.index = pd.RangeIndex(y2.index)
    plot_series(y1, y2)
    plt.gcf().canvas.draw_idle()
Beispiel #2
0
def test_plot_series_uniform_treatment_of_int64_range_index_types():
    # We test that int64 and range indices are treated uniformly and do not raise an
    # error of inconsistent index types
    _check_soft_dependencies("matplotlib")
    import matplotlib.pyplot as plt

    y1 = pd.Series(np.arange(10))
    y2 = pd.Series(np.random.normal(size=10))
    y1.index = pd.Int64Index(y1.index)
    y2.index = pd.RangeIndex(y2.index)
    plot_series(y1, y2)
    plt.gcf().canvas.draw_idle()
Beispiel #3
0
 def plot(self):
     from sktime.utils.plotting import plot_series
     from io import BytesIO
     buf = BytesIO()
     fig, _ = plot_series(self.pd_past5days, labels=['past5days'])
     fig.savefig(buf)
     self.plot = buf.getvalue()
     self.next(self.end)
def load_forecast(
        data,
        model_path='Models/6689489_NaiveForecaster_2017-01_2019-04_5.model'):
    """
    Load saved forcasting model and plotting

    Parameters
    ----------
    data: pandas DataFrame
        main dataset with customer_id, product_id and Timestamp

    model_path: .model file
        path to previously saved model

    Returns
    -------
    sMAPE Loss: print

    plot: matplotlib figure
        plot train, test and predicted values
    """
    y_train, y_test = temporal_train_test_split(
        prepare_data(data,
                     int(model_path.split('_')[0].split('/')[-1]),
                     start=model_path.split('_')[-3],
                     end=model_path.split('_')[-2]),
        test_size=int(model_path.split('_')[-1].split('.')[0]))
    fh = ForecastingHorizon(y_test.index, is_relative=False)

    f = load(model_path)

    y_pred = f.predict(fh)

    print('sMAPE Loss :', smape_loss(y_pred, y_test))
    plot = plot_series(y_train,
                       y_test,
                       y_pred,
                       labels=["y_train", "y_test", "y_pred"])
    return plot
Beispiel #5
0
def _plot_series(series, ax=None, **kwargs):
    if isinstance(series, tuple):
        return plot_series(*series, ax=ax, **kwargs)
    else:
        return plot_series(series, ax=ax, **kwargs)
Beispiel #6
0
from sktime.forecasting.model_selection import (
    ForecastingGridSearchCV,
    SlidingWindowSplitter,
    temporal_train_test_split,
)
from sktime.forecasting.naive import NaiveForecaster
from sktime.forecasting.theta import ThetaForecaster
from sktime.forecasting.trend import PolynomialTrendForecaster
from sktime.performance_metrics.forecasting import sMAPE, smape_loss
from sktime.transformations.series.detrend import Deseasonalizer, Detrender
from sktime.utils.plotting import plot_series

y = load_airline()
type(y)

plot_series(y)

y.index

y_train, y_test = temporal_train_test_split(y, test_size = 24)
plot_series(y_train, y_test)



fh = ForecastingHorizon(y_test.index, is_relative=False)
fh


ets_frcstr = ExponentialSmoothing(trend='additive', seasonal='additive', sp=12)

ets_frcstr.fit(y_train)
def forecast(data,
             customer_id,
             start='2017-01',
             end='2019-04',
             model_type='NaiveForecaster',
             test_size_month=5,
             model_storage_path=''):
    """
    Main function for build forecasting model on selected customer and time interval, save the model and plotting

    Parameters
    ----------
    data: pandas DataFrame
        main dataset with customer_id, product_id and Timestamp

    customer_id: int

    start: string
        start year and month in '2020-01' format

    end: string
        end year and month in '2020-01' format *** this month will not be included ***

    model_type:
        type of model to use in forecasting
        select from : ['NaiveForecaster', 'PolynomialTrendForecaster', 'ThetaForecaster', 'KNeighborsRegressor',
                       'ExponentialSmoothing', 'AutoETS', 'AutoARIMA', 'TBATS', 'BATS', 'EnsembleForecaster']

    test_size_month:
        number of month that will be excluded from end of interval to use as test dataset

    model_storage_path: string
        the folder that you want to store saved models
    Returns
    -------
    sMAPE Loss: print

    plot: matplotlib figure
        plot train, test and predicted values
    """
    y_train, y_test = temporal_train_test_split(prepare_data(data,
                                                             customer_id,
                                                             start=start,
                                                             end=end),
                                                test_size=test_size_month)
    fh = ForecastingHorizon(y_test.index, is_relative=False)

    if model_type == 'NaiveForecaster':
        forecaster = NaiveForecaster(strategy="last", sp=12)
    elif model_type == 'PolynomialTrendForecaster':
        forecaster = PolynomialTrendForecaster(degree=2)
    elif model_type == 'ThetaForecaster':
        forecaster = ThetaForecaster(sp=6)
    elif model_type == 'KNeighborsRegressor':
        regressor = KNeighborsRegressor(n_neighbors=1)
        forecaster = ReducedRegressionForecaster(regressor=regressor,
                                                 window_length=12,
                                                 strategy="recursive")
    elif model_type == 'ExponentialSmoothing':
        forecaster = ExponentialSmoothing(trend="add",
                                          seasonal="multiplicative",
                                          sp=12)
    elif model_type == 'AutoETS':
        forecaster = AutoETS(auto=True, sp=12, n_jobs=-1)
    elif model_type == 'AutoARIMA':
        forecaster = AutoARIMA(sp=12, suppress_warnings=True)
    elif model_type == 'TBATS':
        forecaster = TBATS(sp=12, use_trend=True, use_box_cox=False)
    elif model_type == 'BATS':
        forecaster = BATS(sp=12, use_trend=True, use_box_cox=False)
    elif model_type == 'EnsembleForecaster':
        forecaster = EnsembleForecaster([
            ("ses", ExponentialSmoothing(seasonal="multiplicative", sp=12)),
            (
                "holt",
                ExponentialSmoothing(trend="add",
                                     damped_trend=False,
                                     seasonal="multiplicative",
                                     sp=12),
            ),
            (
                "damped",
                ExponentialSmoothing(trend="add",
                                     damped_trend=True,
                                     seasonal="multiplicative",
                                     sp=12),
            ),
        ])

    try:
        forecaster.fit(y_train)
    except:
        forecaster.fit(y_train + 1)

    y_pred = forecaster.predict(fh)
    dump(
        forecaster,
        f'{model_storage_path}/{customer_id}_{model_type}_{start}_{end}_{test_size_month}.model'
    )

    print('sMAPE Loss :', smape_loss(y_pred, y_test))
    plot = plot_series(y_train,
                       y_test,
                       y_pred,
                       labels=["y_train", "y_test", "y_pred"])
    return plot
# setting graphs size
plt.rcParams["figure.figsize"] = [16, 7]
# for fancy plots
plt.style.use('ggplot')

df = pd.read_csv(
    'https://raw.githubusercontent.com/selva86/datasets/master/a10.csv',
    parse_dates=['date'],
    index_col="date")

df.index = pd.PeriodIndex(df.index, freq="M")

series = df.T.iloc[0]

plot_series(series)

model_auto = AutoARIMA(sp=12, suppress_warnings=True).fit(series)

summary = model_auto.summary()


def get_params(summary_text):
    full = re.findall(r'SARIMAX\(.*?\)x\(.*?\)', summary_text)[0]
    info = [int(_) for _ in re.findall(r'\d+', full)]
    return info


p, d, q, P, D, Q, S = get_params(summary.as_text())

y_train, y_test = temporal_train_test_split(series, test_size=24)
Beispiel #9
0
def app():
    """
    Part for creating web page
    """
    state = _get_state()

    st.title("ARIMA модель")
    state.uploaded_file = st.sidebar.file_uploader("Выберите файл",
                                                   type=['csv', 'xlsx', 'xls'])

    if state.uploaded_file is not None:
        state.data_frame = reading_data_frame(state.uploaded_file)
        state.column_to_predict = st.selectbox('Выберите колонку для обучения',
                                               state.data_frame.columns,
                                               key="column_training")

        if state.column_to_predict is not None:

            # state.data_frame = state.data_frame.dropna(subset=[state.column_to_predict])

            state.tts = st.slider(
                'Выберите необходимую величину обучающей выборки',
                0.05,
                0.5, (0.2),
                step=0.05,
                key='split_size')
            state.y_train, state.y_test = temporal_train_test_split(
                state.data_frame[state.column_to_predict], test_size=state.tts)

            with _lock:
                fig0, ax0 = plot_series(state.y_train,
                                        state.y_test,
                                        labels=['Train', 'Test'])
                st.pyplot(fig0)

            state.window = st.slider(
                'Выберите необходимую величину rolling window',
                1,
                20, (5),
                step=1,
                key='window')

            state.rolling_mean = state.data_frame[
                state.column_to_predict].rolling(window=state.window).mean()
            state.rolling_std = state.data_frame[
                state.column_to_predict].rolling(window=state.window).std()

            with _lock:
                fig1, ax1 = plt.subplots()
                state.data_frame[state.column_to_predict].plot()
                ax1.plot(state.rolling_mean, color='red', label='Rolling Mean')
                ax1.plot(state.rolling_std, color='black', label='Rolling Std')
                ax1.legend(loc='best')
                ax1.set_title('Rolling Mean & Standard Deviation')
                st.pyplot(fig1)

            # Dickey–Fuller test:
            with st_stdout("code"):
                adfuller_func(state.data_frame[state.column_to_predict])

    else:
        st.warning("Загрузите файл для начала работы")

    state.sync()
Beispiel #10
0
def app():
    """
    Part for creating web page
    """
    state = _get_state()
    st.title('Туториал по исследованию временных рядов при помощи Python.')
    st.write(
        'Мы рассмотрим как работать с ARIMA-моделью в Python. Есть несколько различных библиотек, которые позволяют исследовать временные ряды. Мы решили использовать sktime, statsmodels, и классическую библиотеку pandas. Где это будет возможно, мы даже сравним возможности этих библиотек, хотя в основном наш выбор пал на самие понятные и негромоздкие решения.'
    )

    code1 = """
    import numpy as np
    import pandas as pd
    from matplotlib import pyplot as plt
    from statsmodels.tsa.stattools import adfuller
    from statsmodels.tsa.seasonal import seasonal_decompose
    from statsmodels.tsa.arima_model import ARIMA
    from sktime.datasets import load_airline
    from sktime.utils.plotting import plot_series
    from pandas.plotting import register_matplotlib_converters
    from sktime.forecasting.model_selection import temporal_train_test_split
    import pmdarima as pm
    register_matplotlib_converters()
            """
    st.code(code1, language="python")
    st.write(
        "Для начала, рассмотрим самые стандартные операции с времеными рядами. У нас есть шаблонный набор даных об авиаперелётах, собранный по конкретонй компании. В следующих нескольких строках мы просто загружаем эти самые данные, и что-нибудь делаем. Если конкретней, строим график, делаем train-test split. Это, в целом, стандартный подход к временным рядам, но от этого не менее важный."
    )
    code2 = """
    y = load_airline()
    plot_series(y)
    """
    st.code(code2, language="python")
    y, df, rolling_mean, rolling_std = load_dataset()
    st.line_chart(df)
    st.write(
        "На получившийся график можно взглянуть повнимательней. Сразу видна сезонность данных, явные пики и проседания, Ну и прииерно на глазок можно углядеть тренд на увеличение среднегодового колличества пассажиров, даже несмотря на сезонные провалы."
    )
    code3 = """
    y_train, y_test = temporal_train_test_split(y, test_size=24)
    plot_series(y_train, y_test, labels=['Train', 'Test'])
    """
    st.code(code3, language="python")
    y_train, y_test = temporal_train_test_split(y, test_size=24)

    with _lock:
        fig0, ax0 = plot_series(y_train, y_test, labels=['Train', 'Test'])
        st.pyplot(fig0)

    st.write(
        "А вот тут мы уже сделали разбивку данных на тестовый и обучающий набор. Синим обозначен обучающий, а золотым - тестовый."
    )

    st.write(
        "Посмотрим на график. Синим показано наблюдаемое количество пассажиров авиалиний. Красным показано скользящее среднее, а чёрным - скользящее стандартное отклонение."
    )
    code4 = """
    df = pd.DataFrame(y)
    df.index = df.index.to_timestamp()
    rolling_mean = df.rolling(window = 12).mean()
    rolling_std = df.rolling(window = 12).std()
    df.plot()
    plt.plot(rolling_mean, color = 'red', label = 'Rolling Mean')
    plt.plot(rolling_std, color = 'black', label = 'Rolling Std')
    plt.legend(loc = 'best')
    plt.title('Rolling Mean & Rolling Standard Deviation')
    plt.show()
    """
    st.code(code4, language="python")

    with _lock:
        fig1, ax1 = plots(df, rolling_mean, rolling_std,
                          'Number of airline passengers')
        """
        fig1, ax1 = plt.subplots()
        ax1.plot(df, label='Number of airline passengers')
        ax1.plot(rolling_mean, color='red', label='Rolling Mean')
        ax1.plot(rolling_std, color='black', label='Rolling Std')
        ax1.legend(loc='best')
        ax1.set_title('Rolling Mean & Rolling Standard Deviation')
        """
        st.pyplot(fig1)

    y = y
    st.write(
        "Здесь мы переходим к немного более сложным вещам. Мы применяем к нашему ряду расширенный тест Дики - Фуллера."
    )
    with st.echo():
        result = adfuller(y)
        print('ADF Statistic: {}'.format(result[0]))
        print('p-value: {}'.format(result[1]))
        print('Critical Values:')
        for key, value in result[4].items():
            print("\t{}: {}".format(key, value))
        if result[0] > result[4]["5%"]:
            print(
                "Не удалось отклонить нулевую гипотезу - временной ряд нестационарный"
            )
        else:
            print("Нулевая гипотеза отклонена – временной ряд стационарен")

    st.text("Output:")
    output = st.empty()
    with st_capture(output.code):
        result = adfuller(y)
        print('ADF Statistic: {}'.format(result[0]))
        print('p-value: {}'.format(result[1]))
        print('Critical Values:')
        for key, value in result[4].items():
            print("\t{}: {}".format(key, value))
        if result[0] > result[4]["5%"]:
            print(
                "Не удалось отклонить нулевую гипотезу - временной ряд нестационарный"
            )
        else:
            print("Нулевая гипотеза отклонена – временной ряд стационарен")

    code5 = """
    df_log = np.log(y)
    df_log.plot()
    """
    st.code(code5, language="python")

    df_log = np.log(y)
    df_log.index = df_log.index.to_timestamp()

    with _lock:
        fig2, ax2 = plt.subplots()
        ax2.plot(df_log, label='Log')
        ax2.legend(loc='best')
        ax2.set_title('Logged number of airline passengers')
        st.pyplot(fig2)

    st.write(
        "Далее будет функция, считающая наши скользящие средние, делающая тест Дики - Фуллера, и заодно показывающая график."
    )

    with st.echo():

        def get_stationarity(timeseries):

            # rolling statistics
            rolling_mean = timeseries.rolling(window=12).mean()
            rolling_std = timeseries.rolling(window=12).std()

            # rolling statistics plot
            timeseries.plot()
            plt.plot(rolling_mean, color='red', label='Rolling Mean')
            plt.plot(rolling_std, color='black', label='Rolling Std')
            plt.legend(loc='best')
            plt.title('Rolling Mean & Standard Deviation')
            plt.show(block=False)

            # Dickey–Fuller test:
            result = adfuller(timeseries)
            print('ADF Statistic: {}'.format(result[0]))
            print('p-value: {}'.format(result[1]))
            print('Critical Values:')
            for key, value in result[4].items():
                print('\t{}: {}'.format(key, value))
            if result[0] > result[4]["5%"]:
                print(
                    "Не удалось отклонить нулевую гипотезу - временной ряд нестационарный"
                )
            else:
                print("Нулевая гипотеза отклонена – временной ряд стационарен")

    st.write(
        "Отметим, что тут мы немного корректируем данные, вычитая среднее.")

    code6 = """
    rolling_mean = df_log.rolling(window=12).mean()
    df_log_minus_mean = df_log - rolling_mean
    df_log_minus_mean.dropna(inplace=True)
    get_stationarity(df_log_minus_mean)
    """
    st.code(code6, language="python")
    rolling_mean = df_log.rolling(window=12).mean()
    df_log_minus_mean = df_log - rolling_mean
    df_log_minus_mean.dropna(inplace=True)
    rolling_mean_log_minus_mean = df_log_minus_mean.rolling(window=12).mean()
    rolling_std_log_minus_mean = df_log_minus_mean.rolling(window=12).std()

    with _lock:
        fig3, ax3 = plots(df_log_minus_mean, rolling_mean_log_minus_mean,
                          rolling_std_log_minus_mean,
                          'Number of airline passengers (log minus mean)')
        """
        fig3, ax3 = plt.subplots()
        ax3.plot(df_log, label='Log')
        ax3.legend(loc='best')
        ax3.set_title('Logged number of airline passengers')
        """
        st.pyplot(fig3)
    output = st.empty()
    with st_capture(output.code):
        result = adfuller(df_log_minus_mean)
        print('ADF Statistic: {}'.format(result[0]))
        print('p-value: {}'.format(result[1]))
        print('Critical Values:')
        for key, value in result[4].items():
            print("\t{}: {}".format(key, value))
        if result[0] > result[4]["5%"]:
            print(
                "Не удалось отклонить нулевую гипотезу - временной ряд нестационарный"
            )
        else:
            print("Нулевая гипотеза отклонена – временной ряд стационарен")
    st.write(
        "График сверху показывает получившийся результат. Поверх количества пассажиров можно увидеть скользящие соеднее и стандартное отклонение."
    )
    code7 = """
    rolling_mean_exp_decay = df_log.ewm(halflife=12, min_periods=0, adjust=True).mean()
    df_log_exp_decay = df_log - rolling_mean_exp_decay
    df_log_exp_decay.dropna(inplace=True)
    get_stationarity(df_log_exp_decay)
    """
    st.code(code7, language="python")
    rolling_mean_exp_decay = df_log.ewm(halflife=12,
                                        min_periods=0,
                                        adjust=True).mean()

    df_log_exp_decay = df_log - rolling_mean_exp_decay
    df_log_exp_decay.dropna(inplace=True)
    rolling_mean_log_exp_decay = df_log_exp_decay.rolling(window=12).mean()
    rolling_std_log_exp_decay = df_log_exp_decay.rolling(window=12).std()
    with _lock:
        fig4, ax4 = plots(df_log_exp_decay, rolling_mean_log_exp_decay,
                          rolling_std_log_exp_decay,
                          'Number of airline passengers')
        st.pyplot(fig4)
    output1 = st.empty()
    with st_capture(output1.code):
        result = adfuller(df_log_exp_decay)
        print('ADF Statistic: {}'.format(result[0]))
        print('p-value: {}'.format(result[1]))
        print('Critical Values:')
        for key, value in result[4].items():
            print("\t{}: {}".format(key, value))
        if result[0] > result[4]["5%"]:
            print(
                "Не удалось отклонить нулевую гипотезу - временной ряд нестационарный"
            )
        else:
            print("Нулевая гипотеза отклонена – временной ряд стационарен")
    code8 = """
    df_log_shift = df_log - df_log.shift()
    df_log_shift.dropna(inplace=True)
    get_stationarity(df_log_shift)
    """
    st.code(code8, language="python")
    df_log_shift = df_log - df_log.shift()

    df_log_shift.dropna(inplace=True)
    rolling_mean_shift = df_log_shift.rolling(window=12).mean()
    rolling_std_shift = df_log_shift.rolling(window=12).std()
    with _lock:
        fig5, ax5 = plots(df_log_shift, rolling_mean_shift, rolling_std_shift,
                          'Number of airline passengers')
        st.pyplot(fig5)
    output2 = st.empty()
    with st_capture(output2.code):
        result = adfuller(df_log_shift)
        print('ADF Statistic: {}'.format(result[0]))
        print('p-value: {}'.format(result[1]))
        print('Critical Values:')
        for key, value in result[4].items():
            print("\t{}: {}".format(key, value))
        if result[0] > result[4]["5%"]:
            print(
                "Не удалось отклонить нулевую гипотезу - временной ряд нестационарный"
            )
        else:
            print("Нулевая гипотеза отклонена – временной ряд стационарен")
    st.write(
        "Мы рассмотрели как можно изменять датасет для того, чтобы получить стационарный временной ряд. Теперь мы применим autoarima, для автоматического расчета оптимальных параметров модели"
    )

    model = pm.auto_arima(y_train, seasonal=True, m=12)

    # make your forecasts
    # predict N steps into the future
    forecasts = model.predict(y_test.shape[0])

    x = np.arange(y.shape[0])
    code9 = """
model = pm.auto_arima(y_train, seasonal=True, m=12)

forecasts = model.predict(y_test.shape[0])

x = np.arange(y.shape[0])
plt.plot(x[:120], y_train, c='blue')
plt.plot(x[120:], forecasts, c='green')
plt.show()
    """
    st.code(code9, language="python")

    st.write(
        "Приведенный код обучает модель с автоподбором параметров на тренировочных данных (y_train), строит прогноз на количество элементов в тестовых данных, а затем мы строим график прогнозных значений"
    )
    fig6, ax6 = plt.subplots()
    ax6.plot(x[:120], y_train, c='blue', label='Тренировочные данные')
    ax6.plot(x[120:], forecasts, c='green', label='Предсказанные значения')
    ax6.legend(loc='best')
    st.pyplot(fig6)

    st.write('Теперь посмотрим какие параметры у нашей модели')
    code10 = """
model.summary()
    """
    st.code(code10, language="python")
    output3 = st.empty()
    with st_capture(output3.code):
        print(model.summary())

    code11 = """
# Create predictions for the future, evaluate on test
preds, conf_int = model.predict(
    n_periods=y_test.shape[0], return_conf_int=True)

# #############################################################################
# Plot the points and the forecasts

df.index = df.index.to_timestamp()

plt.plot(df.index[:y_train.shape[0]], y_train, alpha=0.75)
plt.plot(df.index[y_train.shape[0]:], preds, alpha=0.75)  # Forecasts
plt.scatter(df.index[y_train.shape[0]:], y_test,
            alpha=0.4, marker='x')  # Test data
plt.fill_between(df.index[-preds.shape[0]:],
                 conf_int[:, 0], conf_int[:, 1],
                 alpha=0.1, color='b')
    """
    st.code(code11, language="python")
    st.write(
        "Теперь мы построим график предсказаний, а Х будут обозначать реальные данные"
    )
    # Create predictions for the future, evaluate on test
    preds, conf_int = model.predict(n_periods=y_test.shape[0],
                                    return_conf_int=True)

    # #############################################################################
    # Plot the points and the forecasts

    fig7, ax7 = plt.subplots()
    ax7.plot(df.index[:y_train.shape[0]], y_train, alpha=0.75)
    ax7.plot(df.index[y_train.shape[0]:], preds, alpha=0.75)  # Forecasts
    ax7.scatter(df.index[y_train.shape[0]:], y_test, alpha=0.4,
                marker='x')  # Test data
    ax7.fill_between(df.index[-preds.shape[0]:],
                     conf_int[:, 0],
                     conf_int[:, 1],
                     alpha=0.1,
                     color='b')
    st.pyplot(fig7)
    st.write(
        "Как мы видим, модель достаточно точно описала график, давайте теперь оценим нашу модель метрикой MAPE (средняя абсолютная ошибка в процентах)"
    )
    code12 = """
def mean_absolute_percentage_error(y_true, y_pred): 
    y_true, y_pred = np.array(y_true), np.array(y_pred)
    return np.mean(np.abs((y_true - y_pred) / y_true)) * 100

print(mean_absolute_percentage_error(y_test, preds))
    """
    st.code(code12, language="python")
    output4 = st.empty()
    with st_capture(output4.code):

        def mean_absolute_percentage_error(y_true, y_pred):
            y_true, y_pred = np.array(y_true), np.array(y_pred)
            return np.mean(np.abs((y_true - y_pred) / y_true)) * 100

        print(mean_absolute_percentage_error(y_test, preds))
    st.write("10% отклонение выглядит отлично, модель справилась на ура")
    state.sync()