И что бесплатно на всю жизнь.

Введение

В моей последней статье я обсуждал, как CyberDeck, бесплатный комплексный инструмент Data Science, не требующий написания кода, можно использовать для решения конечной проблемы. решить проблему машинного обучения за считанные минуты.

Эта статья заставила почти 1500 пользователей зайти на эту платформу в течение 24 часов и зарегистрироваться!

Чтобы действительно доказать это, я пошел дальше и также написал коды, чтобы провести параллельное сравнение того, сколько времени точно сэкономлено с помощью этого инструмента, вместо того, чтобы тратить недели на тысячи строк кода!

В этой статье я проведу сравнение кодирования и использования CyberDeck для различных типов проблем прогнозирования временных рядов.

Мы начнем с простой одноэтапной многомерной задачи (Прогнозирование продаж для одного магазина и всех товаров вместе взятых), а затем перейдем к наиболее сложному типу задачи прогнозирования, т. е. к многомерным многошаговым временным рядам. проблема (Прогнозирование продаж для нескольких магазинов и нескольких товаров одновременно).

Готовый? Пойдем!

Постановка задачи. Наука о данных требует чертовски много кода!

Наука о данных — одна из самых красивых вещей. Это потому, что способность извлекать значимую информацию из ничего сама по себе является чудом. Но быть специалистом по данным имеет свои особенности. Другими словами, одной из основных задач науки о данных является написание кода.

Например, часто пишут сотни строк кода, чтобы извлечь ценную информацию из данных. Но даже тогда это не масштабируется. Потому что по мере изменения данных меняется и код.

Поэтому нам снова приходится писать сотни строк кода, хотя процессы/конвейеры остаются прежними. Но что, если бы мы могли сделать универсальную платформу для выполнения нашей обычной работы по обработке данных одним щелчком мыши, начиная с обработки данных и EDA вплоть до моделирования?

Инструмент для анализа данных без кода наверняка пригодился бы здесь!

Решение — комплексный инструмент Data Science без кода.

Мы сами столкнулись с этой проблемой. Поэтому мы разрабатываем БЕСПЛАТНУЮ универсальную платформу сообщества для специалистов по данным под названием CyberDeck.

Однако каждая подобная платформа, которую мы видели, стоит больших денег. Но не это. Это не для выпуска. Но если мы получим положительные отзывы от этого золотого рудника сообщества, мы скоро воплотим это в реальность ориентировочно к концу этого месяца!

С помощью этой платформы вы можете выполнять обработку данных, исследовательский анализ данных, информационные панели, AutoML, автоматические временные ряды, автокластеризацию и генерировать объяснимый AI одним щелчком мыши. мышь!

Прежде чем мы углубимся в формулировки проблем, вот несколько полезных ресурсов о CyberDeck.

  1. Веб-сайт CyberDeck
  2. Полная демонстрация AutoML
  3. Программирование и использование CyberDeck на титанических данных
  4. Подпишитесь на предварительную версию
  5. Заказать демонстрацию
  6. О CyberDeck
  7. CyberDeck — Чем мы занимаемся

Просто нажмите кнопку «Зарегистрироваться сегодня и заполните форму, и мы свяжемся с вами в течение того же дня.

Давайте перейдем к идеальному инструменту для анализа данных без кода, которым является CyberDeck!

Более простая задача — прогнозирование общего объема продаж для магазина (многомерная задача с одношаговым временным рядом)

Для первой задачи попробуем спрогнозировать общий объем продаж для конкретного магазина. Данные выглядят так.

Итак, у нас есть ежемесячные данные о продажах магазина. У нас также есть расходы на маркетинг в месяц и еще одна переменная, называемая v1. Мы будем использовать эти переменные в качестве экзогенных переменных для прогнозирования продаж в будущем.

А) Исследовательский анализ данных

Для любой проблемы науки о данных всегда лучше сначала провести тщательный исследовательский анализ данных (EDA). Итак, давайте сделаем это!

1) Построение графика данных временного ряда

С кодированием

def plot_ts(df, target, ts_column):
    fig = px.line(df, x=ts_column, y=target)
    fig.update_layout(xaxis_title=df.index.name,
                      # yaxis_title=col_name,
                      paper_bgcolor='rgba(0,0,0,0)',
                      plot_bgcolor='rgba(0,0,0,0)',
                      font={'color': 'grey'}
                      )
    fig.update_xaxes(showgrid=False, zeroline=False)
    fig.update_yaxes(showgrid=False, zeroline=False)
return fig
plot_ts(df, ['Sales', 'Marketing Expense'], 'Time Period')

С CyberDeck

Читать данные

Перейдите в TS-EDA (Time-Series EDA) и загрузите свой файл. Нажмите «Читать файл»

Запустить EDA

Выберите столбец даты. Выберите, отсутствуют ли временные метки в данных. Если отсутствуют временные метки, наш запатентованный алгоритм исправит их за вас.

Наконец, нажмите «Запустить EDA». Вы в основном сделали!

Сразу же приложение показывает вам четыре раздела: график временных рядов, декомпозиция, корреляция и стационарность.

