從軟體哲學角度談 Amazon SageMaker

亞馬遜雲開發者發表於2023-05-03

如果你喜歡哲學並且你是一個 IT 從業者,那麼你很可能對軟體哲學感興趣,你能發現存在於軟體領域的哲學之美。本文我們就從軟體哲學的角度來了解一下亞馬遜雲科技的拳頭級產品 Amazon SageMaker,有兩個出發點:一是 SageMaker 本身設計所遵循的軟體哲學;二是從軟體哲學的角度我們應該如何使用 SageMaker 提供的功能。SageMaker 是一個全託管的機器學習平臺(包括傳統機器學習和深度學習),它覆蓋了整個機器學習的生命週期,如下圖所示:

亞馬遜雲科技開發者社群為開發者們提供全球的開發技術資源。這裡有技術文件、開發案例、技術專欄、培訓影片、活動與競賽等。幫助中國開發者對接世界最前沿技術,觀點,和專案,並將中國優秀開發者或技術推薦給全球雲社群。如果你還沒有關注/收藏,看到這裡請一定不要匆匆劃過,點這裡讓它成為你的技術寶庫!

我們從如下的幾個方面來展開討論:

  • 天下沒有免費的午餐——權衡之道
  • 簡單之美——大道至簡
  • 沒有規矩不成方圓——循規蹈矩
  • 沒有“銀彈”——對症下藥
  • 變化之本——進化本質
  • 知其所以然——心中有數
  • 保持一致性——質量可控

天下沒有免費的午餐——權衡之道

軟體有很多的品質(品質也叫非功能性需求):效能(比如時間效能,空間效能,模型效能),可用性,易用性,可擴充套件性,相容性,可移植性,靈活性,安全性,可維護性,成本等。一個軟體沒有辦法滿足所有的品質,因此我們在和使用者交流的過程中,要真的弄清楚使用者想要的是什麼(沒有想象中那麼簡單),哪個或者哪些軟體的品質是使用者當前最關心的。很多軟體品質經常會互相制約(一個經典的例子就是安全性和時間效能,安全這個品質就是一個讓人又愛又恨的東西,一般來說需要加入安全性的時候,在其他上下文不變的情況下,基本上時間效能就會變差了),所以我們需要權衡,而在權衡的時候一定要把握好“度“。

對於 SageMaker 來說:

  • SageMaker Processing job 要求資料的輸入和輸出都需要在 S3,基本原理圖如下:

SageMaker Processing job 提供了託管的單個例項或者叢集來做資料預處理,特徵工程以及模型評估。如果你的原始資料並沒有存放在 S3,這個時候你需要權衡空間效能與可託管性(可託管性的好處是很多運維的工作就不需要你關心了,交給了亞馬遜雲科技來運維),是把資料從源複製到 S3 來使用託管的 Processing job 服務還是就地來用自建的叢集來處理;如果你的原始資料本身就存放在 S3,那麼直接用 Processing job 來使用 SkLearn 或者 SparkML 來進行資料預處理或者特徵工程是你的首選。

  • SageMaker 的內建演算法對資料輸入格式的要求以及可配置的有限的超引數。SageMaker 提供的內建演算法(SageMaker 對常見的 ML 任務基本都提供了一種或者多種演算法)對資料輸入格式的要求以及提供的超引數可能與開源界的演算法的資料輸入格式和提供的超引數略有區別。這裡你需要權衡易用性與靈活性:如果你只是想實現一個 ML 的任務並且不想關注演算法的實現細節,那麼可以優先嚐試 SageMaker 的內建演算法;如果你想更深入瞭解演算法的實現細節以及更靈活的超引數設定,那麼建議的選擇是把你的演算法或者開源的演算法遷移到 SageMaker 中。
  • SageMaker 訓練時的 HPO 自動超引數最佳化功能的使用。自動超引數最佳化的初衷是為了減輕演算法工程師/資料科學家/應用科學家們手工調參的痛苦。SageMaker 的 HPO 自動超引數最佳化對於內建演算法和非內建演算法都支援,並提供了貝葉斯搜尋和隨機搜尋兩種方式供你選擇。不是所有的演算法都需要走自動超引數調優,需要權衡模型效能(就是指模型效果)與成本。一般來說,對於深度學習模型或者海量資料集的情況下可能做自動超引數調優的時間代價和成本代價太大。因此在實際的 ML 專案中,使用者很少對深度學習模型或者海量資料集做自動超引數調優;對於傳統的機器學習模型並且在資料集不大的情況下,可以考慮用自動超引數調優來找到可能的最優解。
  • SageMaker 內建的 inference pipeline 的資料流。SageMaker Inference pipeline 可以把多個容器(容器中可以跑特徵處理邏輯或者跑模型 serving 邏輯)串接起來,它的目的是把推理時的特徵處理模組和模型串接起來,或者把多個模型做成上下游串接起來。它的資料流是這樣的:

也就是說,每個容器的輸出由 SageMaker 內部元件做中轉,該元件把上一個容器的輸出做為新的 request 傳送到下一個容器。透過使用 Inference pipeline 這個功能可以簡單方便的實現模型的上下游串接或者特徵處理模組和模型的串接,但從上面的資料流可以看到會帶入一些延遲,這個時候你需要考慮延遲是否在可以接受的範圍內並使用 Inference pipeline,也就是需要權衡易用性與時間效能

  • SageMaker 中對於 Tensorflow 和 Pytorch 兩種框架都提供了多種訓練方式。訓練方式包括開源框架原生的方式以及 SageMaker 專門實現的針對這兩種框架的資料並行和模型並行兩種方式。SageMaker 的資料並行訓練方式適合每個 GPU 卡可以跑完整的模型訓練但是資料集是海量的情況;SageMaker 的模型並行訓練方式適合單個 GPU 卡無法直接跑模型訓練的情況(比如模型太大了)。也就是說,在海量資料集大規模訓練或者超大模型訓練的場景,使用 SageMaker 的這兩種專有的訓練方式比框架原生的訓練方式會更高效,但是使用 SageMaker 的資料並行和模型並行的訓練方式的話,對於框架的版本有要求並且需要一定的程式碼修改,因此需要你權衡程式碼的可移植性與時間效能。

簡單之美——大道至簡

“簡單”可能的含義有很多,比如精簡,簡樸,可讀性好等。“簡單”的度量標準可能每個人的理解都不一樣,但是一個通用的原則是,“您”在設計軟體的時候儘量多想著:“軟體需要別人來用,還需要別人來迭代和維護”,您一定要高抬貴手。“簡單”的對立面就是“複雜”,業界的共識是透過降低複雜度來得到高質量長生命期的軟體,而如何降低複雜度是每個軟體設計人員以及開發人員無時無刻需要關注的事情。

在 SageMaker 中的體現:

  • SageMaker 是基於 container 的設計,到目前為止沒有選擇 Kubernetes。在當前業界大興 Kubernetes 的情況下,SageMaker 並沒有隨大流。Kubernetes 的功能很強大但是很複雜,對於 SageMaker 來說,很多 Kubernetes 的功能用不上,那麼為了減少軟體依賴以及降低複雜度,SageMaker 選擇了更輕量的設計(殺雞真的沒有必要用牛刀)。
  • SageMaker high level API(high level API 指的是SageMaker Python SDK,這個 API 的使用習慣類似常見的 ML 框架比如SKLearn)設計很簡潔,類層次也很清晰(分層就是一種降低複雜度的方法),很多 feature 透過簡單的引數設定就能搞定。比如透過簡單的設定distribution 引數就把底層複雜的分散式環境部署隱藏掉了(資訊隱藏也是降低複雜度的一種方法),讓 API 呼叫者的關注點更集中在訓練指令碼本身;比如簡單的設定模型的 S3 儲存位置,SageMaker 就會幫助你在訓練結束或者訓練中斷時把對應目錄下的模型壓縮打包並上傳到 S3 指定路徑;比如透過設定 git_config 引數,你就可以直接用 github 中的程式碼在 SageMake 中來訓練,而不需要你關心程式碼的拉取過程。
  • SageMaker 提供了多種演算法選擇:內建演算法,BYOS(基於預置的機器學習框架來自定義演算法),BYOC(自定義演算法設計並自己來打包容器映象)和第三方應用市場(在 Amazon Marketplace 中挑選第三方演算法包,直接在 Amazon SageMaker 中使用)。而 BYOS 和 BYOC 是 SageMaker 中實際用的最多的兩種選擇。那如何選擇 BYOS 和 BYOC?總的來說,優先看 BYOS 是否能滿足需求。BYOS 相對於 BYOC 要容易,需要遷移到 SageMaker 的工作量也少。而選擇 BYOC,常見的是如下的情景:

除了上面這些情景,儘量優先考慮 BYOS 的方式,它使用方式簡單,學習曲線也相對平緩。

  • SageMaker 提供了兩個可用於超引數的變數 sagemaker_program 和 sagemaker_submit_directory 來幫助你輕鬆的完成 BYOC 的除錯。前者告知 SageMaker 把這個引數的值作為 user entry point(就是使用者提供的需要 SageMaker 呼叫的指令碼),後者則是這個 entry_point 對應的程式碼以及它所依賴的程式碼打包(tar.gz)後的 S3 路徑。透過設定這兩個引數,在除錯程式碼的時候只是需要把修改後的程式碼重新打包上傳就可以,而不是每次都 build docker file,簡單方便而且很節省時間。

沒有規矩不成方圓——循規蹈矩

擁有豐富經驗的你可能聽過或者踐行過契約式程式設計,而契約式程式設計簡單說就是,你需要按照對方的一些約定來 coding。一般來說,只要是提供給別人使用的軟體/工具,或多或少都會有一些約定。SageMaker 從儘量減少程式碼侵入性和最小程式碼遷移工作量的思路出發,提供了很多約定。

在 SageMaker 中的體現:

訓練時,資料 Channel 相關的約定:

  • 訓練容器本地路徑相關的約定,如下圖所示:

我們重點關注下表中的四種路徑(除了下面這些路徑,訓練過程中放置在其他路徑下的檔案,在訓練結束後都會被丟棄):

SageMaker 給容器提供了很多方便使用的環境變數,包括 SageMaker 相關的和內建框架相關的。比如 SageMaker 相關的一部分環境變數如下:

SageMaker 內建的 TF serving 框架的 service side batch 相關的環境變數如下:

  • SageMaker 內建演算法對輸入資料格式的要求。SageMaker 內建演算法對輸入資料的格式要求可能和開源演算法對資料格式的要求不同,如果不注意這個,在除錯模型的時候可能會出現比較奇怪的結果。比如 SageMaker 目標檢測演算法對 BBOX 的格式要求如下:對於 json 格式的輸入標註檔案, 要求的座標格式是 [top, left, width, height],如果你的資料集的標註是PASCAL VOC 格式的(xmin,ymin,xmax,ymax)或者是 COCO 格式的(x,y,width,height),都需要做不同的轉換;對於 recordIO 格式的輸入檔案, 要求座標格式是相對座標,[xmin/width,ymin/height,xmax/width,ymax/height]。
  • Spot 例項與 SageMaker checkpoint 機制的配合。為了節省成本,使用 spot 例項進行訓練是首選。為了讓 spot 例項被回收對你的訓練任務造成的影響最小化,SageMaker 透過兩個引數 checkpoint_local_path 和checkpoint_s3_uri 來助你一臂之力(當然你不使用 spot 例項,也仍然可以利用 SageMaker 的 checkpoint 機制)。這樣訓練 job 被 spot 回收中斷以後並自動重新開始訓練後,就不用從頭開始訓練了,而是從最新的 checkpoint 開始接著訓練(SageMaker 提供了 checkpoint 上傳和下載的機制,你需要修改你的程式碼來配合,也就是你需要從約定的 checkpoint local 路徑來初始化你的模型引數,否則是空談),從而在節省成本的同時節省訓練時間。

沒有“銀彈”——對症下藥

可能我們自己腦海中或者遇到過別人問我們如下的問題:對於XX任務當前哪個模型效果最好?使用 AutoML 是不是就不需要我們做特徵工程和樣本工程了?自動超參調優是不是就徹底解放我們的手動超參調優了?如果真的是這樣的話,那就太美好了。在軟體界,“沒有銀彈”這句話流行很久了,對於人工智慧領域也是同樣道理,都需要 case by case 來分析每一個目標任務。

現在 Bert 以及 bert-like 的模型比如 GPT3,T5 等很火,恨不得只要是 NLP 的任務都用這樣的模型。我覺得還是應該至少要考慮具體的目標任務是什麼,目標任務的建模難度這兩個因素來進行模型選型。如果在語料充足的情況下,做一個簡單的文字分類任務,這個時候可能用一個簡單的模型比如 fasttext 來就夠用了,而不用 bert 模型做 fine tuning 這麼複雜;如果是針對使用者評論做細粒度情感分析任務,這個任務就很複雜了,用簡單模型就可能不合適了,這個時候用比如 T5 這樣的複雜模型才合適。盲目的追新和追熱點,受傷的是你的專案(可能你能從中受益)。

