0
本文作者: skura | 2020-02-08 12:40 |
本文作者是 Omry Yadan,他是 Facebook 人工智能軟件工程師,創(chuàng)建了 Hydra。
Hydra 是最近發(fā)布的一個(gè)開(kāi)源 Python 框架,由 Facebook AI 開(kāi)發(fā),能夠簡(jiǎn)化科研和其他復(fù)雜應(yīng)用程序的開(kāi)發(fā)。這個(gè)新框架功能強(qiáng)大,可以從命令行和配置文件中組合和重寫(xiě)配置。作為 PyTorch 生態(tài)系統(tǒng)的一部分,Hydra 幫助 PyTorch 的研究人員和開(kāi)發(fā)人員更容易地管理復(fù)雜的機(jī)器學(xué)習(xí)項(xiàng)目。Hydra 是通用的,可以應(yīng)用于機(jī)器學(xué)習(xí)以外的領(lǐng)域。
這篇文章分為兩部分,第一部分描述開(kāi)發(fā)機(jī)器學(xué)習(xí)軟件時(shí)出現(xiàn)的常見(jiàn)問(wèn)題,第二部分主要是 Hydra 如何解決這些問(wèn)題。
part1.你的代碼比你想象的更加復(fù)雜
命令行是每個(gè)軟件開(kāi)發(fā)人員最先了解的知識(shí)之一。命令行的核心是一個(gè)字符串列表,這些字符串通常被分解為標(biāo)志(例如,-verbose)和參數(shù)(例如,-port=80)。這對(duì)于許多簡(jiǎn)單的應(yīng)用程序來(lái)說(shuō)已經(jīng)足夠了,你可能只需要在命令行界面(CLI)解析庫(kù)中定義 2 到 3 個(gè)命令行參數(shù)就足夠了。
當(dāng)人們開(kāi)始使用你的應(yīng)用程序時(shí),他們將不可避免地發(fā)現(xiàn)缺少的功能。很快,你將添加更多功能,導(dǎo)致更多的命令行標(biāo)志。這在機(jī)器學(xué)習(xí)中尤其常見(jiàn)。
上面的圖片來(lái)自 PyTorch ImageNet 訓(xùn)練示例。盡管是一個(gè)很小的例子,但是命令行標(biāo)志的數(shù)量已經(jīng)很高了。其中一些標(biāo)志在邏輯上描述了相同的組件,它們?cè)诶硐肭闆r下應(yīng)該被分成一組(例如,與分布式訓(xùn)練相關(guān)的標(biāo)志),但是沒(méi)有一種簡(jiǎn)單的方法可以將這些標(biāo)志分組并使用。
在此示例的基礎(chǔ)上,你可能希望添加新功能,支持需要附加命令行標(biāo)志的新模型、數(shù)據(jù)集或優(yōu)化器。你可以想象在這個(gè)例子,隨著你的擴(kuò)展支持新的想法是如何做到的。
這種樣式的另一個(gè)微妙問(wèn)題是,所有東西都需要解析的 args 對(duì)象。這會(huì)鼓勵(lì)耦合,并使單個(gè)組件更難在不同的項(xiàng)目中重用。
配置文件
一個(gè)常見(jiàn)的解決方案是切換到配置文件。配置文件可以是分層的,并且可以幫助減少定義命令行參數(shù)的代碼的復(fù)雜性。不幸的是,配置文件中也會(huì)面臨挑戰(zhàn),你將在下一節(jié)中看到。
配置文件很難更改
在嘗試時(shí),你需要使用不同的配置選項(xiàng)運(yùn)行應(yīng)用程序。起初,你可能只是在每次運(yùn)行之前更改配置文件,但你很快就會(huì)意識(shí)到跟蹤與每次運(yùn)行相關(guān)聯(lián)的更改是非常困難的。
試圖解決該問(wèn)題的方法可能是復(fù)制配置文件,在實(shí)驗(yàn)后命名,并對(duì)新文件進(jìn)行更改。這種方法也不是很完美,因?yàn)樗鼊?chuàng)建了一個(gè)很長(zhǎng)的配置文件進(jìn)行跟蹤,這個(gè)文件將很快就不能與代碼同步,變得毫無(wú)用處。此外,通過(guò)查看實(shí)驗(yàn)配置文件很難判斷你要做什么,因?yàn)樗c其他配置文件 99% 相同。
最后,對(duì)于經(jīng)常更改的內(nèi)容,你可能會(huì)返回到命令行標(biāo)志,以允許從命令行更改它們。這是乏味的,并且會(huì)讓命令行代碼再次變得復(fù)雜。理想情況下,你可以從命令行重寫(xiě)配置中的所有內(nèi)容,而不必為每種情況單獨(dú)編寫(xiě)代碼。
配置文件變得單一
當(dāng)開(kāi)發(fā)人員編寫(xiě)代碼時(shí),他們喜歡將事情分解成很小的部分(模塊、函數(shù))。這可以幫助他們保存代碼模型,并使代碼更易于維護(hù)。它還支持函數(shù)重用——調(diào)用一個(gè)函數(shù)比復(fù)制它容易。
配置文件不提供類(lèi)似的功能。如果希望應(yīng)用程序使用不同的配置選項(xiàng),例如一個(gè)用于 ImageNet 數(shù)據(jù)集,一個(gè)用于 CIFAR-10 數(shù)據(jù)集,則有兩個(gè)選擇:
維護(hù)兩個(gè)配置文件
將這兩個(gè)選項(xiàng)放在一個(gè)配置文件中,并在運(yùn)行時(shí)以某種方式使用所需的內(nèi)容
第一種方法似乎很好,但后面你會(huì)意識(shí)到,隨著你增加更多的選項(xiàng),事情很快就會(huì)崩潰。例如,除了兩個(gè)數(shù)據(jù)集選擇之外,你可能還想嘗試三種不同的模型體系結(jié)構(gòu)(AlexNet、ResNet50 和一些新的、令人興奮的、你稱之為 BestNet 的東西)。你還可以在兩個(gè)損失函數(shù)之間進(jìn)行選擇。這使組合總數(shù)達(dá)到 12 個(gè)!你確實(shí)希望避免維護(hù) 12 個(gè)類(lèi)似的配置文件。
第二種方法最初的效果更好。你只需得到一個(gè)大的配置文件,該文件知道所選的兩個(gè)數(shù)據(jù)集、三個(gè)體系結(jié)構(gòu)和兩個(gè)損失函數(shù)。但是,等等,當(dāng)你在 AlexNet 和 ResNet50 上進(jìn)行訓(xùn)練時(shí),你的學(xué)習(xí)速率需要有所不同,而且你需要在單個(gè)配置文件中表達(dá)出來(lái)。
這種復(fù)雜性也會(huì)泄漏到代碼中,現(xiàn)在需要找出在運(yùn)行時(shí)使用的學(xué)習(xí)速率!在設(shè)計(jì)、運(yùn)行和調(diào)試實(shí)驗(yàn)時(shí),大部分未使用的大型配置會(huì)產(chǎn)生顯著的認(rèn)知負(fù)載。由于 90% 的配置未使用,很難判斷每次運(yùn)行最重要 10% 在哪里。
通過(guò)添加從命令行重寫(xiě)配置中所有內(nèi)容的功能來(lái)組合配置,可以為這些問(wèn)題提供一個(gè)強(qiáng)大的解決方案。由于這個(gè)原因,許多日益復(fù)雜的項(xiàng)目最終到達(dá)了開(kāi)發(fā) Hydra 所提供的功能子集的必要位置。這種功能往往與單個(gè)項(xiàng)目的需求緊密結(jié)合,因此很難重用,迫使開(kāi)發(fā)人員不斷地在每個(gè)新項(xiàng)目中重新發(fā)明輪子。
不幸的是,在許多開(kāi)發(fā)人員意識(shí)到這一點(diǎn)的時(shí)候,他們已經(jīng)有了一個(gè)復(fù)雜且不靈活的代碼庫(kù),具有高耦合、硬編碼的配置。理想情況下,你希望像編寫(xiě)代碼一樣編寫(xiě)配置。這使你可以擴(kuò)大項(xiàng)目的復(fù)雜性。
part2.像使用 Hydra 編寫(xiě)代碼一樣編寫(xiě)配置
如果你走到了這一步,你一定會(huì)想,對(duì)于我在第 1 部分中描述的那些軟件工程的問(wèn)題,有什么神奇的解決方案?你可能會(huì)猜到它就是 Hydra。
Hydra 是 Facebook AI Research 開(kāi)發(fā)的一個(gè)開(kāi)源 Python 框架,它通過(guò)允許你組合傳遞給應(yīng)用程序的配置來(lái)解決很多問(wèn)題,包括第 1 部分中概述的問(wèn)題。合成可以通過(guò)配置文件或命令行進(jìn)行,合成配置中的所有內(nèi)容也可以通過(guò)命令行重寫(xiě)。
基本示例
下面示例的源代碼在這里可以找到:https://github.com/omry/hydra-article-code。
假設(shè)你的數(shù)據(jù)集的配置如下:
config.yaml
以下是加載此配置的簡(jiǎn)單 Hydra 應(yīng)用程序:
my_app.py
這里最有趣的一行是 @hydra.main()修飾器。它采用一個(gè) config_ 路徑,提到了上面的 config.yaml 文件。
程序很好地打印了它得到的配置對(duì)象。毫無(wú)疑問(wèn),config 對(duì)象包含 ImageNet 數(shù)據(jù)集配置:
my_app 的常規(guī)輸出
我們現(xiàn)在可以從命令行重寫(xiě)此配置文件中的任何內(nèi)容:
重寫(xiě) dataset.path 時(shí)的輸出
構(gòu)成示例
有時(shí),你可能希望在兩個(gè)不同的數(shù)據(jù)集之間進(jìn)行替換,每個(gè)數(shù)據(jù)集都有自己的配置。要支持此功能,請(qǐng)為數(shù)據(jù)集引入一個(gè)配置組,并在其中放置單個(gè)配置文件,每個(gè)選項(xiàng)一個(gè):
你還可以在 config.yaml 中添加「defaults」部分,告訴 Hydra 如何編寫(xiě)配置。在這種情況下,我們只想默認(rèn)加載 cifar10 的配置,因?yàn)樵谒厦嬗?xùn)練更快:
config.yaml
這個(gè)應(yīng)用看起來(lái)幾乎相同,唯一的區(qū)別是配置路徑現(xiàn)在指向 conf/config.yaml。運(yùn)行應(yīng)用程序時(shí),會(huì)加載預(yù)期的 cifar10 配置:
但我們也可以很容易地選擇使用 imagenet:
你可以擁有多個(gè)配置組,讓我們?cè)趦?yōu)化器中添加一個(gè):
默認(rèn)情況下,還可以更新 config.yaml 以加載 adam:
config.yaml
運(yùn)行應(yīng)用程序時(shí),我們會(huì)得到一個(gè)包含 cifar10 和 adam 的聯(lián)合配置:
這里還有很多可以談的,但現(xiàn)在,讓我們轉(zhuǎn)到下一個(gè)激動(dòng)人心的特性。
Multirun
Multirun 是 Hydra 的一種功能,它可以多次運(yùn)行你的函數(shù),每次都組成一個(gè)不同的配置對(duì)象。這是一個(gè)自然的擴(kuò)展,可以輕松地組合復(fù)雜的配置,并且非常方便地進(jìn)行參數(shù)掃描,而無(wú)需編寫(xiě)冗長(zhǎng)的腳本。
例如,我們可以掃描所有 4 個(gè)組合(2 個(gè)數(shù)據(jù)集 X 2 個(gè)優(yōu)化器):
基本的內(nèi)置啟動(dòng)程序是串行運(yùn)行,但是其他啟動(dòng)程序插件可以并行運(yùn)行代碼,甚至遠(yuǎn)程運(yùn)行代碼。這些插件還沒(méi)有公開(kāi),但在社區(qū)的幫助下,我希望很快能看到它們。
自動(dòng)工作目錄
如果仔細(xì)觀察上面的輸出,你會(huì)注意到 sweep 輸出目錄是根據(jù)我運(yùn)行命令的時(shí)間生成的。人們?cè)谧鲅芯繒r(shí)經(jīng)常遇到的一個(gè)問(wèn)題是如何保存輸出。典型的解決方案是傳入一個(gè)指定輸出目錄的命令行標(biāo)志,但這很快會(huì)變得乏味。當(dāng)你希望同時(shí)運(yùn)行多項(xiàng)任務(wù),并且必須為每個(gè)任務(wù)傳遞不同的輸出目錄時(shí),這尤其令人惱火。
Hydra 通過(guò)為每次運(yùn)行生成輸出目錄并在運(yùn)行代碼之前更改當(dāng)前工作目錄來(lái)解決此問(wèn)題。使用 --multirun 執(zhí)行掃描時(shí),會(huì)為每個(gè)任務(wù)生成一個(gè)附加子目錄。
這樣可以很好地將來(lái)自同一 sweep 的任務(wù)分組在一起,同時(shí)保持每個(gè)任務(wù)與其他任務(wù)的輸出分離。
你仍然可以通過(guò) Hydra 中的 API 訪問(wèn)原始工作目錄。
original_cwd
從 /home/omry/dev/hydra 運(yùn)行時(shí)的輸出:
生成的工作目錄可以完全自定義,這包括讓它作為路徑的一部分,包含命令行參數(shù)或配置中的任何其他內(nèi)容。
寫(xiě)在最后
本文中包含的只是 Hydra 提供的特性之一。其他功能包括動(dòng)態(tài)選項(xiàng)卡完成、Python 日志記錄子系統(tǒng)的自動(dòng)配置、庫(kù)和應(yīng)用程序打包配置支持等等。
在 Facebook AI 中,我們使用 Hydra 從命令行直接向內(nèi)部集群發(fā)送代碼。在社區(qū)的幫助下,我希望 Hydra 能夠成長(zhǎng)為支持 AWS 和 GCP,并為 Facebook AI 之外的研究人員提供類(lèi)似的功能。另一個(gè)感興趣的領(lǐng)域是命令行驅(qū)動(dòng)的超參數(shù)優(yōu)化。第一個(gè)這樣的插件,Ax 正在開(kāi)發(fā)中。
Hydra 是新的,我們剛剛開(kāi)始了解它是如何改變事物的。
我期待著看到社區(qū)在未來(lái)幾年如何使用 Hydra。
要了解有關(guān) Hydra 的更多信息,請(qǐng)參閱 Hydra 網(wǎng)站上的教程和文檔:https://hydra.cc/ 。
雷鋒網(wǎng)雷鋒網(wǎng)雷鋒網(wǎng)
雷峰網(wǎng)版權(quán)文章,未經(jīng)授權(quán)禁止轉(zhuǎn)載。詳情見(jiàn)轉(zhuǎn)載須知。