# 需要予測モジュールforecastと予測システム ABD-Forecast


<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->

![](06forecast_files/figure-commonmark/cell-3-output-1.jpeg)

\#hide \## 解釈可能な予測（最適決定木）

解釈可能な人工知能の必要性から，決定木の作成に最適化を適用する．

特徴量が連続の場合の分類は，数理最適化モデルとして記述できる．

\#hide \### 最適分類木

Optimal Trees for Prediction and Prescription by Jack William
Dunn　（MIT PhD Thesis) 2018

変数 - d\[t\] : ブランチtで分枝をするとき１ - b\[t\] :
ブランチtでの閾値 - a\[j,t\]: ブランチtが特徴jで分けるとき1 - l\[t\]:
葉が空でないとき1 - z\[i,t\]: データiが葉tに入るとき１ - N\[k,t\] :
葉tに入ったクラスkのデータ数 - c\[k,t\]: 葉tがクラスkに分類されるとき1 -
NN\[t\]: 葉tに入ったデータの総数 - L\[t\]: 葉tにおける誤りの数

\#hide \###
２値分類のための最適決定木（すべてのデータはカテゴリーデータと仮定）

Optimal Decision Trees for Categorical Data via Integer Programming
Oktay Gu ̈nlu ̈k · Jayant Kalagnanam · Minhan Li · Matt Menickelly ·
Katya Scheinberg

変数

- v\[g,t\]: グループ g がブランチ t で分割対象となるとき 1
- z\[j,t\]: 特徴 j がブランチ t で左の子に行くとき 1
- L\[i,t\]: データ i がブランチ t で左に行くとき 1
- R\[i,t\]: データ i がブランチ t で右に行くとき 1
- c\[i,t\]: データ i が葉 t に行くとき １ SCOP C\[i\] domain Leaf

定式化

- 各ブランチでは1つのグループが選択される：

``` python
for t in Branch:
    m.addConstr( quicksum(v[g,t] for g in G)  == 1  )
```

- 特徴 j　がブランチ t
  で選ばれるなら，その特徴を含んだグループが選ばれなければならない：

``` python
for t in Branch:
    for j in range(p):
          m.addConstr( z[j,t] <= v[group[j], t] )
```

- 追加制約 =\> グループが選ばれるなら，その中の特徴は1つ以上選択

``` python
for t in Branch:
    for g in G:
          m.addConstr( quicksum(z[j,t] for j in J[g]) >= v[g, t] )
```

- 選択された特徴をもつデータ i は左の子に行き，それ以外は右の子に行く：

``` python
for i in range(n):
    for t in Branch:
        m.addConstr( L[i,t] == quicksum( X[i][j]*z[j,t] for j in range(p)) )
        m.addConstr( L[i,t] + R[i,t]== 1 )
```

- データ i が葉 t
  に含まれるなら，その葉に行く先祖点において左（右）に行くデータでなければならない：

``` python
for t in Leaf:
    for i in range(n):
        for ansestor in AL[t]:
            m.addConstr( c[i,t] <= L[i,ansestor] ) 
        for ansestor in AR[t]:
            m.addConstr( c[i,t] <= R[i,ansestor] ) 
```

- データ i は何れかの葉に含まれなければならない：

``` python
for i in range(n):
    m.addConstr( quicksum(c[i,t] for t in Leaf) == 1 ) 
```

- 目的関数： 正しいクラスの葉に割り当てられたデータの数の合計を最大化：

``` python
m.setObjective( quicksum( c[i,t] for i in DataPos for t in LeafPos ) + 
                quicksum( c[i,t] for i in DataNeg for t in LeafNeg ), GRB.MAXIMIZE )
```

## 需要予測

サプライ・チェインにおける需要の予測のための入力は，一般的には以下の形式をもつデータである．

<table style="width:100%;">
<colgroup>
<col style="width: 10%" />
<col style="width: 12%" />
<col style="width: 12%" />
<col style="width: 12%" />
<col style="width: 12%" />
<col style="width: 12%" />
<col style="width: 12%" />
<col style="width: 12%" />
</colgroup>
<thead>
<tr>
<th style="text-align: left;">日付時刻</th>
<th style="text-align: center;">顧客</th>
<th style="text-align: center;">製品</th>
<th style="text-align: center;">需要量</th>
<th style="text-align: center;">売上</th>
<th style="text-align: center;">付加情報1</th>
<th style="text-align: center;">付加情報2</th>
<th style="text-align: center;">…</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left;">2020年1月3日（何時何分）</td>
<td style="text-align: center;">A商店</td>
<td style="text-align: center;">製品α</td>
<td style="text-align: center;">10</td>
<td style="text-align: center;">2600</td>
<td style="text-align: center;">特売日</td>
<td style="text-align: center;"></td>
<td style="text-align: center;">…</td>
</tr>
<tr>
<td style="text-align: left;">2020年1月３日</td>
<td style="text-align: center;">B商店</td>
<td style="text-align: center;">製品β</td>
<td style="text-align: center;">6</td>
<td style="text-align: center;">6000</td>
<td style="text-align: center;"></td>
<td style="text-align: center;">ポイント10倍</td>
<td style="text-align: center;">…</td>
</tr>
<tr>
<td style="text-align: left;">…</td>
<td style="text-align: center;">…</td>
<td style="text-align: center;">…</td>
<td style="text-align: center;">…</td>
<td style="text-align: center;">…</td>
<td style="text-align: center;">…</td>
<td style="text-align: center;">…</td>
<td style="text-align: center;">…</td>
</tr>
</tbody>
</table>

最初の列は日付時刻型のデータが入る．通常は，日付だけだが，何時何分に購入されたかの情報も入れたい場合には，日付時刻型で入力する．
この列をインデックスにすることによって，時間の単位にデータを集約することができる．

2番目と3番目の列には，それぞれ顧客と製品（商品）のデータを入れる．
次の列は，予測をしたいデータ（ターゲット，従属変数）を入れる．通常は，需要量（何個売れたか）を予測するが，それに販売金額を乗じた売上を予測する場合もある．
付加的な情報がある場合には，その次の列に入力する．たとえば，特売日やポイント付加などの情報を入力する．
販売金額が変動する場合には，価格を入れることもある．

予測を行う際には，顧客と製品別に集約し，時系列データに変換してから予測手法を適用する場合が多い．
その場合には，（販売金額が一定なら），需要を予測しても，売上を予測しても同じである．
顧客・製品別に予測を行うのは，簡便性のためであるが，顧客ごとの特徴や製品ごとの特徴を考慮できないことがある．
さらに，顧客や製品から抽出できる付加情報を，付加情報列に追加しても良い．たとえば，同じ系列の顧客の場合には系列名を追加しておくと，特徴が認識しやすくなる．

日付は，自動的に特徴を表す列に変換して扱うこともある．ここでは，以下の列を追加する．（時刻も考慮する場合には，さらに時間，分，秒の列を追加する．）

- ‘Year’: 年
- ‘Month’: 月
- ‘Day’ : 日
- ‘Dayofweek’: 曜日
- ‘Dayofyear’: 年初からの経過日数
- ‘Is_month_end’: 月の最終日
- ‘Is_month_start’: 月の開始日
- ‘Is_quarter_end’: 四半期の終了日
- ‘Is_quarter_start’: 四半期の開始日
- ‘Is_year_end’: 年の最終日
- ‘Is_year_start’: 何の開始日
- ‘Elapsed’: 経過時間

ここで用いるサンプルデータは，
データ生成モジュールのgenerate_demand_with_promo関数を用いて生成したものである．
以下のように読み込んで使用する．

``` python
demand_with_promo_df = pd.read_csv(folder + "demand_with_promo.csv", index_col=0)
demand_with_promo_df.head()
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }
&#10;    .dataframe tbody tr th {
        vertical-align: top;
    }
&#10;    .dataframe thead th {
        text-align: right;
    }
</style>

<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: right;">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">date</th>
<th data-quarto-table-cell-role="th">cust</th>
<th data-quarto-table-cell-role="th">prod</th>
<th data-quarto-table-cell-role="th">promo_0</th>
<th data-quarto-table-cell-role="th">promo_1</th>
<th data-quarto-table-cell-role="th">demand</th>
</tr>
</thead>
<tbody>
<tr>
<td data-quarto-table-cell-role="th">0</td>
<td>2019-01-01</td>
<td>札幌市</td>
<td>A</td>
<td>0</td>
<td>0</td>
<td>2</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">1</td>
<td>2019-01-01</td>
<td>札幌市</td>
<td>B</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">2</td>
<td>2019-01-01</td>
<td>札幌市</td>
<td>C</td>
<td>0</td>
<td>0</td>
<td>2</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">3</td>
<td>2019-01-01</td>
<td>札幌市</td>
<td>D</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">4</td>
<td>2019-01-01</td>
<td>札幌市</td>
<td>E</td>
<td>0</td>
<td>0</td>
<td>1</td>
</tr>
</tbody>
</table>

</div>

## 指数平滑法

サプライ・チェインの古典手法に、指数平滑法と呼ばれる予測法がある。

航空機の乗客数の時系列データを用いて、様々な手法の比較を行う。

## Holt-Wintersの季節変動と傾向変動を考慮した指数平滑法

パラメータ

- *y*<sub>*t*</sub>: 期 *t* の実現値
- *s*<sub>*t*</sub>: 基本水準係数
- *b*<sub>*t*</sub>: 傾向変動係数
- *c*<sub>*t*</sub>: 季節変動係数
- *ŷ*<sub>*t* + *m*</sub>: 期 *t* における *m*期後の予測値
- *L* ：季節変動の周期 (seasonal_periods)
- *α*: 平滑化定数 (smoothing_level)
- *β*: 傾向変動に対する平滑化定数 (smoothing_slope)
- *γ*: 季節変動に対する平滑化定数 (smoothing_seasonal)

加法的季節変動：
$$
\begin{array}{lll}
&s_0  & =&  y_0\\
&s\_{t} & =&  \alpha (y\_{t}-c\_{t-L}) + (1-\alpha)(s\_{t-1} + b\_{t-1})\\
&b\_{t} &=& \beta (s_t - s\_{t-1}) + (1-\beta)b\_{t-1}\\
&c\_{t} &=& \gamma (y\_{t}-s\_{t})+(1-\gamma)c\_{t-L}\\
&\hat{y}\_{t+m} &=& s_t + m b_t+c\_{t-L+1+(m-1)\mod L}
\end{array}
$$

乗法的季節変動：

$$
\begin{array}{lll}
s_0  &=& y_0\\
s\_{t} &=& \alpha (y\_{t}/c\_{t-L}) + (1-\alpha)(s\_{t-1} + b\_{t-1})\\
b\_{t} &=& \beta (s_t - s\_{t-1}) + (1-\beta)b\_{t-1}\\
c\_{t} &=& \gamma (y\_{t}/s\_{t})+(1-\gamma)c\_{t-L}\\
\hat{y}\_{t+m} &=& (s_t + m b_t) c\_{t-L+1+(m-1)\mod L}
\end{array}
$$

手法

- SimpleExpSmoothing: 単純指数平滑法（ *γ* のみ用いる）
- Holt: Holt法 (*β* と *γ* を用いる）
- ExponentialSmoothing: Holt-Wintersの指数平滑法（すべて用いる）

最後の2年間（24ヶ月）をテストデータとする。Holt-Winters法に対しては、パラメータは自動調整とし，
Box-Cox変換をしてデータを正規化しておく（引数のuse_boxcoxをTrueにする）．

``` python
passengers = pd.read_csv("http://logopt.com/data/AirPassengers.csv")
passengers["Month"] = pd.to_datetime(passengers.Month) # Monthの列を日付時刻型に変換
passengers.set_index("Month", inplace=True) #月をインデックスとする
passengers.index.freq ="MS" #月のはじめを頻度にする
passengers.head()

fit1 = SimpleExpSmoothing(passengers[:-24]).fit(smoothing_level=0.2,optimized=False)
fit2 = Holt(passengers[:-24]).fit(smoothing_level=0.8, smoothing_slope=0.2, optimized=False)
fit3 = ExponentialSmoothing(passengers[:-24],seasonal_periods=12, trend='add', seasonal='add').fit()
start, end = len(passengers)-24, len(passengers)
predict1 = fit1.predict(start, end)
predict2 = fit2.predict(start, end)
predict3 = fit3.predict(start, end)
```

### SARIMAX で予測

ARIMA (autoregressive integrated moving average)モデル

*y*<sub>*t*</sub> − *y*<sub>*t* − *d*</sub> = *c* + *ϕ*<sub>1</sub>*y*<sub>*t* − 1</sub> + *ϕ*<sub>2</sub>*y*<sub>*t* − 2</sub> + ⋯ + *ϕ*<sub>*p*</sub>*y*<sub>*t* − *p*</sub> + *ε*<sub>*t*</sub> + *θ*<sub>1</sub>*ε*<sub>*t* − 1</sub> + ⋯ + *θ*<sub>*q*</sub>*ε*<sub>*t* − *q*</sub>

パラメータ

- 自己回帰 AR (autoregressive): *p*； 過去 *p* 期の値の多項式で予測
- 差分 I (integrated): *d*； *d*
  期前との差分をとることによって傾向変動を予測
- 移動平均 MA (moving average): *q*； 過去 *q* 期の誤差の多項式で予測

季節変動の追加 SARIMA (seasonal ARIMA)

パラメータ

- 季節自己回帰 SAR: *P*
- 季節差分 SI : *D*
- 季節移動平均 SMA: *Q*
- 周期: *L*

SARIMA**X** 外生変数 (e**X**ogenous variables) の追加

``` python
mod = SARIMAX(passengers[:-24],                                                                
                                order=(1, 1, 1),
                                seasonal_order=(1, 1, 1, 12),
                                enforce_stationarity=False,
                                enforce_invertibility=False)
fit4 = mod.fit()
predict4 = fit4.predict(start,end)
```

``` python
df = passengers.reset_index()
df.rename(columns={"Month": "ds", "#Passengers": "y"}, inplace=True)
```

``` python
model = Prophet(daily_seasonality=False, weekly_seasonality=False, yearly_seasonality=True,seasonality_mode='multiplicative')
model.fit(df[:-24])
future = model.make_future_dataframe(periods=24, freq="MS")
forecast = model.predict(future)
forecast.head()
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }
&#10;    .dataframe tbody tr th {
        vertical-align: top;
    }
&#10;    .dataframe thead th {
        text-align: right;
    }
</style>

<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: right;">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">ds</th>
<th data-quarto-table-cell-role="th">trend</th>
<th data-quarto-table-cell-role="th">yhat_lower</th>
<th data-quarto-table-cell-role="th">yhat_upper</th>
<th data-quarto-table-cell-role="th">trend_lower</th>
<th data-quarto-table-cell-role="th">trend_upper</th>
<th data-quarto-table-cell-role="th">multiplicative_terms</th>
<th data-quarto-table-cell-role="th">multiplicative_terms_lower</th>
<th data-quarto-table-cell-role="th">multiplicative_terms_upper</th>
<th data-quarto-table-cell-role="th">yearly</th>
<th data-quarto-table-cell-role="th">yearly_lower</th>
<th data-quarto-table-cell-role="th">yearly_upper</th>
<th data-quarto-table-cell-role="th">additive_terms</th>
<th data-quarto-table-cell-role="th">additive_terms_lower</th>
<th data-quarto-table-cell-role="th">additive_terms_upper</th>
<th data-quarto-table-cell-role="th">yhat</th>
</tr>
</thead>
<tbody>
<tr>
<td data-quarto-table-cell-role="th">0</td>
<td>1949-01-01</td>
<td>115.732114</td>
<td>92.193672</td>
<td>116.702905</td>
<td>115.732114</td>
<td>115.732114</td>
<td>-0.097351</td>
<td>-0.097351</td>
<td>-0.097351</td>
<td>-0.097351</td>
<td>-0.097351</td>
<td>-0.097351</td>
<td>0.0</td>
<td>0.0</td>
<td>0.0</td>
<td>104.465421</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">1</td>
<td>1949-02-01</td>
<td>117.417721</td>
<td>89.359809</td>
<td>112.239922</td>
<td>117.417721</td>
<td>117.417721</td>
<td>-0.142170</td>
<td>-0.142170</td>
<td>-0.142170</td>
<td>-0.142170</td>
<td>-0.142170</td>
<td>-0.142170</td>
<td>0.0</td>
<td>0.0</td>
<td>0.0</td>
<td>100.724450</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">2</td>
<td>1949-03-01</td>
<td>118.940205</td>
<td>107.671109</td>
<td>130.977234</td>
<td>118.940205</td>
<td>118.940205</td>
<td>0.004902</td>
<td>0.004902</td>
<td>0.004902</td>
<td>0.004902</td>
<td>0.004902</td>
<td>0.004902</td>
<td>0.0</td>
<td>0.0</td>
<td>0.0</td>
<td>119.523276</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">3</td>
<td>1949-04-01</td>
<td>120.625813</td>
<td>104.280365</td>
<td>128.476356</td>
<td>120.625813</td>
<td>120.625813</td>
<td>-0.031312</td>
<td>-0.031312</td>
<td>-0.031312</td>
<td>-0.031312</td>
<td>-0.031312</td>
<td>-0.031312</td>
<td>0.0</td>
<td>0.0</td>
<td>0.0</td>
<td>116.848788</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">4</td>
<td>1949-05-01</td>
<td>122.257045</td>
<td>106.734658</td>
<td>130.131457</td>
<td>122.257045</td>
<td>122.257045</td>
<td>-0.027676</td>
<td>-0.027676</td>
<td>-0.027676</td>
<td>-0.027676</td>
<td>-0.027676</td>
<td>-0.027676</td>
<td>0.0</td>
<td>0.0</td>
<td>0.0</td>
<td>118.873491</td>
</tr>
</tbody>
</table>

</div>

``` python
passengers["Exp.Smooth."] = predict1
passengers["Holt"] = predict2
passengers["Holt-Winter"] = predict3
passengers["SARIMAX"] = predict4
passengers["Prophet"] = forecast.loc[:,"yhat"].values
tacked_df = pd.DataFrame(passengers[-24:].stack(),columns=["num"]).reset_index()
fig = px.line(stacked_df,x="Month",y="num",color="level_1")
plotly.offline.plot(fig);
```