На первой вкладке просто выберите столбцы, для которых вы хотите увидеть график временного ряда, и вуаля! Это здесь!

2) Создайте гистограмму

С кодированием

def ts_histogram(df, target):
    fig = px.histogram(df, x=target, marginal="box",  
                       hover_data=df.columns)
    return fig

С CyberDeck

Если вы прокрутите вниз в том же разделе, вы также можете построить гистограмму любого столбца одним щелчком мыши.

3) Отображение сводной статистики

С кодированием

Это займет так много времени с кодированием, что я даже не буду пытаться! Но давайте посмотрим CyberDeck.

И это только половина дела! Вы можете прокрутить страницу вниз до оставшейся половины.

Теперь представьте, что вы пытаетесь закодировать все эти сотни переменных! Пожалуйста!

4) Декомпозиция временных рядов

С кодированием

def plot_seasonal_decompose(df, target, ts_column, model='additive', period=None):
    series = df[[ts_column, target]]
    series.set_index(ts_column, inplace=True)
    series.index = pd.to_datetime(series.index)
    result = seasonal_decompose(series, model=model)
    fig = make_subplots(rows=4, cols=1,
                        subplot_titles=("Actual Data", "Trend Component", "Seasonal Component", "Residual Component"))
fig.append_trace(go.Scatter(
        x=series.index,
        y=result.observed
    ), row=1, col=1)
fig.append_trace(go.Scatter(
        x=series.index,
        y=result.trend
    ), row=2, col=1)
fig.append_trace(go.Scatter(
        x=series.index,
        y=result.seasonal
    ), row=3, col=1)
    fig.append_trace(go.Scatter(
        x=series.index,
        y=result.resid
    ), row=4, col=1)
fig.update_layout(title_text="Time-Series Decomposition", showlegend=False)
    return fig
plot_seasonal_decompose(df, 'Sales', 'Time Period')

С CyberDeck

Для этого переходим на вкладку Декомпозиция, выбираем нужный столбец (Продажи) и готово!

5) Построение графиков ACF и PACF

С кодированием

def plot_acf(df, colname, nlag=10):
    df_acf = pd.DataFrame(acf(df[colname], nlags=nlag, alpha=None))
    df_acf.columns = ['Auto-Correlation']
    fig = px.bar(df_acf, y='Auto-Correlation', x=df_acf.index, title="Auto-Correlation Plot")
    return fig
def plot_pacf(df, colname, nlag=10, method='yw'):
    df_pacf = pd.DataFrame(pacf(df[colname], nlags=nlag, alpha=None))
    df_pacf.columns = ['Partial Auto-Correlation']
    fig = px.bar(df_pacf, y=['Partial Auto-Correlation'], x=df_pacf.index, title="Partial Auto-Correlation Plot")
    return fig
plot_acf(df, 'Sales')
plot_pacf(df, 'Sales')

С CyberDeck

Перейдите на вкладку «Корреляции», выберите нужные столбцы и готово!

6) Проверка стационарности временных рядов

С кодированием

def ts_test_stationarity(df, colname, maxlag=31, regression='c', autolag='BIC',
                         window=None, verbose=True):
    """
    Check unit root stationarity of a time series array or an entire dataframe.
    Note that you must send in a dataframe as df.values.ravel() - otherwise ERROR.
    Null hypothesis: the series is non-stationary.
    If p >= alpha, the series is non-stationary.
    If p < alpha, reject the null hypothesis (has unit root stationarity).
    Original source: http://www.analyticsvidhya.com/blog/2016/02/time-series-forecasting-codes-python/
    Function: http://statsmodels.sourceforge.net/devel/generated/statsmodels.tsa.stattools.adfuller.html
    window argument is only required for plotting rolling functions. Default=4.
    """
    # os.remove('output.txt')
    timeseries = df[colname].values
    if len(timeseries) <= int(1.5 * maxlag):
        maxlag = 5  ## set it to a low number
    # set defaults (from function page)
    if type(timeseries) == pd.DataFrame:
        print('modifying time series dataframe into an array to test', file=open("output.txt", "a"))
        timeseries = timeseries.values.ravel()
    if regression is None:
        regression = 'c'
    if verbose:
        print('Running Augmented Dickey-Fuller test with paramters:', file=open("output.txt", "a"))
        print('    maxlag: {}'.format(maxlag), 'regression: {}'.format(regression), 'autolag: {}'.format(autolag),
              file=open("output.txt", "a"))
    alpha = 0.05
