iT邦幫忙

2026 iThome 鐵人賽

DAY 12
0
Build on Google AI

AI-Driven MarTech:用 Google Cloud + Vertex AI 打造全自動廣告歸因與多模態素材分析系統系列 第 12 篇

Day 12 | 哪種客人值得多投廣告?讓機器學習預測顧客的長期價值

  • 分享至 

  • xImage
  •  

1. 前言:同樣花錢拿到一位新客,長期帶來的營收卻差很多

廣告後台最常看的是取得一位新客要花多少錢,以及這筆訂單賺回多少,但同樣花幾百元拿到的新客,有人一個月後又回來買、有人買完一次就不再出現,如果只用第一筆訂單的金額決定出價,會把預算投給首單大但不會回來的客人,錯過首單小但會一直回購的客人。

比較好的做法是看顧客的長期價值(Customer Lifetime Value,常簡稱 LTV),也就是這位顧客未來還會帶來多少營收,但新客剛下單時還看不出來他會不會回購,等看得出來又太晚了,所以今天要做的是只用第一筆訂單當下就知道的資訊,讓 BigQuery ML 預測他接下來 30 天還會帶來多少營收。

Day 11 的分群要等顧客回購才分得準,今天換個方向,同樣在最後揭曉 Day 05 合成器藏進去的四種顧客類型,看預測值和真實的回購節奏對不對得上,今天的雲端費用都以 1 美元約 32 元換算成新台幣。

今日核心目標:

  1. 把每位顧客整理成一列首購特徵,加上首購後 30 天內的回購營收,用 1,458 位已經觀察滿 30 天的顧客訓練與驗證
  2. 先算兩條不用機器學習的基準線,再用 BigQuery ML 線性迴歸預測,看模型有沒有贏過基準線
  3. 把預測值依通路與活動加總、除以取得成本,回答哪種客人值得多投廣告,最後揭曉答案表

2. 系統架構全景與設計理念

圖一:訂單整理成每位顧客一列首購特徵與 30 天回購營收,線性迴歸預測後寫進 mart_customer_ltv,再和廣告花費算出每個通路與活動的價值成本比,答案表只在揭曉時讀

步驟 做什麼 產出
整理特徵 從 Day 07 的 fct_orders 取每位顧客的第一筆訂單,加上之後 30 天的回購營收 ltv_features,2,461 人
基準線 全體平均、依首購商品平均,不用機器學習 驗證集誤差
建模型 用首購在 8/8 以前的 1,183 人訓練線性迴歸 ltv_linreg
評估 用首購在 8/9–8/17 的 275 人驗證,和基準線比誤差 誤差比較表
預測 驗證集與首購在 8/18 之後的 1,003 人 mart_customer_ltv
算價值 新客的首單金額加預測回購,除以同期取得成本 通路與活動價值表
揭曉 預測值和答案表對照 對照表

💡 核心工程理念:

  1. 只用當下知道的資訊:特徵只能是首購那一刻就知道的事,之後才發生的回購紀錄一律不能放進來
  2. 先有基準線再訓練:模型要贏過簡單的平均值才有意義,否則直接用平均值就好
  3. 預測結果要落表:寫進 mart_customer_ltv,Day 13 的驗收與之後的 AI 查詢都會用到

3. 核心技術深度拆解

3.1 題目怎麼出:只能用第一筆訂單當下知道的事

機器學習的題目要先想清楚「在什麼時間點、用什麼資訊、預測什麼」,今天的時間點是顧客剛完成第一筆訂單,這時候知道的只有他買了哪項商品、買幾件、花多少錢,以及從哪個來源、哪個媒介、哪個活動進來,要預測的是首購後 30 天內的回購營收,第一筆訂單本身不算在內。