![](06forecast_files/figure-commonmark/cell-18-output-1.png)

``` python
methods = ["Exp.Smooth.", "Holt", "Holt-Winter", "SARIMAX", "Prophet"]
#passengers[-24:]
target = "#Passengers"
metrics_list =[ [] for m in methods]
for i, m in enumerate(methods):
    y_pred = passengers[m][-24:]
    y_true = passengers[target][-24:] 

    metrics_list[i] =[ mean_squared_error(y_true, y_pred), mean_absolute_error(y_true, y_pred),
                 mean_squared_log_error(y_true, y_pred), median_absolute_error(y_true, y_pred), max_error(y_true, y_pred) ]

metrics = pd.DataFrame({m:metrics_list[i] for i,m in enumerate(methods)}, index=["mean_squared", "mean_absolute", "mean_squared_log", "median_abusolute", "max"])
metrics
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }
&#10;    .dataframe tbody tr th {
        vertical-align: top;
    }
&#10;    .dataframe thead th {
        text-align: right;
    }
</style>

<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: right;">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">Exp.Smooth.</th>
<th data-quarto-table-cell-role="th">Holt</th>
<th data-quarto-table-cell-role="th">Holt-Winter</th>
<th data-quarto-table-cell-role="th">SARIMAX</th>
<th data-quarto-table-cell-role="th">Prophet</th>
</tr>
</thead>
<tbody>
<tr>
<td data-quarto-table-cell-role="th">mean_squared</td>
<td>11560.124288</td>
<td>90391.493041</td>
<td>1278.707087</td>
<td>5719.201415</td>
<td>936.384334</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">mean_absolute</td>
<td>82.410342</td>
<td>270.694737</td>
<td>31.076413</td>
<td>69.895789</td>
<td>25.504026</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">mean_squared_log</td>
<td>0.055542</td>
<td>1.431378</td>
<td>0.005957</td>
<td>0.031673</td>
<td>0.004042</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">median_abusolute</td>
<td>51.102678</td>
<td>254.302112</td>
<td>29.663906</td>
<td>62.913468</td>
<td>24.663997</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">max</td>
<td>247.102678</td>
<td>517.826696</td>
<td>74.254745</td>
<td>129.229564</td>
<td>74.062530</td>
</tr>
</tbody>
</table>

</div>

## Prophet

### 顧客の需要予測

過去の需要系列dfをもとに、Prophetによる予測を行う関数 forecast_demand
を準備する。
比較として、（需要の定常性を仮定して）平均と標準偏差も算出する。

引数：

- demand_df:
  需要の系列を表すデータフレーム。顧客Cust、製品Prod,日時Date、需要量demandの列をもつものと仮定する。
- cust_selected: 顧客のリスト
- prod_selected: 製品のリスト
- agg_period:
  集約を行う期。例えば１週間を１期とするなら”1w”とする。既定値は1日（“1d”）
- forecast_period: 予測を行う未来の期数。既定値は1
- cumulative: 累積需要量を用いて予測するとき True；既定値はFalse
- lb:
  下限値（傾向変動がロジスティック曲線の場合に有効になる．）既定値は0.
- ub: 上限値（傾向変動がロジスティック曲線の場合に有効になる．）既定値は
  Noneで，その場合にはデータの最大値が設定される．
- kwargs: その他のProphetの引数

Prophetの引数と既定値：

- growth=‘linear’
  :傾向変動の関数．規定値は線形．ロジスティック曲線にするには，引数を’logistic’に設定する．
  また傾向変動をなくすためには引数を ’flat’に設定する．
- changepoints=None : 傾向変更点のリスト
- changepoint_range =0.8 :
  傾向変化点の候補の幅（先頭から何割を候補とするか）
- n_changepoints=25 : 傾向変更点の数
- yearly_seasonality=‘auto’ : 年次の季節変動を考慮するか否か
- weekly_seasonality=‘auto’ : 週次の季節変動を考慮するか否か
- daily_seasonality=‘auto’ : 日時の季節変動を考慮するか否か
- holidays=None : 休日のリスト
- seasonality_prior_scale=10.0 :
  季節変動の事前分布のスケール値（パラメータの柔軟性をあら表す）
- holidays_prior_scale=10.0 :
  休日のの事前分布のスケール値（パラメータの柔軟性をあら表す）
- changepoint_prior_scale=0.05 :
  傾向変更点の事前分布のスケール値（パラメータの柔軟性をあら表す）
- mcmc_samples=0 : MCMC法のサンプル数
- interval_width=0.80 : 不確実性の幅
- uncertainty_samples=1000 : 不確実性の幅を計算する際のサンプル数

返値：

以下の情報を列情報にもつデータフレーム

- dic:
  顧客と製品のタプルをキーとし、モデルと予測オブジェクトのタプルを値とした辞書

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L111"
target="_blank" style="float:right; font-size:smaller">source</a>

### forecast_demand

``` python

def forecast_demand(
    demand_df, cust_selected, prod_selected, agg_period:str='1d', forecast_periods:int=1, cumulative:bool=False,
    lb:float=0.0, ub:NoneType=None, kwargs:VAR_KEYWORD
):

```

*Prophetを用いた需要予測（顧客と製品に対して）*

### forecast_demand関数の使用例

``` python
demand_df = pd.read_csv(folder+"demand.csv")

#cust_selected = [ demand_df["cust"].iloc[350] ]
#prod_selected = [ demand_df["prod"].iloc[350] ]
cust_selected = ["前橋市"]
prod_selected = ["F"]

print(cust_selected, prod_selected)
dic = forecast_demand(demand_df, cust_selected, prod_selected, agg_period ="1d", forecast_periods =10, cumulative=False, lb=0., ub=None, growth ="logistic",
                     daily_seasonality=False, weekly_seasonality=True, yearly_seasonality=True)
print(cust_selected[0], prod_selected[0])
if dic[ cust_selected[0], prod_selected[0] ] is not None:
    model, forecast = dic[ cust_selected[0], prod_selected[0] ]
    model.plot(forecast);
else:
    print("too few data")
```

    ['前橋市'] ['F']
    前橋市 F
    too few data

## 特徴量を入れたProphetによる需要予測

過去の需要系列demand_dfとプロモーション情報promo_dfを用いてProphetによる予測を行う関数
forecast_demand_with_featuresを準備する。

引数：

- demand_df:
  需要の系列を表すデータフレーム。顧客Cust、製品Prod,日時Date、需要量demandの列をもつものと仮定する。
- cust_selected: 顧客のリスト
- prod_selected: 製品のリスト
- promo_df:
  プロモーション情報を入れたデータフレーム；demand_dfと同じ日時と、予測する期間に対する日時の情報を含むものとする。
- feature: promo_df内で特徴量として用いる列名のリスト
- agg_period:
  集約を行う期。例えば１週間を１期とするなら”1w”とする。既定値は1日（“1d”）
- forecast_period: 予測を行う未来の期数。既定値は1
- cumulative: 累積需要量を用いて予測するとき True；既定値はFalse
- lb:
  下限値（傾向変動がロジスティック曲線の場合に有効になる．）既定値は0.
- ub: 上限値（傾向変動がロジスティック曲線の場合に有効になる．）既定値は
  Noneで，その場合にはデータの最大値が設定される．
- kwargs: その他のProphetのキーワード引数

Prophetの引数と既定値：

- growth=‘linear’
  :傾向変動の関数．既定値は線形．ロジスティック曲線にするに’logistic’に設定する．また傾向変動をなくすためには引数を
  ’flat’に設定する．
- changepoints=None : 傾向変更点のリスト
- changepoint_range =0.8 :
  傾向変化点の候補の幅（先頭から何割を候補とするか）
- n_changepoints=25 : 傾向変更点の数
- yearly_seasonality=‘auto’ : 年次の季節変動を考慮するか否か
- weekly_seasonality=‘auto’ : 週次の季節変動を考慮するか否か
- daily_seasonality=‘auto’ : 日時の季節変動を考慮するか否か
- holidays=None : 休日のリスト
- seasonality_prior_scale=10.0 :
  季節変動の事前分布のスケール値（パラメータの柔軟性をあら表す）
- holidays_prior_scale=10.0 :
  休日のの事前分布のスケール値（パラメータの柔軟性をあら表す）
- changepoint_prior_scale=0.05 :
  傾向変更点の事前分布のスケール値（パラメータの柔軟性をあら表す）
- mcmc_samples=0 : MCMC法のサンプル数
- interval_width=0.80 : 不確実性の幅
- uncertainty_samples=1000 : 不確実性の幅を計算する際のサンプル数

返値：

以下の情報を列情報にもつデータフレーム

- dic:
  顧客と製品のタプルをキーとし、モデルと予測オブジェクトのタプルを値とした辞書

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L175"
target="_blank" style="float:right; font-size:smaller">source</a>

### forecast_demand_with_features

``` python

def forecast_demand_with_features(
    demand_df, cust_selected, prod_selected, promo_df:NoneType=None, features:NoneType=None, agg_period:str='1d',
    forecast_periods:int=1, cumulative:bool=False, lb:float=0.0, ub:NoneType=None, kwargs:VAR_KEYWORD
):

```

*Prophetを用いた需要予測（顧客と製品に対して）：特徴ベクトルの追加*

### forecast_demand_with_features関数の使用例

``` python
promo_df = pd.read_csv(folder+"promo.csv", index_col=0)
demand_df = pd.read_csv(folder+"demand_with_promo.csv")

cust_selected = [ demand_df["cust"].iloc[90],demand_df["cust"].iloc[101] ]
prod_selected = [ demand_df["prod"].iloc[1] ]
#cust_selected = ["前橋市"]
#prod_selected = ["F"]
print(cust_selected, prod_selected)
dic, df  = forecast_demand_with_features(demand_df, cust_selected, prod_selected, promo_df, features=['promo_0', 'promo_1'], 
                                     agg_period ="1d", forecast_periods =0, cumulative=False, growth="linear",
                     daily_seasonality=False, weekly_seasonality=True, yearly_seasonality=True)

if dic[ cust_selected[0], prod_selected[0] ] is not None:
    model, forecast = dic[ cust_selected[0], prod_selected[0] ]
    model.plot(forecast);
else:
    print("too few data")
```

    ['札幌市', '仙台市'] ['B']

    AttributeError: 'Prophet' object has no attribute 'stan_backend'
    [0;31m---------------------------------------------------------------------------[0m
    [0;31mAttributeError[0m                            Traceback (most recent call last)
    [0;32m/var/folders/69/5y96sdc94jxf6khgc8mlmxrr0000gn/T/ipykernel_94971/15301494.py[0m in [0;36m<module>[0;34m[0m
    [1;32m      7[0m [0;31m#prod_selected = ["F"][0m[0;34m[0m[0;34m[0m[0;34m[0m[0m
    [1;32m      8[0m [0mprint[0m[0;34m([0m[0mcust_selected[0m[0;34m,[0m [0mprod_selected[0m[0;34m)[0m[0;34m[0m[0;34m[0m[0m
    [0;32m----> 9[0;31m dic, df  = forecast_demand_with_features(demand_df, cust_selected, prod_selected, promo_df, features=['promo_0', 'promo_1'], 
    [0m[1;32m     10[0m                                      [0magg_period[0m [0;34m=[0m[0;34m"1d"[0m[0;34m,[0m [0mforecast_periods[0m [0;34m=[0m[0;36m0[0m[0;34m,[0m [0mcumulative[0m[0;34m=[0m[0;32mFalse[0m[0;34m,[0m [0mgrowth[0m[0;34m=[0m[0;34m"linear"[0m[0;34m,[0m[0;34m[0m[0;34m[0m[0m
    [1;32m     11[0m                      daily_seasonality=False, weekly_seasonality=True, yearly_seasonality=True)

    [0;32m/var/folders/69/5y96sdc94jxf6khgc8mlmxrr0000gn/T/ipykernel_94971/3772577099.py[0m in [0;36mforecast_demand_with_features[0;34m(demand_df, cust_selected, prod_selected, promo_df, features, agg_period, forecast_periods, cumulative, lb, ub, **kwargs)[0m
    [1;32m     45[0m                     [0mdf[0m[0;34m[[0m[0;34m"floor"[0m[0;34m][0m [0;34m=[0m [0mlb[0m[0;34m[0m[0;34m[0m[0m
    [1;32m     46[0m [0;34m[0m[0m
    [0;32m---> 47[0;31m                 [0mmodel[0m [0;34m=[0m [0mProphet[0m[0;34m([0m[0;34m**[0m[0mkwargs[0m[0;34m)[0m[0;34m[0m[0;34m[0m[0m
    [0m[1;32m     48[0m [0;34m[0m[0m
    [1;32m     49[0m                 [0;31m#プロモーションの特徴ベクトルを追加[0m[0;34m[0m[0;34m[0m[0;34m[0m[0m

    [0;32m~/Library/Caches/pypoetry/virtualenvs/scmopt-KVX_UVCf-py3.8/lib/python3.8/site-packages/fbprophet/forecaster.py[0m in [0;36m__init__[0;34m(self, growth, changepoints, n_changepoints, changepoint_range, yearly_seasonality, weekly_seasonality, daily_seasonality, holidays, seasonality_mode, seasonality_prior_scale, holidays_prior_scale, changepoint_prior_scale, mcmc_samples, interval_width, uncertainty_samples, stan_backend)[0m
    [1;32m    139[0m         [0mself[0m[0;34m.[0m[0mfit_kwargs[0m [0;34m=[0m [0;34m{[0m[0;34m}[0m[0;34m[0m[0;34m[0m[0m
    [1;32m    140[0m         [0mself[0m[0;34m.[0m[0mvalidate_inputs[0m[0;34m([0m[0;34m)[0m[0;34m[0m[0;34m[0m[0m
    [0;32m--> 141[0;31m         [0mself[0m[0;34m.[0m[0m_load_stan_backend[0m[0;34m([0m[0mstan_backend[0m[0;34m)[0m[0;34m[0m[0;34m[0m[0m
    [0m[1;32m    142[0m [0;34m[0m[0m
    [1;32m    143[0m     [0;32mdef[0m [0m_load_stan_backend[0m[0;34m([0m[0mself[0m[0;34m,[0m [0mstan_backend[0m[0;34m)[0m[0;34m:[0m[0;34m[0m[0;34m[0m[0m

    [0;32m~/Library/Caches/pypoetry/virtualenvs/scmopt-KVX_UVCf-py3.8/lib/python3.8/site-packages/fbprophet/forecaster.py[0m in [0;36m_load_stan_backend[0;34m(self, stan_backend)[0m
    [1;32m    152[0m             [0mself[0m[0;34m.[0m[0mstan_backend[0m [0;34m=[0m [0mStanBackendEnum[0m[0;34m.[0m[0mget_backend_class[0m[0;34m([0m[0mstan_backend[0m[0;34m)[0m[0;34m([0m[0;34m)[0m[0;34m[0m[0;34m[0m[0m
    [1;32m    153[0m [0;34m[0m[0m
    [0;32m--> 154[0;31m         [0mlogger[0m[0;34m.[0m[0mdebug[0m[0;34m([0m[0;34m"Loaded stan backend: %s"[0m[0;34m,[0m [0mself[0m[0;34m.[0m[0mstan_backend[0m[0;34m.[0m[0mget_type[0m[0;34m([0m[0;34m)[0m[0;34m)[0m[0;34m[0m[0;34m[0m[0m
    [0m[1;32m    155[0m [0;34m[0m[0m
    [1;32m    156[0m     [0;32mdef[0m [0mvalidate_inputs[0m[0;34m([0m[0mself[0m[0;34m)[0m[0;34m:[0m[0;34m[0m[0;34m[0m[0m

    [0;31mAttributeError[0m: 'Prophet' object has no attribute 'stan_backend'

### 集約したデータに対する予測

``` python
demand_df = pd.read_csv(folder+"aggregate_demand.csv")

cust_selected = [ demand_df["cust"].iloc[3] ]
prod_selected = [ demand_df["prod"].iloc[3] ]
print(cust_selected, prod_selected)

dic, df  = forecast_demand_with_features(demand_df, cust_selected, prod_selected, features=[], agg_period ="1d", forecast_periods =100, cumulative=False
                                         ,growth="logistic", daily_seasonality=False, weekly_seasonality=True, yearly_seasonality=True)


print(cust_selected[0], prod_selected[0])
if dic[ cust_selected[0], prod_selected[0] ] is not None:
    model, forecast = dic[ cust_selected[0], prod_selected[0] ]
    model.plot(forecast);
else:
    print("too few data")