# Perform Augmented Dickey-Fuller test:
    try:
        ### Use Statsmodels for tests ###########
        dftest = smt.adfuller(timeseries, regression=regression, autolag=autolag)
        dfoutput = pd.Series(dftest[0:4], index=['Test Statistic',
                                                 'p-value',
                                                 '#Lags Used',
                                                 'Number of Observations Used',
                                                 ], name='Dickey-Fuller Augmented Test')
        for key, value in dftest[4].items():
            dfoutput['Critical Value (%s)' % key] = value
        if verbose:
            print('Results of Augmented Dickey-Fuller Test:', file=open("output.txt", "a"))
            pretty_print_table(dfoutput)
            print(dfoutput, file=open("output.txt", "a"))
        if dftest[1] >= alpha:
            print(' this series is non-stationary. Trying test again after differencing...',
                  file=open("output.txt", "a"))
            timeseries = pd.Series(timeseries).diff(1).dropna().values
            dftest = smt.adfuller(timeseries, regression=regression, autolag=autolag)
            dfoutput = pd.Series(dftest[0:4], index=['Test Statistic',
                                                     'p-value',
                                                     '#Lags Used',
                                                     'Number of Observations Used',
                                                     ], name='Dickey-Fuller Augmented Test')
            for key, value in dftest[4].items():
                dfoutput['Critical Value (%s)' % key] = value
            if verbose:
                print('After differencing=1, results of Augmented Dickey-Fuller Test:',
                      file=open("output.txt", "a"))
                pretty_print_table(dfoutput)
                print(dfoutput, file=open("output.txt", "a"))
            if dftest[1] >= alpha:
                print(' this series is not stationary', file=open("output.txt", "a"))
                return False
            else:
                print(' this series is stationary', file=open("output.txt", "a"))
                return True
        else:
            print(' this series is stationary', file=open("output.txt", "a"))
            return True
    except:
        print('Error: Stationary test failed. Data must be np.array. Check your input and try stationary test again')
        return

С CyberDeck

Перейдите на вкладку «Стационарность», выберите столбец и вуаля!

7. График разницы временных рядов

С кодированием

def plot_ts_difference(df, target, ts_column, diff):
    df_diff = df[[ts_column, target]]
    if diff == 1:
df_diff['diff_1'] = np.append(np.nan, np.diff(df_diff[target]))
    else:
        df_diff['diff_{}'.format(diff)] = np.append([np.nan] * diff, np.diff(df_diff[target], n=diff))
diff_col = [col for col in df_diff.columns if 'diff_' in col]
fig = px.line(df_diff, x=ts_column, y=[target, diff_col[0]])
    return fig
plot_ts_difference(df, 'Sales', 'Time Period', 2)

С CyberDeck

На вкладке Стационарность прокрутите вниз до следующего графика. Выберите нужный столбец и количество лагов, которые вы хотите увидеть, и готово!

Итак, вы видели, что всего за несколько кликов мы сэкономили много строк кода? Вау!

Теперь, когда EDA завершено, давайте перейдем к фактическому прогнозированию.

B) Обучение модели временных рядов и прогнозирование

Если мы хотим обучить одиночные модели, то это не займет много времени. Но как узнать, какая модель лучше всего подойдет для соответствующего варианта использования?

Итак, вам нужно обучить несколько моделей, верно?

Допустим, мы начнем с малого и возьмем ARIMA, VAR и Prophet.

Но у этих моделей так много параметров, которые вы можете настроить, верно? Как узнать, какая комбинация работает лучше всего?

Хорошо, давайте попробуем закодировать это для системы, основанной на таблице лидеров.

С кодированием

def arima_leaderboard(backtester_errors, kats_ts, p, d, q, seasonal_p, seasonal_d, seasonal_q, trend,
                      time_varying_regression, train_percentage, seasonal_period, exog, target, ts_freq):
    print('ts_freq {}'.format(ts_freq))
    train_percentage = int(exog.shape[0] * train_percentage / 100)
    exog_train = exog[:train_percentage]
    exog_test = exog[train_percentage:]
    kats_ts_train = kats_ts[:train_percentage]
    kats_ts_test = kats_ts[train_percentage:]
if time_varying_regression is True:
        mle_regression = False
    else:
        mle_regression = True
for i in range(p + 1):
        for j in range(d + 1):
            for k in range(q + 1):
                # for l in range(seasonal_p + 1):
                #     for m in range(seasonal_d + 1):
                #         for n in range(seasonal_q + 1):
                # try:
params = ARIMAParams(p=i, d=j, q=k,
                                     trend=trend,
                                     # seasonal_order=(l, m, n, seasonal_period),
                                     time_varying_regression=time_varying_regression, mle_regression=mle_regression,
                                     exog=exog_train)
                #                             ALL_ERRORS = ['mape', 'smape', 'mae', 'mase', 'mse', 'rmse']
                model = ARIMAModel(kats_ts_train, params)
                model.fit()
                fcst = model.predict(exog_test.shape[0], exog=exog_test)
                fcst = fcst['fcst']
                
                ts_test = kats_ts_test.to_dataframe()
                ts_test = ts_test[target]
                backtester_arima_errors = timeseries_evaluation_metrics_function(ts_test, fcst)
backtester_errors[
                    'arima_({},{},{})'.format(i, j, k)] = {}
                for error, value in backtester_arima_errors.items():
                    backtester_errors['arima_({},{},{})'.format(i, j, k)][error] = value
                # except:
                #     pass
return backtester_errors
def prophet_leaderboard(backtester_errors, kats_ts, growth, yearly_seasonality, weekly_seasonality,
                        daily_seasonality, seasonality_mode, train_percentage, seasonal_period, exog, target, ts_freq):
    train_percentage = int(exog.shape[0] * train_percentage / 100)
    growth_list = []
    seasonality_mode_list = []
    exog_train = exog[:train_percentage]
    exog_test = exog[train_percentage:]
    kats_ts_train = kats_ts[:train_percentage]
    kats_ts_test = kats_ts[train_percentage:]
