22 minute read

Sesuai dengan janji saya pada tulisan sebelumnya, pada tulisan ini saya akan mencoba membuat model MMM menggunakan Meta Robyn. Syukurnya Meta Robyn bisa kita gunakan menggunakan bahasa R. Namun, untuk menggunakan Meta Robyn kita harus melakukan setting agar Python bisa digunakan di compute environment kita.

Caranya cukup mudah, kalian bisa refer ke tulisan saya yang ini. Perbedaannya, kita harus meng-install libraries numpy dan nevergrad. Agar mudah, saya akan tuliskan kembali skripnya sebagai berikut:

# silakan di-run di console atau terminal
# kita update dan upgrade sistem linux nya
apt update
apt upgrade -y

# kita akan install python3 environment terlebih dahulu
python3 -m venv .env
source .env/bin/activate

# proses install numpy dan nevergrad
pip install numpy
pip install nevergrad

Sebelum lanjut, saya coba jelaskan mengenai teknologi dibalik Meta Robyn. Setidaknya ada tiga komponen penting, yakni:

  • Ridge Regression untuk meregularisasi multikolinearitas dan mencegah overfitting. Ridge Regression menambahkan “penalti” pada model regresi linier biasa. Penalti ini berupa L2 regularization, yang berarti kita menambahkan kuadrat dari besarnya koefisien ke fungsi loss yang diminimalkan.
  • Optimasi hiperparameter otomatis dengan algoritma evolusioner dari library AI Facebook bernama Nevergrad.
  • Library Prophet dari Facebook untuk dekomposisi data time series secara otomatis menjadi tren, musimanitas, dan pola hari libur.

Nevergrad adalah sebuah library open-source Python yang dikembangkan oleh Facebook AI Research (FAIR). Library ini dirancang untuk melalukan optimasi tanpa turunan (derivative-free optimization). Hal ini akan berguna saat melakukan fine tuning hyperparameter di model ridge regression.

Prophet adalah library open-source yang dikembangkan oleh tim Core Data Science di Facebook. Library ini dirancang khusus untuk melakukan time series forecasting.

Dalam konteks MMM, Prophet dapat digunakan untuk dekomposisi nilai sales dan menjadikan komponen seasonal dan tren sebagai input dari MMM.


Jika rekan-rekan perhatikan, bahwa pada data marketing di tulisan sebelumnya tidak terdapat informasi mengenai tanggal sedangkan pada Meta Robyn kita memerlukan data tanggal. Oleh karena itu, saya akan membuat data tanggal dummy sebanyak 200 buah. Berikut adalah sample datanya:

date youtube facebook newspaper sales
2021-01-01 276.12 45.36 83.04 26.52
2021-01-08 53.40 47.16 54.12 12.48
2021-01-15 20.64 55.08 83.16 11.16
2021-01-22 181.80 49.56 70.20 22.20
2021-01-29 216.96 12.96 70.08 15.48
2021-02-05 10.44 58.68 90.00 8.64
2021-02-12 69.00 39.36 28.20 14.16
2021-02-19 144.24 23.52 13.92 15.84
2021-02-26 10.32 2.52 1.20 5.76
2021-03-05 239.76 3.12 25.44 12.72
2021-03-12 79.32 6.96 29.04 10.32
2021-03-19 257.64 28.80 4.80 20.88
2021-03-26 28.56 42.12 79.08 11.04
2021-04-02 117.00 9.12 8.64 11.64
2021-04-09 244.92 39.48 55.20 22.80
2021-04-16 234.48 57.24 63.48 26.88
2021-04-23 81.36 43.92 136.80 15.00
2021-04-30 337.68 47.52 66.96 29.28
2021-05-07 83.04 24.60 21.96 13.56
2021-05-14 176.76 28.68 22.92 17.52

Selanjutnya kita perlu memanggil libraries yang digunakan. Sejatinya hanya library(Robyn) saja yang perlu dipanggil. Tapi seperti biasa, saya juga memanggil library tidyverse yang lain. Selain itu, kita akan tambah skrip agar memungkinkan komputasi paralel pada Robyn.