對於 SageMaker 來說:

  • SageMaker 有內建演算法,BYOS,BYOC 和 Marketplace 以及新出的 JumpStart 上面的演算法可供你選擇,總有一款適合你。很有意思的一個現象是,SageMaker 在剛釋出的時候 bulid 了17種內建演算法,很多年過後一直也沒有在增加新的內建演算法。我猜測 SageMaker 的開發團隊會認為,即使不斷的增加一些內建演算法,也沒有辦法及時對主流的一些演算法進行跟進。正是因為針對任何一種細分場景,沒有包治百病的“演算法”,SageMaker 就不在內建演算法上花費更多的時間和精力,它提供更靈活的 BYOS 和 BYOC 讓使用者把開源的演算法方便的遷移過來,或者透過 Marketplace 讓買家和賣家都能嚐到使用演算法的甜頭。
  • SageMaker 提供了 Autopilot 和 Auto model tuning(即自動超引數調優)這樣兩種 AutoML 機制。AutoML 一直是一個很熱門的研究方向,也是我們人類很期待的一個能大量落地的方向(誰不喜歡簡單省事就能完成一項任務呢?)。如果每個目標任務都可以用 AutoML 來解決的很好,那麼大部分人都可以騰出時間來攻克別的技術難題了。雖然 Autopilot 可以直接對結構化資料來建模,它也能自動做一些特徵處理,但是它並不是銀彈,不是什麼資料集直接丟給它就能出一個不錯的效果的;要使用 Autopilot,自己提前做一些特徵工程可能效果會更好(比如特徵縮放,特徵生成,特徵交叉,甚至不同的缺失值處理方法,異常值處理等)。

而對於自動超引數調優,如果使用預設的超引數搜尋空間,時間成本和金錢成本太大,那麼還是需要人工首先限定每個需要搜尋的超引數的區間的左右端點,同樣這裡沒有“銀彈”,左右端點的確定要麼根據已有的經驗,要麼就是透過實驗來大致選取。一定不要無條件的使用 Autopilot 或者自動超引數調優來解決你的問題,三思而後行

變化之本——進化本質

為什麼要考慮“變化”?設計之初就應該考慮到將來的可能變化,也就是說系統框架要設計的比較有彈性(就像亞馬遜雲科技的很多服務那樣彈),對於將來的需求的改動不會付出很高代價。在軟體設計中,經常會談到“面向變化程式設計”,即永遠不要假設需求不變,現實中需求大大小小經常變。變化是創新的必經之路永恆不變的東西只有變化

在 SageMaker 中的體現:

  • SageMaker 早期的版本提供了 SageMaker-container 包供你使用來建立 SageMaker 相容的容器和自定義的框架。後期的版本,為了讓基於 SageMaker-container 包的容器映象儘量更小更內聚,SageMaker 把這個 SageMaker-container 包拆分為 sagemaker-training toolkit(專為訓練的容器)和 sagemaker inference toolkit(專為推理 /serving 的容器)兩個包來瘦身。
  • 隨著不斷的進化,SageMaker 現在是一個完全自洽的全生命週期的機器學習平臺。在早期的時候,SageMaker 只有三大核心功能:訓練,推理(離線推理和線上推理),notebook 例項。為了能把ML生命週期中的資料預處理,特徵工程,模型評估這些功能也納入,SageMaker 後續推出了 Processing job 來做這些事情。而隨著很多使用者對於多種機器學習任務的高質量標註需求的上升,SageMaker 推出了帶有人工標註和機器自動標註的 Ground Truth 功能(這裡又體現了客戶至上的企業文化)。而隨著 SageMaker Studio(它是用於機器學習的整合式開發環境 IDE,可讓你構建、訓練、除錯、部署和監控機器學習模型)的推出,以及 MLOps 的更多功能的加入,現在的 SageMaker 變成了“超人”(短時間能增加如此多的功能並且還保持健壯,正是因為 SageMaker 的設計基因就是面向變化的)。

知其所以然——做到心中有數

我們可能知其然,但是所以然知道了嗎?可能有些感興趣的東西我們會去了解其深層的原因,但是軟體的問題我們去研究了嗎?軟體是枯燥的,很多時候我們都是作為謀生的手段來應付之,因此不知所以然也就很正常了。但是如果您是要真正的學習東西,或者更好的服務於使用者,最好還是”再深一點“。