if growth == 'both':
        growth_list.append(['linear', 'logistic'])
        growth_list = growth_list[0]
    else:
        growth_list.append(growth)
if yearly_seasonality == 'auto':
        yearly_seasonality = 'auto'
    elif yearly_seasonality == 'True':
        yearly_seasonality = True
    else:
        yearly_seasonality = False
if weekly_seasonality == 'auto':
        weekly_seasonality = 'auto'
    elif weekly_seasonality == 'True':
        weekly_seasonality = True
    else:
        weekly_seasonality = False
if daily_seasonality == 'auto':
        daily_seasonality = 'auto'
    elif daily_seasonality == 'True':
        daily_seasonality = True
    else:
        daily_seasonality == False
if seasonality_mode == 'both':
        seasonality_mode_list.append(['additive', 'multiplicative'])
        seasonality_mode_list = seasonality_mode_list[0]
    else:
        seasonality_mode_list.append(seasonality_mode)
print(growth_list)
    print(seasonality_mode_list)
for i in growth_list:
        for j in seasonality_mode_list:
            print(i)
            print(j)
params = ProphetParams(growth=i, yearly_seasonality=yearly_seasonality,
                                   weekly_seasonality=weekly_seasonality,
                                   daily_seasonality=daily_seasonality, seasonality_mode=j)
m = ProphetModel(kats_ts_train, params)
            # m.add_regressor(exog_train)
            m.fit()
            fcst = m.predict(steps=exog_test.shape[0], exog=exog_test, freq=ts_freq)
            fcst = fcst['fcst']
            ts_test = kats_ts_test.to_dataframe()
            ts_test = ts_test[target]
            backtester_prophet_errors = timeseries_evaluation_metrics_function(ts_test, fcst)
backtester_errors['prophet_{}_{}'.format(i, j)] = {}
            for error, value in backtester_prophet_errors.items():
                backtester_errors['prophet_{}_{}'.format(i, j)][error] = value
return backtester_errors
def var_leaderboard(backtester_errors, kats_ts, target, ts_freq, train_percentage):
    train_percentage = int(len(kats_ts) * train_percentage / 100)
    kats_ts_train = kats_ts[:train_percentage]
    kats_ts_test = kats_ts[train_percentage:]
params = VARParams()
m = VARModel(kats_ts_train, params)
    m.fit()
    fcst = m.predict(steps=len(kats_ts_test))
    fcst = fcst[target].to_dataframe()
    fcst = fcst['fcst']
    ts_test = kats_ts_test.to_dataframe()
    ts_test = ts_test[target]
    backtester_VAR_errors = timeseries_evaluation_metrics_function(ts_test, fcst)
backtester_errors['VAR'] = {}
    for error, value in backtester_VAR_errors.items():
        backtester_errors['VAR'][error] = value
return backtester_errors
def multivariate_leaderboard(kats_ts, kats_ts_var, exog, p, d, q, seasonal_p, seasonal_d, seasonal_q, trend,
                             time_varying_regression,
                             growth, yearly_seasonality, weekly_seasonality, daily_seasonality, seasonality_mode,
                             seasonal_period, train_percentage, ts_freq, target
                             ):
    backtester_errors = {}
prophet_dict = prophet_leaderboard(backtester_errors, kats_ts, growth, yearly_seasonality, weekly_seasonality,
                                       daily_seasonality, seasonality_mode, train_percentage, seasonal_period, exog,
                                       target, ts_freq)
    var_dict = var_leaderboard(prophet_dict, kats_ts_var, target, ts_freq, train_percentage)
try:
        arima_dict = arima_leaderboard(var_dict, kats_ts, p, d, q, seasonal_p, seasonal_d, seasonal_q, trend,
                                       time_varying_regression, train_percentage, seasonal_period, exog, target,
                                       ts_freq)
    except:
        pass
try:
        leaderboard = pd.DataFrame.from_dict(arima_dict).T
    except:
        leaderboard = pd.DataFrame.from_dict(var_dict).T
leaderboard['model_name'] = leaderboard.index
    leaderboard = leaderboard[['model_name', 'mape', 'smape', 'mae', 'mase', 'mse', 'rmse']]
return leaderboard
################## Forecast ###############################
def arima_forecast(kats_ts, p, d, q, trend, time_varying_regression,
                   exog, exog_predict, target, forecast_period, ts_freq):
    if time_varying_regression is True:
        mle_regression = False
    else:
        mle_regression = True
    params = ARIMAParams(p=p, d=d, q=q,
                         trend=trend,
                         # seasonal_order=(seasonal_p, seasonal_d, seasonal_q, seasonal_period),
                         time_varying_regression=time_varying_regression,
                         mle_regression=mle_regression,
                         exog=exog)
    #                             ALL_ERRORS = ['mape', 'smape', 'mae', 'mase', 'mse', 'rmse']
    m = ARIMAModel(kats_ts, params)
    m.fit()
    fcst = m.predict(exog_predict.shape[0], exog=exog_predict)
    # sarimax = sm.tsa.statespace.SARIMAX(kats_ts.to_dataframe()[target], order=(p, d, q),
    #                                     seasonal_order=(seasonal_p, seasonal_d, seasonal_q, seasonal_period), exog=exog,
    #                                     enforce_stationarity=False, enforce_invertibility=False).fit()
    # #                             fcst = model.predict(steps = 10, exog = exog_test)
    # fcst = sarimax.predict(start=len(kats_ts), end=len(kats_ts)+ forecast_period-1, exog=exog_predict)[1:]
    # print('fcst {}'.format(fcst))