library(dplyr)
library(tidyr)
library(Robyn)

Sys.setenv(R_FUTURE_FORK_ENABLE = "true")
options(future.fork.enable = TRUE)

Satu hal yang menarik adalah kita bisa menambahkan data hari libur berdasarkan kalendar dari Facebook. Kalendar hari libur tersebut tersedia untuk berbagai negara, termasuk Indonesia. Berikut adalah sample datanya:

data("dt_prophet_holidays")
dt_prophet_holidays %>% 
  filter(country == "ID") %>% 
  filter(year >= 2021) %>% 
  head(10) %>% 
  knitr::kable()
ds holiday country year
2021-01-01 Tahun Baru Masehi ID 2021
2021-02-12 Tahun Baru Imlek ID 2021
2021-03-11 Isra’ Mi’raj Nabi Muhammad ID 2021
2021-03-14 Hari Suci Nyepi ID 2021
2021-04-02 Wafat Yesus Kristus ID 2021
2021-05-01 Hari Buruh Internasional ID 2021
2021-05-13 Hari Raya Idul Fitri ID 2021
2021-05-13 Kenaikan Yesus Kristus ID 2021
2021-05-14 Hari kedua dari Hari Raya Idul Fitri ID 2021
2021-05-26 Hari Raya Waisak ID 2021

Berikutnya kita perlu membuat satu folder sebagai tempat bernaung files hasil komputasinya.

robyn_directory = "./output"

Berikutnya adalah membuat input bagi Robyn. Tentunya saya sesuaikan dari data yang dimiliki.

Secara default, MMM memerlukan data numerik sebagai input-nya. Namun, dalam documentation Meta Robyn dijelaskan bahwa data kategorik juga bisa digunakan sebagai input. Namun perlu diperhatikan bahwa:

Specifying the discount % of each promotion (which is continuous data) will provide more accurate information to the model vs. a dummy variable that indicates the presence of a promotion with 0 and 1.

Tipe Data

Ada tiga tipe data input Meta Robyn, yakni:

  1. paid_media_vars : Semua variabel yang memiliki nilai spending yang jelas. Data yang termasuk ke dalam tipe ini akan dikenai teknik transformasi untuk mencerminkan carryover effect dan saturation. Ada dua subtipe data yang bisa dijadikan input, yakni impressions dan spending.
  2. organic_vars : Semua aktivitas pemasaran tanpa ada nilai spending yang jelas. Biasanya ini mungkin termasuk newsletter, push notification, social media post, dan lain-lain. Karena variabel ini juga diperkirakan memiliki carryover effect dan saturation, maka teknik transformasi serupa juga akan diterapkan pada variabel ini.
  3. context_vars : Ini mencakup variabel lain yang bukan paid media atau organik, tetapi dapat membantu menjelaskan nilai sales. Contohnya adalah aktivitas kompetitor, price level, promosi, faktor ekonomi makro, dan lain-lain. Variabel-variabel ini tidak akan diterapkan teknik transformasi apa pun dan diharapkan memiliki dampak langsung pada nilai sales.

Berbicara mengenai data paid_media_vars, Robyn bisa diberikan input berupa media exposure (seperti impressions dan sejenisnya) dan media spending. Dalam dokumentasinya, dijelaskan bahwa metrik media exposure lebih disarankan untuk digunakan tapi penggunaan media spending bisa memberikan keuntungan untuk menghitung ROAS.

Sebagai best practice, dijelaskan bahwa analis bisa menggunakan keduanya atau salah satu tergantung dari availability dari data.

    InputCollect <- robyn_inputs(
      dt_input = sampledf,
      dt_holidays = dt_prophet_holidays,
      date_var = "date", 
      dep_var = "sales", 
      dep_var_type = "revenue", 
      prophet_vars = c("trend", "season", "holiday"), 
      prophet_country = "ID", 
      paid_media_spends = c("youtube","facebook","newspaper"),
      window_start = "2021-01-01",
      window_end = "2024-10-25",
      adstock = "geometric" 
    )
    print(InputCollect)