最容易犯的錯是把 Day 11 的分群當成特徵,分群用了訂單數、回購間隔、距今天數,這些都是首購之後才發生的事,拿來預測未來回購等於先偷看答案,驗證時分數會很漂亮,真的拿去預測新客時卻用不了,因為新客還沒有這些紀錄,機器學習稱這種情況為資料洩漏(Data Leakage)。

第二個要決定的是觀察多久,資料最後一天是 9/16,我原本想看 60 天,但首購後已經滿 60 天的人只剩 628 位,而且重訓襪專案 7/15 才開始,60 天窗裡幾乎沒有這個活動的顧客,改成 30 天後有 1,458 人可以用,代價是回購間隔比 30 天長的顧客,30 天內還看不到他們回來,Day 11 的輪廓裡浴巾客首購買得多、之後很少回來,就是可能被低估的一群,3.4 用預測做決策時要記得這一點。

還沒滿 30 天的人不能拿來訓練,例如 9/10 才首購的人,到 9/16 只觀察了 6 天,回購營收是 0 不代表他不會回來,只是還沒到時間,把這些人當成「不會回購」訓練,模型就會學到錯的東西,所以 ltv_features 用 label_complete 標出已經觀察滿 30 天的人,只有他們可以用來訓練和驗證。

訓練和驗證的切法也要照時間,已滿 30 天的 1,458 人依首購日期排序,最早的約八成(首購在 8/8 以前的 1,183 人)訓練,最晚的約兩成(8/9–8/17 的 275 人)驗證,同一天首購的人不拆開,隨機切的話訓練資料會混進比驗證顧客更晚首購的人,等於用未來預測過去,實際使用時永遠是用過去預測未來,驗證也要照這個方向,特徵的 SQL 在 ltv/features.sql。

整理完後,已滿 30 天的 1,458 人平均 30 天回購營收是 92.8 元,其中 25.2% 的人在 30 天內有回購,大部分人是 0,少數人回購好幾次,這種分布本身就不好預測。

3.2 先有基準線,再讓模型來比

在訓練模型之前,我先算兩個不用機器學習的猜法,第一個是全體平均,每個人都猜訓練集的平均 96.4 元,第二個是依首購商品平均,買同一項商品的人猜同一個數字,這兩條基準線是模型的及格線,模型的誤差要比它們小,才代表機器學習真的有幫上忙。

模型用 BigQuery ML 的線性迴歸,也就是把每個特徵乘上一個權重再加總,字串欄位像首購商品、來源、媒介,BigQuery ML 會自動拆成是或否的欄位,data_split_method = 'CUSTOM' 讓模型照 is_eval 欄位切訓練與驗證,而不是隨機切:

CREATE OR REPLACE MODEL martech_dw.ltv_linreg
OPTIONS(
  model_type = 'LINEAR_REG',
  input_label_cols = ['future_revenue_30d'],
  data_split_method = 'CUSTOM',
  data_split_col = 'is_eval'
) AS
SELECT
  first_item_id, first_qty, first_revenue,
  first_source, first_medium,
  future_revenue_30d, is_eval
FROM martech_dw.ltv_features
WHERE label_complete;

活動代號沒有放進來,原因在第 6 章說明,三種方法在驗證集 275 人上的誤差如下,MAE 是平均絕對誤差,也就是平均猜錯多少元,RMSE 會放大猜錯很多的情況:

方法 MAE RMSE 平均預測 平均實際
① 全體平均 131.0 171.8 96.4 77.4
② 依首購商品平均 111.4 161.8 104.8 77.4
③ 線性迴歸 110.9 160.8 102.4 77.4

線性迴歸比全體平均好很多,但只比「依首購商品平均」少猜錯 0.5 元,也就是說加上來源、媒介、件數、金額之後,準確度幾乎沒有進步,模型能用的資訊幾乎都來自「買什麼」,ML.EVALUATE 回傳的 R²(模型解釋了多少變異,1 代表完全解釋)只有 0.113,看起來很低,但只看 R² 會誤以為模型沒用,和基準線比才知道它比全體平均好,只是幾乎沒有比最簡單的分組平均好。