return fcst
def prophet_forecast(kats_ts, growth, yearly_seasonality, weekly_seasonality, daily_seasonality, seasonality_mode,
                     ts_freq, exog, exog_predict):
    params = ProphetParams(growth=growth, yearly_seasonality=yearly_seasonality, weekly_seasonality=weekly_seasonality,
                           daily_seasonality=daily_seasonality, seasonality_mode=seasonality_mode)
m = ProphetModel(kats_ts, params)
m.fit()
# make prediction for next 30 month
    fcst = m.predict(steps=exog_predict.shape[0], exog=exog_predict, freq=ts_freq)
return fcst
def var_forecast(kats_ts_var, target, ts_freq, forecast_period):
    params = VARParams()
    m = VARModel(kats_ts_var, params)
    m.fit()
    fcst = m.predict(steps=forecast_period)
    fcst = fcst[target].to_dataframe()
return fcst
def multivariate_forecast_var(kats_ts_var, target, ts_freq, forecast_period):
    fcst = var_forecast(kats_ts_var, target, ts_freq, forecast_period)
    kats_ts_var_df = kats_ts_var.to_dataframe()
    time_range = pd.date_range(start=kats_ts_var_df.iloc[len(kats_ts_var_df) - 1]['time'], periods=forecast_period,
                               freq=ts_freq)
    fcst['time'] = time_range
    return fcst
def multivariate_forecast(leaderboard, row_selected, kats_ts, trend, time_varying_regression,
                          yearly_seasonality, weekly_seasonality, daily_seasonality,
                          holt_trend, damped, seasonal,
                          alpha,
                          seasonal_period, forecast_period, ts_freq, exog, exog_predict, ts_col, target):
    model_name = leaderboard.iloc[row_selected]['model_name']
    model_name_split = model_name[0].split('_')
if model_name_split[0] == 'prophet':
        growth = 'linear'
        seasonality_mode = model_name_split[2]
fcst = prophet_forecast(kats_ts, growth, yearly_seasonality, weekly_seasonality, daily_seasonality,
                                seasonality_mode, ts_freq, exog, exog_predict)
        kats_ts_df = kats_ts.to_dataframe()
        print(kats_ts_df)
        time_range = pd.date_range(start=kats_ts_df.iloc[len(kats_ts_df) - 1][ts_col], periods=forecast_period,
                                   freq=ts_freq)
        fcst[ts_col] = time_range
elif model_name_split[0] == 'arima':
        cleanString = model_name_split[1].replace('(', ' ').replace(')', ' ').replace(',', ' ')
        param_list = [int(s) for s in cleanString.split() if s.isdigit()]
        p = param_list[0]
        d = param_list[1]
        q = param_list[2]
        # seasonal_p = param_list[3]
        # seasonal_d = param_list[4]
        # seasonal_q = param_list[5]
fcst = arima_forecast(kats_ts, p, d, q, trend, time_varying_regression,
                              exog, exog_predict, target, forecast_period, ts_freq)
        kats_ts_df = kats_ts.to_dataframe()
        print(kats_ts_df)
        time_range = pd.date_range(start=kats_ts_df.iloc[len(kats_ts_df) - 1][ts_col], periods=forecast_period,
                                   freq=ts_freq)
        # fcst = pd.DataFrame()
        # fcst['predicted'] = fcst1
        # fcst['predicted_lower'] = 0
        # fcst['predicted_upper'] = 0
        fcst[ts_col] = time_range
else:
        fcst = None
return fcst
def fit_plot_var(kats_ts_var, target, ts_freq, forecast_period, df):
    y_pred = multivariate_forecast_var(kats_ts_var, target, ts_freq, forecast_period)
    y_pred.index = y_pred['time']
    y_pred.drop('time', axis=1, inplace=True)
    y_pred.columns = ["predicted", "predicted_lower", "predicted_upper"]
    df_plt = pd.merge(df[target], y_pred[["predicted", "predicted_lower", "predicted_upper"]], left_index=True,
                      right_index=True, how='outer')
    # df_plt = pd.merge(df_plt, y_pred["predicted"], left_index=True, right_index=True, how='outer')
    # df_plt = pd.merge(df_plt, y_pred["predicted"], left_index=True, right_index=True, how='outer')
    df_plt.columns = ['Actual', "predicted", "predicted_lower", "predicted_upper"]
fig = px.line(df_plt, x=df_plt.index, y=['Actual', "predicted", "predicted_lower", "predicted_upper"],
                  color_discrete_sequence=px.colors.qualitative.D3)