Ada dua teknik adstock yang bisa dipilih pada Robyn. Masing-masing memiliki advantages dan disadvantages oleh karena itu disarankan agar mencoba keduanya.

Fitur Geometric Weibull
Jumlah Parameter 1 (theta) 2 (shape, scale)
Kompleksitas Sederhana Lebih Kompleks
Kecepatan Komputasi Lebih cepat Lebih lambat
Interpretasi Intuitif dan mudah dijelaskan kepada pihak non-teknis Lebih sulit dijelaskan kepada pihak non-teknis (membutuhkan grafik)
Fleksibilitas Kurang fleksibel, decay rate tetap Lebih fleksibel dalam bentuk dan skala distribusi
Cocok untuk Media Digital Kurang cocok untuk transformasi media digital modern Lebih cocok untuk media digital modern (seperti Facebook)
Keunggulan Sederhana, cepat, mudah dikomunikasikan Lebih fleksibel, lebih cocok untuk media digital modern
Kelemahan Terlalu sederhana, kurang fleksibel, kurang cocok untuk media digital Lebih kompleks, lebih lambat, sulit dijelaskan kepada pihak non-teknis

Pada tulisan ini, saya akan gunakan adstock Geometry.

Ada tiga hyperparameters yang bisa dimasukkan range nilainya. Kelak Robyn akan secara otomatis akan mencari nilai yang optimal sehingga MMM yang dihasilkan memiliki R^2 terbaik.

  • Adstock parameters (theta). Ini merupakan parameter decay rate seperti yang pernah saya jelaskan pada tulisan sebelumnya. Kita gunakan theta jika menggunakan adstock berjenis geometry.
  • Saturation parameters (alpha/gamma). Robyn menggunakan fungsi Hill untuk menghitung nilai saturasi. Ini saya sadur langsung dari documentation Robyn mengenai apa arti alpha dan gamma: Alpha controls the shape of the curve between exponential and s-shape. Recommended bound is c(0.5, 3). The larger the alpha, the more S-shape. The smaller, the more C-shape. Gamma controls the inflexion point. Recommended bounce is c(0.01, 1). The larger the gamma, the later the inflection point in the response curve.
  • Time series validation parameter (train_size). Train size menyatakan berapa persen data untuk train dan test.

Setelah kode dieksekusi, R akan melakukan komputasi dengan membuat semua kemungkinan (hingga ribuan) model. Setelah menunggu 5-10 menit, kita akan mendapati beberapa files hasil export sudah berada pada folder yang telah kita definisikan sebelumnya.

Pada kasus ini, Robyn memberikan output dari empat model terbaik. Saya akan coba bahas salah satun model saja ya.

Saya akan memilih model yang terbaik dengan cara:

  • Semua model menghasilkan R^2 yang mirip-mirip di angka 0.6 sekian.
  • Oleh karena itu, saya coba lihat plot fitted vs residuals yang dihasilkan. Model mana saja yang memberikan gambaran titik-titik secara acak. Sebagai pengingat, saya pernah menuliskan tentang pengujian asumsi regresi. Secara simpel:
    • Linearitas:
      • Model yang baik akan menunjukkan titik-titik yang tersebar secara acak di sekitar garis horizontal nol.
      • Jika ada pola melengkung, itu menandakan hubungan non-linear dan model perlu diperbaiki.
    • Homoskedastisitas:
      • Model yang baik akan menunjukkan varians residual yang konstan di seluruh rentang nilai prediksi.
      • Pola “corong” (funnel) menandakan heteroskedastisitas, yang berarti varians residual tidak konstan.
    • Independensi:
      • Plot seharusnya tidak menunjukkan pola tertentu yang mengindikasikan korelasi antara residual.
      • Walaupun plot ini tidak secara langsung menguji independensi, dengan melihat sebaran acak kita dapat mengasumsikan bahwa data tersebut independen.