三種方法的平均預測都比實際高,驗證期這批顧客實際的回購營收平均 77.4 元,比訓練期的 96.4 元低,模型用過去的平均水準去猜,碰到回購比較少的一批人就會整體高估,這也是依時間切才看得到的問題,隨機切的話訓練和驗證混在一起,平均水準差不多,這個落差就被藏起來了。

3.3 揭曉答案表:買襪子的沉睡客,模型分不出來

合成器藏進去的四種顧客是高頻買襪客、浴巾大量客、新手組合客和沉睡客,答案表裡寫的回購節奏是高頻買襪客每次約 75% 的機率回購、平均隔 25 天,新手組合客 35%、隔 40 天,浴巾大量客只有 10%、隔 60 天,沉睡客買完第一次就不會再回來,Day 12 只有揭曉用的 reveal.sql 和檢查第 9 項的 check.sql 會讀答案表,下表是驗證集 275 人:

真實類型 人數 平均預測 平均實際 30 天內回購比例
高頻買襪客 84 169.9 244.8 67.9%
沉睡客 116 103.4 0 0%
新手組合客 44 17.1 16.4 9.1%
浴巾大量客 31 39.6 0 0%

表中四種類型在答案表(reveal.sql 的輸出)裡的英文分別是 sock_regular、dormant、starter_new、bath_bulk,reveal.sql 第一段另外還會印出新客 1,003 人的平均預測。

高頻買襪客的平均預測最高,是其他三種顧客合計平均(73.2 元)的 2.3 倍,方向是對的,但實際值比預測還高。

浴巾大量客在驗證集裡 30 天內都沒有回購,他們回購的機率本來就低,就算回購也要隔 60 天左右,30 天的標籤看不到,這是 3.1 說的觀察期代價,和模型準不準是兩回事。

最大的問題在沉睡客,實際是 0,模型卻平均猜了 103.4 元,拆開首購商品來看就知道原因,下表包含驗證集與新客共 1,278 人:

首購商品 真實類型 人數 平均預測
日常中筒襪 高頻買襪客 282 178.5
日常中筒襪 沉睡客 131 173.6
厚底毛巾訓練襪 高頻買襪客 136 157.9
厚底毛巾訓練襪 沉睡客 114 149.6
純棉大浴巾 浴巾大量客 164 38.3
純棉大浴巾 沉睡客 49 33.3
日常入門組合 新手組合客 266 16.7
日常入門組合 沉睡客 66 18.9
純棉洗臉毛巾 沉睡客 70 4.3

同樣第一次買日常中筒襪,高頻買襪客和沉睡客拿到的預測只差 5 元,因為兩種人的第一筆訂單幾乎一樣,高頻買襪客只是平均多買一點件數,這個差別太小,模型只看得到第一筆訂單,幾乎只能給他們同一個平均值,這和 Day 11 分不出沉睡客是同一件事,差別只在後來有沒有回來,而首購當下還沒有後來。

所以這個預測值應該讀成「模型估計買中筒襪進來的新客,平均 30 天會再帶來約 177 元」,而不是「這位顧客會再花 177 元」,拿來比較一群人的價值沒問題,拿來判斷單一顧客就不準。

3.4 預測值變成廣告決策

有了每位新客的預測,就可以回答哪種客人值得多投廣告,我取首購在 8/18–9/16 的新客,依首購訂單的通路與活動分組,預期 30 天價值是首單金額加上模型預測的回購營收,取得成本是同期這個通路這個活動的廣告花費除以新客數,兩個相除就是每花 1 元能在 30 天內換回多少營收:

通路 活動 新客數 取得成本 首單 預測回購 價值 ÷ 成本
Google 搜尋 常態 141 354 元 817 元 88 元 2.56
Google 搜尋 秋日棉織 71 348 元 797 元 57 元 2.45
Google 搜尋 重訓襪 124 316 元 598 元 121 元 2.27
LINE 重訓襪 57 783 元 576 元 138 元 0.91
Meta 常態 59 951 元 775 元 82 元 0.90
LINE 秋日棉織 27 941 元 766 元 70 元 0.89
LINE 常態 45 1,038 元 681 元 89 元 0.74
Meta 秋日棉織 34 1,114 元 741 元 65 元 0.72
Meta 重訓襪 79 1,651 元 559 元 128 元 0.42

活動欄對應的 utm_campaign 是 evergreen、autumn-cotton、training-socks,重訓襪是「重訓襪專案」,秋日棉織是「秋日棉織專案」。

重訓襪專案帶進來的新客,在三個通路的預測回購都是最高的(121–138 元),模型沒有用活動當特徵,這個差距主要來自首購商品,重訓襪專案的新客有 73.8% 首購襪子,答案表裡重訓襪專案確實把高頻買襪客的權重調成兩倍,此外這個活動的商品只有兩款襪子,被活動帶進來的沉睡客首購的也都是襪子,模型一樣給他們高分。

重訓襪專案的新客首單最低、預測回購最高,兩者抵銷了一部分,但除了 LINE 以外,每花 1 元換回的營收仍然是同通路裡最低,LINE 裡則從只看首單時的第二名升到第一名,和秋日棉織專案只差 0.02,人數也少,還不足以下結論。

表上看起來最划算的是 Google 搜尋,每花 1 元換回 2 元以上,最不划算的是 Meta 的重訓襪專案,取得一位新客要 1,651 元,30 天只換回 687 元,但這張表有四個限制,讀的時候要一起考慮:

  1. 通路用的是最後接觸:新客的通路取自首購訂單的 utm,Day 08 分析過,Meta 多半出現在購買路徑的開頭、Google 搜尋多半在最後一步,這張表會高估 Google 搜尋、低估 Meta,直接砍掉 Meta 的話,Google 搜尋能收割的顧客可能也會跟著變少
  2. 取得成本是粗算:同期這個通路這個活動的花費全部算在新客身上,但 Meta 和 LINE 還有打給舊訪客的再行銷廣告,Google 搜尋沒有,Meta 和 LINE 的取得成本會偏高,另外 Day 09 找到 Meta 重訓襪專案的開發新客廣告從 8/12 起點擊成本變成兩倍,整段 8/18–9/16 都在這個期間內,0.42 有一部分是競價變貴造成的
  3. 只算 30 天:新手組合客和浴巾大量客回購間隔比 30 天長,他們的價值被低估,首購組合或浴巾比例高的活動會吃虧,例如秋日棉織專案的商品包含日常入門組合
  4. 只算營收不算毛利:價值 ÷ 成本大於 1 也不代表賺錢,毛利率 50% 的話要大於 2 才打平,小於 1 則代表 30 天內營收都還不夠付廣告費

所以這張表比較適合回答「同一個通路裡,哪個活動帶來的客人比較好」,同一個通路內最後接觸和再行銷的影響差不多,但只算 30 天的偏差還在,Meta 重訓襪專案還要扣掉競價變貴的影響,回購間隔長的活動要打個折扣看,跨通路的比較則要搭配 Day 08 的歸因一起看。