```

    ['Plnt_Odawara'] ['B']
    Plnt_Odawara B

![](06forecast_files/figure-commonmark/cell-24-output-2.png)

``` python
len(forecast)
```

    730

## 交差検証

``` python
#df_cv = cross_validation(model, initial='220 days', period='100 days', horizon = '100 days')
df_cv = cross_validation(model, initial='200 days', period='30 days', horizon = '60 days')
df_cv.head()
```

    INFO:fbprophet:Making 16 forecasts with cutoffs between 2019-08-08 00:00:00 and 2020-10-31 00:00:00
    WARNING:fbprophet:Seasonality has period of 365.25 days which is larger than initial window. Consider increasing initial.

      0%|          | 0/16 [00:00<?, ?it/s]

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }
&#10;    .dataframe tbody tr th {
        vertical-align: top;
    }
&#10;    .dataframe thead th {
        text-align: right;
    }
</style>

<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: right;">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">ds</th>
<th data-quarto-table-cell-role="th">yhat</th>
<th data-quarto-table-cell-role="th">yhat_lower</th>
<th data-quarto-table-cell-role="th">yhat_upper</th>
<th data-quarto-table-cell-role="th">y</th>
<th data-quarto-table-cell-role="th">cutoff</th>
</tr>
</thead>
<tbody>
<tr>
<td data-quarto-table-cell-role="th">0</td>
<td>2019-08-09</td>
<td>2.806365</td>
<td>1.621363</td>
<td>3.974812</td>
<td>2</td>
<td>2019-08-08</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">1</td>
<td>2019-08-10</td>
<td>4.407486</td>
<td>3.145626</td>
<td>5.640692</td>
<td>5</td>
<td>2019-08-08</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">2</td>
<td>2019-08-11</td>
<td>1.621587</td>
<td>0.445880</td>
<td>2.891954</td>
<td>0</td>
<td>2019-08-08</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">3</td>
<td>2019-08-12</td>
<td>1.618451</td>
<td>0.417103</td>
<td>2.789864</td>
<td>0</td>
<td>2019-08-08</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">4</td>
<td>2019-08-13</td>
<td>3.644485</td>
<td>2.507137</td>
<td>4.867713</td>
<td>3</td>
<td>2019-08-08</td>
</tr>
</tbody>
</table>

</div>

``` python
df_p = performance_metrics(df_cv, rolling_window=0.1)
df_p.head()
```

    INFO:fbprophet:Skipping MAPE because y close to 0

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }
&#10;    .dataframe tbody tr th {
        vertical-align: top;
    }
&#10;    .dataframe thead th {
        text-align: right;
    }
</style>

<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: right;">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">horizon</th>
<th data-quarto-table-cell-role="th">mse</th>
<th data-quarto-table-cell-role="th">rmse</th>
<th data-quarto-table-cell-role="th">mae</th>
<th data-quarto-table-cell-role="th">mdape</th>
<th data-quarto-table-cell-role="th">coverage</th>
</tr>
</thead>
<tbody>
<tr>
<td data-quarto-table-cell-role="th">0</td>
<td>6 days</td>
<td>1.866793</td>
<td>1.366306</td>
<td>1.128297</td>
<td>0.556571</td>
<td>0.625000</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">1</td>
<td>7 days</td>
<td>1.823782</td>
<td>1.350475</td>
<td>1.101126</td>
<td>0.452552</td>
<td>0.645833</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">2</td>
<td>8 days</td>
<td>1.747038</td>
<td>1.321756</td>
<td>1.099327</td>
<td>0.506288</td>
<td>0.677083</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">3</td>
<td>9 days</td>
<td>1.669610</td>
<td>1.292134</td>
<td>1.050407</td>
<td>0.445765</td>
<td>0.697917</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">4</td>
<td>10 days</td>
<td>1.858351</td>
<td>1.363214</td>
<td>1.065813</td>
<td>0.410124</td>
<td>0.687500</td>
</tr>
</tbody>
</table>

</div>

``` python
plot_cross_validation_metric(df_cv, metric='mse');
```

![](06forecast_files/figure-commonmark/cell-29-output-1.png)

## 平均や標準偏差も計算

過去の需要系列dfをもとに、Prophetによる予測を行う関数 forecast_prophet
を準備する。
比較として、（需要の定常性を仮定して）平均と標準偏差も算出する。

引数：

- demand_df:
  需要の系列を表すデータフレーム。顧客Cust、製品Prod,日時Date、需要量demandの列をもつものと仮定する。
- agg_period:
  集約を行う期。例えば１週間を１期とするなら”1w”とする。既定値は1日（“1d”）
- forecast_period: 予測を行う未来の期数。既定値は1

返値：

以下の情報を列情報にもつデータフレーム

- mean: 需要の平均
- std : 需要の標準偏差
- Prophet\[0..forecast_period-1\]:
  Prophetによる予測から計算された未来のforecast_periods 期分の最大在庫量

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L254"
target="_blank" style="float:right; font-size:smaller">source</a>

### forecast_prophet

``` python

def forecast_prophet(
    df, agg_period:str='1d', forecast_periods:int=1
):

```

*Prophetを用いた需要予測*

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L282"
target="_blank" style="float:right; font-size:smaller">source</a>

### forecast_prophet_cust_prod

``` python

def forecast_prophet_cust_prod(
    demand_df, cust_selected, prod_selected, agg_period:str='1d', forecast_periods:int=1, cumulative:bool=False
):

```

*Prophetを用いた需要予測（顧客と製品に対して）*

``` python
# ProphetのWarningがたくさん出る場合には、以下を生かす。
import warnings
warnings.simplefilter('ignore')
demand_df = pd.read_csv(folder+"demand.csv")
cust_selected = [ demand_df["cust"].iloc[0], demand_df["cust"].iloc[-1] ]
prod_selected = [ demand_df["prod"].iloc[0], demand_df["prod"].iloc[-1] ]
print(cust_selected, prod_selected)
forecast_df = forecast_prophet_cust_prod(demand_df, cust_selected, prod_selected, agg_period ="1w", forecast_periods =10)
print(forecast_df.head())
```

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L314"
target="_blank" style="float:right; font-size:smaller">source</a>

### forecast_prophet_cust

``` python

def forecast_prophet_cust(
    demand_df, cust_selected, agg_period:str='1d', forecast_periods:int=1
):

```

*各顧客に対する（すべての製品の）合計需要の予測*

``` python
demand_df = pd.read_csv(folder+"demand.csv")
cust_selected = [ demand_df["cust"].iloc[0], demand_df["cust"].iloc[-1] ]
forecast_df = forecast_prophet_cust(demand_df, cust_selected, agg_period ="1w", forecast_periods =10)
print(forecast_df.head())
```

    Prophet Error while computing for 札幌市
    Prophet Error while computing for 那覇市
    Empty DataFrame
    Columns: [cust, mean, std, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    Index: []

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L349"
target="_blank" style="float:right; font-size:smaller">source</a>

### forecast_prophet_prod

``` python

def forecast_prophet_prod(
    demand_df, prod_selected, agg_period:str='1d', forecast_periods:int=1
):

```

*各製品に対する（すべての顧客の）合計需要の予測*

``` python
demand_df = pd.read_csv(folder+"demand.csv")
prod_selected = [ demand_df["prod"].iloc[0], demand_df["prod"].iloc[-1] ]    
forecast_df = forecast_prophet_prod(demand_df, prod_selected, agg_period ="1w", forecast_periods =10)
print(forecast_df.head())
```

    Prophet Error while computing for A
    Prophet Error while computing for J
    Empty DataFrame
    Columns: [prod, mean, std, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    Index: []

## 深層学習ライブラリ fastai を用いた需要予測

### 未来の時系列データフレームを生成する関数 make_future_dataframe

過去の時系列データから未来のデータを生成する関数

- history_dates: 過去の時系列データの日付を表す
- finish: 終了日
- periods: 生成する未来の期数
- freq: 生成する期の単位（頻度）を表す文字列;
  たとえば，1日単位の場合には”1d”とする．

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L380"
target="_blank" style="float:right; font-size:smaller">source</a>

### make_future_dataframe

``` python

def make_future_dataframe(
    history_dates, periods, freq:str='1d', include_history:bool=True
):

```

*未来の時系列データフレームを生成する関数*

#### make_future_dataframe関数の使用例

``` python
#製品／顧客を切り出したデータフレームの保存
promo_df = pd.read_csv(folder+"promo.csv", index_col=0)
demand_df = pd.read_csv(folder+"demand_with_promo.csv",index_col=0)
customer = "仙台市" 
product = "A"
agg_period ="1d"
try:
    demand_df.reset_index(inplace=True)
except ValueError:
    pass
demand_df["date"] = pd.to_datetime(demand_df["date"])
demand_df.set_index("date", inplace=True)
demand_grouped = demand_df.groupby(
    ["cust", "prod"]).resample(agg_period)["demand"].sum()

if (customer,product) in demand_grouped:
    df = pd.DataFrame(demand_grouped[customer, product])

# df.reset_index(inplace=True)
# if promo_df is not None:
#     promo_df["date"] = pd.to_datetime(promo_df["date"])
#     df = pd.merge(df, promo_df,on="date", how="left")
#df.to_csv("maebashi-f.csv")
df.head()
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }
&#10;    .dataframe tbody tr th {
        vertical-align: top;
    }
&#10;    .dataframe thead th {
        text-align: right;
    }
</style>

<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: right;">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">demand</th>
</tr>
<tr>
<th data-quarto-table-cell-role="th">date</th>
<th data-quarto-table-cell-role="th"></th>
</tr>
</thead>
<tbody>
<tr>
<td data-quarto-table-cell-role="th">2019-01-01</td>
<td>13</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">2019-01-02</td>
<td>19</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">2019-01-03</td>
<td>17</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">2019-01-04</td>
<td>12</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">2019-01-05</td>
<td>19</td>
</tr>
</tbody>
</table>

</div>

``` python
future = make_future_dataframe(history_dates=df.index, periods=10, freq="1w", include_history=False)
future.head()
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }
&#10;    .dataframe tbody tr th {
        vertical-align: top;
    }
&#10;    .dataframe thead th {
        text-align: right;
    }
</style>

<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: right;">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">date</th>
</tr>
</thead>
<tbody>
<tr>
<td data-quarto-table-cell-role="th">0</td>
<td>2021-01-03</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">1</td>
<td>2021-01-10</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">2</td>
<td>2021-01-17</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">3</td>
<td>2021-01-24</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">4</td>
<td>2021-01-31</td>
</tr>
</tbody>
</table>

</div>

### Excelのテンプレートを生成する関数 make_excel_forecast

Excelインターフェイスのテンプレートを生成する関数．

引数：

- start: 開始日
- finish: 終了日
- period: 期を構成する単位期間の数；既定値は 1
- period_unit: 期の単位 （時，日，週，月から選択）； 既定値は日；
  periodとあわせて期間の生成に用いる．
  たとえば，既定値だと１日が1期となる．
- num_features: （休日を除く）特徴の数
- holiday: 日本のカレンダーに基づく休日を表す特徴を追加するときTrue

返値：

- 需要予測用のExcelのWorkbook

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L399"
target="_blank" style="float:right; font-size:smaller">source</a>

### make_excel_forecast

``` python

def make_excel_forecast(
    start, finish, period:int=1, period_unit:str='日', num_features:int=0, holiday:bool=True
):

```

*Call self as a function.*

#### make_excel_forecast関数の使用例

``` python
start = '2015-01-05' #開始日
finish = '2019-1-30'
period=1
period_unit="週"
wb = make_excel_forecast(start, finish, period, period_unit, num_features = 0, holiday=False)
wb.save("forecast-templete.xlsx")
```

### Excelファイルを読み込んで予測を行う関数 forecast_excel

ExcelのWorkbookを与えると予測を記入して返す関数

引数： - wb: 日付，需要，特徴のデータを入れたExcel Workbook -
valid_start: 検証開始日 - predict_start: 予測開始日

返値： - wb: 予測結果と誤差の列を追加したExcel Workbook - best:
最良の予測をしたモデルオブジェクト - result_df:
予測結果のデータフレーム - forecast:
最良の予測モデルを用いた予測結果のデータフレーム - demand_df:
予測結果から需要を抽出し，誤差列を追加したデータフレーム - valid_df:
demand_dfから検証開始から予測開始の直前までを抜き出したデータフレーム

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L458"
target="_blank" style="float:right; font-size:smaller">source</a>

### forecast_excel

``` python

def forecast_excel(
    wb, valid_start, predict_start
):

```

*Call self as a function.*

#### forecast_excel関数の使用例

``` python
# wb = load_workbook("forecast-ex2.xlsx", data_only=True)
# valid_start = "2019-09-01"
# predict_start = "2020-12-30"

wb = load_workbook("forecast-ex1.xlsx", data_only=True)
valid_start = "2021-02-24"
predict_start = "2021-3-03"

#wb = load_workbook(folder+"forecast-walmart.xlsx", data_only=True)
#valid_start = "2011-8-19"
#predict_start = "2011-12-30"
#wb = load_workbook("forecast-ex5.xlsx", data_only=True)
#valid_start = "2020-10-19"
#predict_start = "2020-12-30"
wb, best, result_df, forecast, demand_df, valid_df = forecast_excel(wb, valid_start, predict_start)
```

<style  type="text/css" >
    #T_fbdf092a_fe59_11ec_90bf_d0817adb47c1 th {
          text-align: left;
    }#T_fbdf092a_fe59_11ec_90bf_d0817adb47c1row0_col0{
            text-align:  left;
            text-align:  left;
        }#T_fbdf092a_fe59_11ec_90bf_d0817adb47c1row0_col1,#T_fbdf092a_fe59_11ec_90bf_d0817adb47c1row0_col2,#T_fbdf092a_fe59_11ec_90bf_d0817adb47c1row0_col3,#T_fbdf092a_fe59_11ec_90bf_d0817adb47c1row0_col4,#T_fbdf092a_fe59_11ec_90bf_d0817adb47c1row0_col5,#T_fbdf092a_fe59_11ec_90bf_d0817adb47c1row0_col6{
            text-align:  left;
            text-align:  left;
            background-color:  yellow;
        }#T_fbdf092a_fe59_11ec_90bf_d0817adb47c1row0_col7{
            text-align:  left;
            text-align:  left;
            background-color:  yellow;
            background-color:  lightgrey;
        }</style>

<table id="T_fbdf092a_fe59_11ec_90bf_d0817adb47c1"
data-quarto-postprocess="true">
<thead>
<tr>
<th class="blank level0" data-quarto-table-cell-role="th"></th>
<th class="col_heading level0 col0"
data-quarto-table-cell-role="th">Model</th>
<th class="col_heading level0 col1"
data-quarto-table-cell-role="th">MAE</th>
<th class="col_heading level0 col2"
data-quarto-table-cell-role="th">MSE</th>
<th class="col_heading level0 col3"
data-quarto-table-cell-role="th">RMSE</th>
<th class="col_heading level0 col4"
data-quarto-table-cell-role="th">R2</th>
<th class="col_heading level0 col5"
data-quarto-table-cell-role="th">RMSLE</th>
<th class="col_heading level0 col6"
data-quarto-table-cell-role="th">MAPE</th>
<th class="col_heading level0 col7" data-quarto-table-cell-role="th">TT
(Sec)</th>
</tr>
</thead>
<tbody>
<tr>
<td id="T_fbdf092a_fe59_11ec_90bf_d0817adb47c1level0_row0"
class="row_heading level0 row0"
data-quarto-table-cell-role="th">dummy</td>
<td id="T_fbdf092a_fe59_11ec_90bf_d0817adb47c1row0_col0"
class="data row0 col0">Dummy Regressor</td>
<td id="T_fbdf092a_fe59_11ec_90bf_d0817adb47c1row0_col1"
class="data row0 col1">10.5139</td>
<td id="T_fbdf092a_fe59_11ec_90bf_d0817adb47c1row0_col2"
class="data row0 col2">228.3212</td>
<td id="T_fbdf092a_fe59_11ec_90bf_d0817adb47c1row0_col3"
class="data row0 col3">15.1103</td>
<td id="T_fbdf092a_fe59_11ec_90bf_d0817adb47c1row0_col4"
class="data row0 col4">-0.1966</td>
<td id="T_fbdf092a_fe59_11ec_90bf_d0817adb47c1row0_col5"
class="data row0 col5">0.1213</td>
<td id="T_fbdf092a_fe59_11ec_90bf_d0817adb47c1row0_col6"
class="data row0 col6">0.0811</td>
<td id="T_fbdf092a_fe59_11ec_90bf_d0817adb47c1row0_col7"
class="data row0 col7">0.0000</td>
</tr>
</tbody>
</table>

    [DummyRegressor(constant=None, quantile=None, strategy='mean')]

### 予測に基づく動的発注量シートの生成関数 dynamic_inv_excel

引数： - wb: 在庫シミュレーションシートを入れるExcel Workbook -
valid_start: 検証開始日 - predict_start: 予測開始日 - valid_df:
demand_dfから検証開始から予測開始の直前までを抜き出したデータフレーム -
demand_df: 予測結果から需要を抽出し，誤差列を追加したデータフレーム - h:
在庫費用（定数かリスト）;
関数内で需要と同じ長さのNumPy配列に変換される． - fc:
固定費用（定数かリスト）;
関数内で需要と同じ長さのNumPy配列に変換される． - vc:
変動費用（定数かリスト）;
関数内で需要と同じ長さのNumPy配列に変換される；既定値は0. - z:
安全在庫係数；初期安全在庫量を決めるために使われる定数（既定値は2.33）

返値： - wb: 在庫シミュレーションシートを追加したExcel Workbook

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L505"
target="_blank" style="float:right; font-size:smaller">source</a>

### dynamic_inv_excel

``` python

def dynamic_inv_excel(
    wb, valid_start, predict_start, valid_df, demand_df, h, fc, vc:float=0.0, z:float=2.33
):

```

*Call self as a function.*

#### dynamic_inv_excel関数の使用例

``` python
h = 1
fc = 100. 
vc = 0.
z = 1.65 
wb = dynamic_inv_excel(wb, valid_start, predict_start, valid_df, demand_df, h, fc, vc, z)
wb.save("forecast-ex5-simu.xlsx")
```

    2995.525076709324 [44.36038177  0.          0.         65.51441261  0.          0.
      0.          0.         61.73584662  0.          0.         49.47059588
      0.          0.          0.          0.         57.16618104  0.
      0.          0.          0.          0.         50.6413246   0.
      0.          0.         29.14120463  0.          0.          0.
     54.8727735   0.          0.          0.          0.          0.
     60.59831692  0.          0.          0.          0.          0.
      0.         51.70768912  0.          0.          0.          0.
      0.          0.         53.16539093  0.          0.          0.
      0.          0.          0.         48.67772177  0.          0.
      0.          0.          0.          0.         52.11188276  0.
      0.          0.          0.          0.          0.          0.
     62.27572896  0.          0.          0.          0.          0.
     53.92021115  0.          0.         42.08768594  0.          0.        ]

### 顧客と製品を与えると、訓練用データフレームと予測用の未来のデータフレームを生成する関数

需要がない日を自動的に追加し，その需要を0と補完する．

引数： - demand_df: 需要データフレーム - customer: 予測を行いたい顧客 -
product: 予測を行うたい製品 - promo_df:
追加特徴（プロモーション）情報を含んだデータフレーム（オプション）；予測期間に対しても追加情報を準備する必要がある．
予測期間内のデータが空 (NaN)の場合には，訓練データにも空
(NaN)のものがある必要がある． - agg_period:
期間を表す文字列（例えば1日のときは”1d”） - forecast_periods:
予測したい期間

返値： - df: 訓練用データフレーム - future:
訓練用と予測用の未来のデータを入れたデータフレーム

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L551"
target="_blank" style="float:right; font-size:smaller">source</a>

### make_forecast_df

``` python