Masalahnya adalah tidak ada satupun model yang sesuai dengan deskripsi asumsi di atas. Namun ada satu model yang paling acceptable (acak tapi masih ada pola dan berbentuk funnel), yakni model nomor 2_34_6.

Berikut adalah one pager output dari Robyn untuk model tersebut:

Dari one pager di atas, kita dapati R^2 = 0.6419. Kemudian kita bisa melakukan analisa dari beberapa grafik yang ada.

Plot I & II Actual vs Predicted Response dan Waterfall

Grafik Actual vs Predicted menggambarkan bagaimana komparasi antara hasil prediksi model dengan data sebenarnya. Semakin mepet kedua garis, maka semakin baik model memprediksi nilai sebenarnya.

Grafik Waterfall menggambarkan kontribusi masing-masing prediktor terhadap nilai sales-nya. Kita bisa lihat bahwa Youtube memberikan dampak incrementa sales terbesar dibandingkan predictors lainnya.

Plot III & IV Share Spend, Effect & ROAS

Robyn bisa memberikan penjelasan tentang tiga parameter dalam channel marketing yang kita gunakan kemudian menyajikannya dalam grafik di atas. Ketiganya adalah:

  1. Spend Share.
    • Metrik ini menunjukkan berapa banyak anggaran pemasaran yang dialokasikan ke setiap channel marketing.
    • Misalnya, jika iklan TV mendapatkan 50% dari anggaran, maka bagian pengeluarannya adalah 50%.
  2. Effect Share.
    • Metrik ini mengukur seberapa besar dampak setiap channel terhadap peningkatan sales.
  3. ROAS (Return on Ad Spend).
    • Metrik ini mengukur efisiensi setiap channel, yaitu seberapa banyak pendapatan yang dihasilkan untuk setiap spending yang dikeluarkan.
    • ROAS yang tinggi berarti channel tersebut menghasilkan banyak pendapatan dengan sedikit pengeluaran.

Plot V & VI Geometric Adstock dan Immediate vs Carryover

Grafik di atas memberikan kita gambaran tentang besaran nilai theta dari masing-masing channel marketing.

Grafik immediate vs carryover memberikan gambaran tentang apakah efek dari masing-masing channel marketing merupakan efek langsung saat itu (immediate) atau efek yang memiliki jangka waktu (carryover).

Plot VII & VIII Response Curve dan Fitted vs Residual

Grafik response curve memberikan gambaran kepada kita tentang hubungan antara spending channel marketing dan respons nilai sales yang dihasilkan. Ada tiga hal yang bisa kita analisa:

  1. Titik Jenuh (Saturation).
    • Channel marketing dapat mencapai titik jenuh, di mana peningkatan spending tidak lagi menghasilkan peningkatan sales yang signifikan.
  2. Titik Infleksi (Inflection Point).
    • Titik infleksi adalah titik pada kurva di mana laju perubahan respons mulai melambat.
    • Sebelum titik infleksi, laju perubahan respon meningkat, dan sesudah titik infleksi laju perubahan respon menurun.
  3. Realokasi Anggaran.
    • Dengan membandingkan kurva respons dari berbagai saluran media, kita dapat mengidentifikasi channel mana yang mendekati titik jenuh dan channel mana yang masih memiliki potensi pertumbuhan.
    • Akibatnya kita bisa merealokasi spending ke channel yang masih bertumbuh.

Dari MMM yang dihasilkan Robyn, kita bisa membuat beberapa skenario marketing. Ada tiga skenario yang bisa dilakukan:

  1. Memaksimalkan respon sales berdasarkan x minggu terakhir.
  2. Memaksimalkan nilai ROAS menjadi 1.

Sebagai contoh, saya membuat skenario untuk memaksimalkan nilai ROAS. Berikut adalah hasilnya:

Kita bisa dapatkan bahwa dengan membabat 90% budget spending, bisa mendapatkan ROAS = 1 dengan total response separuh dari initial.


if you find this article helpful, support this blog by clicking the ads.