4. FinOps 成本防護實踐:三道防線體系

  1. 第一道防線:善用 Google Cloud 每月免費額度:ML.EVALUATE、ML.PREDICT 和一般查詢一樣含在每月 1 TiB(約 1 兆位元組)的免費額度內,CREATE MODEL 不在免費額度裡,線性迴歸和 K-means 一樣是 BigQuery 內建模型,每 TiB 312.5 美元
  2. 第二道防線:架構層被動成本防護:特徵表一人一列只有 2,461 列,建模型實際處理約 0.15 MB,照每個查詢最低 10 MB 計費,每個模型約新台幣 0.1 元、實際執行 17 到 19 秒,開發時和寫文章前重跑各建了正式模型與第 6 章的對照模型,共 4 個約新台幣 0.4 元,我選線性迴歸而不選提升樹(Boosted Tree),是因為提升樹、隨機森林、深度神經網路在 BigQuery ML 裡屬於外部模型,實際在 Vertex AI(現名 Gemini Enterprise Agent Platform)訓練,BigQuery 的處理費雖然比較低,但要另外加上訓練費,官方文件也提到部分模型類型在訓練完成前 dry run 估不出處理量,事前比較難掌握要花多少
  3. 第三道防線:Cloud Billing 預算警報:沿用 Day 03 由 Terraform 建立的預算警報(新台幣帳戶 NT$ 300/美元帳戶 US$ 10),50%、80%、100% 三段通知,今天的操作不會觸發

3.2 已經看到線性迴歸只比依首購商品平均好一點點,換成更複雜的提升樹,也很難從「買什麼、從哪來」這幾個欄位擠出更多資訊,資訊不夠時換成要另付訓練費的模型通常只是多花錢,先用基準線確認還有沒有進步空間,再決定要不要升級模型。


5. Cloud Shell 實戰演練:一行指令從首購預測到揭曉

5.1 事前準備

  • 已完成 Day 07,martech_dw 裡有 fct_orders 和 fct_ad_daily
  • 揭曉要用的答案表 martech_gt:Day 11 載入過就可以直接用,沒有的話 Cloud Shell 裡要有 Day 05 合成器的答案檔 synthesizer/out/ground_truth/,run.sh 會自動載入
  • 確認 gcloud 有登入中的帳號,輸入 gcloud auth list,帳號前面要有星號

5.2 路線 A|懶人包:一行指令從特徵到揭曉

cd ~/ai-driven-martech-pipeline && git pull && bash ltv/run.sh

畫面先印出特徵摘要與預估費用,輸入 yes 後依序會看到模型評估、基準線比較、10 項檢查、通路與活動價值表和揭曉對照表,想重現第 6 章「沒看過的活動」加上 --unseen,會多建一個對照模型,約多花新台幣 0.1 元,最後多印一張兩個模型的對照表。

5.3 路線 B|逐步教學:理解每一個步驟

步驟 1:整理首購特徵

cd ~/ai-driven-martech-pipeline
git pull
bash scripts/load_ground_truth.sh
bq query --nouse_legacy_sql < ltv/features.sql

第三行是載入答案表,Day 11 做過的話可以略過,features.sql 最後會印出已滿 30 天 1,458 人、驗證集 275 人、待預測 1,003 人、訓練到 8/8、平均 30 天回購營收 92.8。

步驟 2:建模型並和基準線比較

bq query --nouse_legacy_sql < ltv/model.sql
bq query --nouse_legacy_sql --format=pretty < ltv/evaluate.sql
bq query --nouse_legacy_sql --format=pretty < ltv/baseline.sql

建模型不到一分鐘,evaluate.sql 印出 MAE 110.9、R² 0.113,baseline.sql 印出 3.2 的三種方法比較。

步驟 3:預測並算出價值表

bq query --nouse_legacy_sql < ltv/predict.sql
bq query --nouse_legacy_sql --format=pretty < ltv/value.sql

mart_customer_ltv 會有 1,278 列,其中驗證集 275 列、新客 1,003 列,預測是負數的會截成 0。

步驟 4:揭曉

bq query --nouse_legacy_sql --format=pretty < ltv/reveal.sql

第一段是依真實類型的平均預測與實際,第二段是首購商品 × 真實類型。

