摘要:本文整理自阿里巴巴演算法專家趙偉波,在 Flink Forward Asia 2023 AI特徵工程專場的分享。本篇內容主要分為以下四部分:
- Flink ML 概況
- 線上學習的設計與應用
- 線上推理的設計與應用
- 特徵工程演算法與應用
一、Flink ML 概況
Flink ML 是 Apache Flink 的子專案,遵循 Apache 社群規範,願景是成為實時傳統機器學習的事實標準。
2022年1月份 Flink ML API 釋出,7月份釋出完備、高效能的 Flink ML 基礎設施,2023年4月份發力特徵工程演算法並服務使用者,6月份支援 Flink 多版本。
二、線上學習的設計與應用
2.1 線上機器學習工作流樣例
有兩個模型AB,用 online 線上學習的方式去訓練這兩個模型,並且使用模型去進行線上推理,在推理過程中這個模型是流動形式,叫做 Model stream (模型流),以模型流的方式將模型不斷地流入鏈路中,使模型具有更好的實時性。推理結束之後,推理樣本會推薦給一些前方的客戶,客戶對結果進行反饋,再進行一些樣本的拼接,最後返回到訓練的資料流形成閉環,這就是工作流樣例。
接下來以工作流樣例來介紹線上學習的設計。訓練資料進行切分後,切成不同的 window,每個 window 在經過 Estimator 的時候需要更新裡面的模型,之後該模型會流到下面推理的鏈路中,隨著資料的不斷流入,模型會一個接一個的往推理的鏈路中流動,這就是 Model stream(模型流),其思路是透過把模型做成一個佇列的方式去支援推理以達到更好的時效性。
存在的問題:
- 如何使資料拆分更加合理?對不同的業務有不同的要求,有的希望用時間,有的希望用大小,都需要一些策略。
- 因為資料和模型都是流動的,兩個往同一個地方去流,那麼如何決定一條樣本來了之後用哪個模型進行推理?
- 如何保證模型的一致性?因為鏈路中有兩個模型,如果兩個模型的訓練資料不一致會導致出現一些問題。
- 資料是用哪一個模型推理出來的?每一條樣本是哪個模型推理出來的,預測的好壞需要去追溯源頭。
2.2 線上機器學習的設計
針對四個問題,有四條設計需求:
- 支援將輸入資料劃分為多個 window 進行訓練,產生一個模型流。
- 支援使用輸入的模型流來對資料進行預測。
- 支援使用者指定推理資料和當前模型資料的時間差。每一條樣本來了之後,我們希望用最新的模型去進行推理,但是最新的模型可能還沒有訓練出來,這個時候就需要設定一個時間差,允許它用非最新的模型進行推理。
- 支援在輸出資料中暴露預測每條資料時使用的模型版本。從預測結果追溯出模型的需求。
針對這些需求,我們的設計方案是:
- 增加 HasWindows 介面。
允許使用者宣告劃分資料的不同策略。 - 為 ModelData 增加 model version 和 timestamp。
model version 的值從 0 開始,每次增加 1。
模型資料的時間戳為訓練得到該模型的資料的最大時間戳。 - 增加 HasMaxAllowedModelDelayMs 介面。
允許使用者指定預測資料 D 時,使用的模型資料 M 早於 D 的時間小於等於設定的閾值。 - 增加 HasModelVersionCol 介面。
推理過程中,允許使用者輸出預測每條資料時使用的模型版本。
有了方案之後再回來看問題:
- 怎麼切分 window:
提供 window 策略,使用者可以根據自己的需求去做一些適合自己業務場景的切分。 - 選擇哪一種模型來推理當前資料:
透過閾值引數設定允許離當前資料多遠的模型進行推理;理論上可以用最新模型,但是可能會造成等待之類的問題。 - 關於模型的一致性:
每一條樣本在預測的時候都會帶一個模型版本,經過第一個模型預測再到第二個模型推理的時候會自動獲取版本號,兩邊用同樣的版本進行推理,最後輸出的結果會帶有一個版本號。
這樣就把最初提的四個問題解決了。
2.3 線上學習在阿里雲實時日誌聚類的應用
阿里雲 ABM 運維中心會把阿里所有平臺的日誌都收集到一起,然後會針對錯誤日誌做一個聚類,把錯誤日誌傳送到對應的部門,去進行後續的處理。
傳統演算法工程鏈路首先進行資料輸入,用 Flink job 進行資料加工處理,資料會落盤,之後透過定時排程來拉起聚類演算法,然後寫出模型,這個模型再透過載入的方式拉起 Flink job 進行資料預測,但是整個鏈路具有侷限性,流程比較複雜,運維成本比較高,實時性低,並且效能難以保證。
日誌聚類演算法流程把系統日誌進行預處理和編碼後分詞,做特徵選擇提取關鍵詞,然後做日誌的特徵表示和標準化,再做層次聚類,日誌的類別,最後寫出到資料庫,用來指導分詞。
針對該流程我們使用 Flink ML 構建流式日誌聚類就可以把這個流程串起來。透過 Flink job 拼接 SLS 與資料庫全量資料,接著進行清洗和編碼日誌資料,然後分詞和標準化,計算聚類結果,最後選取簇內典型代表日誌。
把這個案例中的運算元進行抽取,像 SLS 流式讀取,分詞,日誌的向量化,特徵選擇,特徵的標準化,這些並不是業務獨有的,而是很多線上學習業務都需要的運算元,把它抽取出來,做成一個獨立的元件,客戶需要做線上學習流程的時候可以來複用這些運算元。
日誌聚類演算法鏈路升級的收益:
- 在鏈路延遲方面,將原來 5 min 的延遲降低到 30s
- 運營成本降低,現在只需要維持 1 個 Flink 作業
- 分析成本降低
- 演算法效能提升
三、線上推理的設計與應用
推理主要分為:
- 批次推理:例如,有 100w 條資料落盤,然後起一個批的任務對這100萬條資料進行推理,再進行落盤。
- Near-line (近線)推理:基於 Flink 的任務,讀取 Kafka 資料,透過 Transformer 的方式對流式的資料進行推理。這種推理有一個比較大的問題是延遲比較高,一般在百毫秒量級,在實際的業務場景中,推理需要很低的延遲,一般是幾十毫秒甚至幾毫秒,這就需要我們做一個推理框架去適應高要求的業務場景。
在做這個之前我們對 Spark ML 的推理進行了一個調研。後來發現 Spark ML 本身是沒有推理模組的,它有一個 mleap,把 Spark 推理這部分做成一個推理框架,這個推理框架與引擎 Runtime 完全無關,減少依賴衝突,是一個更輕量的框架,另外這個新框架可以為推理重寫計算邏輯程式碼,擁有更大的最佳化空間。
3.1 設計需求
設計需求借鑑了 mleap 的做法:
資料表示(與 Flink Runtime 無關)
- 單條資料表示:Row
- 批次資料表示:DataFrame
- 資料型別表示,提供 Vector、Matrix 等型別的支援
- 推理邏輯表示
模型載入
- 支援從 Model/Transoformer#save 的檔案中載入
- 支援動態載入模型資料,而不需要重啟
Utils
- 支援檢查 Transformer/PipelineModel 是否支援線上推理
- 串聯多個推理邏輯成單個推理邏輯
在這個設計需求下,左邊是推理的資料結構 DataFrame,包含了 Column names, Column types, Row,進入推理邏輯之後輸出還是同樣的資料結構,這樣整個推理結構就可以串起來,不需要有資料結構轉換。
模型載入這邊都是透過 save 函式將模型寫入到磁碟,左邊的 save 是 Flink ML 做的事情,右邊的 loadServable 是推理框架做的事情,透過這兩個函式實現了模型的儲存載入和推理。
接下來以邏輯迴歸為例來看程式碼的實現,透過 save 函式把模型寫出到指定的目錄,下面的 load 是推理框架做的事情,以 load 模型的檔案去做推理。
模型的資料更新這部分是透過把一個模型寫入到 kafka 裡面,kafka 再 set 到模型的 Servable 裡面,當把模型寫入到 kafka 裡的時候模型會自然而然的流入到 Servable 裡面,最終實現模型的動態更新。
下面是程式碼
setModelData 的輸入是 InputStream,它可以從 kafka 裡讀入,當更新 kafka 裡的資料時它就可以更新到模型裡面。
另外我們也支援 PipelineModel 推理,可以從 PipelineModel 的模型資料構建 Servable, 檢查 PipelineModel 是否支援線上推理,不需要執行訓練作業就能判斷。
3.2 使用場景
最後來看使用場景,這是一個簡化的 ML 模型訓練、預測和部署的流程。首先是讀入資料,做特徵工程,然後做評估和部署。這邊使用 PipelineModel 將標準化和 GBT 分類這兩個模型打到 Pipeline 裡面去,再去做線上的推理服務。
以下是程式碼
將標準化和 GBT 兩個模型透過 Pipeline 寫出去,在推理模組中最終實現 Pipeline 的推理,並且推理支援寫出和動態載入。
四、特徵工程演算法與應用
4.1 特徵工程演算法
新增27個演算法,總共33個,基本覆蓋常用演算法。
4.2 特徵工程的應用
首先是做推薦,廣告的評估,都需要特徵的處理。第二個應用場景是用於實現一些複雜的演算法,以 GBT 為例,處理數值特徵和處理類別型特徵。另外在大語言模型這塊,Flink ML 也做了一些設計。
接下來以大語言模型為例,來看特徵工程的業務。高質量的文字輸入可以獲得更好的大語言模型,而文字近似去重能提高文字質量。對於網際網路資料來說,文字重複的比例通常 20%-60% 之間,文字規模越大,重複比例越高。
針對這個問題,我們設計了近似去重流程:
- 不同於精確去重:不要求完全一致,或者子串關係
- 基於區域性敏感性雜湊 Locality-sensitive hashing:相似的樣本更容易被 Hash 到相同的 buckets 內
- 對於文字資料來說,通常基於文字特徵化後的 Jaccard 距離,使用 MinHashLSH 來找到相似文字
透過這些元件,可以完成文字去重流程:
- Tokenizer:進行分詞
- HashingTF:將文字變換為 Binary 特徵
- MinHash:計算文字簽名
- MinHashLSH:進行 SimilarityJoin,找到相似對
最後是效能的測試,這是手動構造的 Benchmark 資料集,直接透過複製、刪除之類的操作拿到一個資料集。對於5億的資料,重複率為 50%,耗時大概 1.5h,後面是對應的去重效果。
Flink Forward Asia 2023
本屆 Flink Forward Asia 更多精彩內容,可微信掃描圖片二維碼觀看全部議題的影片回放及 FFA 2023 峰會資料!
更多內容
活動推薦
阿里雲基於 Apache Flink 構建的企業級產品-實時計算 Flink 版現開啟活動:
59 元試用 實時計算 Flink 版(3000CU*小時,3 個月內)
瞭解活動詳情:https://free.aliyun.com/?pipCode=sc