def make_forecast_df(
    demand_df, customer, product, promo_df:NoneType=None, agg_period:str='1d', forecast_periods:int=1
):

```

*顧客と製品を与えると、訓練用データフレームと予測用の未来のデータフレームを生成する関数*

### make_forecast_df関数の使用例

``` python
c = "仙台市" 
p = "A"
agg_period ="1d"
df, future = make_forecast_df(demand_df, customer=c, product=p,promo_df= promo_df, agg_period=agg_period, forecast_periods = 10)
df.head()
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }
&#10;    .dataframe tbody tr th {
        vertical-align: top;
    }
&#10;    .dataframe thead th {
        text-align: right;
    }
</style>

<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: right;">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">demand</th>
<th data-quarto-table-cell-role="th">promo_0</th>
<th data-quarto-table-cell-role="th">promo_1</th>
<th data-quarto-table-cell-role="th">Year</th>
<th data-quarto-table-cell-role="th">Month</th>
<th data-quarto-table-cell-role="th">Week</th>
<th data-quarto-table-cell-role="th">Day</th>
<th data-quarto-table-cell-role="th">Dayofweek</th>
<th data-quarto-table-cell-role="th">Dayofyear</th>
<th data-quarto-table-cell-role="th">Is_month_end</th>
<th data-quarto-table-cell-role="th">Is_month_start</th>
<th data-quarto-table-cell-role="th">Is_quarter_end</th>
<th data-quarto-table-cell-role="th">Is_quarter_start</th>
<th data-quarto-table-cell-role="th">Is_year_end</th>
<th data-quarto-table-cell-role="th">Is_year_start</th>
<th data-quarto-table-cell-role="th">Elapsed</th>
</tr>
</thead>
<tbody>
<tr>
<td data-quarto-table-cell-role="th">0</td>
<td>13</td>
<td>0</td>
<td>0</td>
<td>2019</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>False</td>
<td>True</td>
<td>False</td>
<td>True</td>
<td>False</td>
<td>True</td>
<td>1.546301e+09</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">1</td>
<td>19</td>
<td>1</td>
<td>0</td>
<td>2019</td>
<td>1</td>
<td>1</td>
<td>2</td>
<td>2</td>
<td>2</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>1.546387e+09</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">2</td>
<td>17</td>
<td>0</td>
<td>0</td>
<td>2019</td>
<td>1</td>
<td>1</td>
<td>3</td>
<td>3</td>
<td>3</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>1.546474e+09</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">3</td>
<td>12</td>
<td>0</td>
<td>0</td>
<td>2019</td>
<td>1</td>
<td>1</td>
<td>4</td>
<td>4</td>
<td>4</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>1.546560e+09</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">4</td>
<td>19</td>
<td>0</td>
<td>0</td>
<td>2019</td>
<td>1</td>
<td>1</td>
<td>5</td>
<td>5</td>
<td>5</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>1.546646e+09</td>
</tr>
</tbody>
</table>

</div>

### 実データでの分析

### 全てのデータを用いて深層学習による予測をするためのデータフレームの生成関数

データ数が不足している場合には、顧客や製品もカテゴリー変数として扱うことによって十分なデータを確保することができる。

引数： - demand_df: 需要データフレーム - promo_df:
追加特徴（プロモーション）情報を含んだデータフレーム（オプション）；予測期間に対しても追加情報を準備する必要がある．
予測期間内のデータが空 (NaN)の場合には，訓練データにも空
(NaN)のものがある必要がある． - agg_period:
期間を表す文字列（例えば1日のときは”1d”）

返値： - demand_df: 訓練用データフレーム

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L592"
target="_blank" style="float:right; font-size:smaller">source</a>

### make_forecast_df_all

``` python

def make_forecast_df_all(
    demand_df, promo_df:NoneType=None, agg_period:str='1d', forecast_periods:int=1
):

```

*全データに対する訓練用データフレームを生成する関数*

``` python
demand_df = pd.read_csv(folder+"demand_with_promo.csv", index_col=0)
all_df, future = make_forecast_df_all(demand_df, promo_df, agg_period="1d")
all_df.head()
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }
&#10;    .dataframe tbody tr th {
        vertical-align: top;
    }
&#10;    .dataframe thead th {
        text-align: right;
    }
</style>

<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: right;">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">cust</th>
<th data-quarto-table-cell-role="th">prod</th>
<th data-quarto-table-cell-role="th">Week</th>
<th data-quarto-table-cell-role="th">promo_0</th>
<th data-quarto-table-cell-role="th">promo_1</th>
<th data-quarto-table-cell-role="th">demand</th>
<th data-quarto-table-cell-role="th">Year</th>
<th data-quarto-table-cell-role="th">Month</th>
<th data-quarto-table-cell-role="th">Day</th>
<th data-quarto-table-cell-role="th">Dayofweek</th>
<th data-quarto-table-cell-role="th">Dayofyear</th>
<th data-quarto-table-cell-role="th">Is_month_end</th>
<th data-quarto-table-cell-role="th">Is_month_start</th>
<th data-quarto-table-cell-role="th">Is_quarter_end</th>
<th data-quarto-table-cell-role="th">Is_quarter_start</th>
<th data-quarto-table-cell-role="th">Is_year_end</th>
<th data-quarto-table-cell-role="th">Is_year_start</th>
<th data-quarto-table-cell-role="th">Elapsed</th>
</tr>
</thead>
<tbody>
<tr>
<td data-quarto-table-cell-role="th">0</td>
<td>仙台市</td>
<td>A</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>13</td>
<td>2019</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>False</td>
<td>True</td>
<td>False</td>
<td>True</td>
<td>False</td>
<td>True</td>
<td>1546300800</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">1</td>
<td>仙台市</td>
<td>A</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>19</td>
<td>2019</td>
<td>1</td>
<td>2</td>
<td>2</td>
<td>2</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>1546387200</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">2</td>
<td>仙台市</td>
<td>A</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>17</td>
<td>2019</td>
<td>1</td>
<td>3</td>
<td>3</td>
<td>3</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>1546473600</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">3</td>
<td>仙台市</td>
<td>A</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>12</td>
<td>2019</td>
<td>1</td>
<td>4</td>
<td>4</td>
<td>4</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>1546560000</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">4</td>
<td>仙台市</td>
<td>A</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>19</td>
<td>2019</td>
<td>1</td>
<td>5</td>
<td>5</td>
<td>5</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>1546646400</td>
</tr>
</tbody>
</table>

</div>

### 検証期間を設定するための関数 find_horizon

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L621"
target="_blank" style="float:right; font-size:smaller">source</a>

### find_horizon

``` python

def find_horizon(
    demand_df, ratio:float=0.9
):

```

*Call self as a function.*

``` python
demand_df = pd.read_csv(folder+"demand_with_promo.csv")
find_horizon(demand_df, ratio=0.9)
```

    Timestamp('2020-10-19 00:00:00')

### 訓練データと検証データのインデックスを準備する関数 prepare_index

引数：

- df: 日付情報（Year列、Month列、Day列）を含んだデータフレーム
- horizon:
  検証データを作成するときの閾値の日付；この日付より後のデータは検証データになる。Noneのときには最後の100日を検証データとする。

返値： - train_idx: 訓練データのインデックス - valid_idx:
検証データのインデックス

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L625"
target="_blank" style="float:right; font-size:smaller">source</a>

### prepare_index

``` python

def prepare_index(
    df, horizon:NoneType=None
):

```

*Call self as a function.*

``` python
#train_idx, valid_idx =prepare_index(df, horizon="2020/11/21")
#len(train_idx), len(valid_idx)
```

## 訓練

需要を連続量とする場合と離散量とする場合で異なる予測を行う。連続量の場合には回帰問題となり、離散量の場合には分類問題になる。

### 学習器を作成する関数 make_learn

引数：

- df: 日付 (date)と需要 (deman)の列を含んだデータフレーム
- horizon:
  検証データを作成するときの閾値の日付；この日付より後のデータは検証データになる。
- classification:
  分類問題としてモデルを作成する場合にはTrue、回帰問題としてモデルを作成する場合には
  Falseを入れる。

返値：

- learn: fastaiの学習器

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L638"
target="_blank" style="float:right; font-size:smaller">source</a>

### make_learn

``` python

def make_learn(
    df, horizon:NoneType=None, classification:bool=False
):

```

*深層学習を用いた需要予測用のデータを生成*

### make_learn関数の使用例

``` python
learn = make_learn(df, horizon="2020-10-01", classification=False)
#learn = make_learn(all_df, horizon="2016-10-01", classification=False)
#learn = make_learn(all_df, horizon="2020-10-01", classification=False)
#df.drop("level_0", axis=1, inplace=True)
#learn = make_learn(df, horizon="2016-12-01", classification=False)
```

    INFO:numexpr.utils:Note: NumExpr detected 16 cores but "NUMEXPR_MAX_THREADS" not set, so enforcing safe limit of 8.
    INFO:numexpr.utils:NumExpr defaulting to 8 threads.

## 適正な学習率を見つけるための関数 lr_find

``` python
lr_min= learn.lr_find() 
print(lr_min)
```

    SuggestedLRs(valley=0.002511886414140463)

### lr_findの結果をPlotlyで描画する関数 plot_lr_find

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L679"
target="_blank" style="float:right; font-size:smaller">source</a>

### plot_lr_find

``` python

def plot_lr_find(
    learn
):

```

*Call self as a function.*

``` python
fig = plot_lr_find(learn)
plotly.offline.plot(fig);
```

## 訓練を行う関数 train

引数： - learn: 学習器 - kwargs:
訓練を行う関数fit_one_cycleの任意のキーワード引数

> https://docs.fast.ai/callback.schedule#Learner.fit_one_cycle 参照

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L699"
target="_blank" style="float:right; font-size:smaller">source</a>

### train

``` python

def train(
    learn, kwargs:VAR_KEYWORD
):

```

*fit_one_cycle法を用いて訓練を行う関数*

``` python
train(learn, n_epoch = 30, lr_max =0.01, wd=2., cbs=ShowGraphCallback())
```

<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: left;">
<th data-quarto-table-cell-role="th">epoch</th>
<th data-quarto-table-cell-role="th">train_loss</th>
<th data-quarto-table-cell-role="th">valid_loss</th>
<th data-quarto-table-cell-role="th">_rmse</th>
<th data-quarto-table-cell-role="th">mae</th>
<th data-quarto-table-cell-role="th">msle</th>
<th data-quarto-table-cell-role="th">time</th>
</tr>
</thead>
<tbody>
<tr>
<td>0</td>
<td>3446.414062</td>
<td>7105.580566</td>
<td>84.294609</td>
<td>66.609749</td>
<td>4.805219</td>
<td>00:03</td>
</tr>
<tr>
<td>1</td>
<td>2210.760254</td>
<td>1613.519287</td>
<td>40.168633</td>
<td>26.273926</td>
<td>2.868655</td>
<td>00:03</td>
</tr>
<tr>
<td>2</td>
<td>1863.013672</td>
<td>656.649414</td>
<td>25.625174</td>
<td>13.304914</td>
<td>0.741323</td>
<td>00:03</td>
</tr>
<tr>
<td>3</td>
<td>1639.386475</td>
<td>976.197571</td>
<td>31.244160</td>
<td>14.256841</td>
<td>0.766732</td>
<td>00:03</td>
</tr>
<tr>
<td>4</td>
<td>1687.551270</td>
<td>648.089172</td>
<td>25.457594</td>
<td>12.055953</td>
<td>0.347193</td>
<td>00:03</td>
</tr>
<tr>
<td>5</td>
<td>1956.444458</td>
<td>1265.262207</td>
<td>35.570530</td>
<td>14.617914</td>
<td>0.479162</td>
<td>00:03</td>
</tr>
<tr>
<td>6</td>
<td>1698.531738</td>
<td>466.392212</td>
<td>21.596113</td>
<td>11.547545</td>
<td>1.536979</td>
<td>00:03</td>
</tr>
<tr>
<td>7</td>
<td>2314.256104</td>
<td>1495.722778</td>
<td>38.674576</td>
<td>16.015421</td>
<td>0.508270</td>
<td>00:03</td>
</tr>
<tr>
<td>8</td>
<td>1567.057861</td>
<td>456.358246</td>
<td>21.362545</td>
<td>17.110693</td>
<td>1.679504</td>
<td>00:03</td>
</tr>
<tr>
<td>9</td>
<td>1580.399536</td>
<td>583.629700</td>
<td>24.158430</td>
<td>16.468655</td>
<td>1.654195</td>
<td>00:03</td>
</tr>
<tr>
<td>10</td>
<td>1677.902344</td>
<td>658.983154</td>
<td>25.670668</td>
<td>14.227415</td>
<td>0.733416</td>
<td>00:03</td>
</tr>
<tr>
<td>11</td>
<td>1710.951782</td>
<td>3192.795898</td>
<td>56.504829</td>
<td>31.815025</td>
<td>1.787573</td>
<td>00:03</td>
</tr>
<tr>
<td>12</td>
<td>1314.445557</td>
<td>1115.158813</td>
<td>33.393997</td>
<td>17.580637</td>
<td>2.050577</td>
<td>00:03</td>
</tr>
<tr>
<td>13</td>
<td>1093.038452</td>
<td>407.138885</td>
<td>20.177683</td>
<td>11.029508</td>
<td>0.769333</td>
<td>00:03</td>
</tr>
<tr>
<td>14</td>
<td>954.789368</td>
<td>1112.169678</td>
<td>33.349209</td>
<td>16.030300</td>
<td>1.018057</td>
<td>00:03</td>
</tr>
<tr>
<td>15</td>
<td>1350.003052</td>
<td>617.209290</td>
<td>24.843697</td>
<td>12.732859</td>
<td>0.934637</td>
<td>00:03</td>
</tr>
<tr>
<td>16</td>
<td>1671.424316</td>
<td>484.320282</td>
<td>22.007277</td>
<td>11.749466</td>
<td>0.757320</td>
<td>00:03</td>
</tr>
<tr>
<td>17</td>
<td>800.749023</td>
<td>998.935669</td>
<td>31.605944</td>
<td>15.915786</td>
<td>0.790849</td>
<td>00:03</td>
</tr>
<tr>
<td>18</td>
<td>749.288147</td>
<td>683.855164</td>
<td>26.150621</td>
<td>13.572218</td>
<td>1.163126</td>
<td>00:03</td>
</tr>
<tr>
<td>19</td>
<td>858.682617</td>
<td>876.759644</td>
<td>29.610126</td>
<td>13.271565</td>
<td>0.624707</td>
<td>00:03</td>
</tr>
<tr>
<td>20</td>
<td>594.039185</td>
<td>418.807831</td>
<td>20.464794</td>
<td>8.975345</td>
<td>0.675335</td>
<td>00:03</td>
</tr>
<tr>
<td>21</td>
<td>476.235504</td>
<td>276.303314</td>
<td>16.622375</td>
<td>9.983256</td>
<td>0.377772</td>
<td>00:03</td>
</tr>
<tr>
<td>22</td>
<td>443.672668</td>
<td>179.968506</td>
<td>13.415236</td>
<td>6.672860</td>
<td>0.587208</td>
<td>00:03</td>
</tr>
<tr>
<td>23</td>
<td>423.546722</td>
<td>132.249161</td>
<td>11.499963</td>
<td>5.285238</td>
<td>0.299202</td>
<td>00:03</td>
</tr>
<tr>
<td>24</td>
<td>334.764893</td>
<td>209.028351</td>
<td>14.457813</td>
<td>6.568413</td>
<td>0.476533</td>
<td>00:03</td>
</tr>
<tr>
<td>25</td>
<td>208.162155</td>
<td>72.868652</td>
<td>8.536314</td>
<td>4.375165</td>
<td>0.419365</td>
<td>00:03</td>
</tr>
<tr>
<td>26</td>
<td>155.964676</td>
<td>41.782406</td>
<td>6.463932</td>
<td>3.183359</td>
<td>0.320197</td>
<td>00:04</td>
</tr>
<tr>
<td>27</td>
<td>119.822289</td>
<td>44.234440</td>
<td>6.650898</td>
<td>3.861167</td>
<td>0.297581</td>
<td>00:03</td>
</tr>
<tr>
<td>28</td>
<td>93.038322</td>
<td>25.414803</td>
<td>5.041310</td>
<td>2.986454</td>
<td>0.235738</td>
<td>00:03</td>
</tr>
<tr>
<td>29</td>
<td>86.351746</td>
<td>15.100967</td>
<td>3.885997</td>
<td>2.207297</td>
<td>0.232204</td>
<td>00:03</td>
</tr>
</tbody>
</table>

![](06forecast_files/figure-commonmark/cell-74-output-2.png)

### Plotlyで損出関数を描画する関数 plot_loss

引数： - learn: 学習器 - valid:
テストデータも描画するときにTrue（既定値）

返り値： - fig: 損出関数のグラフ

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L706"
target="_blank" style="float:right; font-size:smaller">source</a>

### plot_loss

``` python

def plot_loss(
    learn, valid:bool=True
):

```

*Call self as a function.*

``` python
fig = plot_loss(learn)
plotly.offline.plot(fig);
```

![](06forecast_files/figure-commonmark/cell-77-output-1.png)

## 深層学習を用いて予測を行う関数 predict_using_dl

引数： - learn:学習器 - df: 日付 (date)と需要
(deman)の列を含んだデータフレーム - future:
訓練用と予測用の未来のデータを入れたデータフレーム - classification:
分類問題のとき True、それ以外のとき False

返値： - fig: 予測結果を入れた図オブジェクト - predict:
予測結果を入れた配列 - error: 予測の2乗誤差 - r2: 決定係数

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L736"
target="_blank" style="float:right; font-size:smaller">source</a>

### predict_using_dl

``` python