5.4 驗證成果

  • ltv_features 2,461 列,已滿 30 天 1,458 人,驗證集 275 人,訓練集的首購日期都早於驗證集
  • 線性迴歸的 MAE 比全體平均小,高頻買襪客的平均預測是其他類型的 1.5 倍以上
  • run.sh 的 10 項檢查全部通過,其中一項會確認特徵、模型、預測與價值表的 SQL 都沒有讀 martech_gt

5.5 用完後怎麼處理

bq rm -f -m martech_dw.ltv_linreg
bq rm -f -m martech_dw.ltv_linreg_campaign

第二行是用了 --unseen 才需要,模型和表都很小,在每月 10 GiB 的免費儲存額度內,mart_customer_ltv 明天的驗收會用到,建議保留,模型刪掉之後要重建才能替新顧客預測,重建一次約新台幣 0.1 元。


6. 工程實務避坑指南

  1. 未來的資訊不能當特徵:Day 11 的分群、訂單數、回購間隔都是首購之後才知道的事,放進特徵驗證分數會很好看,實際上新客根本沒有這些資料
  2. 觀察期不夠的人不能訓練:首購不滿 30 天的人回購營收是 0,只是還沒到時間,混進訓練資料會讓模型低估所有人
  3. 依時間切訓練與驗證:隨機切會讓訓練資料混進比驗證顧客更晚的人,等於用未來預測過去,今天驗證期的顧客回購比訓練期少,隨機切就看不到模型會高估
  4. 只看 R² 不比基準線:R² 0.113 看起來很差,但模型比全體平均好 20 元,反過來說,模型只比依首購商品平均好 0.5 元,沒有基準線就不知道複雜的模型其實沒幫上忙
  5. 訓練資料沒出現過的類別:我一開始把活動代號也放進特徵,但秋日棉織專案 9/1 才開始,訓練資料(首購 8/8 以前)完全沒有這個值,同一批秋日棉織專案的新客依首購商品分組,這個模型預測的 30 天回購平均是 746 到 927 元,拿掉活動代號的正式模型是 -12 到 174 元(負數是還沒截成 0 的原始預測),模型碰到沒看過的類別不會報錯,只會安靜地給出離譜的數字,用 bash ltv/run.sh --unseen 可以重現這個對照
  6. 平均預測不是個人保證:同樣首購中筒襪的高頻買襪客和沉睡客預測只差 5 元,預測值適合比較一群人,不適合判斷單一顧客
  7. CREATE MODEL 不在免費額度內:每建一個模型至少收 10 MB,反覆調特徵重建模型時,每一次都會計費

7. 總結與明日預告

今天只用第一筆訂單當下就知道的資訊,用 BigQuery ML 線性迴歸預測新客接下來 30 天的回購營收,模型比全體平均好很多,但幾乎只學到「買什麼」,和依首購商品平均差不多,揭曉之後高頻買襪客的平均預測最高,方向正確,但買襪子的沉睡客和高頻買襪客首購幾乎一樣,模型分不出來。

回到篇名,把預測值換算成每花 1 元換回多少營收之後,重訓襪專案的新客首單最低、預測回購卻最高,只看首單金額會低估他們,但這張表同時帶著最後接觸、粗算取得成本、只看 30 天三個偏差,也還沒扣毛利,最適合用在同一個通路內比較活動,跨通路的預算分配要搭配 Day 08 的歸因一起看。

明日預告:Day 13《先把答案藏好再來考 AI,看它能找回幾個》,Day 08 到今天,我們一路從合成資料裡找回 Day 05 藏進去的訊號,明天把這些訊號當成考卷,先把判準寫死再看成績,整理出一張成績單,再做一次不給任何提示的 AI 盲測,看它自己能找回幾個!


上一篇
Day 11 | 讓資料自己分組,才發現你的顧客其實只有這幾種人
下一篇
Day 13 | 先把答案藏好再來考 AI,看它能找回幾個
系列文
AI-Driven MarTech:用 Google Cloud + Vertex AI 打造全自動廣告歸因與多模態素材分析系統 共 18 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言