譯自:How to Code Neat Machine Learning Pipelines
說明:翻譯只是為了加強(qiáng)思考岛蚤,請(qǐng)閱讀原文或者對(duì)照閱讀芜壁。
編寫機(jī)器學(xué)習(xí)流水線,此乃正解芭概。
你是否曾經(jīng)編寫過這樣的機(jī)器學(xué)習(xí)流水線:它運(yùn)行時(shí)間非常很長(zhǎng)?或者更悲劇的,你是否到過這樣的節(jié)點(diǎn):你需要把中間結(jié)果保存在磁盤上以便使用檢查點(diǎn)一次把精力集中在一個(gè)步驟上桩蓉?或者更悲慘的,你是否嘗試重構(gòu)寫得不好的機(jī)器學(xué)習(xí)代碼以便把它放到線上環(huán)境儡首,而這花費(fèi)了你數(shù)月時(shí)間?好吧产场,我們都在搭建機(jī)器學(xué)習(xí)流水線上工作過很長(zhǎng)時(shí)間。我們應(yīng)該如何構(gòu)建一個(gè)流水線,既有一定的自由度鄙皇,又可以在日后輕松重構(gòu)為線上代碼呢膘壶?
首先漱竖,我們將定義機(jī)器學(xué)習(xí)流水線,并探索在流水線步驟間使用檢查點(diǎn)的想法万矾。接著笨枯,我們來看一下如何實(shí)現(xiàn)這樣的檢查點(diǎn)严嗜,以免在把代碼放到線上時(shí)弄得搬起石頭砸到自己的腳。我們也討論了數(shù)據(jù)流睦优,以及在流水線中選擇超參數(shù)時(shí)采用面向?qū)ο缶幊谭庋b的權(quán)衡。
什么的是流水線
流水線就是一系列用于轉(zhuǎn)換數(shù)據(jù)的步驟。它來自于古老的“管道和過濾器”設(shè)計(jì)模式(舉例來說,你可以認(rèn)為它是Unix的命令中的管道符“|”和重定向操作符“>”)。只是,流水線是代碼中的對(duì)象。所以,每個(gè)過濾器有一個(gè)類(或者說是每個(gè)流水線步驟)茸塞,然后另外一個(gè)類把這些步驟組合最終的流水線笋庄。有些流水線會(huì)串行的或者并行的包含其他流水線,擁有多個(gè)輸入或輸出,等等闪盔。我把機(jī)器學(xué)習(xí)流水線視作:
- 管道和過濾器。這些流水線步驟處理數(shù)據(jù),并且管理它們自身的狀態(tài),這些狀態(tài)可以從數(shù)據(jù)中學(xué)到颂碧。
- 組合。流水線可以嵌套:比如一個(gè)流水線可以當(dāng)作一個(gè)單獨(dú)的流水線步驟放到另一個(gè)流水線中。一個(gè)流水線步驟不一定是一個(gè)流水線,但一個(gè)流水線自己至少是一個(gè)流水線步驟。
-
有向無環(huán)圖(DAG)栅干。一個(gè)流水線步驟的輸出可以被傳給許多其他的步驟,輸出也可以進(jìn)行組合。注意:盡管流水線是無環(huán)的,它們可以依次處理多個(gè)數(shù)據(jù)項(xiàng)热康,而一旦它們的狀態(tài)發(fā)生了變化(例如:每次使用
fit_transform
方法時(shí))庶弃,它們就被視為隨時(shí)序循環(huán)展開,保持它們的狀態(tài)(類似于RNN)。一個(gè)非常有意思的事情是讓流水線在部署到生產(chǎn)環(huán)境中后進(jìn)行在線學(xué)習(xí)村砂,使用更多的數(shù)據(jù)訓(xùn)練它們。
流水線的方法
流水線(或者流水線中的步驟)必須有下面的兩個(gè)方法:
- “
fit
”用來從數(shù)據(jù)中學(xué)習(xí)屹逛,從而獲取狀態(tài)(例如:神經(jīng)網(wǎng)絡(luò)中的神經(jīng)權(quán)重就是這樣的狀態(tài)) - “
transform
”(或者“predict
”)用來真正的處理數(shù)據(jù)并生成預(yù)測(cè)础废。
注意:如果流水線中的一個(gè)步驟不需要這里面的某個(gè)方法,它可以從NonFittableMixin
或者NonTransformableMixin
繼承得到這個(gè)方法的默認(rèn)實(shí)現(xiàn)罕模,當(dāng)然默認(rèn)實(shí)現(xiàn)并不做什么事评腺。
很可能,流水線或者它們的步驟會(huì)定義以下可選方法:
- “
fit_transform
”用來在一遍計(jì)算中適應(yīng)并轉(zhuǎn)換數(shù)據(jù)淑掌,與必須讓這兩種操作依次執(zhí)行相比蒿讥,它提供了代碼優(yōu)化的潛力。 - “
setup
”會(huì)調(diào)用每一步驟的setup
方法。舉例來說芋绸,如果一個(gè)步驟包含TensorFlow媒殉、PyTorch、或者Keras神經(jīng)網(wǎng)絡(luò)侥钳,這些步驟可以在訓(xùn)練之前在setup
方法中創(chuàng)建它們的神經(jīng)圖并把它們注冊(cè)到GPU中适袜。不建議在這些步驟的構(gòu)造函數(shù)中直接創(chuàng)建圖,原因有若干舷夺,比如在一個(gè)為你搜索最佳超參數(shù)的自動(dòng)化機(jī)器學(xué)習(xí)算法中苦酱,這些步驟是否會(huì)被復(fù)制后用不同的超參數(shù)多次運(yùn)行。 - “
teardown
”是setup
方法的逆向操作给猾,它負(fù)責(zé)清除資源疫萤。
為了管理超參數(shù),下面這些方法是默認(rèn)提供的:
- “
get_hyperparams
”會(huì)返回超參數(shù)的字典敢伸。如果你的流水線包含更多流水線(嵌套流水線)扯饶,超參數(shù)的鍵是用兩個(gè)下劃線“__
”作分隔符拼接起來的。 - “
set_hyperparams
”允許你以獲取超參數(shù)時(shí)的格式設(shè)置新的超參數(shù)池颈。 - “
get_hyperparams_space
”允許你獲取超參數(shù)的空間尾序,如果你定義了一個(gè)超參數(shù)空間,它就不為空躯砰。它與get_hyperparams
的區(qū)別是它返回統(tǒng)計(jì)分布的多個(gè)值每币,而不是一個(gè)精確的值。例如琢歇,一個(gè)超參數(shù)表示層數(shù)的取值可能是RandInt(1, 3)
兰怠,意思是1到3層。你可以調(diào)用字典的.rvs
方法隨機(jī)選取一個(gè)值傳給set_hyperparams
并嘗試用它來訓(xùn)練李茫。 - “
set_hyperparams_space
”可以用于設(shè)置新的空間揭保,它使用與get_hyperparams_space
相同的超參數(shù)分布類。
重訓(xùn)練流水線魄宏、小批量以及在線學(xué)習(xí)
對(duì)于像用于訓(xùn)練深度神經(jīng)網(wǎng)絡(luò)(DNN)的小批量算法秸侣,或者像強(qiáng)化學(xué)習(xí)(RL)算法中的在線學(xué)習(xí)算法,最理想的是宠互,流水線或者流水線步驟能夠通過一個(gè)接一個(gè)鏈接多次對(duì)于fit
的調(diào)用來更新他們自己塔次,在現(xiàn)場(chǎng)在小批量上進(jìn)行重訓(xùn)練。一些流水線和流水線步驟支持這樣做名秀,但是励负,有些步驟當(dāng)再次被調(diào)用到fit
就會(huì)重置自己。這取決于你是怎樣為你的流水線步驟編碼的匕得。理想的情況是你的流水線步驟只在調(diào)用teardown
方法時(shí)進(jìn)行重置继榆,在下次訓(xùn)練前再次setup
巾表,而在每次訓(xùn)練之間不要重置,在轉(zhuǎn)換期間也不要重置略吨。
在流水線中使用檢查點(diǎn)
在流水線中使用檢查點(diǎn)是個(gè)好想法 - 直到你需要重用這些代碼做其他事或者變更數(shù)據(jù)集币。如果你在代嗎中沒有使用合理的抽象,你可能會(huì)搬起石頭砸了自己的腳翠忠。
在流水線中使用檢查點(diǎn)的好處
- 檢查點(diǎn)可以提高編寫代碼的速度鞠苟。當(dāng)編寫或者調(diào)試流水線中間或結(jié)尾的那些步驟時(shí),可以避免每次都去運(yùn)行前面那些步驟秽之。
- 當(dāng)進(jìn)行超參數(shù)優(yōu)化時(shí)(或者是手工調(diào)參和元學(xué)習(xí))当娱,可以避免重復(fù)計(jì)算前面的步驟。例如考榨,你的流水線的開頭部分沒有超參數(shù)或者只有很少的超參數(shù)的話跨细,在你的調(diào)參過程中開頭部分很可能都是一樣的。有了檢查點(diǎn)河质,就能夠從超參數(shù)發(fā)生改變的位置之前的檢查點(diǎn)繼續(xù)運(yùn)行冀惭。
- 如果你受到硬件能計(jì)算力的限制,可能可行的辦法就是一次只運(yùn)行一步掀鹅。你可以使用檢查點(diǎn)散休,并逐步在檢查點(diǎn)的基礎(chǔ)上增加后面的步驟。
在流水線中使用檢查點(diǎn)的壞處
- 如果做得不好乐尊,它會(huì)因?yàn)樽x寫磁盤而使你的代碼變慢戚丸。你可以使用RAM Disk或者把緩存文件夾映射到內(nèi)存的方式來加速。
- 它會(huì)占用大量的磁盤空間科吭。如果使用了內(nèi)存映射文件的話,也會(huì)需要大量?jī)?nèi)存猴鲫。
- 保存在磁盤上的狀態(tài)管理起來比較困難:這給你的代碼增加了復(fù)雜性对人,也可能會(huì)影響到代碼的運(yùn)行速度。畢竟在編程時(shí)拂共,緩存失效問題是最難解的問題之一牺弄。
計(jì)算機(jī)科學(xué)中有兩個(gè)難題:緩存失效和起名字。 --- Phil Karlton
流水線中合理管理狀態(tài)和緩存的建議
程序框架和設(shè)計(jì)模式會(huì)強(qiáng)制一些設(shè)計(jì)原則宜狐,以希望通過這樣簡(jiǎn)單的方式來替你管理一些事情势告,以免你自己犯錯(cuò)或者寫出一堆亂糟糟的代碼。這里是我對(duì)于流水線和狀態(tài)管理的建議:
- 流水線步驟不應(yīng)管理檢查點(diǎn)的數(shù)據(jù)輸出抚恒。
這應(yīng)該由一個(gè)單獨(dú)的函數(shù)庫管理咱台。
為什么?
為什么流水線步驟不應(yīng)該管理它們的檢查點(diǎn)數(shù)據(jù)輸出俭驮?下面這些原因會(huì)告訴你應(yīng)該使用函數(shù)庫或者框架而不是自己做:
- 當(dāng)部署到線上時(shí)回溺,你可以很輕松的完全打開或者關(guān)閉檢查點(diǎn)春贸。
- 當(dāng)你需要使用新的數(shù)據(jù)重新訓(xùn)練時(shí),良好的緩存管理機(jī)制會(huì)檢測(cè)到你的數(shù)據(jù)變了遗遵,并忽略之前的緩存萍恕。這并不需要你的特別注意,也會(huì)避免很多問題车要。
- 你不需要在流水線步驟中自己編寫代碼進(jìn)行I/O操作與磁盤交互允粤。大多數(shù)程序員更喜歡編寫機(jī)器學(xué)習(xí)算法和構(gòu)建流水線,而不是編寫數(shù)據(jù)序列化方法翼岁。在Neuraxio类垫,我們從沒有聽說誰更喜歡處理數(shù)據(jù)的緩存,而不是編寫神經(jīng)網(wǎng)絡(luò)登澜。
- 你將有機(jī)會(huì)為你的每一個(gè)流水線實(shí)驗(yàn)或者迭代起一個(gè)名字阔挠,一個(gè)新的緩存文件夾就會(huì)被創(chuàng)建出來,即使你使用的是相同的流水線步驟脑蠕。甚至如果你的數(shù)據(jù)變了购撼,都不需要給這個(gè)實(shí)驗(yàn)起名字。
- 如果你修改了流水線步驟的代碼,就會(huì)檢查并對(duì)比代碼的摘要双泪,從而決定緩存是否需要重新處理传货。真香。
- 你將有機(jī)會(huì)為中間數(shù)據(jù)結(jié)果計(jì)算摘要揩局,并且在超參數(shù)相同而且你的流水線已經(jīng)處理過這些數(shù)據(jù)(所以才有緩存)時(shí)跳過流水線對(duì)這些數(shù)據(jù)的計(jì)算。這樣做掀虎,即使在某些時(shí)間中間的流水線步驟變了凌盯,也可以簡(jiǎn)化超參數(shù)調(diào)參。舉個(gè)例子烹玉,前幾個(gè)流水線步驟保持緩存因?yàn)樗鼈儧]變驰怎,如果你流水線中接下來的幾個(gè)步驟有不少超參數(shù)需要調(diào)整,而且在這些步驟后會(huì)記錄多個(gè)檢查點(diǎn)二打,那么這些中間流水線步驟就會(huì)有多份緩存被保存县忌,并利用前面的摘要計(jì)算出一個(gè)唯一的名字。你可以稱之為區(qū)塊鏈继效,如果你愿意症杏,因?yàn)樗鼘?shí)際上就是一個(gè)區(qū)塊鏈。
這很酷瑞信。使用合適的抽象厉颤,你現(xiàn)在能夠編寫這樣的流水線,在超參數(shù)調(diào)參時(shí)凡简,它可以通過緩存每次實(shí)驗(yàn)的中間結(jié)果走芋,當(dāng)超參數(shù)不變時(shí)跳過流水線步驟绩郎,從而大大提速。不僅如此翁逞,一旦你做好準(zhǔn)備把代碼放到線上肋杖,你現(xiàn)在可以很容易的完全關(guān)掉緩存,而無須花一個(gè)月時(shí)間去重構(gòu)代碼挖函。避免撞墻状植。
關(guān)于用于競(jìng)賽的代碼
很常見的,從Kaggle競(jìng)賽來的代碼缺少正確的抽象用于把流水線部署到生產(chǎn)環(huán)境怨喘。這有其合理的原因津畸,參加競(jìng)賽者沒有為把代碼部署到生產(chǎn)環(huán)境而作準(zhǔn)備的動(dòng)機(jī),他們唯一的需求是獲得最好的結(jié)果去贏得競(jìng)賽必怜。大多數(shù)為發(fā)論文而研究的代碼也是這樣的肉拓,通常代碼編寫者追求的是打敗基線指標(biāo)。也有時(shí)候梳庆,機(jī)器學(xué)習(xí)程序員在深入機(jī)器學(xué)習(xí)之前沒有學(xué)過如何恰當(dāng)?shù)木帉懘a暖途,對(duì)于他們以及他們的雇用者,這會(huì)使事情變得困難膏执。
這里有一些壞模式的例子:
- 在一個(gè)文件夾中驻售,放一堆小的“main”文件,手工一個(gè)個(gè)依次或者并行去運(yùn)行這些文件更米。是的欺栗,我們見過太多這樣的流水線。
- 在上面說的小文件之間強(qiáng)制使用磁盤持久化存儲(chǔ)征峦,把代碼和存儲(chǔ)強(qiáng)耦合起來迟几,無法只運(yùn)行代碼而不保存到磁盤。是的栏笆,見過太多类腮。
- 不同的小文件使用不同的磁盤持久化機(jī)制。例如竖伯,混合使用JSON存哲、CSV因宇、Pickles七婴,時(shí)不時(shí)用HDFS和或者直接輸出numpy數(shù)組。更糟的是察滑,混合使用多種數(shù)據(jù)庫或者大型框架而不是保持簡(jiǎn)單或?qū)懘疟P打厘。哦,保持簡(jiǎn)單贺辰。
- 沒有說明到底怎么才能按順序運(yùn)行這些東西户盯。把一堆狗屎當(dāng)作作業(yè)留給看代碼的人嵌施。
- 沒有單元測(cè)試,或者單元測(cè)試是在測(cè)試算法莽鸭,但是需要寫磁盤或者使用已經(jīng)寫在磁盤上的東西吗伤。呃。當(dāng)你運(yùn)行這些沒有測(cè)試的代碼時(shí)硫眨,發(fā)現(xiàn)有一個(gè)依賴項(xiàng)版本更新了足淆,但是這里并沒有告訴需要安裝的版本,至此礁阁,這些代碼再也不像之前一樣了巧号,它們根本運(yùn)行不了。
這些壞模式不僅僅出現(xiàn)在編程比賽的代碼中(比如這里是我匆忙中中寫的---當(dāng)然姥闭,在身負(fù)重壓時(shí)我還可能這樣做)丹鸿。這里是一些使用磁盤設(shè)置檢查點(diǎn)的代碼,以及我的一點(diǎn)分析:
- BERT棚品。要有耐心---試著重構(gòu)一下“run_squad.py”靠欢,你就會(huì)意識(shí)到每一層抽象都耦合在了一起。隨便說幾個(gè)南片,控制臺(tái)參數(shù)解析邏輯和模型定義邏輯放在同一個(gè)層次混起來掺涛,滿眼都是全局標(biāo)志變量。不僅如此疼进,模型定義邏輯跟使用云端加載和保存數(shù)據(jù)的邏輯混在一個(gè)巨大的文件里薪缆,這個(gè)大文件有一千多行代碼。這其實(shí)只是一個(gè)小項(xiàng)目伞广。
- FastText拣帽。Python API從磁盤加載數(shù)據(jù),并在這些數(shù)據(jù)上進(jìn)行訓(xùn)練嚼锄,然后把結(jié)果輸出到磁盤减拭。難道不能把輸出到磁盤和使用文件作輸入做成可選項(xiàng)?
- 大多數(shù)Kaggle比賽獲勝代碼区丑。我們遇到過很多這樣的代碼拧粪,里面沒有適當(dāng)?shù)某橄蟆?/li>
有時(shí)候,公司可能從Kaggle代碼中得到啟發(fā)沧侥,我建議在產(chǎn)品最終上線版中自己編寫流水線可霎,使用這些比賽代碼是有風(fēng)險(xiǎn)的。有一種說法是宴杀,公司不應(yīng)使用比賽代碼癣朗,甚至也不應(yīng)雇用比賽獲獎(jiǎng)的人,因?yàn)樗麄儠?huì)寫糟糕的代碼旺罢。
我不會(huì)這么極端(因?yàn)槲易约涸诖蠖鄶?shù)時(shí)間也在編碼比賽中賺積分)旷余,倒不是說比賽代碼的目的只是獲勝而不考慮將來使用绢记。出乎意料的是,在那個(gè)時(shí)候去讀Clean Code和Clean Coder是很重要的正卧。使用好的流水線抽象能夠幫助機(jī)器學(xué)習(xí)項(xiàng)目存活蠢熄。
這里是當(dāng)你要構(gòu)建準(zhǔn)備在產(chǎn)品線上使用的機(jī)器學(xué)習(xí)流水線時(shí)想要的東西:
- 理想化的,你想要一個(gè)流水線炉旷,它能夠通過只調(diào)用一個(gè)函數(shù)就能處理你的數(shù)據(jù)护赊,而不是執(zhí)行一堆小文件。如果運(yùn)行過程很慢砾跃,你可能想要使用緩存骏啰,但是要讓緩存盡可能小,緩存也不一定是檢查點(diǎn)抽高。
- 要能夠通過一個(gè)開關(guān)禁用所有流水線步驟之間的數(shù)據(jù)檢查點(diǎn)判耕。當(dāng)開發(fā)、調(diào)試和訓(xùn)練模型時(shí)翘骂,檢查點(diǎn)很有用壁熄,但是在生產(chǎn)線上,它應(yīng)該能輕松關(guān)掉碳竟。
- 在一個(gè)機(jī)器集群上擴(kuò)展的能力草丧。
- 最后,你希望它具有良好的容錯(cuò)性以及預(yù)測(cè)能力莹桅。自動(dòng)機(jī)器學(xué)習(xí)會(huì)有用昌执。
機(jī)器學(xué)習(xí)流水線中的數(shù)據(jù)流
在并行處理理論中,流水線是一種流式處理數(shù)據(jù)的方法诈泼,這樣流水線步驟就能并行運(yùn)算懂拾。洗衣房的例子很好的展現(xiàn)了這個(gè)問題及其解決辦法。舉例來說铐达,一個(gè)流式流水線的第二步能夠處理第一步的部分結(jié)果岖赋,同時(shí)第一步還在處理更多數(shù)據(jù),而不用第一步處理完全部數(shù)據(jù)第二步再開始瓮孙。我們把這些特別的流水線稱為流式流水線(參見 streaming 101, streaming 102)唐断。
不要誤解,scikit-learn流水線是很好用的杭抠。但是脸甘,它不允許流式處理數(shù)據(jù)。不僅僅是scikit-learn祈争,大多數(shù)機(jī)器學(xué)習(xí)流水線程序庫沒有使用流式數(shù)據(jù)斤程,盡管他們可以使用角寸。整個(gè)Python生態(tài)系統(tǒng)有線程問題菩混。在多數(shù)流水線程序庫中忿墅,每一步是完全阻塞的,必須一次處理完所有數(shù)據(jù)沮峡。只有少數(shù)庫允許流式處理疚脐。
使用流式數(shù)據(jù)處理很簡(jiǎn)單,只要使用StreamingPipeline類而不是Pipeline類來連接流水線步驟邢疙,并且在步驟之間提供一個(gè)小批量的大小和隊(duì)列大泄髋(避免占用太多內(nèi)存,這會(huì)使線上環(huán)境更加穩(wěn)定)疟游。這也需要使用在生產(chǎn)者-消費(fèi)者問題中描述的帶信號(hào)量的多線程隊(duì)列來在流水線步驟之間傳遞信息呼畸。
Neuraxle比scikit-learn做的好的一件事是擁有序列化的流水線,可以通過MiniBatchSequentialPipeline類來使用颁虐。它還沒有線程化蛮原,但在我們的計(jì)劃當(dāng)中。至少另绩,我們已經(jīng)可以在訓(xùn)練或者處理時(shí)可以在收集結(jié)果前傳遞小批量數(shù)據(jù)到流水線儒陨,這允許大的流水線用小批量數(shù)據(jù)使用像scikit-learn一樣的流水線。再加上我們另外的功能笋籽,例如超參數(shù)空間蹦漠、初始化方法、自動(dòng)機(jī)器學(xué)習(xí)等等车海。
我們對(duì)Python中并行數(shù)據(jù)流的解決方案
- fit和transform方法能在一行數(shù)據(jù)上被調(diào)用多次笛园,這樣在新的小批量數(shù)據(jù)上提升訓(xùn)練性能。
- 在流水線中使用像生產(chǎn)者-消費(fèi)者問題中線程化的隊(duì)列侍芝。在支持流式數(shù)據(jù)的流水線步驟之間需要一個(gè)隊(duì)列喘沿。
- 允許流水線步驟有多個(gè)并行副本并行處理多條數(shù)據(jù)。
- 一個(gè)流水線參數(shù)可以設(shè)定是否數(shù)據(jù)在送入一個(gè)步驟前需要保持?jǐn)?shù)據(jù)的順序竭贩。
- 可以在流水線步驟之前使用障礙器蚜印。
- 我們也計(jì)劃編寫重復(fù)器和批量隨機(jī)器,它可以重復(fù)訓(xùn)練數(shù)據(jù)多次留量,這在訓(xùn)練神經(jīng)網(wǎng)絡(luò)時(shí)很常見窄赋。
不僅如此,在Python使用每個(gè)對(duì)象線程化的方法會(huì)使它們可序列化和重新加載楼熄。在Neuraxle忆绰,我們很快就會(huì)實(shí)現(xiàn)它們。這樣就可以動(dòng)態(tài)發(fā)送代碼到遠(yuǎn)程工作進(jìn)程中去執(zhí)行可岂。
對(duì)封裝的權(quán)衡
在多數(shù)機(jī)器學(xué)習(xí)流水線庫中错敢,還有一件事仍在困擾著我們。這就是如何處置超參數(shù)。拿scikit-learn做例子稚茅,超參數(shù)空間(例如超參數(shù)值的統(tǒng)計(jì)分布)往往需要在流水線之外在步驟與步驟之間或者流水線與流水線之間用帶下劃線方式指定纸淮。正如在scipy分布中定義出的,隨機(jī)搜索和網(wǎng)格搜索能夠搜索超參數(shù)網(wǎng)格和超參數(shù)概率空間亚享,scikit-learn并沒有為每個(gè)分類器和轉(zhuǎn)換器提供默認(rèn)超參數(shù)空間咽块。這理應(yīng)是流水線中每個(gè)對(duì)象的職責(zé)。這樣的話欺税,一個(gè)對(duì)象就是自包含的侈沪,也包含它的超參數(shù),這不會(huì)破壞面向?qū)ο缶幊蹋∣OP)中SOLID原則中的單一職責(zé)原則(SRP)和開放關(guān)閉原則(OCP)晚凿。使用Neuraxle是不破壞這些OOP原則的一個(gè)好辦法亭罪。
兼容性和集成
在編寫機(jī)器學(xué)習(xí)流水線時(shí),最好能想著讓流水線兼容盡量多的東西歼秽。Neuraxle就兼容scikit-learn皆撩、TensorFlow、Keras哲银、PyTorch扛吞,以及許多其他機(jī)器和深度學(xué)習(xí)庫。
例如荆责,neuraxle有一個(gè)方法叫作.tosklearn()
滥比,它允許流水線步驟或者整個(gè)流水線變成一個(gè)scikit-learn的BaseEstimator,這是一個(gè)基本的scikit-learn對(duì)象做院。對(duì)于其他機(jī)器學(xué)習(xí)庫盲泛,也很簡(jiǎn)單,只要?jiǎng)?chuàng)建一個(gè)新的類键耕,讓它繼承自Neuraxle的BaseStep寺滚,并至少重寫你自己的 fit、transform屈雄,也許還有setup和teardown方法村视,再定義一個(gè)保存器來保存和加載你的模型【颇蹋可以閱讀BaseStep的文檔學(xué)習(xí)怎么做蚁孔,也可以閱讀文檔中相關(guān)的Neuraxle樣例。
結(jié)論
總結(jié)一下惋嚎,編寫產(chǎn)品級(jí)別的機(jī)器學(xué)習(xí)流水線需要很多質(zhì)量標(biāo)準(zhǔn)杠氢,如果在代碼中使用好的設(shè)計(jì)模型和好的結(jié)構(gòu),這些問題很可能都會(huì)解決另伍”前伲總的來說:
- 在你的機(jī)器學(xué)習(xí)代碼中使用流水線是一件好事情, 流水線的每一步可以定義成流水線步驟,例如“BaseStep”温艇。
- 接著因悲,當(dāng)搜索最佳超參數(shù)和使用相同數(shù)據(jù)再次運(yùn)行代碼時(shí),就能使用檢查點(diǎn)來優(yōu)化整個(gè)流程(也許使用不同超參數(shù)或者代碼改變時(shí))中贝。
- 順序的訓(xùn)練或者處理數(shù)據(jù),而不是壓爆內(nèi)存臼朗,也是一個(gè)好主意邻寿。這樣,當(dāng)從順序流水線變成流式流水線時(shí)视哑,所有過程也可能并行化绣否。
- 如果你要編寫自己的流水線步驟,你只需要繼承法BaseStep類挡毅,再實(shí)現(xiàn)所需的方法蒜撮。