def predict_using_dl(
    learn, df, future, classification:bool=False
):

```

*深層学習を用いた予測*

### predict_using_dl関数の使用例

``` python
fig, yhat, error, r2 = predict_using_dl(learn, df, future, classification=False)
print("error=", error, r2)
plotly.offline.plot(fig);
```

    error= 103425.1953125 0.023292243480682373

![](06forecast_files/figure-commonmark/cell-80-output-1.png)

### 全てのデータで訓練した学習器による予測関数 predict_using_all_dl

引数：

- learn: 学習器
- df: 該当する顧客と製品の需要データを入れたデータフレーム
- furure: 予測したい全期間の需要以外のデータを入れたデータフレーム
- customer: 顧客名
- product: 製品名
- classification: 分類問題のとき True、それ以外のとき False

返値：

- fig: 予測結果を入れた図オブジェクト
- predict: 予測結果を入れた配列
- error: 予測の2乗誤差

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L788"
target="_blank" style="float:right; font-size:smaller">source</a>

### predict_using_all_dl

``` python

def predict_using_all_dl(
    learn, df, future, customer, product, classification:bool=True
):

```

*深層学習を用いた予測（全部で訓練）*

### predict_using_all_dl関数の使用例

``` python
# demand_df = pd.read_csv(folder+"demand_with_promo.csv", index_col=0)
c = "前橋市" 
p = "B"
df, future = make_forecast_df(demand_df, customer=c, product=p, promo_df= promo_df, agg_period="1d", forecast_periods =100)
fig, predict, error, r2 = predict_using_all_dl(learn, df, future, customer=c, product = p, classification=False)
print("error=", error, r2)
plotly.offline.plot(fig);
```

    error= 15.100969314575195 0.9979501962661743

``` python
#hide_iinput
Image("../figure/predict_using_all_dl.png")
```

![](06forecast_files/figure-commonmark/cell-84-output-1.png)

### 埋め込み層の描画関数 draw_embedding

引数：

- learn: 学習器（訓練済み）
- cust: 顧客を描画するときTrue, 製品を描画するとき False
- pca: 主成分分析で次元削減するときTrue、TSNEでするとき False

返値：

- fig: Plotlyの図オブジェクト

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L833"
target="_blank" style="float:right; font-size:smaller">source</a>

### draw_embedding

``` python

def draw_embedding(
    learn, cust:bool=True, pca:bool=True
):

```

*draw embedding*

### draw_embedding関数の使用例

``` python
fig = draw_embedding(learn, cust=False, pca=True)
plotly.offline.plot(fig);
```

``` python
fig = draw_embedding(learn, cust=True, pca=True)
plotly.offline.plot(fig);
```

![](06forecast_files/figure-commonmark/cell-89-output-1.png)

## scikit learnのランダム森によって予測をする関数 random_forest

引数：

- df: 日付 (date)と需要 (deman)の列を含んだデータフレーム
- horizon:
  検証データを作成するときの閾値の日付；この日付より後のデータは検証データになる。
- feature: 特徴ベクトルとして使用する列名のリスト；
  Noneのときには全ての列とする。
- classification: 分類問題のときTrue、回帰問題のときFalse

返値：

- forest: ランダム森のモデルオブジェクト
- importance: permutation_importanceによる特徴ベクトルの重要度の情報

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L871"
target="_blank" style="float:right; font-size:smaller">source</a>

### random_forest

``` python

def random_forest(
    df, horizon:NoneType=None, feature:NoneType=None, classification:bool=False
):

```

*ランダム森による需要予測*

### random_forest関数の呼び出し例

``` python
# list(imp[imp.importance>0.01].features)
#feature = ['promo_1', 'Week', 'Month', 'Dayofyear', 'promo_0', 'Dayofweek']
#feature = list(df.columns[1:])
feature = None
forest, importance = random_forest(df, horizon="2020-10-01", feature=feature, classification=False)
```

### 重要度のデータフレームと図を返す関数 show_importance

引数： - importance: 重要度（順列重要度を
random_forest関数で計算したときの返値として得られる．） - feature:
特徴ベクトルの名前のリスト - df:
データフレーム；特徴ベクトルの元の列名を得るためだけに使用する．

返値： imp_df: 重要度を入れたデータフレーム fig: 重要度の棒グラフ

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L896"
target="_blank" style="float:right; font-size:smaller">source</a>

### show_importance

``` python

def show_importance(
    importance, feature, df
):

```

*Call self as a function.*

``` python
feature = None
imp_df, fig = show_importance(importance, feature=feature, df=df)
plotly.offline.plot(fig);
```

![](06forecast_files/figure-commonmark/cell-94-output-1.png)

### ランダム森による予測 predict_using_rf

引数： - df: 日付 (date)と需要 (deman)の列を含んだデータフレーム -
future: 訓練用と予測用の未来のデータを入れたデータフレーム - forest:
ランダム森のモデルオブジェクト - horizon: 予測期間

返値： - fig: 予測結果を入れた図オブジェクト - predict:
予測結果を入れた配列 - error: 予測の2乗誤差 - r2: 決定係数

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L905"
target="_blank" style="float:right; font-size:smaller">source</a>

### predict_using_rf

``` python

def predict_using_rf(
    df, future, forest, horizon:NoneType=None, feature:NoneType=None
):

```

*ランダム木を用いた予測*

``` python
fig, yhat_rf, error_rf, r2 =  predict_using_rf(df, future, forest, horizon="2020-10-01", feature=feature)
plotly.offline.plot(fig);
print("error", error_rf, r2)
```

    error 1.0633877777777778 0.5972015993265993

    error 1.1132505494505496

![](06forecast_files/figure-commonmark/cell-97-output-2.png)

## AutoMLで予測をする関数 automl

AutoMLパッケージPyCaretによる予測

引数：

- df: 日付 (date)と需要 (demand)の列を含んだデータフレーム
- horizon:
  検証データを作成するときの閾値の日付；この日付より後のデータは検証データになる。Noneの場合には100日前からが検証データになる．
- num_bests: 最良モデルの選択数
- sort: 良い順に並べるときの評価尺度名（既定値は”R2”）
- model_name:

返値：

- best: 最良の予測をしたモデルオブジェクト
- result_df: 結果のデータフレーム

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L954"
target="_blank" style="float:right; font-size:smaller">source</a>

### automl

``` python

def automl(
    df, horizon:NoneType=None, num_bests:int=5, sort:str='R2', model_name:NoneType=None
):

```

*Prediction using pycaret regression models*

### automl関数の使用例

``` python
horizon="2020/10/01"
best, result_df = automl(df, horizon, 5, model_name=None)
```

<style  type="text/css" >
    #T_6db89fea_fe58_11ec_90bf_d0817adb47c1 th {
          text-align: left;
    }#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row0_col0,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row1_col0,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row1_col1,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row1_col2,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row1_col3,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row1_col4,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row1_col5,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row1_col6,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row2_col0,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row2_col1,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row2_col2,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row2_col3,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row2_col4,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row2_col5,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row2_col6,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row3_col0,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row3_col1,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row3_col2,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row3_col3,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row3_col4,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row3_col5,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row3_col6,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row4_col0,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row4_col1,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row4_col2,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row4_col3,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row4_col4,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row4_col5,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row4_col6,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row5_col0,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row5_col1,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row5_col2,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row5_col3,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row5_col4,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row5_col5,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row5_col6,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row6_col0,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row6_col1,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row6_col2,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row6_col3,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row6_col4,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row6_col5,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row6_col6,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row7_col0,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row7_col1,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row7_col2,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row7_col3,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row7_col4,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row7_col5,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row7_col6,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row8_col0,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row8_col1,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row8_col2,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row8_col3,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row8_col4,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row8_col5,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row8_col6,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row9_col0,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row9_col1,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row9_col2,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row9_col3,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row9_col4,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row9_col5,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row9_col6,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row10_col0,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row10_col1,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row10_col2,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row10_col3,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row10_col4,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row10_col5,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row10_col6,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row11_col0,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row11_col1,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row11_col2,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row11_col3,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row11_col4,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row11_col5,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row11_col6,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row12_col0,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row12_col1,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row12_col2,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row12_col3,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row12_col4,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row12_col5,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row12_col6,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row13_col0,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row13_col1,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row13_col2,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row13_col3,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row13_col4,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row13_col5,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row13_col6,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row14_col0,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row14_col1,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row14_col2,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row14_col3,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row14_col4,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row14_col5,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row14_col6,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row15_col0,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row15_col1,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row15_col2,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row15_col3,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row15_col4,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row15_col5,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row15_col6,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row16_col0,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row16_col1,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row16_col2,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row16_col3,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row16_col4,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row16_col5,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row16_col6,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row17_col0,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row17_col1,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row17_col2,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row17_col3,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row17_col4,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row17_col5,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row17_col6,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row18_col0,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row18_col1,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row18_col2,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row18_col3,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row18_col4,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row18_col5,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row18_col6,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row19_col0,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row19_col1,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row19_col2,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row19_col3,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row19_col4,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row19_col5,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row19_col6,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row20_col0,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row20_col1,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row20_col2,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row20_col3,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row20_col4,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row20_col5,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row20_col6,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row21_col0,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row21_col1,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row21_col2,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row21_col3,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row21_col4,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row21_col5,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row21_col6,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row22_col0,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row22_col1,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row22_col2,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row22_col3,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row22_col4,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row22_col5,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row22_col6{
            text-align:  left;
            text-align:  left;
        }#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row0_col1,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row0_col2,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row0_col3,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row0_col4,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row0_col5,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row0_col6{
            text-align:  left;
            text-align:  left;
            background-color:  yellow;
        }#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row0_col7,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row1_col7,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row2_col7,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row3_col7,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row4_col7,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row5_col7,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row6_col7,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row7_col7,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row8_col7,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row9_col7,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row10_col7,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row11_col7,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row13_col7,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row14_col7,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row16_col7,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row19_col7,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row22_col7{
            text-align:  left;
            text-align:  left;
            background-color:  lightgrey;
        }#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row12_col7,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row15_col7,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row17_col7,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row18_col7,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row20_col7,#T_6db89fea_fe58_11ec_90bf_d0817adb47c1row21_col7{
            text-align:  left;
            text-align:  left;
            background-color:  yellow;
            background-color:  lightgrey;
        }</style>

<table id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1"
data-quarto-postprocess="true">
<thead>
<tr>
<th class="blank level0" data-quarto-table-cell-role="th"></th>
<th class="col_heading level0 col0"
data-quarto-table-cell-role="th">Model</th>
<th class="col_heading level0 col1"
data-quarto-table-cell-role="th">MAE</th>
<th class="col_heading level0 col2"
data-quarto-table-cell-role="th">MSE</th>
<th class="col_heading level0 col3"
data-quarto-table-cell-role="th">RMSE</th>
<th class="col_heading level0 col4"
data-quarto-table-cell-role="th">R2</th>
<th class="col_heading level0 col5"
data-quarto-table-cell-role="th">RMSLE</th>
<th class="col_heading level0 col6"
data-quarto-table-cell-role="th">MAPE</th>
<th class="col_heading level0 col7" data-quarto-table-cell-role="th">TT
(Sec)</th>
</tr>
</thead>
<tbody>
<tr>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1level0_row0"
class="row_heading level0 row0" data-quarto-table-cell-role="th">et</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row0_col0"
class="data row0 col0">Extra Trees Regressor</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row0_col1"
class="data row0 col1">1.6620</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row0_col2"
class="data row0 col2">4.9674</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row0_col3"
class="data row0 col3">2.2288</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row0_col4"
class="data row0 col4">0.9262</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row0_col5"
class="data row0 col5">0.3713</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row0_col6"
class="data row0 col6">0.2443</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row0_col7"
class="data row0 col7">0.1500</td>
</tr>
<tr>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1level0_row1"
class="row_heading level0 row1" data-quarto-table-cell-role="th">rf</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row1_col0"
class="data row1 col0">Random Forest Regressor</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row1_col1"
class="data row1 col1">2.3624</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row1_col2"
class="data row1 col2">7.3216</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row1_col3"
class="data row1 col3">2.7058</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row1_col4"
class="data row1 col4">0.8913</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row1_col5"
class="data row1 col5">0.4690</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row1_col6"
class="data row1 col6">0.3809</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row1_col7"
class="data row1 col7">0.1900</td>
</tr>
<tr>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1level0_row2"
class="row_heading level0 row2" data-quarto-table-cell-role="th">dt</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row2_col0"
class="data row2 col0">Decision Tree Regressor</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row2_col1"
class="data row2 col1">2.4286</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row2_col2"
class="data row2 col2">10.6044</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row2_col3"
class="data row2 col3">3.2564</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row2_col4"
class="data row2 col4">0.8425</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row2_col5"
class="data row2 col5">0.5424</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row2_col6"
class="data row2 col6">0.3973</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row2_col7"
class="data row2 col7">0.0100</td>
</tr>
<tr>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1level0_row3"
class="row_heading level0 row3"
data-quarto-table-cell-role="th">gbr</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row3_col0"
class="data row3 col0">Gradient Boosting Regressor</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row3_col1"
class="data row3 col1">3.3336</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row3_col2"
class="data row3 col2">14.5483</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row3_col3"
class="data row3 col3">3.8142</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row3_col4"
class="data row3 col4">0.7840</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row3_col5"
class="data row3 col5">0.4328</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row3_col6"
class="data row3 col6">0.5026</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row3_col7"
class="data row3 col7">0.0800</td>
</tr>
<tr>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1level0_row4"
class="row_heading level0 row4"
data-quarto-table-cell-role="th">ada</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row4_col0"
class="data row4 col0">AdaBoost Regressor</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row4_col1"
class="data row4 col1">5.7564</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row4_col2"
class="data row4 col2">40.3512</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row4_col3"
class="data row4 col3">6.3523</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row4_col4"
class="data row4 col4">0.4008</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row4_col5"
class="data row4 col5">0.8888</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row4_col6"
class="data row4 col6">1.1191</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row4_col7"
class="data row4 col7">0.1200</td>
</tr>
<tr>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1level0_row5"
class="row_heading level0 row5" data-quarto-table-cell-role="th">br</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row5_col0"
class="data row5 col0">Bayesian Ridge</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row5_col1"
class="data row5 col1">6.5873</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row5_col2"
class="data row5 col2">61.8033</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row5_col3"
class="data row5 col3">7.8615</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row5_col4"
class="data row5 col4">0.0823</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row5_col5"
class="data row5 col5">1.0977</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row5_col6"
class="data row5 col6">1.7060</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row5_col7"
class="data row5 col7">0.0100</td>
</tr>
<tr>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1level0_row6"
class="row_heading level0 row6"
data-quarto-table-cell-role="th">ridge</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row6_col0"
class="data row6 col0">Ridge Regression</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row6_col1"
class="data row6 col1">6.6831</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row6_col2"
class="data row6 col2">63.5019</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row6_col3"
class="data row6 col3">7.9688</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row6_col4"
class="data row6 col4">0.0571</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row6_col5"
class="data row6 col5">1.1030</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row6_col6"
class="data row6 col6">1.7497</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row6_col7"
class="data row6 col7">0.0100</td>
</tr>
<tr>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1level0_row7"
class="row_heading level0 row7"
data-quarto-table-cell-role="th">huber</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row7_col0"
class="data row7 col0">Huber Regressor</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row7_col1"
class="data row7 col1">6.4650</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row7_col2"
class="data row7 col2">63.8005</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row7_col3"
class="data row7 col3">7.9875</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row7_col4"
class="data row7 col4">0.0527</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row7_col5"
class="data row7 col5">1.0793</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row7_col6"
class="data row7 col6">1.4744</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row7_col7"
class="data row7 col7">0.0200</td>
</tr>
<tr>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1level0_row8"
class="row_heading level0 row8" data-quarto-table-cell-role="th">kr</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row8_col0"
class="data row8 col0">Kernel Ridge</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row8_col1"
class="data row8 col1">6.5818</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row8_col2"
class="data row8 col2">65.3509</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row8_col3"
class="data row8 col3">8.0840</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row8_col4"
class="data row8 col4">0.0296</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row8_col5"
class="data row8 col5">1.0998</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row8_col6"
class="data row8 col6">1.5512</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row8_col7"
class="data row8 col7">0.1100</td>
</tr>
<tr>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1level0_row9"
class="row_heading level0 row9" data-quarto-table-cell-role="th">en</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row9_col0"
class="data row9 col0">Elastic Net</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row9_col1"
class="data row9 col1">6.7439</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row9_col2"
class="data row9 col2">67.1895</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row9_col3"
class="data row9 col3">8.1969</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row9_col4"
class="data row9 col4">0.0023</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row9_col5"
class="data row9 col5">1.1457</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row9_col6"
class="data row9 col6">1.7762</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row9_col7"
class="data row9 col7">0.0100</td>
</tr>
<tr>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1level0_row10"
class="row_heading level0 row10"
data-quarto-table-cell-role="th">lasso</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row10_col0"
class="data row10 col0">Lasso Regression</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row10_col1"
class="data row10 col1">6.7995</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row10_col2"
class="data row10 col2">68.3639</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row10_col3"
class="data row10 col3">8.2682</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row10_col4"
class="data row10 col4">-0.0151</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row10_col5"
class="data row10 col5">1.1519</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row10_col6"
class="data row10 col6">1.7897</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row10_col7"
class="data row10 col7">0.0100</td>
</tr>
<tr>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1level0_row11"
class="row_heading level0 row11"
data-quarto-table-cell-role="th">tr</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row11_col0"
class="data row11 col0">TheilSen Regressor</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row11_col1"
class="data row11 col1">7.0673</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row11_col2"
class="data row11 col2">69.5302</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row11_col3"
class="data row11 col3">8.3385</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row11_col4"
class="data row11 col4">-0.0324</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row11_col5"
class="data row11 col5">1.1465</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row11_col6"
class="data row11 col6">1.8813</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row11_col7"
class="data row11 col7">1.6900</td>
</tr>
<tr>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1level0_row12"
class="row_heading level0 row12"
data-quarto-table-cell-role="th">lr</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row12_col0"
class="data row12 col0">Linear Regression</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row12_col1"
class="data row12 col1">7.0492</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row12_col2"
class="data row12 col2">69.5646</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row12_col3"
class="data row12 col3">8.3405</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row12_col4"
class="data row12 col4">-0.0329</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row12_col5"
class="data row12 col5">1.1389</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row12_col6"
class="data row12 col6">1.8974</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row12_col7"
class="data row12 col7">0.0000</td>
</tr>
<tr>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1level0_row13"
class="row_heading level0 row13"
data-quarto-table-cell-role="th">lar</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row13_col0"
class="data row13 col0">Least Angle Regression</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row13_col1"
class="data row13 col1">7.0492</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row13_col2"
class="data row13 col2">69.5646</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row13_col3"
class="data row13 col3">8.3405</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row13_col4"
class="data row13 col4">-0.0329</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row13_col5"
class="data row13 col5">1.1389</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row13_col6"
class="data row13 col6">1.8974</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row13_col7"
class="data row13 col7">0.0100</td>
</tr>
<tr>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1level0_row14"
class="row_heading level0 row14"
data-quarto-table-cell-role="th">ard</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row14_col0"
class="data row14 col0">Automatic Relevance Determination</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row14_col1"
class="data row14 col1">7.0675</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row14_col2"
class="data row14 col2">69.8744</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row14_col3"
class="data row14 col3">8.3591</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row14_col4"
class="data row14 col4">-0.0375</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row14_col5"
class="data row14 col5">1.1409</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row14_col6"
class="data row14 col6">1.8141</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row14_col7"
class="data row14 col7">0.0100</td>
</tr>
<tr>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1level0_row15"
class="row_heading level0 row15"
data-quarto-table-cell-role="th">omp</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row15_col0"
class="data row15 col0">Orthogonal Matching Pursuit</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row15_col1"
class="data row15 col1">7.1926</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row15_col2"
class="data row15 col2">71.5753</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row15_col3"
class="data row15 col3">8.4602</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row15_col4"
class="data row15 col4">-0.0628</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row15_col5"
class="data row15 col5">1.1591</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row15_col6"
class="data row15 col6">1.8336</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row15_col7"
class="data row15 col7">0.0000</td>
</tr>
<tr>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1level0_row16"
class="row_heading level0 row16"
data-quarto-table-cell-role="th">svm</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row16_col0"
class="data row16 col0">Support Vector Regression</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row16_col1"
class="data row16 col1">7.0575</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row16_col2"
class="data row16 col2">72.9081</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row16_col3"
class="data row16 col3">8.5386</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row16_col4"
class="data row16 col4">-0.0826</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row16_col5"
class="data row16 col5">1.1784</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row16_col6"
class="data row16 col6">1.8887</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row16_col7"
class="data row16 col7">0.0200</td>
</tr>
<tr>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1level0_row17"
class="row_heading level0 row17"
data-quarto-table-cell-role="th">llar</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row17_col0"
class="data row17 col0">Lasso Least Angle Regression</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row17_col1"
class="data row17 col1">7.2027</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row17_col2"
class="data row17 col2">75.3612</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row17_col3"
class="data row17 col3">8.6811</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row17_col4"
class="data row17 col4">-0.1190</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row17_col5"
class="data row17 col5">1.1951</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row17_col6"
class="data row17 col6">1.9659</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row17_col7"
class="data row17 col7">0.0000</td>
</tr>
<tr>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1level0_row18"
class="row_heading level0 row18"
data-quarto-table-cell-role="th">dummy</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row18_col0"
class="data row18 col0">Dummy Regressor</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row18_col1"
class="data row18 col1">7.2027</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row18_col2"
class="data row18 col2">75.3612</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row18_col3"
class="data row18 col3">8.6811</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row18_col4"
class="data row18 col4">-0.1190</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row18_col5"
class="data row18 col5">1.1951</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row18_col6"
class="data row18 col6">1.9659</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row18_col7"
class="data row18 col7">0.0000</td>
</tr>
<tr>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1level0_row19"
class="row_heading level0 row19"
data-quarto-table-cell-role="th">ransac</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row19_col0"
class="data row19 col0">Random Sample Consensus</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row19_col1"
class="data row19 col1">8.5524</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row19_col2"
class="data row19 col2">105.8737</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row19_col3"
class="data row19 col3">10.2895</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row19_col4"
class="data row19 col4">-0.5721</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row19_col5"
class="data row19 col5">1.2047</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row19_col6"
class="data row19 col6">2.2048</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row19_col7"
class="data row19 col7">0.0500</td>
</tr>
<tr>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1level0_row20"
class="row_heading level0 row20"
data-quarto-table-cell-role="th">knn</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row20_col0"
class="data row20 col0">K Neighbors Regressor</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row20_col1"
class="data row20 col1">9.4000</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row20_col2"
class="data row20 col2">117.2127</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row20_col3"
class="data row20 col3">10.8265</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row20_col4"
class="data row20 col4">-0.7404</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row20_col5"
class="data row20 col5">1.3451</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row20_col6"
class="data row20 col6">2.7281</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row20_col7"
class="data row20 col7">0.0000</td>
</tr>
<tr>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1level0_row21"
class="row_heading level0 row21"
data-quarto-table-cell-role="th">par</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row21_col0"
class="data row21 col0">Passive Aggressive Regressor</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row21_col1"
class="data row21 col1">8.5968</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row21_col2"
class="data row21 col2">122.1332</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row21_col3"
class="data row21 col3">11.0514</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row21_col4"
class="data row21 col4">-0.8135</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row21_col5"
class="data row21 col5">1.2091</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row21_col6"
class="data row21 col6">0.8227</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row21_col7"
class="data row21 col7">0.0000</td>
</tr>
<tr>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1level0_row22"
class="row_heading level0 row22"
data-quarto-table-cell-role="th">mlp</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row22_col0"
class="data row22 col0">MLP Regressor</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row22_col1"
class="data row22 col1">7927.3291</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row22_col2"
class="data row22 col2">62842730.7068</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row22_col3"
class="data row22 col3">7927.3407</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row22_col4"
class="data row22 col4">-933111.6422</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row22_col5"
class="data row22 col5">6.9995</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row22_col6"
class="data row22 col6">1633.9990</td>
<td id="T_6db89fea_fe58_11ec_90bf_d0817adb47c1row22_col7"
class="data row22 col7">0.2000</td>
</tr>
</tbody>
</table>

``` python
#予測
result = predict_model(best[0], df)
result.head()
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }
&#10;    .dataframe tbody tr th {
        vertical-align: top;
    }
