https://www.leiphone.com/news/202002/xkY9d1hhWJH1MoJs.htmlhtml
本文做者是 Omry Yadan,他是 Facebook 人工智能軟件工程師,建立了 Hydra。git
Hydra 是最近發佈的一個開源 Python 框架,由 Facebook AI 開發,可以簡化科研和其餘複雜應用程序的開發。這個新框架功能強大,能夠從命令行和配置文件中組合和重寫配置。做爲 PyTorch 生態系統的一部分,Hydra 幫助 PyTorch 的研究人員和開發人員更容易地管理複雜的機器學習項目。Hydra 是通用的,能夠應用於機器學習之外的領域。github
這篇文章分爲兩部分,第一部分描述開發機器學習軟件時出現的常見問題,第二部分主要是 Hydra 如何解決這些問題。app
part1.你的代碼比你想象的更加複雜框架
命令行是每一個軟件開發人員最早了解的知識之一。命令行的核心是一個字符串列表,這些字符串一般被分解爲標誌(例如,-verbose)和參數(例如,-port=80)。這對於許多簡單的應用程序來講已經足夠了,你可能只須要在命令行界面(CLI)解析庫中定義 2 到 3 個命令行參數就足夠了。iphone
當人們開始使用你的應用程序時,他們將不可避免地發現缺乏的功能。很快,你將添加更多功能,致使更多的命令行標誌。這在機器學習中尤爲常見。機器學習
上面的圖片來自 PyTorch ImageNet 訓練示例。儘管是一個很小的例子,可是命令行標誌的數量已經很高了。其中一些標誌在邏輯上描述了相同的組件,它們在理想狀況下應該被分紅一組(例如,與分佈式訓練相關的標誌),可是沒有一種簡單的方法能夠將這些標誌分組並使用。分佈式
在此示例的基礎上,你可能但願添加新功能,支持須要附加命令行標誌的新模型、數據集或優化器。你能夠想象在這個例子,隨着你的擴展支持新的想法是如何作到的。函數
這種樣式的另外一個微妙問題是,全部東西都須要解析的 args 對象。這會鼓勵耦合,並使單個組件更難在不一樣的項目中重用。學習
配置文件
一個常見的解決方案是切換到配置文件。配置文件能夠是分層的,而且能夠幫助減小定義命令行參數的代碼的複雜性。不幸的是,配置文件中也會面臨挑戰,你將在下一節中看到。
配置文件很難更改
在嘗試時,你須要使用不一樣的配置選項運行應用程序。起初,你可能只是在每次運行以前更改配置文件,但你很快就會意識到跟蹤與每次運行相關聯的更改是很是困難的。
試圖解決該問題的方法多是複製配置文件,在實驗後命名,並對新文件進行更改。這種方法也不是很完美,由於它建立了一個很長的配置文件進行跟蹤,這個文件將很快就不能與代碼同步,變得毫無用處。此外,經過查看實驗配置文件很難判斷你要作什麼,由於它與其餘配置文件 99% 相同。
最後,對於常常更改的內容,你可能會返回到命令行標誌,以容許從命令行更改它們。這是乏味的,而且會讓命令行代碼再次變得複雜。理想狀況下,你能夠從命令行重寫配置中的全部內容,而沒必要爲每種狀況單獨編寫代碼。
配置文件變得單一
當開發人員編寫代碼時,他們喜歡將事情分解成很小的部分(模塊、函數)。這能夠幫助他們保存代碼模型,並使代碼更易於維護。它還支持函數重用——調用一個函數比複製它容易。
配置文件不提供相似的功能。若是但願應用程序使用不一樣的配置選項,例如一個用於 ImageNet 數據集,一個用於 CIFAR-10 數據集,則有兩個選擇:
維護兩個配置文件
將這兩個選項放在一個配置文件中,並在運行時以某種方式使用所需的內容
第一種方法彷佛很好,但後面你會意識到,隨着你增長更多的選項,事情很快就會崩潰。例如,除了兩個數據集選擇以外,你可能還想嘗試三種不一樣的模型體系結構(AlexNet、ResNet50 和一些新的、使人興奮的、你稱之爲 BestNet 的東西)。你還能夠在兩個損失函數之間進行選擇。這使組合總數達到 12 個!你確實但願避免維護 12 個相似的配置文件。
第二種方法最初的效果更好。你只需獲得一個大的配置文件,該文件知道所選的兩個數據集、三個體系結構和兩個損失函數。可是,等等,當你在 AlexNet 和 ResNet50 上進行訓練時,你的學習速率須要有所不一樣,並且你須要在單個配置文件中表達出來。
這種複雜性也會泄漏到代碼中,如今須要找出在運行時使用的學習速率!在設計、運行和調試實驗時,大部分未使用的大型配置會產生顯著的認知負載。因爲 90% 的配置未使用,很難判斷每次運行最重要 10% 在哪裏。
經過添加從命令行重寫配置中全部內容的功能來組合配置,能夠爲這些問題提供一個強大的解決方案。因爲這個緣由,許多日益複雜的項目最終到達了開發 Hydra 所提供的功能子集的必要位置。這種功能每每與單個項目的需求緊密結合,所以很難重用,迫使開發人員不斷地在每一個新項目中從新發明輪子。
不幸的是,在許多開發人員意識到這一點的時候,他們已經有了一個複雜且不靈活的代碼庫,具備高耦合、硬編碼的配置。理想狀況下,你但願像編寫代碼同樣編寫配置。這使你能夠擴大項目的複雜性。
part2.像使用 Hydra 編寫代碼同樣編寫配置
若是你走到了這一步,你必定會想,對於我在第 1 部分中描述的那些軟件工程的問題,有什麼神奇的解決方案?你可能會猜到它就是 Hydra。
Hydra 是 Facebook AI Research 開發的一個開源 Python 框架,它經過容許你組合傳遞給應用程序的配置來解決不少問題,包括第 1 部分中概述的問題。合成能夠經過配置文件或命令行進行,合成配置中的全部內容也能夠經過命令行重寫。
基本示例
下面示例的源代碼在這裏能夠找到:https://github.com/omry/hydra-article-code。
假設你的數據集的配置以下:
config.yaml
如下是加載此配置的簡單 Hydra 應用程序:
my_app.py
這裏最有趣的一行是 @hydra.main()修飾器。它採用一個 config_ 路徑,提到了上面的 config.yaml 文件。
程序很好地打印了它獲得的配置對象。毫無疑問,config 對象包含 ImageNet 數據集配置:
my_app 的常規輸出
咱們如今能夠從命令行重寫此配置文件中的任何內容:
重寫 dataset.path 時的輸出
構成示例
有時,你可能但願在兩個不一樣的數據集之間進行替換,每一個數據集都有本身的配置。要支持此功能,請爲數據集引入一個配置組,並在其中放置單個配置文件,每一個選項一個:
你還能夠在 config.yaml 中添加「defaults」部分,告訴 Hydra 如何編寫配置。在這種狀況下,咱們只想默認加載 cifar10 的配置,由於在它上面訓練更快:
config.yaml
這個應用看起來幾乎相同,惟一的區別是配置路徑如今指向 conf/config.yaml。運行應用程序時,會加載預期的 cifar10 配置:
但咱們也能夠很容易地選擇使用 imagenet:
你能夠擁有多個配置組,讓咱們在優化器中添加一個:
默認狀況下,還能夠更新 config.yaml 以加載 adam:
config.yaml
運行應用程序時,咱們會獲得一個包含 cifar10 和 adam 的聯合配置:
這裏還有不少能夠談的,但如今,讓咱們轉到下一個激動人心的特性。
Multirun
Multirun 是 Hydra 的一種功能,它能夠屢次運行你的函數,每次都組成一個不一樣的配置對象。這是一個天然的擴展,能夠輕鬆地組合複雜的配置,而且很是方便地進行參數掃描,而無需編寫冗長的腳本。
例如,咱們能夠掃描全部 4 個組合(2 個數據集 X 2 個優化器):
基本的內置啓動程序是串行運行,可是其餘啓動程序插件能夠並行運行代碼,甚至遠程運行代碼。這些插件尚未公開,但在社區的幫助下,我但願很快能看到它們。
自動工做目錄
若是仔細觀察上面的輸出,你會注意到 sweep 輸出目錄是根據我運行命令的時間生成的。人們在作研究時常常遇到的一個問題是如何保存輸出。典型的解決方案是傳入一個指定輸出目錄的命令行標誌,但這很快會變得乏味。當你但願同時運行多項任務,而且必須爲每一個任務傳遞不一樣的輸出目錄時,這尤爲使人惱火。
Hydra 經過爲每次運行生成輸出目錄並在運行代碼以前更改當前工做目錄來解決此問題。使用 --multirun 執行掃描時,會爲每一個任務生成一個附加子目錄。
這樣能夠很好地未來自同一 sweep 的任務分組在一塊兒,同時保持每一個任務與其餘任務的輸出分離。
你仍然能夠經過 Hydra 中的 API 訪問原始工做目錄。
original_cwd
從 /home/omry/dev/hydra 運行時的輸出:
生成的工做目錄能夠徹底自定義,這包括讓它做爲路徑的一部分,包含命令行參數或配置中的任何其餘內容。
寫在最後
本文中包含的只是 Hydra 提供的特性之一。其餘功能包括動態選項卡完成、Python 日誌記錄子系統的自動配置、庫和應用程序打包配置支持等等。
在 Facebook AI 中,咱們使用 Hydra 從命令行直接向內部集羣發送代碼。在社區的幫助下,我但願 Hydra 可以成長爲支持 AWS 和 GCP,併爲 Facebook AI 以外的研究人員提供相似的功能。另外一個感興趣的領域是命令行驅動的超參數優化。第一個這樣的插件,Ax 正在開發中。
Hydra 是新的,咱們剛剛開始瞭解它是如何改變事物的。
我期待着看到社區在將來幾年如何使用 Hydra。
要了解有關 Hydra 的更多信息,請參閱 Hydra 網站上的教程和文檔:https://hydra.cc/ 。
雷鋒網(公衆號:雷鋒網)雷鋒網雷鋒網
雷鋒網版權文章,未經受權禁止轉載。詳情見轉載須知。