MMMによる振返り分析¶

準備¶

モジュールの読み込み¶

In [ ]:
from mmm_functions import *

データセットの読み込み¶

In [ ]:
dataset = 'MMM_ts_manga5.csv'
df = pd.read_csv(
    dataset,
    parse_dates=['week'],
    index_col='week',
)

アドストックを考慮する特徴量のリストを作成¶

In [ ]:
# アドストックを考慮する特徴量のリストを作成
apply_effects_features = ['traditional', 'internet', 'promotional']

季節性を表現する三角関数特徴量を追加¶

In [ ]:
# 三角関数特徴量を追加したデータフレームを表示して確認
df = add_fourier_terms(df, num=5, seasonal=52.25)

説明変数と目的変数の設定¶

In [ ]:
# 対象データ期間、ここでは直近5年間(52週間×5)を指定
data_term = int(52.25 * 5)

# 説明変数Xと目的変数yに分解
X = df.drop(columns=['sales'])[-data_term:]
y = df['sales'][-data_term:]

MMM構築¶

ハイパーパラメータ自動調整¶

In [ ]:
study = run_optimization(
    regarima_objective, 
    X, y, 
    apply_effects_features, 
    n_trials=1000)
Best trial: 774. Best value: 6.83292e+07: 100%|██████████| 1000/1000 [6:04:27<00:00, 21.87s/it]Best trial:
Value: 68329231.74223903
Params: 
carryover_length_traditional: 4
carryover_peak_traditional: 1
carryover_rate1_traditional: 0.42364549680850105
carryover_rate2_traditional: 0.3221551829058693
carryover_c1_traditional: 1.100058555093823
carryover_c2_traditional: 1.35926768060174
saturation_function_traditional: exponential
curve_param_d_traditional: 8.66920316052875
carryover_length_internet: 1
carryover_peak_internet: 1
carryover_rate1_internet: 0.48242413151803915
carryover_rate2_internet: 0.838762477722768
carryover_c1_internet: 0.15469665409644473
carryover_c2_internet: 0.16155665150054466
saturation_function_internet: exponential
curve_param_d_internet: 7.125480113466326
carryover_length_promotional: 1
carryover_peak_promotional: 1
carryover_rate1_promotional: 0.8625489339045411
carryover_rate2_promotional: 0.33558146110226694
carryover_c1_promotional: 1.3735047137335028
carryover_c2_promotional: 0.9766236392078338
saturation_function_promotional: logistic
curve_param_L_promotional: 3.2388171277544022
curve_param_k_promotional: 3.004277401467686
curve_param_x0_promotional: 0.31528819464451074
alpha: 0.033073901582595266

In [ ]:
# optunaのstudyの保存

joblib.dump(study, 'ridgeMMM_study.joblib')
Out[ ]:
['ridgeMMM_study.joblib']

MMMの構築¶

In [ ]:
trained_model,model_params,pred = create_model_from_trial_regarima(
    study.best_trial, 
    X, y, 
    apply_effects_features
)
No description has been provided for this image
RMSE: 39618591.89259509
MAE: 29210499.97885065
MAPE: 0.02408058665609639
R2: 0.9971799048072444
In [ ]:
# グラフで確認
best_carryover_params = model_params[0]
best_curve_params = model_params[1]

plot_effects(
    best_carryover_params, 
    best_curve_params, 
    apply_effects_features)
No description has been provided for this image

学習済みモデルの保存¶

In [ ]:
# 学習済みモデルtrained_modelを外部ファイルとして保存する 
model_path = 'ridgeMMM_trained_model.joblib'
joblib.dump(trained_model, model_path)
Out[ ]:
['ridgeMMM_trained_model.joblib']

MMM予測の出力(CSVファイル)¶

In [ ]:
pred = trained_model.predict(X)
pred = pd.DataFrame(pred, index=X.index, columns=['y'])
pred.to_csv('pred.csv')

MMM結果¶

売上貢献度¶

In [ ]:
# 貢献度の算出
contribution = calculate_and_plot_contribution(
    y, X, 
    trained_model, 
    (0, np.max(y)*1.1), 
    apply_effects_features
)
# 数値を表示
print(contribution)
No description has been provided for this image
                    Base   traditional      internet   promotional
week                                                              
2018-12-30  3.433205e+08  0.000000e+00  1.402245e+08  0.000000e+00
2019-01-06  3.417836e+08  0.000000e+00  1.104684e+08  0.000000e+00
2019-01-13  3.642532e+08  0.000000e+00  9.529778e+07  0.000000e+00
2019-01-20  4.465800e+08  0.000000e+00  1.077111e+08  2.479799e+08
2019-01-27  5.168261e+08  0.000000e+00  1.313363e+08  3.398946e+08
...                  ...           ...           ...           ...
2023-11-26  5.435474e+08  0.000000e+00  2.960696e+08  0.000000e+00
2023-12-03  5.680613e+08  0.000000e+00  0.000000e+00  2.612527e+08
2023-12-10  5.655370e+08  0.000000e+00  2.869750e+08  0.000000e+00
2023-12-17  5.460165e+08  4.172595e+08  0.000000e+00  0.000000e+00
2023-12-24  5.099405e+08  3.316402e+08  2.053751e+08  2.502643e+08

[261 rows x 4 columns]
In [ ]:
# 貢献度構成比の算出
contribution_results = summarize_and_plot_contribution(contribution)

# 数値を表示
print(contribution_results)
No description has been provided for this image
             contribution     ratio
Base         1.777476e+11  0.508565
traditional  6.990969e+10  0.200023
internet     6.438713e+10  0.184222
promotional  3.746384e+10  0.107190

マーケティングROI¶

In [ ]:
# マーケティングROIの算出
ROI = calculate_marketing_roi(
    X[apply_effects_features], 
    contribution[apply_effects_features]
)

# 数値を表示
print(ROI)
No description has been provided for this image
traditional    0.924837
internet       1.139253
promotional    0.730037
dtype: float64

売上貢献度×マーケティングROI¶

In [ ]:
# 散布図作成(売上貢献度×マーケティングROI)
data_to_plot = plot_scatter_of_contribution_and_roi(
    X[apply_effects_features], 
    contribution[apply_effects_features]
)

# 散布図の数値を表示
print(data_to_plot)
No description has been provided for this image
             contribution_percentage       ROI         cost
traditional                 0.407018  0.924837  36319800000
internet                    0.374865  1.139253  30097950000
promotional                 0.218117  0.730037  21654937500