iT邦幫忙

2024 iThome 鐵人賽

DAY 13
1

https://ithelp.ithome.com.tw/upload/images/20240927/20168816aI95VeojPi.png

『如果可以,我想和你回到那天相遇』(韋禮安,2021)

「與當時查出來的資料面貌再次相遇」在資料的世界,可能嗎?這和軟體工程,又有什麼牽連?

為什麼需要重現 (reproduce)?


我們曾經提過,資料倉儲是一個 OLAP 系統,常用於生成報表、執行多維資料分析,並提供關鍵決策的支援。如果資料分析的結果在不同時間點產生不一致的結果,會導致錯誤的解讀或決策。
在以下幾種資料分析的情況,資料可重現性都至關重要。

  • 保持資料分析的一致性與可靠性
    以網購服務公司為例,七月上旬在 OLAP 系統中產出 2024 年第二季的銷售分析報告,十月中旬時,要重新產製第二季的報表與第三季比對,卻發現第二季的結果與上次不同了,那麼管理層將難以信任報告資料。
  • 歷史情況的回溯與排查
  • 法律上合規和審計需求 (審計查核日與帳務發生日有一段距離)

在機器學習的領域上,資料的可重現性也是重要的。它能夠確保模型的訓練、測試和評估過程的一致性。以下場景是為什麼可重現性在機器學習中如此關鍵的幾個原因:

  • 模型的公平性與評估準確性
    模型的評估是通過訓練集和測試集的數據進行的。當研究者重新進行訓練過程時,若使用相同的資料集,應該要得到一致的結果。
    例如 Data Scientist 希望對比 SVM 與 Random Forest 的效能,若每次執行時資料分群或處理的結果不同,則無法重現相同的訓練集和測試集,比較結果將無法具有信服力。
  • 模型訓練過程的可重現性
    模型訓練的過程往往涉及到超參數調整、特徵工程、資料前處理等。如果這些步驟的結果無法重現,後續的模型訓練結果可能會大幅不同,導致模型的表現變化很大。
    例如模型的訓練需要多次調整學習率、正規化等超參數。每次調整都應該在相同的基礎上進行比較。若資料前處理過程每次都不同,訓練結果無法對比,將無法判斷哪個超參數組合效果最好。
  • 錯誤排查
    發現模型在某些特定情況下效能不佳,於是試圖重新進行模型訓練來進行排查。如果每次的訓練結果因資料集變動而有所不同,將無從找尋問題。
  • 研究成果的驗證
    學術研究中,其他研究者需要能夠重現某個模型的訓練過程和結果,以檢驗該研究的有效性。如果資料或實驗環境無法重現,研究的可信度會大幅降低。

總結來說,資料可重現性在描述的是對同一份資料,我和別人做同樣的操作,獲取結果要一樣。我在今天和過去做同一個操作,獲取結果也要一樣。

任務編排的巧思


可重現性的概念不難理解,但和我們這幾天密切介紹的 Airflow 有什麼關係呢?
Day 08 提到的例子延伸,如果我們在 7/20 時,想要透過 Airflow 重新產製 7/1 的 RFM 分析報表,得要確認分析上游的訂單表 orders 及顧客表 users 都是 7/1 當日的情況。
在一張增量表中,每筆源頭資料的變動紀錄都會被保留下來,我們可以透過 重現當時的狀況了!但衍生兩個問題:
如何正確地選取資料,呈現「當天日期」?
每張表都可以重現當時的狀況嗎?

如何正確地選取時間?
https://ithelp.ithome.com.tw/upload/images/20240927/20168816eq9KlwQI2I.png
圖/DAG 執行日期與邏輯日期的差異。簡書廷製。

從這張圖我們可以掌握到,若想重新呈現 7/1 當時 fct_order 這張增量表的狀況,得先確定是 7/1 開始時還是結束時。

假設是 7/1 結束時的狀況,那就是針對 7/1 00:00 ~ 23:59 這段區間的增量匯入結束為截止線,選取 fct_order 截止線以前的資料使用 window funtion 去除重複 order_id 資料,即可重現 OLTP 裡面的 orders 當時狀況!

--- 增量
WITH orders AS (
    SELECT
        order_id,
        ...,
        ROW_NUMBER() OVER(
            PARTITION BY order_id ORDER BY _processed_at DESC
        ) AS rn
    FROM
        `fct_orders`
    WHERE
        資料時間篩選條件
)
SELECT
    ...
FROM
    orders
WHERE
    rn = 1

資料時間篩選條件的候選寫法:

  • (A) _processed_at <= '{{ logical_date }}' 
  • (B) _processed_at <= '{{ data_interval_start }}' 
  • (C) _processed_at < '{{ data_interval_end }}' 
  • (D) _processed_at < datatime.now()

用 (D) 的 Python datatime 套件作為時間篩選條件,會讓時間線無法重回「當時」,因為 datatime.now() 指的是系統當下時間。只有 (A)(B)(C) 能幫助我們在 7/20 時,透過 Airflow 的 Backfill 重新產製 7/1 的 RFM 分析報表。

airflow dags backfill \
    --start-date START_DATE \
    --end-date END_DATE \
    dag_id

用 Airflow 來做工作流程設計時,別忘了善用 jinja template 參數化 的功能處理 **批量 (batch) ** 特性的資料。若用一般軟體開發的思路進行,用了不適當的時間條件,那 Airflow 就只能做為一個不具資料可重現性的排程器了!

每張表都可以重現當時的狀況嗎?
答案是否定的。如果資料倉儲內每一張表都設計的像 OLTP 一樣,只呈現「事務的最新狀態」,那資料一但被更新就是直接覆蓋寫入,怎麼 query 也回不去了。
因此源頭資料進來後,至少得有一張表做增量或全量的匯入,不能覆蓋任何的歷史,這樣才保有日後需要進行資料回溯時的可重現性。

後記:可重現性(reproducibility)和冪等性(idempotency)


今天提的都是「資料」的可重現性。而軟體工程上,RESTful API 談到的冪等性,指的是指多次對同一資源進行相同的操作,不會導致系統狀態的變化。例如 HTTP method 裡的 GET 操作。

有趣的是,RESTful API 搭配 OLTP 系統下,雖然 GET 操作不會改變該資料的狀態,但是 OLTP 的特性是只呈現事務的最新狀態,一旦該資料被其他請求改變了,下一次 GET 時,就無法重現資料先前的狀況了!

*註:今天並非討論資料庫本身的援備及回溯機制,或應用程式的歷程紀錄。


上一篇
《資料與程式碼的交鋒》Day 12-任務相依性設計
下一篇
《資料與程式碼的交鋒》Day 14-開發環境
系列文
資料與程式碼的交鋒 - Data Engineer 與合作夥伴的協奏曲 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言