fig.update_layout(xaxis_title=df_plt.index.name,
                      yaxis_title='value',
                      paper_bgcolor='rgba(0,0,0,0)',
                      plot_bgcolor='rgba(0,0,0,0)',
                      font={'color': 'grey'}
                      )
fig.update_xaxes(showgrid=False, zeroline=False)
    fig.update_yaxes(showgrid=False, zeroline=False)
return fig, df_plt
def fit_plot(leaderboard, row_selected, kats_ts, trend, time_varying_regression,
             yearly_seasonality, weekly_seasonality, daily_seasonality,
             holt_trend, damped, seasonal,
             alpha,
             seasonal_period, forecast_period, ts_freq, exog, exog_predict, ts_col, df, target):
    y_pred = multivariate_forecast(leaderboard, row_selected, kats_ts, trend, time_varying_regression,
                                   yearly_seasonality, weekly_seasonality, daily_seasonality,
                                   holt_trend, damped, seasonal,
                                   alpha,
                                   seasonal_period, forecast_period, ts_freq, exog, exog_predict, ts_col, target)
    # print('y pred {}'.format(y_pred))
    y_pred.index = y_pred[ts_col]
    # print('y pred {}'.format(y_pred))
    y_pred.drop(ts_col, axis=1, inplace=True)
    y_pred.drop('time', axis=1, inplace=True)
    # print('y pred {}'.format(y_pred))
    y_pred.columns = ["predicted", "predicted_lower", "predicted_upper"]
    df_plt = pd.merge(df[target], y_pred[["predicted", "predicted_lower", "predicted_upper"]], left_index=True,
                      right_index=True, how='outer')
    # df_plt = pd.merge(df_plt, y_pred["predicted"], left_index=True, right_index=True, how='outer')
    # df_plt = pd.merge(df_plt, y_pred["predicted"], left_index=True, right_index=True, how='outer')
    df_plt.columns = ['Actual', "predicted", "predicted_lower", "predicted_upper"]
fig = px.line(df_plt, x=df_plt.index, y=['Actual', "predicted", "predicted_lower", "predicted_upper"],
                  color_discrete_sequence=px.colors.qualitative.D3)
fig.update_layout(xaxis_title=df_plt.index.name,
                      yaxis_title='value',
                      paper_bgcolor='rgba(0,0,0,0)',
                      plot_bgcolor='rgba(0,0,0,0)',
                      font={'color': 'grey'}
                      )
fig.update_xaxes(showgrid=False, zeroline=False)
    fig.update_yaxes(showgrid=False, zeroline=False)
return fig, df_plt

Святое гребаное дерьмо!

Скажи мне что-нибудь, сколько времени тебе потребовалось бы, чтобы закодировать это?

Теперь давайте посмотрим на это с помощью CyberDeck.

С CyberDeck

Перейдите к модулю Auto Time-Series на боковой панели. Загрузите данные.

На следующем шаге вам нужно будет выбрать в основном три вещи:

i) столбец даты

ii) Столбец, который вы хотите прогнозировать

iii) Переключение, если в данных присутствует отсутствующая метка времени или нет (если да, то наш собственный алгоритм разумно позаботится об этом).

Теперь все готово. Если вы хотите выполнить дополнительную настройку, вы можете нажать кнопку Параметр временного ряда, после чего откроется это всплывающее окно.

Здесь вы можете выбрать различные этапы предварительной обработки, такие как размер поезда, ARIMA, SARIMA, параметры пророка и многое другое. Но пока я оставлю все значения по умолчанию.

Теперь осталось только нажать кнопку «Создать таблицу лидеров». Как только вы это сделаете, множество моделей запустится в бэкенде и представит вам таблицу лидеров.

Итак, мы видим, что линейная мультипликативная модель Prophet работает лучше всего.

Мы выберем эту модель. Теперь нам нужно указать количество месяцев, на которые нам нужен прогноз. Я выберу 12 месяцев и нажму кнопку Прогноз.

И вуаля! Прогноз создается на следующие 12 месяцев вместе с доверительным интервалом 95%.

Теперь пользователь может загрузить прогноз, просто нажав кнопку Загрузить прогноз.

Вау! Это была настоящая поездка, не так ли! Вы можете подняться и посмотреть, сколько кликов я сделал для решения этого сквозного варианта использования и сколько строк кода мне пришлось написать, чтобы сделать то же самое!

Более сложная задача — Прогнозирование продаж для нескольких магазинов и нескольких товаров одновременно (многомерная, многошаговая задача временных рядов)

Теперь, когда вы освоили CyberDeck, я познакомлю вас с самой сложной проблемой в области задач прогнозирования, т. е. с многомерными многошаговыми задачами временных рядов.

Эти типы проблем имеют несколько временных рядов, встроенных в одни и те же данные. Позвольте мне объяснить, как. Давайте сначала посмотрим на набор данных.

Итак, если вы видите здесь, у нас есть розничный набор данных для нескольких магазинов и нескольких товаров. Так что, если подумать, каждый магазин будет продавать несколько товаров каждый день.

