[{"data":1,"prerenderedAt":1237},["ShallowReactive",2],{"article-alternates":3,"article-\u002Fru\u002Fdata\u002Frobyn-marketing-mix-modeling-praktika":13},{"i18nKey":4,"paths":5},"data-005-2026-08",{"de":6,"en":7,"es":8,"fr":9,"it":10,"ru":11,"tr":12},"\u002Fde\u002Fdata\u002Frobyn-praktik-kurulum-marketing-mix-modeling","\u002Fen\u002Fdata\u002Fmarketing-mix-modeling-robyn-practical-setup","\u002Fes\u002Fdata\u002Fmarketing-mix-modeling-robyn-configuracion-practica","\u002Ffr\u002Fdata\u002Fmarketing-mix-modeling-robyn-setup","\u002Fit\u002Fdata\u002Fmarketing-mix-modeling-robyn-setup","\u002Fru\u002Fdata\u002Frobyn-marketing-mix-modeling-praktika","\u002Ftr\u002Fdata\u002Fmarketing-mix-modeling-robyn-ile-pratik-kurulum",{"_path":11,"_dir":14,"_draft":15,"_partial":15,"_locale":16,"title":17,"description":18,"publishedAt":19,"modifiedAt":19,"category":14,"i18nKey":4,"tags":20,"readingTime":26,"author":27,"body":28,"_type":1231,"_id":1232,"_source":1233,"_file":1234,"_stem":1235,"_extension":1236},"data",false,"","Marketing Mix Modeling: Практическая настройка с Robyn","Внедрите открытый инструмент MMM от Meta — Robyn — в production: кривые насыщения, затухание adstock и валидация holdout для точной атрибуции маркетинг-микса.","2026-08-09",[21,22,23,24,25],"marketing-mix-modeling","robyn","adstock","attribution","data-science",8,"Roibase",{"type":29,"children":30,"toc":1224},"root",[31,39,46,60,104,196,216,237,243,248,256,300,305,359,392,412,418,423,491,502,515,546,557,563,579,630,1014,1027,1032,1158,1178,1183,1189,1194,1208,1213,1218],{"type":32,"tag":33,"props":34,"children":35},"element","p",{},[36],{"type":37,"value":38},"text","Marketing Mix Modeling (MMM) вернулся в конце 2020-х с крахом cookie-based атрибуции. Но переход от академических статей к production-среде — это совсем другой уровень. Robyn, открытый инструмент Meta с 2021 года, привязывает этот переход к инженерной дисциплине: предлагает конкретные инструменты для перемещения статистических концепций — кривых насыщения, затухания adstock и валидации holdout — из R-скриптов в операционный pipeline. В этой статье показываем, как настроить три механизма, лежащих в основе Robyn — затухание эффекта рекламы во времени, выход на насыщение отношения расходов к доходу и процесс holdout, тестирующий предсказательную силу модели — в production setup.",{"type":32,"tag":40,"props":41,"children":43},"h2",{"id":42},"adstock-decay-распределение-рекламного-эффекта-во-времени",[44],{"type":37,"value":45},"Adstock Decay: Распределение рекламного эффекта во времени",{"type":32,"tag":33,"props":47,"children":48},{},[49,51,58],{"type":37,"value":50},"ТВ-спот не создаёт продажи в день трансляции — эффект длится неделю. Поисковая реклама может привести к конверсии в момент клика, но вспомнивание бренда триггирует покупку через три дня. Adstock — это математическая конструкция, моделирующая эту временную задержку. В Robyn есть два типа adstock: geometric и Weibull. Geometric — это простой экспоненциальный спад; эффект каждого дня умножается на параметр ",{"type":32,"tag":52,"props":53,"children":55},"code",{"className":54},[],[56],{"type":37,"value":57},"theta",{"type":37,"value":59},". Weibull более гибкий — позволяет независимо контролировать кривую подъёма и спада эффекта.",{"type":32,"tag":33,"props":61,"children":62},{},[63,65,71,73,79,81,87,89,95,97,102],{"type":37,"value":64},"В практической настройке параметры adstock устанавливаются по типу канала. Paid search обычно ",{"type":32,"tag":52,"props":66,"children":68},{"className":67},[],[69],{"type":37,"value":70},"theta=0.3",{"type":37,"value":72}," (быстрый спад), ТВ ",{"type":32,"tag":52,"props":74,"children":76},{"className":75},[],[77],{"type":37,"value":78},"theta=0.7",{"type":37,"value":80}," (длинный хвост), display около ",{"type":32,"tag":52,"props":82,"children":84},{"className":83},[],[85],{"type":37,"value":86},"theta=0.5",{"type":37,"value":88},". Эти значения не произвольны — они находятся гиперпараметрическим поиском на исторических holdout-наборах. В функции ",{"type":32,"tag":52,"props":90,"children":92},{"className":91},[],[93],{"type":37,"value":94},"robyn_inputs()",{"type":37,"value":96}," Robyn задаёте аргумент ",{"type":32,"tag":52,"props":98,"children":100},{"className":99},[],[101],{"type":37,"value":23},{"type":37,"value":103}," по каналам:",{"type":32,"tag":105,"props":106,"children":110},"pre",{"code":107,"language":108,"meta":16,"className":109,"style":16},"InputCollect \u003C- robyn_inputs(\n  dt_input = dt_simulated_weekly,\n  adstock = \"geometric\",\n  adstock_params = list(\n    tv_s = c(0.3, 0.8),\n    search_clicks_p = c(0.0, 0.3),\n    facebook_i = c(0.0, 0.5)\n  )\n)\n","r","language-r shiki shiki-themes github-dark",[111],{"type":32,"tag":52,"props":112,"children":113},{"__ignoreMap":16},[114,125,134,143,152,161,170,179,187],{"type":32,"tag":115,"props":116,"children":119},"span",{"class":117,"line":118},"line",1,[120],{"type":32,"tag":115,"props":121,"children":122},{},[123],{"type":37,"value":124},"InputCollect \u003C- robyn_inputs(\n",{"type":32,"tag":115,"props":126,"children":128},{"class":117,"line":127},2,[129],{"type":32,"tag":115,"props":130,"children":131},{},[132],{"type":37,"value":133},"  dt_input = dt_simulated_weekly,\n",{"type":32,"tag":115,"props":135,"children":137},{"class":117,"line":136},3,[138],{"type":32,"tag":115,"props":139,"children":140},{},[141],{"type":37,"value":142},"  adstock = \"geometric\",\n",{"type":32,"tag":115,"props":144,"children":146},{"class":117,"line":145},4,[147],{"type":32,"tag":115,"props":148,"children":149},{},[150],{"type":37,"value":151},"  adstock_params = list(\n",{"type":32,"tag":115,"props":153,"children":155},{"class":117,"line":154},5,[156],{"type":32,"tag":115,"props":157,"children":158},{},[159],{"type":37,"value":160},"    tv_s = c(0.3, 0.8),\n",{"type":32,"tag":115,"props":162,"children":164},{"class":117,"line":163},6,[165],{"type":32,"tag":115,"props":166,"children":167},{},[168],{"type":37,"value":169},"    search_clicks_p = c(0.0, 0.3),\n",{"type":32,"tag":115,"props":171,"children":173},{"class":117,"line":172},7,[174],{"type":32,"tag":115,"props":175,"children":176},{},[177],{"type":37,"value":178},"    facebook_i = c(0.0, 0.5)\n",{"type":32,"tag":115,"props":180,"children":181},{"class":117,"line":26},[182],{"type":32,"tag":115,"props":183,"children":184},{},[185],{"type":37,"value":186},"  )\n",{"type":32,"tag":115,"props":188,"children":190},{"class":117,"line":189},9,[191],{"type":32,"tag":115,"props":192,"children":193},{},[194],{"type":37,"value":195},")\n",{"type":32,"tag":33,"props":197,"children":198},{},[199,201,207,209,214],{"type":37,"value":200},"Здесь ",{"type":32,"tag":52,"props":202,"children":204},{"className":203},[],[205],{"type":37,"value":206},"c(min, max)",{"type":37,"value":208}," определяет диапазон; алгоритм оптимизации Nevergrad ищет оптимальное значение ",{"type":32,"tag":52,"props":210,"children":212},{"className":211},[],[213],{"type":37,"value":57},{"type":37,"value":215}," в этом диапазоне. Если вместо geometric используете Weibull, добавляются параметры shape и scale. Преимущество Weibull в том, что он лучше подходит для каналов типа display с \"поздним пиком\" — эффект низкий в первые два дня, достигает пика на 3–5-й день.",{"type":32,"tag":33,"props":217,"children":218},{},[219,221,227,229,235],{"type":37,"value":220},"Неправильная настройка adstock приводит к неверному распределению вклада каналов. Например, если моделировать ТВ с geometric ",{"type":32,"tag":52,"props":222,"children":224},{"className":223},[],[225],{"type":37,"value":226},"theta=0.1",{"type":37,"value":228},", эффект приписывается только дню трансляции, упускается органический трафик на протяжении недели. Наоборот, присвоение paid search'у ",{"type":32,"tag":52,"props":230,"children":232},{"className":231},[],[233],{"type":37,"value":234},"theta=0.9",{"type":37,"value":236}," означает, что сегодняшняя продажа приписывается клику неделю назад — нелогично. Поэтому настройка adstock должна соответствовать характеру канала и ограничиваться domain knowledge.",{"type":32,"tag":40,"props":238,"children":240},{"id":239},"кривая-насыщения-выход-отношения-расходов-доходов-на-плато",[241],{"type":37,"value":242},"Кривая насыщения: Выход отношения расходов-доходов на плато",{"type":32,"tag":33,"props":244,"children":245},{},[246],{"type":37,"value":247},"Линейная регрессия предполагает, что каждый рубль расходов даёт одинаковый доход. На самом деле первые 10 тыс. рублей дают ROAS 8, 100 тыс. рублей — 3, 1 млн рублей — менее 1. Предельный доход падает по кривой. Насыщение — это трансформация, моделирующая эту кривую. В Robyn наиболее распространённый тип насыщения — уравнение Hill (Michaelis-Menten):",{"type":32,"tag":105,"props":249,"children":251},{"code":250},"y = Vmax * (x^S) \u002F (K^S + x^S)\n",[252],{"type":32,"tag":52,"props":253,"children":254},{"__ignoreMap":16},[255],{"type":37,"value":250},{"type":32,"tag":33,"props":257,"children":258},{},[259,261,267,269,275,277,283,285,290,292,298],{"type":37,"value":260},"Где ",{"type":32,"tag":52,"props":262,"children":264},{"className":263},[],[265],{"type":37,"value":266},"Vmax",{"type":37,"value":268}," — максимальный эффект, ",{"type":32,"tag":52,"props":270,"children":272},{"className":271},[],[273],{"type":37,"value":274},"K",{"type":37,"value":276}," — уровень расходов, при котором достигается полусыщение (точка перегиба), ",{"type":32,"tag":52,"props":278,"children":280},{"className":279},[],[281],{"type":37,"value":282},"S",{"type":37,"value":284}," — крутизна кривой (shape). Если ",{"type":32,"tag":52,"props":286,"children":288},{"className":287},[],[289],{"type":37,"value":274},{"type":37,"value":291}," низкий, канал быстро насыщается; если высокий — позже. Когда ",{"type":32,"tag":52,"props":293,"children":295},{"className":294},[],[296],{"type":37,"value":297},"S>1",{"type":37,"value":299},", кривая принимает S-образную форму — медленное начало, быстрый рост, затем замедление.",{"type":32,"tag":33,"props":301,"children":302},{},[303],{"type":37,"value":304},"В Robyn параметры Hill устанавливаются также по каналам:",{"type":32,"tag":105,"props":306,"children":308},{"code":307,"language":108,"meta":16,"className":109,"style":16},"hyperparameters \u003C- list(\n  tv_s_alphas = c(0.5, 3),\n  tv_s_gammas = c(0.3, 1),\n  search_clicks_p_alphas = c(0.5, 3),\n  search_clicks_p_gammas = c(0.3, 1)\n)\n",[309],{"type":32,"tag":52,"props":310,"children":311},{"__ignoreMap":16},[312,320,328,336,344,352],{"type":32,"tag":115,"props":313,"children":314},{"class":117,"line":118},[315],{"type":32,"tag":115,"props":316,"children":317},{},[318],{"type":37,"value":319},"hyperparameters \u003C- list(\n",{"type":32,"tag":115,"props":321,"children":322},{"class":117,"line":127},[323],{"type":32,"tag":115,"props":324,"children":325},{},[326],{"type":37,"value":327},"  tv_s_alphas = c(0.5, 3),\n",{"type":32,"tag":115,"props":329,"children":330},{"class":117,"line":136},[331],{"type":32,"tag":115,"props":332,"children":333},{},[334],{"type":37,"value":335},"  tv_s_gammas = c(0.3, 1),\n",{"type":32,"tag":115,"props":337,"children":338},{"class":117,"line":145},[339],{"type":32,"tag":115,"props":340,"children":341},{},[342],{"type":37,"value":343},"  search_clicks_p_alphas = c(0.5, 3),\n",{"type":32,"tag":115,"props":345,"children":346},{"class":117,"line":154},[347],{"type":32,"tag":115,"props":348,"children":349},{},[350],{"type":37,"value":351},"  search_clicks_p_gammas = c(0.3, 1)\n",{"type":32,"tag":115,"props":353,"children":354},{"class":117,"line":163},[355],{"type":32,"tag":115,"props":356,"children":357},{},[358],{"type":37,"value":195},{"type":32,"tag":33,"props":360,"children":361},{},[362,368,370,375,377,383,385,390],{"type":32,"tag":52,"props":363,"children":365},{"className":364},[],[366],{"type":37,"value":367},"alphas",{"type":37,"value":369}," соответствует параметру ",{"type":32,"tag":52,"props":371,"children":373},{"className":372},[],[374],{"type":37,"value":282},{"type":37,"value":376}," Hill, ",{"type":32,"tag":52,"props":378,"children":380},{"className":379},[],[381],{"type":37,"value":382},"gammas",{"type":37,"value":384}," — параметру ",{"type":32,"tag":52,"props":386,"children":388},{"className":387},[],[389],{"type":37,"value":274},{"type":37,"value":391}," (нотация Robyn). Оптимизация ищет лучший fit в этих диапазонах. Но не полагайтесь на слепой поиск — если уже тратите 80% бюджета на ТВ, насыщение должно быть >90%, иначе модель выдаст нереалистичный предельный ROAS.",{"type":32,"tag":33,"props":393,"children":394},{},[395,397,403,405,410],{"type":37,"value":396},"Настройка насыщения напрямую влияет на стратегию бюджетного распределения. Если модель правильно построила кривую насыщения, можно рассчитать предельный ROAS каждого канала и перераспределить бюджет. Функция ",{"type":32,"tag":52,"props":398,"children":400},{"className":399},[],[401],{"type":37,"value":402},"robyn_allocator()",{"type":37,"value":404}," делает именно это — при фиксированном общем бюджете какой канал урезать и на какой направить, чтобы максимизировать продажи? Но это рекомендация валидна только если параметры насыщения правильны. Неправильное значение ",{"type":32,"tag":52,"props":406,"children":408},{"className":407},[],[409],{"type":37,"value":274},{"type":37,"value":411}," — это ошибка в миллионы рублей.",{"type":32,"tag":40,"props":413,"children":415},{"id":414},"holdout-validation-тестирование-предсказательной-силы-модели",[416],{"type":37,"value":417},"Holdout Validation: Тестирование предсказательной силы модели",{"type":32,"tag":33,"props":419,"children":420},{},[421],{"type":37,"value":422},"Главный риск MMM — переобучение: модель заучивает исторические данные, не предсказывает будущее. Чтобы это предотвратить, нужна временная валидация на holdout-наборе. В Robyn'е последние 4–8 недель отделяются как holdout-набор, модель обучается на остальных данных и делает прогноз на holdout-период. Если NRMSE (нормализованная среднеквадратичная ошибка) и MAPE (средняя абсолютная процентная ошибка) низкие, модель обобщается.",{"type":32,"tag":105,"props":424,"children":426},{"code":425,"language":108,"meta":16,"className":109,"style":16},"InputCollect \u003C- robyn_inputs(\n  dt_input = dt_simulated_weekly,\n  window_start = \"2022-01-01\",\n  window_end = \"2023-10-31\",\n  rollingWindowStartWhich = 1,\n  rollingWindowEndWhich = 52,\n  rollingWindowLength = 4\n)\n",[427],{"type":32,"tag":52,"props":428,"children":429},{"__ignoreMap":16},[430,437,444,452,460,468,476,484],{"type":32,"tag":115,"props":431,"children":432},{"class":117,"line":118},[433],{"type":32,"tag":115,"props":434,"children":435},{},[436],{"type":37,"value":124},{"type":32,"tag":115,"props":438,"children":439},{"class":117,"line":127},[440],{"type":32,"tag":115,"props":441,"children":442},{},[443],{"type":37,"value":133},{"type":32,"tag":115,"props":445,"children":446},{"class":117,"line":136},[447],{"type":32,"tag":115,"props":448,"children":449},{},[450],{"type":37,"value":451},"  window_start = \"2022-01-01\",\n",{"type":32,"tag":115,"props":453,"children":454},{"class":117,"line":145},[455],{"type":32,"tag":115,"props":456,"children":457},{},[458],{"type":37,"value":459},"  window_end = \"2023-10-31\",\n",{"type":32,"tag":115,"props":461,"children":462},{"class":117,"line":154},[463],{"type":32,"tag":115,"props":464,"children":465},{},[466],{"type":37,"value":467},"  rollingWindowStartWhich = 1,\n",{"type":32,"tag":115,"props":469,"children":470},{"class":117,"line":163},[471],{"type":32,"tag":115,"props":472,"children":473},{},[474],{"type":37,"value":475},"  rollingWindowEndWhich = 52,\n",{"type":32,"tag":115,"props":477,"children":478},{"class":117,"line":172},[479],{"type":32,"tag":115,"props":480,"children":481},{},[482],{"type":37,"value":483},"  rollingWindowLength = 4\n",{"type":32,"tag":115,"props":485,"children":486},{"class":117,"line":26},[487],{"type":32,"tag":115,"props":488,"children":489},{},[490],{"type":37,"value":195},{"type":32,"tag":33,"props":492,"children":493},{},[494,500],{"type":32,"tag":52,"props":495,"children":497},{"className":496},[],[498],{"type":37,"value":499},"rollingWindowLength = 4",{"type":37,"value":501}," откладывает последние 4 недели как holdout. Модель обучается без этих недель, затем делает прогноз. В выходах Robyn показывается holdout NRMSE для каждой модели — ниже 10% хорошо, выше 20% подозрительно. Но не принимайте решение по одной метрике; проверьте, есть ли аномалии в holdout-периоде (кампания, праздник). Например, если неделя Black Friday попадает в holdout, модель недооценит, потому что в нормальном паттерне спроса таких скачков нет.",{"type":32,"tag":33,"props":503,"children":504},{},[505,507,513],{"type":37,"value":506},"После holdout'а обычно переобучают модель — финальный fit на всех данных, но гиперпараметры выбираются на основе holdout-результатов. Это цикл \"train-validate-finalize\". В Robyn это делается через ",{"type":32,"tag":52,"props":508,"children":510},{"className":509},[],[511],{"type":37,"value":512},"robyn_refresh()",{"type":37,"value":514},":",{"type":32,"tag":105,"props":516,"children":518},{"code":517,"language":108,"meta":16,"className":109,"style":16},"Robyn1 \u003C- robyn_run(InputCollect = InputCollect, plot_folder = OutputCollect$plot_folder)\nOutputCollect \u003C- robyn_outputs(Robyn1, select_model = \"1_100_3\")\nRobynRefresh \u003C- robyn_refresh(Robyn1, dt_input = dt_simulated_weekly, refresh_steps = 4)\n",[519],{"type":32,"tag":52,"props":520,"children":521},{"__ignoreMap":16},[522,530,538],{"type":32,"tag":115,"props":523,"children":524},{"class":117,"line":118},[525],{"type":32,"tag":115,"props":526,"children":527},{},[528],{"type":37,"value":529},"Robyn1 \u003C- robyn_run(InputCollect = InputCollect, plot_folder = OutputCollect$plot_folder)\n",{"type":32,"tag":115,"props":531,"children":532},{"class":117,"line":127},[533],{"type":32,"tag":115,"props":534,"children":535},{},[536],{"type":37,"value":537},"OutputCollect \u003C- robyn_outputs(Robyn1, select_model = \"1_100_3\")\n",{"type":32,"tag":115,"props":539,"children":540},{"class":117,"line":136},[541],{"type":32,"tag":115,"props":542,"children":543},{},[544],{"type":37,"value":545},"RobynRefresh \u003C- robyn_refresh(Robyn1, dt_input = dt_simulated_weekly, refresh_steps = 4)\n",{"type":32,"tag":33,"props":547,"children":548},{},[549,555],{"type":32,"tag":52,"props":550,"children":552},{"className":551},[],[553],{"type":37,"value":554},"refresh_steps = 4",{"type":37,"value":556}," обновляет модель на новых 4 неделях данных, но сохраняет параметры насыщения и adstock (калибровка сохраняется). Это основа постоянно работающего production-pipeline — каждую неделю добавляется новая строка, модель переподгоняется, dashboard обновляется.",{"type":32,"tag":40,"props":558,"children":560},{"id":559},"перемещение-robyn-pipelineа-в-production",[561],{"type":37,"value":562},"Перемещение Robyn Pipeline'а в Production",{"type":32,"tag":33,"props":564,"children":565},{},[566,568,577],{"type":37,"value":567},"Robyn — не R-скрипт, а инструмент, который должен быть интегрирован в production data-pipeline. Типичная архитектура: таблица маркетинг-расходов в BigQuery + таблица конверсий из GA4 + таблица выручки из CRM → dbt создаёт еженедельный агрегированный стол → DAG'а в Cloud Composer (Airflow) триггирует Robyn R-скрипт → результат JSON в Looker Studio dashboard. Этот стек работает в контексте ",{"type":32,"tag":569,"props":570,"children":574},"a",{"href":571,"rel":572},"https:\u002F\u002Fwww.roibase.com.tr\u002Fru\u002Ffirstparty",[573],"nofollow",[575],{"type":37,"value":576},"архитектуры first-party данных",{"type":37,"value":578},".",{"type":32,"tag":33,"props":580,"children":581},{},[582,584,590,592,598,600,606,608,614,615,621,622,628],{"type":37,"value":583},"Первый шаг — стандартизировать схему данных. Robyn ждёт таблицу ",{"type":32,"tag":52,"props":585,"children":587},{"className":586},[],[588],{"type":37,"value":589},"dt_input",{"type":37,"value":591}," со столбцами: ",{"type":32,"tag":52,"props":593,"children":595},{"className":594},[],[596],{"type":37,"value":597},"DATE",{"type":37,"value":599}," (еженедельно), ",{"type":32,"tag":52,"props":601,"children":603},{"className":602},[],[604],{"type":37,"value":605},"revenue",{"type":37,"value":607},", ",{"type":32,"tag":52,"props":609,"children":611},{"className":610},[],[612],{"type":37,"value":613},"tv_spend",{"type":37,"value":607},{"type":32,"tag":52,"props":616,"children":618},{"className":617},[],[619],{"type":37,"value":620},"search_spend",{"type":37,"value":607},{"type":32,"tag":52,"props":623,"children":625},{"className":624},[],[626],{"type":37,"value":627},"facebook_impressions",{"type":37,"value":629}," и т. д. Каждый канал — отдельный столбец; без разделения organic\u002Fpaid модель не может делать attribution. Пропущенные недели нужно заполнить (нулями или интерполяцией), выбросы — отметить. Пример dbt-модели:",{"type":32,"tag":105,"props":631,"children":635},{"code":632,"language":633,"meta":16,"className":634,"style":16},"with base as (\n  select\n    date_trunc(event_date, week) as week_start,\n    sum(case when source = 'google\u002Fcpc' then cost else 0 end) as search_spend,\n    sum(case when source = 'facebook' then cost else 0 end) as facebook_spend,\n    count(distinct case when event_name = 'purchase' then user_pseudo_id end) as conversions\n  from `project.analytics_123456789.events_*`\n  where _table_suffix between '20220101' and '20231231'\n  group by 1\n)\nselect * from base\norder by week_start\n","sql","language-sql shiki shiki-themes github-dark",[636],{"type":32,"tag":52,"props":637,"children":638},{"__ignoreMap":16},[639,664,672,699,777,842,909,922,955,968,976,1000],{"type":32,"tag":115,"props":640,"children":641},{"class":117,"line":118},[642,648,654,659],{"type":32,"tag":115,"props":643,"children":645},{"style":644},"--shiki-default:#F97583",[646],{"type":37,"value":647},"with",{"type":32,"tag":115,"props":649,"children":651},{"style":650},"--shiki-default:#E1E4E8",[652],{"type":37,"value":653}," base ",{"type":32,"tag":115,"props":655,"children":656},{"style":644},[657],{"type":37,"value":658},"as",{"type":32,"tag":115,"props":660,"children":661},{"style":650},[662],{"type":37,"value":663}," (\n",{"type":32,"tag":115,"props":665,"children":666},{"class":117,"line":127},[667],{"type":32,"tag":115,"props":668,"children":669},{"style":644},[670],{"type":37,"value":671},"  select\n",{"type":32,"tag":115,"props":673,"children":674},{"class":117,"line":136},[675,680,685,690,694],{"type":32,"tag":115,"props":676,"children":677},{"style":650},[678],{"type":37,"value":679},"    date_trunc(event_date, ",{"type":32,"tag":115,"props":681,"children":682},{"style":644},[683],{"type":37,"value":684},"week",{"type":32,"tag":115,"props":686,"children":687},{"style":650},[688],{"type":37,"value":689},") ",{"type":32,"tag":115,"props":691,"children":692},{"style":644},[693],{"type":37,"value":658},{"type":32,"tag":115,"props":695,"children":696},{"style":650},[697],{"type":37,"value":698}," week_start,\n",{"type":32,"tag":115,"props":700,"children":701},{"class":117,"line":145},[702,708,713,718,723,728,733,739,744,749,754,759,764,768,772],{"type":32,"tag":115,"props":703,"children":705},{"style":704},"--shiki-default:#79B8FF",[706],{"type":37,"value":707},"    sum",{"type":32,"tag":115,"props":709,"children":710},{"style":650},[711],{"type":37,"value":712},"(",{"type":32,"tag":115,"props":714,"children":715},{"style":644},[716],{"type":37,"value":717},"case",{"type":32,"tag":115,"props":719,"children":720},{"style":644},[721],{"type":37,"value":722}," when",{"type":32,"tag":115,"props":724,"children":725},{"style":650},[726],{"type":37,"value":727}," source ",{"type":32,"tag":115,"props":729,"children":730},{"style":644},[731],{"type":37,"value":732},"=",{"type":32,"tag":115,"props":734,"children":736},{"style":735},"--shiki-default:#9ECBFF",[737],{"type":37,"value":738}," 'google\u002Fcpc'",{"type":32,"tag":115,"props":740,"children":741},{"style":644},[742],{"type":37,"value":743}," then",{"type":32,"tag":115,"props":745,"children":746},{"style":650},[747],{"type":37,"value":748}," cost ",{"type":32,"tag":115,"props":750,"children":751},{"style":644},[752],{"type":37,"value":753},"else",{"type":32,"tag":115,"props":755,"children":756},{"style":704},[757],{"type":37,"value":758}," 0",{"type":32,"tag":115,"props":760,"children":761},{"style":644},[762],{"type":37,"value":763}," end",{"type":32,"tag":115,"props":765,"children":766},{"style":650},[767],{"type":37,"value":689},{"type":32,"tag":115,"props":769,"children":770},{"style":644},[771],{"type":37,"value":658},{"type":32,"tag":115,"props":773,"children":774},{"style":650},[775],{"type":37,"value":776}," search_spend,\n",{"type":32,"tag":115,"props":778,"children":779},{"class":117,"line":154},[780,784,788,792,796,800,804,809,813,817,821,825,829,833,837],{"type":32,"tag":115,"props":781,"children":782},{"style":704},[783],{"type":37,"value":707},{"type":32,"tag":115,"props":785,"children":786},{"style":650},[787],{"type":37,"value":712},{"type":32,"tag":115,"props":789,"children":790},{"style":644},[791],{"type":37,"value":717},{"type":32,"tag":115,"props":793,"children":794},{"style":644},[795],{"type":37,"value":722},{"type":32,"tag":115,"props":797,"children":798},{"style":650},[799],{"type":37,"value":727},{"type":32,"tag":115,"props":801,"children":802},{"style":644},[803],{"type":37,"value":732},{"type":32,"tag":115,"props":805,"children":806},{"style":735},[807],{"type":37,"value":808}," 'facebook'",{"type":32,"tag":115,"props":810,"children":811},{"style":644},[812],{"type":37,"value":743},{"type":32,"tag":115,"props":814,"children":815},{"style":650},[816],{"type":37,"value":748},{"type":32,"tag":115,"props":818,"children":819},{"style":644},[820],{"type":37,"value":753},{"type":32,"tag":115,"props":822,"children":823},{"style":704},[824],{"type":37,"value":758},{"type":32,"tag":115,"props":826,"children":827},{"style":644},[828],{"type":37,"value":763},{"type":32,"tag":115,"props":830,"children":831},{"style":650},[832],{"type":37,"value":689},{"type":32,"tag":115,"props":834,"children":835},{"style":644},[836],{"type":37,"value":658},{"type":32,"tag":115,"props":838,"children":839},{"style":650},[840],{"type":37,"value":841}," facebook_spend,\n",{"type":32,"tag":115,"props":843,"children":844},{"class":117,"line":163},[845,850,854,859,864,868,873,877,882,886,891,896,900,904],{"type":32,"tag":115,"props":846,"children":847},{"style":704},[848],{"type":37,"value":849},"    count",{"type":32,"tag":115,"props":851,"children":852},{"style":650},[853],{"type":37,"value":712},{"type":32,"tag":115,"props":855,"children":856},{"style":644},[857],{"type":37,"value":858},"distinct",{"type":32,"tag":115,"props":860,"children":861},{"style":644},[862],{"type":37,"value":863}," case",{"type":32,"tag":115,"props":865,"children":866},{"style":644},[867],{"type":37,"value":722},{"type":32,"tag":115,"props":869,"children":870},{"style":650},[871],{"type":37,"value":872}," event_name ",{"type":32,"tag":115,"props":874,"children":875},{"style":644},[876],{"type":37,"value":732},{"type":32,"tag":115,"props":878,"children":879},{"style":735},[880],{"type":37,"value":881}," 'purchase'",{"type":32,"tag":115,"props":883,"children":884},{"style":644},[885],{"type":37,"value":743},{"type":32,"tag":115,"props":887,"children":888},{"style":650},[889],{"type":37,"value":890}," user_pseudo_id ",{"type":32,"tag":115,"props":892,"children":893},{"style":644},[894],{"type":37,"value":895},"end",{"type":32,"tag":115,"props":897,"children":898},{"style":650},[899],{"type":37,"value":689},{"type":32,"tag":115,"props":901,"children":902},{"style":644},[903],{"type":37,"value":658},{"type":32,"tag":115,"props":905,"children":906},{"style":650},[907],{"type":37,"value":908}," conversions\n",{"type":32,"tag":115,"props":910,"children":911},{"class":117,"line":172},[912,917],{"type":32,"tag":115,"props":913,"children":914},{"style":644},[915],{"type":37,"value":916},"  from",{"type":32,"tag":115,"props":918,"children":919},{"style":735},[920],{"type":37,"value":921}," `project.analytics_123456789.events_*`\n",{"type":32,"tag":115,"props":923,"children":924},{"class":117,"line":26},[925,930,935,940,945,950],{"type":32,"tag":115,"props":926,"children":927},{"style":644},[928],{"type":37,"value":929},"  where",{"type":32,"tag":115,"props":931,"children":932},{"style":650},[933],{"type":37,"value":934}," _table_suffix ",{"type":32,"tag":115,"props":936,"children":937},{"style":644},[938],{"type":37,"value":939},"between",{"type":32,"tag":115,"props":941,"children":942},{"style":735},[943],{"type":37,"value":944}," '20220101'",{"type":32,"tag":115,"props":946,"children":947},{"style":644},[948],{"type":37,"value":949}," and",{"type":32,"tag":115,"props":951,"children":952},{"style":735},[953],{"type":37,"value":954}," '20231231'\n",{"type":32,"tag":115,"props":956,"children":957},{"class":117,"line":189},[958,963],{"type":32,"tag":115,"props":959,"children":960},{"style":644},[961],{"type":37,"value":962},"  group by",{"type":32,"tag":115,"props":964,"children":965},{"style":704},[966],{"type":37,"value":967}," 1\n",{"type":32,"tag":115,"props":969,"children":971},{"class":117,"line":970},10,[972],{"type":32,"tag":115,"props":973,"children":974},{"style":650},[975],{"type":37,"value":195},{"type":32,"tag":115,"props":977,"children":979},{"class":117,"line":978},11,[980,985,990,995],{"type":32,"tag":115,"props":981,"children":982},{"style":644},[983],{"type":37,"value":984},"select",{"type":32,"tag":115,"props":986,"children":987},{"style":644},[988],{"type":37,"value":989}," *",{"type":32,"tag":115,"props":991,"children":992},{"style":644},[993],{"type":37,"value":994}," from",{"type":32,"tag":115,"props":996,"children":997},{"style":650},[998],{"type":37,"value":999}," base\n",{"type":32,"tag":115,"props":1001,"children":1003},{"class":117,"line":1002},12,[1004,1009],{"type":32,"tag":115,"props":1005,"children":1006},{"style":644},[1007],{"type":37,"value":1008},"order by",{"type":32,"tag":115,"props":1010,"children":1011},{"style":650},[1012],{"type":37,"value":1013}," week_start\n",{"type":32,"tag":33,"props":1015,"children":1016},{},[1017,1019,1025],{"type":37,"value":1018},"Этот стол экспортируется из BigQuery в CSV и подаётся в Robyn-скрипт, или лучше — извлекается прямо через пакет R ",{"type":32,"tag":52,"props":1020,"children":1022},{"className":1021},[],[1023],{"type":37,"value":1024},"bigrquery",{"type":37,"value":1026},". Второй вариант предпочтителен — гарантирует свежесть данных.",{"type":32,"tag":33,"props":1028,"children":1029},{},[1030],{"type":37,"value":1031},"DAG в Airflow для этапа Robyn:",{"type":32,"tag":105,"props":1033,"children":1037},{"code":1034,"language":1035,"meta":16,"className":1036,"style":16},"from airflow.operators.bash import BashOperator\n\nrun_robyn = BashOperator(\n    task_id='run_robyn_mmm',\n    bash_command='Rscript \u002Fpath\u002Fto\u002Frobyn_model.R ',\n    dag=dag\n)\n","python","language-python shiki shiki-themes github-dark",[1038],{"type":32,"tag":52,"props":1039,"children":1040},{"__ignoreMap":16},[1041,1064,1073,1090,1113,1134,1151],{"type":32,"tag":115,"props":1042,"children":1043},{"class":117,"line":118},[1044,1049,1054,1059],{"type":32,"tag":115,"props":1045,"children":1046},{"style":644},[1047],{"type":37,"value":1048},"from",{"type":32,"tag":115,"props":1050,"children":1051},{"style":650},[1052],{"type":37,"value":1053}," airflow.operators.bash ",{"type":32,"tag":115,"props":1055,"children":1056},{"style":644},[1057],{"type":37,"value":1058},"import",{"type":32,"tag":115,"props":1060,"children":1061},{"style":650},[1062],{"type":37,"value":1063}," BashOperator\n",{"type":32,"tag":115,"props":1065,"children":1066},{"class":117,"line":127},[1067],{"type":32,"tag":115,"props":1068,"children":1070},{"emptyLinePlaceholder":1069},true,[1071],{"type":37,"value":1072},"\n",{"type":32,"tag":115,"props":1074,"children":1075},{"class":117,"line":136},[1076,1081,1085],{"type":32,"tag":115,"props":1077,"children":1078},{"style":650},[1079],{"type":37,"value":1080},"run_robyn ",{"type":32,"tag":115,"props":1082,"children":1083},{"style":644},[1084],{"type":37,"value":732},{"type":32,"tag":115,"props":1086,"children":1087},{"style":650},[1088],{"type":37,"value":1089}," BashOperator(\n",{"type":32,"tag":115,"props":1091,"children":1092},{"class":117,"line":145},[1093,1099,1103,1108],{"type":32,"tag":115,"props":1094,"children":1096},{"style":1095},"--shiki-default:#FFAB70",[1097],{"type":37,"value":1098},"    task_id",{"type":32,"tag":115,"props":1100,"children":1101},{"style":644},[1102],{"type":37,"value":732},{"type":32,"tag":115,"props":1104,"children":1105},{"style":735},[1106],{"type":37,"value":1107},"'run_robyn_mmm'",{"type":32,"tag":115,"props":1109,"children":1110},{"style":650},[1111],{"type":37,"value":1112},",\n",{"type":32,"tag":115,"props":1114,"children":1115},{"class":117,"line":154},[1116,1121,1125,1130],{"type":32,"tag":115,"props":1117,"children":1118},{"style":1095},[1119],{"type":37,"value":1120},"    bash_command",{"type":32,"tag":115,"props":1122,"children":1123},{"style":644},[1124],{"type":37,"value":732},{"type":32,"tag":115,"props":1126,"children":1127},{"style":735},[1128],{"type":37,"value":1129},"'Rscript \u002Fpath\u002Fto\u002Frobyn_model.R '",{"type":32,"tag":115,"props":1131,"children":1132},{"style":650},[1133],{"type":37,"value":1112},{"type":32,"tag":115,"props":1135,"children":1136},{"class":117,"line":163},[1137,1142,1146],{"type":32,"tag":115,"props":1138,"children":1139},{"style":1095},[1140],{"type":37,"value":1141},"    dag",{"type":32,"tag":115,"props":1143,"children":1144},{"style":644},[1145],{"type":37,"value":732},{"type":32,"tag":115,"props":1147,"children":1148},{"style":650},[1149],{"type":37,"value":1150},"dag\n",{"type":32,"tag":115,"props":1152,"children":1153},{"class":117,"line":172},[1154],{"type":32,"tag":115,"props":1155,"children":1156},{"style":650},[1157],{"type":37,"value":195},{"type":32,"tag":33,"props":1159,"children":1160},{},[1161,1163,1169,1171,1176],{"type":37,"value":1162},"Внутри скрипта модель сохраняется через ",{"type":32,"tag":52,"props":1164,"children":1166},{"className":1165},[],[1167],{"type":37,"value":1168},"robyn_save()",{"type":37,"value":1170}," в формате RDS и загружается в GCS. На следующие недели ",{"type":32,"tag":52,"props":1172,"children":1174},{"className":1173},[],[1175],{"type":37,"value":512},{"type":37,"value":1177}," загружает её обратно. Таким образом, каждую неделю вместо переобучения с нуля делается incremental update — время вычисления падает с 2 часов до 15 минут.",{"type":32,"tag":33,"props":1179,"children":1180},{},[1181],{"type":37,"value":1182},"Метрики holdout сохраняются в JSON выходе, пишутся в BigQuery, график тренда появляется в Looker Studio. Если NRMSE резко скачет (например, с 8% на 18%), срабатывает alert — модель сломалась, нужна пересчётка. Без этого мониторинга MMM молчаливо отказывает; неправильное распределение бюджета остаётся незамеченным 3 месяца.",{"type":32,"tag":40,"props":1184,"children":1186},{"id":1185},"привязка-выходов-модели-к-механизму-принятия-решений",[1187],{"type":37,"value":1188},"Привязка выходов модели к механизму принятия решений",{"type":32,"tag":33,"props":1190,"children":1191},{},[1192],{"type":37,"value":1193},"Выход Robyn — не pie chart вклада канала, а таблица предельного ROAS. Доход последнего рубля расходов каждого канала. На этой основе запускается бюджетный оптимизатор: если предельный ROAS ТВ равен 2, а поиска — 5, нужно сдвинуть бюджет в пользу поиска. Но эта механическая оптимизация может конфликтовать со стратегией бренда — если ТВ работает на brand awareness, краткосрочный ROAS вводит в заблуждение.",{"type":32,"tag":33,"props":1195,"children":1196},{},[1197,1199,1206],{"type":37,"value":1198},"Поэтому результаты MMM не должны быть инструментом изолированного решения, а синтезироваться с другими сигналами в слое ",{"type":32,"tag":569,"props":1200,"children":1203},{"href":1201,"rel":1202},"https:\u002F\u002Fwww.roibase.com.tr\u002Fru\u002Fverianalizi",[573],[1204],{"type":37,"value":1205},"data analytics",{"type":37,"value":1207},": brand lift study, incrementality test, customer lifetime value. Если Robyn говорит contribution 30%, а geo-lift test показывает 15%, нужно их согласовать — в предположениях модели ошибка (например, adstock decay установлен слишком высоко).",{"type":32,"tag":33,"props":1209,"children":1210},{},[1211],{"type":37,"value":1212},"В production MMM обновляется еженедельно, но решения по бюджету принимаются ежемесячно или ежеквартально. Модель работает каждую неделю, метрики идут в тренд, но вы смотрите на 4-недельное усреднение. Сдвиг в миллионы по одной неделе вызывает волатильность. К тому же holdout-период 4 недели, так что цикл пересмотра бюджета должен совпадать с окном holdout.",{"type":32,"tag":33,"props":1214,"children":1215},{},[1216],{"type":37,"value":1217},"Наконец, MMM не заменяет, а дополняет incremental attribution",{"type":32,"tag":1219,"props":1220,"children":1221},"style",{},[1222],{"type":37,"value":1223},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":16,"searchDepth":136,"depth":136,"links":1225},[1226,1227,1228,1229,1230],{"id":42,"depth":127,"text":45},{"id":239,"depth":127,"text":242},{"id":414,"depth":127,"text":417},{"id":559,"depth":127,"text":562},{"id":1185,"depth":127,"text":1188},"markdown","content:ru:data:robyn-marketing-mix-modeling-praktika.md","content","ru\u002Fdata\u002Frobyn-marketing-mix-modeling-praktika.md","ru\u002Fdata\u002Frobyn-marketing-mix-modeling-praktika","md",1786860295618]