&#10;    .dataframe thead th {
        text-align: right;
    }
</style>

<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: right;">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">demand</th>
<th data-quarto-table-cell-role="th">promo_0</th>
<th data-quarto-table-cell-role="th">promo_1</th>
<th data-quarto-table-cell-role="th">Year</th>
<th data-quarto-table-cell-role="th">Month</th>
<th data-quarto-table-cell-role="th">Week</th>
<th data-quarto-table-cell-role="th">Day</th>
<th data-quarto-table-cell-role="th">Dayofweek</th>
<th data-quarto-table-cell-role="th">Dayofyear</th>
<th data-quarto-table-cell-role="th">Is_month_end</th>
<th data-quarto-table-cell-role="th">Is_month_start</th>
<th data-quarto-table-cell-role="th">Is_quarter_end</th>
<th data-quarto-table-cell-role="th">Is_quarter_start</th>
<th data-quarto-table-cell-role="th">Is_year_end</th>
<th data-quarto-table-cell-role="th">Is_year_start</th>
<th data-quarto-table-cell-role="th">Elapsed</th>
<th data-quarto-table-cell-role="th">Label</th>
</tr>
</thead>
<tbody>
<tr>
<td data-quarto-table-cell-role="th">0</td>
<td>13</td>
<td>0</td>
<td>0</td>
<td>2019</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>False</td>
<td>True</td>
<td>False</td>
<td>True</td>
<td>False</td>
<td>True</td>
<td>1.546301e+09</td>
<td>13.0</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">1</td>
<td>19</td>
<td>1</td>
<td>0</td>
<td>2019</td>
<td>1</td>
<td>1</td>
<td>2</td>
<td>2</td>
<td>2</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>1.546387e+09</td>
<td>19.0</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">2</td>
<td>17</td>
<td>0</td>
<td>0</td>
<td>2019</td>
<td>1</td>
<td>1</td>
<td>3</td>
<td>3</td>
<td>3</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>1.546474e+09</td>
<td>17.0</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">3</td>
<td>12</td>
<td>0</td>
<td>0</td>
<td>2019</td>
<td>1</td>
<td>1</td>
<td>4</td>
<td>4</td>
<td>4</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>1.546560e+09</td>
<td>12.0</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">4</td>
<td>19</td>
<td>0</td>
<td>0</td>
<td>2019</td>
<td>1</td>
<td>1</td>
<td>5</td>
<td>5</td>
<td>5</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>1.546646e+09</td>
<td>19.0</td>
</tr>
</tbody>
</table>

</div>

``` python
#plot_model(best[1], display_format="streamlit")
```

### 複数の製品・顧客に対して予測を行う関数（のサブ関数） automl_all_sub

サプライ・チェイン最適化のためには，すべての顧客と製品に対して一度に需要予測を行う必要がある．しかし，通常は顧客数，製品数ともに非常に多い場合には，計算時間が問題になる．顧客や製品に対するABC分析を事前に行い，A製品（A顧客）に対してだけ，需要予測を行うという経験的手法が従来使われていたが，ここではデータに基づいた手法を考える．

需要予測は，顧客・製品ごとに時系列データ（にプロモーション情報を付加したもの）を抽出し，AutoMLで複数の機械学習・統計分析モデルを適用して，最も良いものを使うことにする．評価尺度としては決定係数を使う．決定係数が負のものは平均を用いた単純な予測より当たらないことを意味する．

顧客・製品ごとに需要の合計量を被増加順に並べ，大きいものから順に予測を行っていく．一般に，zip分布にしたがう需要を想定すると，需要の合計が小さい場合には，どのような予測をしても当たらなくなる．複数の手法を試し，最も良い予測の決定係数が負のものが続く場合には，需要が小さすぎてこれ以上予測をしても無駄だと判断できる．したがって，決定係数が負のものが適当な数（たとえば10）より大きくなったら，予測をやめて，顧客・製品ごとの需要の平均値と標準偏差だけで管理するものとする．

引数：

- demand_df: 顧客 (cust)・製品 (prod) ごとの日付 (date)と需要
  (deman)の列を含んだデータフレーム
- promo_df:
  追加特徴（プロモーション）情報を含んだデータフレーム（オプション）；予測期間に対しても追加情報を準備する必要がある．
  予測期間内のデータが空 (NaN)の場合には，訓練データにも空
  (NaN)のものがある必要がある．
- cust_list: 予測を行いたい顧客のリスト
- prod_list 予測を行うたい製品のリスト
- horizon:
  検証データを作成するときの閾値の日付；この日付より後のデータは検証データになる．
- agg_period: 期間を表す文字列（例えば1日のときは”1d”）
- forecast_periods: 予測したい期間（既定値は1）
- threshold:
  需要の予測誤差の幅を決めるためのパラメータ；外れる確率がthresholdになるように下限と上限を決める．
- max_neg_r2: 予測打ち切りのためのパラメータ；この回数だけ R2
  が負になったら，それ以上予測する必要はないので，
  終了する．　ただし，cust_list と
  prod_listは需要量の降順になっているものと仮定する．

返値： - summary: 予測結果をまとめたデータフレーム；以下の列をもつ．

- cust: 顧客名
- prod: 製品名
- model: 最も良い予測モデル名
- rmse: 平均２乗誤差の平方根
- r2: 決定係数
- forecast: 未来の予測値
- lb: 予測誤差がlb以下になる確率がthresholdになるように設定
- ub: 予測誤差がub以上になる確率がthresholdになるように設定

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L973"
target="_blank" style="float:right; font-size:smaller">source</a>

### automl_all_sub

``` python

def automl_all_sub(
    demand_df, promo_df, cust_list, prod_list, horizon, agg_period:str='1d', forecast_periods:int=1,
    threshold:float=0.05, max_neg_r2:int=10
):

```

*Call self as a function.*

### 複数の製品・顧客に対して予測を行う関数 automl_all

model
列には，最も良い（決定係数が1に近い）モデル名が保管されている．これを用いて，未来の予測をしたい場合には，そのモデルだけで予測をすれば良い．

予測値と実際の需要量が大きく外れた場合には，原因を探ったり，再予測を行ったりする必要がある．それには，予測誤差の下限と上限（lb,ub列）を用いれば良い．実際の運用ができるような，自動処理を行うシステムは，MLOpsと呼ばれる．

ここで開発したものは，MLOpsの基礎として使うことができる．

引数：

- demand_df: 顧客 (cust)・製品 (prod) ごとの日付 (date)と需要
  (deman)の列を含んだデータフレーム
- promo_df:
  追加特徴（プロモーション）情報を含んだデータフレーム（オプション）；予測期間に対しても追加情報を準備する必要がある．
  予測期間内のデータが空 (NaN)の場合には，訓練データにも空
  (NaN)のものがある必要がある．
- horizon:
  検証データを作成するときの閾値の日付；この日付より後のデータは検証データになる．
- agg_period: 期間を表す文字列（例えば1日のときは”1d”）
- forecast_periods: 予測したい期間（既定値は1）
- threshold:
  需要の予測誤差の幅を決めるためのパラメータ；外れる確率がthresholdになるように下限と上限を決める．
- max_neg_r2: 予測打ち切りのためのパラメータ；この回数だけ
  *R*<sup>2</sup> が負になったら，それ以上予測する必要はないので，
  終了する．　ただし，cust_list と
  prod_listは需要量の降順になっているものと仮定する．
- abc_threshold:
  ABC分析のための閾値のリスト（合計が1.0になっている必要がある．）

返値： - summary:
予測結果をまとめたデータフレーム；以下の列をもつ．（ただし予測を打ち切った行以降は
model以降の列はNaNになる．）

- cust: 顧客名
- prod: 製品名
- mean: 平均需要量
- std: 需要の標準偏差
- rank: 需要の降順ランク
- abc: 需要量のABC分析の結果
- model: 最も良い予測モデル名
- rmse: 平均２乗誤差の平方根
- r2: 決定係数
- forecast: 未来の予測値
- lb: 予測誤差がlb以下になる確率がthresholdになるように設定
- ub: 予測誤差がub以上になる確率がthresholdになるように設定

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L1002"
target="_blank" style="float:right; font-size:smaller">source</a>

### automl_all

``` python

def automl_all(
    demand_df, promo_df, horizon, agg_period:str='1d', forecast_periods:int=1, threshold:float=0.05,
    max_neg_r2:int=10, abc_threshold:list=[0.6, 0.2, 0.2]
):

```

*Call self as a function.*

### automl_all関数の使用例

``` python
#summary = automl_all(demand_df, promo_df, horizon="2020/10/19", agg_period="1d", forecast_periods =10, threshold= 0.05, max_neg_r2 = 1)
```

``` python
summary.r2.hist();
```

![](06forecast_files/figure-commonmark/cell-108-output-1.png)

``` python
summary.to_csv("summary.csv")
#summary = pd.read_csv("summary.csv", index_col=0)
#summary.sort_values(by="r2",inplace=True)
summary.r2.hist();
```

![](06forecast_files/figure-commonmark/cell-109-output-1.png)

### すべての顧客・需要の予測結果を用いて，予測を行い図を返す関数 predict_using_automl_all_fig

引数：

- demand_df: 顧客 (cust)・製品 (prod) ごとの日付 (date)と需要
  (deman)の列を含んだデータフレーム
- promo_df:
  追加特徴（プロモーション）情報を含んだデータフレーム（オプション）；予測期間に対しても追加情報を準備する必要がある．
  予測期間内のデータが空 (NaN)の場合には，訓練データにも空
  (NaN)のものがある必要がある．
- summary: 予測結果をまとめたデータフレーム（automl_allの返値）
- customer: 顧客名
- product: 製品名
- agg_period: 期間を表す文字列（例えば1日のときは”1d”）
- forecast_periods: 予測したい期間（既定値は1）

返値： - forecast: 未来の予測値（リスト）

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L1010"
target="_blank" style="float:right; font-size:smaller">source</a>

### predict_using_automl_all_fig

``` python

def predict_using_automl_all_fig(
    demand_df, promo_df, summary, customer, product, agg_period:str='1d', forecast_periods:int=10
):

```

*Call self as a function.*