Это означает, что каждая комбинация товара и магазина будет иметь отдельный временной ряд, встроенный в этот единый набор данных.

Итак, давайте посмотрим, как мы можем решить эту проблему с помощью CyberDeck.

ПРИМЕЧАНИЕ. Для этого мы создали совершенно отдельный модуль, так как это огромная проблема, которую необходимо решить. Если мы увидим достаточный пользовательский спрос, мы будем рады сделать его частью основного приложения.

Для этой части статьи я не буду писать коды по двум причинам:

  1. Это сделает статью излишне длинной. К настоящему моменту вы, скорее всего, уловили суть.
  2. У нас здесь происходят некоторые частные дела.

С этого давайте начнем!

Шаг 1. Чтение данных

Мы выбираем указанный выше набор данных и нажимаем Читать.

Шаг 2. Настройка эксперимента

Выбираем атрибуты эксперимента.

а) Атрибут временного ряда — Дата

б) Атрибут для прогноза — Продажи (это то, что мы хотим прогнозировать)

c) Иерархия прогнозирования — идентификатор элемента и идентификатор торговой точки (это уровень, на котором будет сделан окончательный прогноз). Обратите внимание: если бы нам нужны были прогнозы на уровне товара/торговой точки, мы бы выбрали один из них.

г) Экзогенная переменная — Цена товара (это дополнительный сигнал, который мы получаем из самих данных).

e) Частота данных — ежедневно

f) Добавить данные о погоде — True (если вы установите этот флажок, в зависимости от местоположения мы будем автоматически получать данные о погоде и использовать их в качестве дополнительных сигналов от стороннего поставщика). Аккуратно, не правда ли!

g) Максимальная дата обучения — это не отображается на картинке, так как мне пришлось бы немного прокрутить вниз. Но это, по сути, спрашивает вас, в течение какого периода времени вы хотите, чтобы обучение происходило? Этот набор данных охватывает период с апреля 2013 г. по август 2015 г. Таким образом, мы будем проводить обучение до мая 2015 г. Это позволит нам проверить, насколько хорошо работает наша модель за июнь, июль и август 2015 г., прежде чем использовать модель для прогнозирования. будущее.

Шаг 3. Выберите комбинации магазинов и товаров для прогнозирования

Как только я задаю параметры и нажимаю Применить, автоматически отображаются 10 лучших комбинаций товаров и магазинов по средним продажам.

Теперь он попросит вас выбрать несколько комбинаций идентификатора товара и идентификатора торговой точки, для которых вам нужны прогнозы.

На боковой панели я мог бы выбрать их все. Но в демонстрационных целях я выберу две лучшие комбинации товаров и магазинов и нажму «Выбрать комбинации».

Шаг 4 — автоматический EDA

После завершения комбинаций я автоматически вижу для них различные полезные графики EDA.

а) График временных рядов

b) График декомпозиции временных рядов для понимания тенденции, сезонности и т. д.

c) График разности временных рядов

d) График гистограммы временного ряда

e) График автокорреляции временных рядов

f) График частичной автокорреляции временных рядов

Шаг 5. Выберите конфигурацию модели

Для простоты мы сохранили три предустановки моделей.

  1. Самое быстрое моделирование. Это будет самое быстрое обучение, но точность будет наименьшей.
  2. Промежуточное моделирование – это компромисс между скоростью и производительностью.
  3. Расширенное моделирование — будет самым медленным, но с самой высокой точностью.

Мы обнаружили, что этот подход лучше всего работает для тех людей, которые не имеют опыта работы с Data Science, поскольку их действительно не волнуют ARIMA, Prophet и т. д.

Но для тех, кто занимается наукой о данных, есть кнопка Дополнительные параметры, с помощью которой вы можете настроить именно те модели, которые вам нужны.

Позвольте мне показать их вам на нескольких скриншотах, так как они не помещаются в один.

Итак, вы видите, у вас есть такое огромное разнообразие моделей, с которыми можно поэкспериментировать и доработать одну из них на основе производительности.

Для этого эксперимента я буду использовать следующие модели:

ARIMA, Prophet, модель CyberDeck (это наша проприетарная модель, и, как вы увидите, она работает даже лучше, чем Prophet!), Stacked model, LightGBM и Gradient Boosting.

И последнее, но не менее важное: мы должны выбрать еще два параметра:

a) Количество лагов — нам нужно указать, сколько лагов мы возьмем для моделирования. Это ежедневные данные. Поэтому я возьму отставание 7.

b) Индивидуальные метрики для бизнеса. Вам когда-нибудь было очень трудно объяснить бизнесу MAE, MSE, RMSE, RMSLE, R2 и т. д.? Это снова естественно. Это показатели машинного обучения!

Но не было бы намного лучше, если бы у бизнеса были какие-то показатели в денежном выражении? Вот что здесь может случиться.

Каждое превышение прогноза повлияет на бизнес в виде дополнительного наращивания запасов. Каждый заниженный прогноз повлияет на бизнес в виде упущенной возможности продаж.

Вот почему вы можете указать эти две стоимости на единицу. После завершения обучения модели вы сможете увидеть в таблице лидеров показатели, основанные на этом пользовательском определении, которое вы только что создали.