對於 SageMaker 來說:

  • SageMaker 相關的程式碼比較分散,為了滿足好奇心可以去閱讀原始碼。比如有 SageMaker 平臺相關的開原始碼包 sagemaker-container,sagemaker-training,sagemaker-inference;與內建框架相關的開源的程式碼比如 SageMaker tensorflow training,SageMaker tensorflow serving;SageMaker Python SDK 的開源實現程式碼。透過閱讀這些程式碼,你會對 SageMaker 如何工作有更深刻的理解。
  • 當訓練檔案的數量比較多的時候,SageMaker Pipe mode 和 File mode 哪種方式訓練 更快呢?拿Tensorflow 的 tfrecorddataset API 來舉例,在其他的 dataset API 基本一樣的前提下,File mode 更快(這個在多個實際使用者專案中測試過)。主要的區別就是 pipemodedataset API 和 tfrecorddataset API。tfrecorddataset API 可以設定 num_parallel_reads 來並行讀取多個檔案的資料,還可以設定 buffer_size 來最佳化資料讀取。 Pipemodedataset API 則沒有類似上面的引數來加速資料的讀取。也就是說 Pipe mode 更適合讀取檔案數量不多,但是每個檔案都很大的場景(除了這裡提到的 Pipe mode 和 File mode,SageMaker 訓練的資料讀取方式還提供了 FastFile mode;SageMaker 訓練支援的資料來源除了 S3,還包括 Amazon Elastic File System 以及 Amazon FSX for Lustre,詳細內容可以參考官方部落格)。
  • SageMaker Endpoint for TFS vs for Mxnet/Pytorch 的內建serving 框架複雜性對比. SageMaker Endpoint for TFS 的介紹如下:

SageMaker Endpoint for Pytorch serving 的介紹如下(SageMaker Endpoint for Mxnet serving 是類似的):只使用一個元件 torchserve,它的特點是,直接支援鉤子函式;支援處理 /ping REST API;預設會使用所有的GPU來做推理(而單個 TFS 程式只使用一個 GPU 來推理)。

保持一致性——質量可控

一致性是降低系統複雜度有利的手段。如果一個系統保持一致,意味著類似的事情用類似的方法去做,降低了認知負荷。在ML機器學習領域,我們經常會談到一致性,比如效果線上線下一致性(如果模型離線效果好,模型上線以後表現不好,這就是發生了效果線上線下不一致),特徵的線上線下一致性(特徵的線上線下不一致是效果線上線下不一致的一個常見原因;特徵的線上線下不一致指的是線下訓練時樣本中的特徵的特徵值可能會發生變化,並不和該樣本線上上生成時的特徵值完全一樣。關於特徵的線上線下一致性更詳細的討論請參考我的另一個文章)。保持一致性是模型質量可控的一個重要因素。

對於 SageMaker 來說:

  • 使用 SageMaker Processing job 對訓練集做的一些特徵工程比如某個特徵 Z-score 標準化,那麼為了讓預測時與訓練時有一致的特徵工程,需要如何處理呢?在對訓練集做了某個特徵的 Z-score 標準化以後,用到的該特徵的均值和方差這些 metadata 需要儲存起來(SparkML 和 Sklearn 都有相應的 API 把這些 metadata 以檔案的形式儲存起來);然後利用 SageMaker Inference pipeline 在第一個容器中把之前儲存的 metadata 檔案載入進來對原始特徵進行 Z-score 標準化處理之後再送入第二個容器即模型推理容器。
  • 如果在模型 serving 的時候,能及時知道每個特徵的分佈是否和訓練時的資料集尤其是驗證集的分佈是否基本一致,對於模型才更可控。而 SageMaker 的 model monitor 的一個重要功能就是監控特徵的統計漂移,如果模型在生產過程中接收到的資料的統計性質偏離了訓練所依據的基準資料的性質,則模型將開始失去其預測的準確性。Model Monitor 使用規則檢測資料漂移,並配合 Amazon 其他服務在發生資料漂移時向您發出警報。下圖說明了此流程的工作方式:

總結

本文從軟體哲學角度來介紹了 SageMaker 的一些設計思想以及如何使用 SageMaker 的一些功能。總體來講,不管你是否考慮採用 SageMaker 作為你的機器學習平臺,至少它的這些實現的思路以及設計哲學都是可以用來參考的。SageMaker 作為全球使用量最大的機器學習平臺,是值得你花時間來好好研究和探索以及實踐的。關於 SageMaker 更多詳細和更多深入的內容請參考我的 github。感謝大家的耐心閱讀。

本篇作者

梁宇輝

亞馬遜雲科技機器學習產品技術專家,負責基於亞馬遜雲科技的機器學習方案的諮詢與設計,專注於機器學習的推廣與應用,深度參與了很多真實客戶的機器學習專案的構建以及最佳化。對於深度學習模型分散式訓練,推薦系統和計算廣告等領域具有豐富經驗。

文章來源:https://dev.amazoncloud.cn/column/article/63098fa80c9a20404da...

相關文章