``` python
agg_df,category = abc.abc_analysis_all(demand_df,[0.6, 0.2, 0.2])
agg_df.reset_index(inplace=True)
count = 0
for row in agg_df.itertuples():
    fig, error, result = predict_using_automl_all_fig(demand_df, None, summary, row.cust, row.prod, agg_period='1d', forecast_periods=10)
    plotly.offline.plot(fig)
    count +=1
    if count>=10:
        break
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }
&#10;    .dataframe tbody tr th {
        vertical-align: top;
    }
&#10;    .dataframe thead th {
        text-align: right;
    }
</style>

<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: right;">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">MAE</th>
<th data-quarto-table-cell-role="th">MSE</th>
<th data-quarto-table-cell-role="th">RMSE</th>
<th data-quarto-table-cell-role="th">R2</th>
<th data-quarto-table-cell-role="th">RMSLE</th>
<th data-quarto-table-cell-role="th">MAPE</th>
</tr>
</thead>
<tbody>
<tr>
<td data-quarto-table-cell-role="th">0</td>
<td>245.907394</td>
<td>123375.59375</td>
<td>351.248596</td>
<td>0.1176</td>
<td>2.8776</td>
<td>2.9054</td>
</tr>
</tbody>
</table>

</div>

<style  type="text/css" >
</style>

<table id="T_15e1d_" data-quarto-postprocess="true">
<thead>
<tr>
<th class="blank level0" data-quarto-table-cell-role="th"></th>
<th class="col_heading level0 col0"
data-quarto-table-cell-role="th">Model</th>
<th class="col_heading level0 col1"
data-quarto-table-cell-role="th">MAE</th>
<th class="col_heading level0 col2"
data-quarto-table-cell-role="th">MSE</th>
<th class="col_heading level0 col3"
data-quarto-table-cell-role="th">RMSE</th>
<th class="col_heading level0 col4"
data-quarto-table-cell-role="th">R2</th>
<th class="col_heading level0 col5"
data-quarto-table-cell-role="th">RMSLE</th>
<th class="col_heading level0 col6"
data-quarto-table-cell-role="th">MAPE</th>
</tr>
</thead>
<tbody>
<tr>
<td id="T_15e1d_level0_row0" class="row_heading level0 row0"
data-quarto-table-cell-role="th">0</td>
<td id="T_15e1d_row0_col0" class="data row0 col0">Ridge Regression</td>
<td id="T_15e1d_row0_col1" class="data row0 col1">245.9074</td>
<td id="T_15e1d_row0_col2" class="data row0 col2">123375.5938</td>
<td id="T_15e1d_row0_col3" class="data row0 col3">351.2486</td>
<td id="T_15e1d_row0_col4" class="data row0 col4">0.1176</td>
<td id="T_15e1d_row0_col5" class="data row0 col5">2.8776</td>
<td id="T_15e1d_row0_col6" class="data row0 col6">2.9054</td>
</tr>
</tbody>
</table>

### すべての顧客・需要の予測結果を用いて，予測を行う関数 predict_using_automl_all

引数：

- demand_df: 顧客 (cust)・製品 (prod) ごとの日付 (date)と需要
  (deman)の列を含んだデータフレーム
- promo_df:
  追加特徴（プロモーション）情報を含んだデータフレーム（オプション）；予測期間に対しても追加情報を準備する必要がある．
  予測期間内のデータが空 (NaN)の場合には，訓練データにも空
  (NaN)のものがある必要がある．
- summary: 予測結果をまとめたデータフレーム（automl_allの返値）
- customer: 顧客名
- product: 製品名
- agg_period: 期間を表す文字列（例えば1日のときは”1d”）
- forecast_periods: 予測したい期間（既定値は1）

返値： - forecast: 未来の予測値（リスト）

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L1021"
target="_blank" style="float:right; font-size:smaller">source</a>

### predict_using_automl_all

``` python

def predict_using_automl_all(
    demand_df, promo_df, summary, customer, product, agg_period:str='1d', forecast_periods:int=10
):

```

*Call self as a function.*

### predict_using_automl_all関数の使用例

``` python
# customer = "長崎市"
# product = "D"
customer ="熊本市"
product ="H"
predict_using_automl_all(demand_df, promo_df, summary, customer, product, agg_period='1d', forecast_periods=10)
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }
&#10;    .dataframe tbody tr th {
        vertical-align: top;
    }
&#10;    .dataframe thead th {
        text-align: right;
    }
</style>

<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: right;">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">MAE</th>
<th data-quarto-table-cell-role="th">MSE</th>
<th data-quarto-table-cell-role="th">RMSE</th>
<th data-quarto-table-cell-role="th">R2</th>
<th data-quarto-table-cell-role="th">RMSLE</th>
<th data-quarto-table-cell-role="th">MAPE</th>
</tr>
</thead>
<tbody>
<tr>
<td data-quarto-table-cell-role="th">0</td>
<td>1.863</td>
<td>6.137</td>
<td>2.4773</td>
<td>-9.6113</td>
<td>0.9757</td>
<td>1.4333</td>
</tr>
</tbody>
</table>

</div>

    [2.0, 1.0, 4.0, 0.0, 0.0, 3.0, 4.0, 2.0, 2.0, 4.0]

### AutoMLによる予測関数 predict_using_automl

引数： - df: 日付 (date)と需要 (deman)の列を含んだデータフレーム -
future: 訓練用と予測用の未来のデータを入れたデータフレーム - best:
予測モデルのオブジェクト - horizon: 予測期間

返値： - fig: 予測結果を入れた図オブジェクト - predict:
予測結果を入れた配列 - error: 予測の2乗誤差

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L1034"
target="_blank" style="float:right; font-size:smaller">source</a>

### predict_using_automl

``` python

def predict_using_automl(
    df, future, best, horizon:NoneType=None
):

```

*AutoMLを用いた予測（回帰）*

### predict_using_automl関数の使用例

``` python
#fig, error, result = predict_using_automl(df, future, best[0])
#plotly.offline.plot(fig);
```

![](06forecast_files/figure-commonmark/cell-116-output-1.png)

### 結果の可視化

- ‘residuals’ - Residuals Plot
- ‘error’ - Prediction Error Plot
- ‘cooks’ - Cooks Distance Plot
- ‘rfe’ - Recursive Feat. Selection
- ‘learning’ - Learning Curve
- ‘vc’ - Validation Curve
- ‘manifold’ - Manifold Learning
- ‘feature’ - Feature Importance
- ‘feature_all’ - Feature Importance (All)
- ‘parameter’ - Model Hyperparameter
- ‘tree’ - Decision Tree

``` python
plot_model(best[0], "feature_all", save=True)
```

    INFO:logs:Saving 'Feature Importance (All).png' in current active directory
    INFO:logs:Visual Rendered Successfully
    INFO:logs:plot_model() succesfully completed......................................

    'Feature Importance (All).png'

### 分類モデル

``` python
from pycaret.classification import *   #分類関連の関数のインポート
```

``` python
#def automl(df, horizon=None, num_bests = 5, sort = "R2"):
"""
Prediction using pycaret classification models
"""
horizon = "2020/10/01"
num_bests = 1
sort = 'Accuracy'
train_idx, valid_idx = prepare_index(df, horizon)
ratio = len(train_idx)/(len(train_idx)+len(valid_idx))
df["Week"] = df.Week.astype(int)
df["demand"] = df.demand.astype('category')
#df["demand"] = df.demand.astype(int)
reg = setup(df, target = 'demand', session_id=123, data_split_shuffle=False, fold_strategy= 'timeseries', fold=2, train_size=ratio, silent=True, verbose=False)
best = compare_models(n_select=num_bests,  sort = sort, cross_validation=False)
result_df = pull()
#return best, result_df
```

<style  type="text/css" >
    #T_9166e_ th {
          text-align: left;
    }#T_9166e_row0_col0,#T_9166e_row0_col3,#T_9166e_row0_col4,#T_9166e_row0_col5,#T_9166e_row0_col6,#T_9166e_row1_col0,#T_9166e_row1_col1,#T_9166e_row1_col3,#T_9166e_row1_col7,#T_9166e_row2_col0,#T_9166e_row2_col1,#T_9166e_row2_col3,#T_9166e_row2_col4,#T_9166e_row2_col5,#T_9166e_row2_col6,#T_9166e_row2_col7,#T_9166e_row3_col0,#T_9166e_row3_col1,#T_9166e_row3_col3,#T_9166e_row3_col4,#T_9166e_row3_col5,#T_9166e_row3_col6,#T_9166e_row3_col7,#T_9166e_row4_col0,#T_9166e_row4_col1,#T_9166e_row4_col3,#T_9166e_row4_col4,#T_9166e_row4_col5,#T_9166e_row4_col6,#T_9166e_row4_col7,#T_9166e_row5_col0,#T_9166e_row5_col1,#T_9166e_row5_col3,#T_9166e_row5_col4,#T_9166e_row5_col5,#T_9166e_row5_col6,#T_9166e_row5_col7,#T_9166e_row6_col0,#T_9166e_row6_col1,#T_9166e_row6_col3,#T_9166e_row6_col4,#T_9166e_row6_col5,#T_9166e_row6_col6,#T_9166e_row6_col7,#T_9166e_row7_col0,#T_9166e_row7_col1,#T_9166e_row7_col3,#T_9166e_row7_col4,#T_9166e_row7_col5,#T_9166e_row7_col6,#T_9166e_row7_col7,#T_9166e_row8_col0,#T_9166e_row8_col1,#T_9166e_row8_col4,#T_9166e_row8_col5,#T_9166e_row8_col6,#T_9166e_row8_col7,#T_9166e_row9_col0,#T_9166e_row9_col1,#T_9166e_row9_col3,#T_9166e_row9_col4,#T_9166e_row9_col5,#T_9166e_row9_col6,#T_9166e_row9_col7,#T_9166e_row10_col0,#T_9166e_row10_col1,#T_9166e_row10_col4,#T_9166e_row10_col5,#T_9166e_row10_col6,#T_9166e_row10_col7,#T_9166e_row11_col0,#T_9166e_row11_col1,#T_9166e_row11_col3,#T_9166e_row11_col4,#T_9166e_row11_col5,#T_9166e_row11_col6,#T_9166e_row11_col7,#T_9166e_row12_col0,#T_9166e_row12_col1,#T_9166e_row12_col3,#T_9166e_row12_col4,#T_9166e_row12_col5,#T_9166e_row12_col6,#T_9166e_row12_col7,#T_9166e_row13_col0,#T_9166e_row13_col1,#T_9166e_row13_col3,#T_9166e_row13_col4,#T_9166e_row13_col5,#T_9166e_row13_col6,#T_9166e_row13_col7,#T_9166e_row14_col0,#T_9166e_row14_col1,#T_9166e_row14_col3,#T_9166e_row14_col4,#T_9166e_row14_col5,#T_9166e_row14_col6,#T_9166e_row14_col7{
            text-align:  left;
            text-align:  left;
        }#T_9166e_row0_col1,#T_9166e_row0_col2,#T_9166e_row0_col7,#T_9166e_row1_col2,#T_9166e_row1_col4,#T_9166e_row1_col5,#T_9166e_row1_col6,#T_9166e_row2_col2,#T_9166e_row3_col2,#T_9166e_row4_col2,#T_9166e_row5_col2,#T_9166e_row6_col2,#T_9166e_row7_col2,#T_9166e_row8_col2,#T_9166e_row8_col3,#T_9166e_row9_col2,#T_9166e_row10_col2,#T_9166e_row10_col3,#T_9166e_row11_col2,#T_9166e_row12_col2,#T_9166e_row13_col2,#T_9166e_row14_col2{
            text-align:  left;
            text-align:  left;
            background-color:  yellow;
        }#T_9166e_row0_col8,#T_9166e_row1_col8,#T_9166e_row2_col8,#T_9166e_row3_col8,#T_9166e_row6_col8,#T_9166e_row7_col8,#T_9166e_row8_col8,#T_9166e_row9_col8,#T_9166e_row10_col8,#T_9166e_row11_col8,#T_9166e_row12_col8,#T_9166e_row13_col8,#T_9166e_row14_col8{
            text-align:  left;
            text-align:  left;
            background-color:  lightgrey;
        }#T_9166e_row4_col8,#T_9166e_row5_col8{
            text-align:  left;
            text-align:  left;
            background-color:  yellow;
            background-color:  lightgrey;
        }</style>