Некоторые модели могут быть потрясающими с точки зрения RMSE, но не лучшими с точки зрения этой новой пользовательской метрики. И знаете что, предприятия почти всегда будут выбирать этот показатель вместо RMSE или RMSLE.

Здесь мы говорим, что стоимость наращивания запасов на единицу составляет 9,99 долл. США, а стоимость упущенной возможности продаж составляет 7,99 долл. США.

А теперь мы нажимаем кнопку Запустить модели! И мы ждем.

Шаг 6. Сравнение прогноза периода проверки

После завершения обучения модели мы можем теперь выбрать каждую из выбранных нами комбинаций Item-Store и посмотреть, как модели работали в период проверки, т. е. июнь, июль и август 2015 г., сравнив их с фактическими данными.

Поскольку здесь показаны все модели, которые мы запускали, на одной диаграмме, их очень сложно расшифровать. Итак, позвольте мне выбрать исходные данные и один алгоритм за раз.

АРИМА

Похоже, что ARIMA вообще не смогла зафиксировать закономерность в данных.

Пророк

Пророк почти как дипломатический политик! Он фиксирует общую закономерность в наборе данных, но не может зафиксировать более тонкие нюансы. Это безопасно!

Модель CyberDeck

Теперь вы посмотрите на это! Модель CyberDeck смогла не только уловить общую тенденцию, но и успешно уловить все важные пики и впадины!

LightGBM

LightGBM также перестраховался, как и Пророк!

Модель с накоплением

Модель Stacked также показала прекрасные результаты, способные уловить важные пики и впадины вместе с общей тенденцией.

Вам также представлена ​​таблица лидеров прямо под этим сюжетом.

Последний столбец — «Средняя взвешенная ошибка» — это метрика с точки зрения денежных потерь. Это было получено из потерь запасов и потерь возможностей продаж на единицу, которые вы указали на шаге 5.

Теперь вы можете либо выбрать модели для доработки вручную здесь, либо перейти к следующему шагу.

Шаг 7. Выберите комбинации для окончательного прогноза

Здесь вы можете автоматически выбирать модели на основе вашей метрики оптимизации.

Именно здесь я хочу показать вам, как ваши метрики ошибок могут кардинально изменить модели, которые мы определяем как лучшие.

Возьмем Оценку дисперсии в качестве первой метрики и Среднюю взвешенную ошибку в качестве второй.

Таким образом, мы видим, что если мы возьмем Оценку дисперсии в качестве нашей метрики ошибок, она говорит о том, что в обеих комбинациях Товар-Выпуск Модель Пророка работала лучше всего.

Теперь возьмем средневзвешенную ошибку в качестве показателя оптимизации.

Сейчас мы видим совсем другую историю. Мы видим, что Stacked Model лучше всего работает для первого сочетания Store-Item, а CyberDeck Model — для второго сочетания Store-Item.

Так что, если вас больше волнует оценка дисперсии, выберите пророка для обоих!

Но если вам больше важны деньги в кармане, выбирайте модель Stacked и CyberDeck!

ЛОЛ!!

Шаг 8. Заключительный тренинг по прогнозированию будущего!

Поэтому мы выберем модель Stacked для первой комбинации и модель CyberDeck для второй.

Теперь мы заранее знали, какими будут цены на продукты на каждый день в будущем. Таким образом, мы можем предоставить экзогенный файл с ценами для вышеупомянутых комбинаций Item-Store.

Мы также предоставим, до какой даты мы хотим прогноз.

Нам нужен прогноз до 8 декабря 2015 года. Вот что мы выбрали. Мы также предоставили экзогенные значения цен до 8 декабря в виде файла здесь.

Теперь мы нажимаем кнопку Выполнить прогноз.

Шаг 9. Создание окончательного прогноза

Теперь все сделано, и мы готовы получить наши окончательные прогнозы.

Для этого мы просто выбираем комбинацию Item-Outlet, для которой мы хотим получить прогноз.

И мы получаем прогноз на главной панели!

Вау! Это была настоящая поездка, не так ли!

Но, надеюсь, теперь вы понимаете, что только что показали вам два сквозных проекта за несколько минут, кодирование которых заняло бы месяцы!

Г) Заключение

Это знаменует собой конец второй демонстрации платформы CyberDeck — инструмента Data Science без кода, который мы активно разрабатываем прямо сейчас. Мы планируем сделать это продуктом сообщества специалистов по данным от специалистов по данным. Поэтому, если вы считаете, что этот продукт может сделать вашу жизнь немного проще, не забудьте подписаться на эту комплексную платформу для анализа и анализа данных и превратить месяцы написания кода в минуты щелчка!

Это все на данный момент! Оставайтесь с нами, пока мы не представим следующую демоверсию CyberDeck!

ПОЛЕЗНЫЕ РЕСУРСЫ

  1. Подпишитесь на предварительную версию
  2. Запросите демонстрацию сегодня
  3. Канал YouTube
  4. Блоги
  5. CyberDeck исследует данные о COVID и прогнозирует количество смертей
  6. Кибердек Вики