<table id="T_9166e_" data-quarto-postprocess="true">
<thead>
<tr>
<th class="blank level0" data-quarto-table-cell-role="th"></th>
<th class="col_heading level0 col0"
data-quarto-table-cell-role="th">Model</th>
<th class="col_heading level0 col1"
data-quarto-table-cell-role="th">Accuracy</th>
<th class="col_heading level0 col2"
data-quarto-table-cell-role="th">AUC</th>
<th class="col_heading level0 col3"
data-quarto-table-cell-role="th">Recall</th>
<th class="col_heading level0 col4"
data-quarto-table-cell-role="th">Prec.</th>
<th class="col_heading level0 col5"
data-quarto-table-cell-role="th">F1</th>
<th class="col_heading level0 col6"
data-quarto-table-cell-role="th">Kappa</th>
<th class="col_heading level0 col7"
data-quarto-table-cell-role="th">MCC</th>
<th class="col_heading level0 col8" data-quarto-table-cell-role="th">TT
(Sec)</th>
</tr>
</thead>
<tbody>
<tr>
<td id="T_9166e_level0_row0" class="row_heading level0 row0"
data-quarto-table-cell-role="th">ridge</td>
<td id="T_9166e_row0_col0" class="data row0 col0">Ridge Classifier</td>
<td id="T_9166e_row0_col1" class="data row0 col1">0.5165</td>
<td id="T_9166e_row0_col2" class="data row0 col2">0.0000</td>
<td id="T_9166e_row0_col3" class="data row0 col3">0.2857</td>
<td id="T_9166e_row0_col4" class="data row0 col4">0.2979</td>
<td id="T_9166e_row0_col5" class="data row0 col5">0.3735</td>
<td id="T_9166e_row0_col6" class="data row0 col6">0.2591</td>
<td id="T_9166e_row0_col7" class="data row0 col7">0.3110</td>
<td id="T_9166e_row0_col8" class="data row0 col8">0.0100</td>
</tr>
<tr>
<td id="T_9166e_level0_row1" class="row_heading level0 row1"
data-quarto-table-cell-role="th">rf</td>
<td id="T_9166e_row1_col0" class="data row1 col0">Random Forest
Classifier</td>
<td id="T_9166e_row1_col1" class="data row1 col1">0.5055</td>
<td id="T_9166e_row1_col2" class="data row1 col2">0.0000</td>
<td id="T_9166e_row1_col3" class="data row1 col3">0.2465</td>
<td id="T_9166e_row1_col4" class="data row1 col4">0.4723</td>
<td id="T_9166e_row1_col5" class="data row1 col5">0.4601</td>
<td id="T_9166e_row1_col6" class="data row1 col6">0.2719</td>
<td id="T_9166e_row1_col7" class="data row1 col7">0.2848</td>
<td id="T_9166e_row1_col8" class="data row1 col8">0.2100</td>
</tr>
<tr>
<td id="T_9166e_level0_row2" class="row_heading level0 row2"
data-quarto-table-cell-role="th">et</td>
<td id="T_9166e_row2_col0" class="data row2 col0">Extra Trees
Classifier</td>
<td id="T_9166e_row2_col1" class="data row2 col1">0.4725</td>
<td id="T_9166e_row2_col2" class="data row2 col2">0.0000</td>
<td id="T_9166e_row2_col3" class="data row2 col3">0.2212</td>
<td id="T_9166e_row2_col4" class="data row2 col4">0.4560</td>
<td id="T_9166e_row2_col5" class="data row2 col5">0.4504</td>
<td id="T_9166e_row2_col6" class="data row2 col6">0.2373</td>
<td id="T_9166e_row2_col7" class="data row2 col7">0.2428</td>
<td id="T_9166e_row2_col8" class="data row2 col8">0.1700</td>
</tr>
<tr>
<td id="T_9166e_level0_row3" class="row_heading level0 row3"
data-quarto-table-cell-role="th">lr</td>
<td id="T_9166e_row3_col0" class="data row3 col0">Logistic
Regression</td>
<td id="T_9166e_row3_col1" class="data row3 col1">0.4505</td>
<td id="T_9166e_row3_col2" class="data row3 col2">0.0000</td>
<td id="T_9166e_row3_col3" class="data row3 col3">0.1429</td>
<td id="T_9166e_row3_col4" class="data row3 col4">0.2030</td>
<td id="T_9166e_row3_col5" class="data row3 col5">0.2799</td>
<td id="T_9166e_row3_col6" class="data row3 col6">0.0000</td>
<td id="T_9166e_row3_col7" class="data row3 col7">0.0000</td>
<td id="T_9166e_row3_col8" class="data row3 col8">0.0200</td>
</tr>
<tr>
<td id="T_9166e_level0_row4" class="row_heading level0 row4"
data-quarto-table-cell-role="th">knn</td>
<td id="T_9166e_row4_col0" class="data row4 col0">K Neighbors
Classifier</td>
<td id="T_9166e_row4_col1" class="data row4 col1">0.4505</td>
<td id="T_9166e_row4_col2" class="data row4 col2">0.0000</td>
<td id="T_9166e_row4_col3" class="data row4 col3">0.1429</td>
<td id="T_9166e_row4_col4" class="data row4 col4">0.2030</td>
<td id="T_9166e_row4_col5" class="data row4 col5">0.2799</td>
<td id="T_9166e_row4_col6" class="data row4 col6">0.0000</td>
<td id="T_9166e_row4_col7" class="data row4 col7">0.0000</td>
<td id="T_9166e_row4_col8" class="data row4 col8">0.0000</td>
</tr>
<tr>
<td id="T_9166e_level0_row5" class="row_heading level0 row5"
data-quarto-table-cell-role="th">nb</td>
<td id="T_9166e_row5_col0" class="data row5 col0">Naive Bayes</td>
<td id="T_9166e_row5_col1" class="data row5 col1">0.4505</td>
<td id="T_9166e_row5_col2" class="data row5 col2">0.0000</td>
<td id="T_9166e_row5_col3" class="data row5 col3">0.1429</td>
<td id="T_9166e_row5_col4" class="data row5 col4">0.2030</td>
<td id="T_9166e_row5_col5" class="data row5 col5">0.2799</td>
<td id="T_9166e_row5_col6" class="data row5 col6">0.0000</td>
<td id="T_9166e_row5_col7" class="data row5 col7">0.0000</td>
<td id="T_9166e_row5_col8" class="data row5 col8">0.0000</td>
</tr>
<tr>
<td id="T_9166e_level0_row6" class="row_heading level0 row6"
data-quarto-table-cell-role="th">qda</td>
<td id="T_9166e_row6_col0" class="data row6 col0">Quadratic Discriminant
Analysis</td>
<td id="T_9166e_row6_col1" class="data row6 col1">0.4505</td>
<td id="T_9166e_row6_col2" class="data row6 col2">0.0000</td>
<td id="T_9166e_row6_col3" class="data row6 col3">0.1429</td>
<td id="T_9166e_row6_col4" class="data row6 col4">0.2030</td>
<td id="T_9166e_row6_col5" class="data row6 col5">0.2799</td>
<td id="T_9166e_row6_col6" class="data row6 col6">0.0000</td>
<td id="T_9166e_row6_col7" class="data row6 col7">0.0000</td>
<td id="T_9166e_row6_col8" class="data row6 col8">0.0100</td>
</tr>
<tr>
<td id="T_9166e_level0_row7" class="row_heading level0 row7"
data-quarto-table-cell-role="th">lightgbm</td>
<td id="T_9166e_row7_col0" class="data row7 col0">Light Gradient
Boosting Machine</td>
<td id="T_9166e_row7_col1" class="data row7 col1">0.4396</td>
<td id="T_9166e_row7_col2" class="data row7 col2">0.0000</td>
<td id="T_9166e_row7_col3" class="data row7 col3">0.2687</td>
<td id="T_9166e_row7_col4" class="data row7 col4">0.4085</td>
<td id="T_9166e_row7_col5" class="data row7 col5">0.4170</td>
<td id="T_9166e_row7_col6" class="data row7 col6">0.2088</td>
<td id="T_9166e_row7_col7" class="data row7 col7">0.2120</td>
<td id="T_9166e_row7_col8" class="data row7 col8">1.1100</td>
</tr>
<tr>
<td id="T_9166e_level0_row8" class="row_heading level0 row8"
data-quarto-table-cell-role="th">lda</td>
<td id="T_9166e_row8_col0" class="data row8 col0">Linear Discriminant
Analysis</td>
<td id="T_9166e_row8_col1" class="data row8 col1">0.4066</td>
<td id="T_9166e_row8_col2" class="data row8 col2">0.0000</td>
<td id="T_9166e_row8_col3" class="data row8 col3">0.3163</td>
<td id="T_9166e_row8_col4" class="data row8 col4">0.4123</td>
<td id="T_9166e_row8_col5" class="data row8 col5">0.3898</td>
<td id="T_9166e_row8_col6" class="data row8 col6">0.1879</td>
<td id="T_9166e_row8_col7" class="data row8 col7">0.1927</td>
<td id="T_9166e_row8_col8" class="data row8 col8">0.0100</td>
</tr>
<tr>
<td id="T_9166e_level0_row9" class="row_heading level0 row9"
data-quarto-table-cell-role="th">xgboost</td>
<td id="T_9166e_row9_col0" class="data row9 col0">Extreme Gradient
Boosting</td>
<td id="T_9166e_row9_col1" class="data row9 col1">0.3956</td>
<td id="T_9166e_row9_col2" class="data row9 col2">0.0000</td>
<td id="T_9166e_row9_col3" class="data row9 col3">0.1998</td>
<td id="T_9166e_row9_col4" class="data row9 col4">0.4212</td>
<td id="T_9166e_row9_col5" class="data row9 col5">0.3911</td>
<td id="T_9166e_row9_col6" class="data row9 col6">0.1701</td>
<td id="T_9166e_row9_col7" class="data row9 col7">0.1751</td>
<td id="T_9166e_row9_col8" class="data row9 col8">1.3900</td>
</tr>
<tr>
<td id="T_9166e_level0_row10" class="row_heading level0 row10"
data-quarto-table-cell-role="th">ada</td>
<td id="T_9166e_row10_col0" class="data row10 col0">Ada Boost
Classifier</td>
<td id="T_9166e_row10_col1" class="data row10 col1">0.3407</td>
<td id="T_9166e_row10_col2" class="data row10 col2">0.0000</td>
<td id="T_9166e_row10_col3" class="data row10 col3">0.3163</td>
<td id="T_9166e_row10_col4" class="data row10 col4">0.3963</td>
<td id="T_9166e_row10_col5" class="data row10 col5">0.3462</td>
<td id="T_9166e_row10_col6" class="data row10 col6">0.1451</td>
<td id="T_9166e_row10_col7" class="data row10 col7">0.1545</td>
<td id="T_9166e_row10_col8" class="data row10 col8">0.0700</td>
</tr>
<tr>
<td id="T_9166e_level0_row11" class="row_heading level0 row11"
data-quarto-table-cell-role="th">gbc</td>
<td id="T_9166e_row11_col0" class="data row11 col0">Gradient Boosting
Classifier</td>
<td id="T_9166e_row11_col1" class="data row11 col1">0.3407</td>
<td id="T_9166e_row11_col2" class="data row11 col2">0.0000</td>
<td id="T_9166e_row11_col3" class="data row11 col3">0.2381</td>
<td id="T_9166e_row11_col4" class="data row11 col4">0.3764</td>
<td id="T_9166e_row11_col5" class="data row11 col5">0.3365</td>
<td id="T_9166e_row11_col6" class="data row11 col6">0.1332</td>
<td id="T_9166e_row11_col7" class="data row11 col7">0.1452</td>
<td id="T_9166e_row11_col8" class="data row11 col8">0.9300</td>
</tr>
<tr>
<td id="T_9166e_level0_row12" class="row_heading level0 row12"
data-quarto-table-cell-role="th">catboost</td>
<td id="T_9166e_row12_col0" class="data row12 col0">CatBoost
Classifier</td>
<td id="T_9166e_row12_col1" class="data row12 col1">0.3077</td>
<td id="T_9166e_row12_col2" class="data row12 col2">0.0000</td>
<td id="T_9166e_row12_col3" class="data row12 col3">0.1233</td>
<td id="T_9166e_row12_col4" class="data row12 col4">0.3130</td>
<td id="T_9166e_row12_col5" class="data row12 col5">0.3093</td>
<td id="T_9166e_row12_col6" class="data row12 col6">0.0510</td>
<td id="T_9166e_row12_col7" class="data row12 col7">0.0518</td>
<td id="T_9166e_row12_col8" class="data row12 col8">3.6100</td>
</tr>
<tr>
<td id="T_9166e_level0_row13" class="row_heading level0 row13"
data-quarto-table-cell-role="th">dt</td>
<td id="T_9166e_row13_col0" class="data row13 col0">Decision Tree
Classifier</td>
<td id="T_9166e_row13_col1" class="data row13 col1">0.2857</td>
<td id="T_9166e_row13_col2" class="data row13 col2">0.0000</td>
<td id="T_9166e_row13_col3" class="data row13 col3">0.2113</td>
<td id="T_9166e_row13_col4" class="data row13 col4">0.3375</td>
<td id="T_9166e_row13_col5" class="data row13 col5">0.2947</td>
<td id="T_9166e_row13_col6" class="data row13 col6">0.0424</td>
<td id="T_9166e_row13_col7" class="data row13 col7">0.0438</td>
<td id="T_9166e_row13_col8" class="data row13 col8">0.0100</td>
</tr>
<tr>
<td id="T_9166e_level0_row14" class="row_heading level0 row14"
data-quarto-table-cell-role="th">svm</td>
<td id="T_9166e_row14_col0" class="data row14 col0">SVM - Linear
Kernel</td>
<td id="T_9166e_row14_col1" class="data row14 col1">0.2527</td>
<td id="T_9166e_row14_col2" class="data row14 col2">0.0000</td>
<td id="T_9166e_row14_col3" class="data row14 col3">0.1429</td>
<td id="T_9166e_row14_col4" class="data row14 col4">0.0639</td>
<td id="T_9166e_row14_col5" class="data row14 col5">0.1020</td>
<td id="T_9166e_row14_col6" class="data row14 col6">0.0000</td>
<td id="T_9166e_row14_col7" class="data row14 col7">0.0000</td>
<td id="T_9166e_row14_col8" class="data row14 col8">0.0200</td>
</tr>
</tbody>
</table>

    INFO:logs:create_model_container: 0
    INFO:logs:master_model_container: 0
    INFO:logs:display_container: 2
    INFO:logs:RidgeClassifier(alpha=1.0, class_weight=None, copy_X=True, fit_intercept=True,
                    max_iter=None, normalize=False, random_state=123, solver='auto',
                    tol=0.001)
    INFO:logs:compare_models() succesfully completed......................................

``` python
#検証データに対する予測
result = predict_model(best)
#誤差の計算
dem = result.demand.astype(int)
#error_ = ((result.Label - result.demand)**2).mean()
error_ = ((result.Label - dem)**2).mean()
#実需要量のプロット
trace2 = go.Scatter(
    x =  df.index,
    y =  df.demand,
    mode = 'markers',
    name ="実需要量 Demand"
)

#訓練＋未来のデータに対する予測
result = predict_model(best, future)

#予測プロット
trace1 = go.Scatter(
    x = result.index,
    y = result.Label,
    mode = 'markers + lines',
    name = "予測 Forecast"
)

data = [trace1, trace2]

layout = go.Layout(
    title  ="AutoMLによる予測  Forecasting by AutoML",
)

fig = go.Figure(data, layout)
#return fig, error_, result
plotly.offline.plot(fig);
```

    INFO:logs:Initializing predict_model()
    INFO:logs:predict_model(estimator=RidgeClassifier(alpha=1.0, class_weight=None, copy_X=True, fit_intercept=True,
                    max_iter=None, normalize=False, random_state=123, solver='auto',
                    tol=0.001), probability_threshold=None, encoded_labels=False, round=4, verbose=True, ml_usecase=MLUsecase.CLASSIFICATION, display=None)
    INFO:logs:Checking exceptions
    INFO:logs:Preloading libraries
    INFO:logs:Preparing display monitor

<style  type="text/css" >
</style>

<table id="T_41188_" data-quarto-postprocess="true">
<thead>
<tr>
<th class="blank level0" data-quarto-table-cell-role="th"></th>
<th class="col_heading level0 col0"
data-quarto-table-cell-role="th">Model</th>
<th class="col_heading level0 col1"
data-quarto-table-cell-role="th">Accuracy</th>
<th class="col_heading level0 col2"
data-quarto-table-cell-role="th">AUC</th>
<th class="col_heading level0 col3"
data-quarto-table-cell-role="th">Recall</th>
<th class="col_heading level0 col4"
data-quarto-table-cell-role="th">Prec.</th>
<th class="col_heading level0 col5"
data-quarto-table-cell-role="th">F1</th>
<th class="col_heading level0 col6"
data-quarto-table-cell-role="th">Kappa</th>
<th class="col_heading level0 col7"
data-quarto-table-cell-role="th">MCC</th>
</tr>
</thead>
<tbody>
<tr>
<td id="T_41188_level0_row0" class="row_heading level0 row0"
data-quarto-table-cell-role="th">0</td>
<td id="T_41188_row0_col0" class="data row0 col0">Ridge Classifier</td>
<td id="T_41188_row0_col1" class="data row0 col1">0.5165</td>
<td id="T_41188_row0_col2" class="data row0 col2">0</td>
<td id="T_41188_row0_col3" class="data row0 col3">0.2857</td>
<td id="T_41188_row0_col4" class="data row0 col4">0.2979</td>
<td id="T_41188_row0_col5" class="data row0 col5">0.3735</td>
<td id="T_41188_row0_col6" class="data row0 col6">0.2591</td>
<td id="T_41188_row0_col7" class="data row0 col7">0.3110</td>
</tr>
</tbody>
</table>

    INFO:logs:Initializing predict_model()
    INFO:logs:predict_model(estimator=RidgeClassifier(alpha=1.0, class_weight=None, copy_X=True, fit_intercept=True,
                    max_iter=None, normalize=False, random_state=123, solver='auto',
                    tol=0.001), probability_threshold=None, encoded_labels=False, round=4, verbose=True, ml_usecase=MLUsecase.CLASSIFICATION, display=None)
    INFO:logs:Checking exceptions
    INFO:logs:Preloading libraries
    INFO:logs:Preparing display monitor

### 結果の可視化

``` python
plot_model(best, plot = 'feature', verbose=True)
#fig_param = plot_model(best, plot = 'parameter')
#interpret_model(best, plot = 'correlation')
#plot_model(best, plot = 'error')
```

![](06forecast_files/figure-commonmark/cell-121-output-1.png)

``` python
plot_model(best, plot = 'learning')
```

![](06forecast_files/figure-commonmark/cell-122-output-1.png)

``` python
plot_model(best, plot = 'cooks')
```

![](06forecast_files/figure-commonmark/cell-123-output-1.png)

## 需要の集約

上では、顧客ごとに需要予測を行なった。ここでは、倉庫（配送センター、流通センター）ごとの予測や、工場ごとの予測について考える。

そのためには、ロジスティック・ネットワーク設計モデルで製品の流れを最適化した結果を用いる必要がある。

最適化した結果はflow.csvに保存されているので、そこから生成されたデータフレーム
flow_df と需要データフレーム demand_df を入れると、
地点（工場、倉庫）ごとに集約された需要量を返す関数を準備する。

## 需要を地点ごとに集約する関数 aggregate_demand

引数： - demand_df : 需要データ - flow_df : 製品のフローを保管したデータ

返値： - aggregated_demand_df :
地点（工場、倉庫）と製品ごとに集約された需要データ - G:
製品をキーとし、フロー量を枝上に保管したグラフオブジェクト - Prod:
製品のリスト

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L1073"
target="_blank" style="float:right; font-size:smaller">source</a>

### aggregate_demand

``` python

def aggregate_demand(
    demand_df, flow_df
):

```

*最適化された製品フローデータと需要データから、地点（工場、倉庫）ごとの集約された需要量を計算する関数*

### aggregate_demand関数の使用例

``` python
demand_df = pd.read_csv(folder+"demand.csv", index_col=0)
flow_df = pd.read_csv(folder+"flow.csv", index_col=0)
agg_demand_df, G, Prod = aggregate_demand(demand_df, flow_df)
agg_demand_df.head()
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }
&#10;    .dataframe tbody tr th {
        vertical-align: top;
    }
&#10;    .dataframe thead th {
        text-align: right;
    }
</style>

<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: right;">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">date</th>
<th data-quarto-table-cell-role="th">cust</th>
<th data-quarto-table-cell-role="th">prod</th>
<th data-quarto-table-cell-role="th">demand</th>
</tr>
</thead>
<tbody>
<tr>
<td data-quarto-table-cell-role="th">0</td>
<td>2019-01-01</td>
<td>DC_さいたま市</td>
<td>A</td>
<td>1.0</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">1</td>
<td>2019-01-01</td>
<td>Plnt_Odawara</td>
<td>A</td>
<td>5.0</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">2</td>
<td>2019-01-01</td>
<td>DC_さいたま市</td>
<td>B</td>
<td>1.0</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">3</td>
<td>2019-01-01</td>
<td>Plnt_Odawara</td>
<td>B</td>
<td>4.0</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">4</td>
<td>2019-01-01</td>
<td>DC_さいたま市</td>
<td>C</td>
<td>3.0</td>
</tr>
</tbody>
</table>

</div>

``` python
#グラフ G の描画
p ="B"
pos = G[p].layout()
nx.draw(G[p], pos=pos,  node_color="Blue", node_size=10)
```

![](06forecast_files/figure-commonmark/cell-127-output-1.png)

## 集約した需要をもとに安全在庫量を計算

単一ソース供給でない地点に対しては、安全在庫量を計算するための方法が確立されていない。
ここでは、異なるリード時間をもつ複数の地点から供給される場合には、ロジスティック・ネットワーク設計問題で求めた製品の年間フロー量をもとに、以下の方法で計算するものとする。

地点 *j* が、複数の地点 *i*(*i* ∈ *S*<sub>*j*</sub>) からフロー量
*f*<sub>*i**j*</sub>
で供給を受けているものとする。供給地点をフロー量の大きさに応じてランダムに選ぶものと仮定し、その確率を
*λ*<sub>*i**j*</sub> とする。

$$
\lambda\_{ij} = \frac{f\_{ij}}{\sum\_{i \in S_j} f\_{ij}}
$$

地点 *i* から地点 *j* へのリード時間を *L*′<sub>*i**j*</sub>
としたとき、地点 *j* へのリード時間（確率変数） *L*<sub>*j*</sub>
は、確率 *λ*<sub>*i**j*</sub> で値 *L*′<sub>*i**j*</sub>
をとる離散確率分布になる。

*L*<sub>*j*</sub> の期待値 *E*\[*L*<sub>*j*</sub>\] と分散
*V**a**r*(*L*<sub>*j*</sub>)
は、scipyモジュールを使えば簡単に計算できる。 これらの値を使えば、平均
*μ*、標準偏差 *σ* の正規分布にしたがう需要に対するリード時間内の需要量
*D* の期待値 *E*\[*D*\] と分散 *V**a**r*(*D*)
は、以下のように計算できる。

*E*\[*D*\] = *μ**E*\[*L*<sub>*j*</sub>\]

*V**a**r*(*D*) = *σ**E*\[*L*<sub>*j*</sub>\] + *μ*<sup>2</sup>*V**a**r*(*L*<sub>*j*</sub>)

導出については、「はじめての確率論」（近代科学社）pp.92-94を参照されたい。

安全在庫量は、安全在庫係数を *z* としたとき、以下のように計算される。

$$
 E\[D\] + z \sqrt{ Var(D) } 
$$

## 集約した需要をもとに安全在庫量を計算する関数 compute_safety_stock

引数： - demand_df : 需要データ - agg_demand_df :
地点（工場、倉庫）と製品ごとに集約された需要データ - trans_df :
地点間のリード時間を保管したデータ - plnt_prod_df :
工場ごとの製品の生産リード時間を保管したデータ - Prod: 製品のリスト - G:
製品をキーとし、フロー量を枝上に保管したグラフオブジェクト

返値： - safety_df : 地点・製品ごとの安全在庫量を保管したデータ

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/forecast.py#L1136"
target="_blank" style="float:right; font-size:smaller">source</a>

### compute_safety_stock

``` python

def compute_safety_stock(
    demand_df, agg_demand_df, trans_df, plnt_prod_df, Prod, G
):

```

*倉庫・工場・顧客に対する安全在庫量の計算*

### compute_safety_stock関数の使用例

``` python
#trans_df = pd.read_csv(folder + "trans.csv", index_col=0)
#plnt_prod_df = pd.read_csv(folder + "Plnt-Prod.csv", index_col=0)
safety_df = compute_safety_stock(demand_df, agg_demand_df, trans_df, plnt_prod_df, Prod, G)
#    safety_df.to_csv(folder+"safety.csv")
```
