在先前的章節中,我們瞭解了如何利用PyTorch
建立資料流、模型以及進行訓練的流程。我們可以體會在在PyTorch
中建立訓練所需要的所有元素是相對複雜的(與TensorFlow
相比)。然而,我們可以透過PyTorch-Lightning
這個模組所提供的各種功能來補足PyTorch
所缺少的部份,並得到超越TensorFlow
的彈性以及可塑性。在這個章節,我們將會初步介紹PyTorch-Lightning
所能帶來的便利性,以及與過往使用原生PyTorch
之間的差異。
在開始了解如何利用PyTorch-Lightning
函式庫來最佳化我們的訓練流程之前,我們先來複習如何在利用原生PyTorch
函式庫來建構訓練的流程。
也可瀏覽先前的章節來複習。
想必對於大部分的人來說,這種需要對每一個步驟都進行設定的作法,相較下是比較令人感到麻煩的。在TensorFlow
中都不需要親力親為的部份,在PyTorch
中卻需要一項一項的處理,會花費掉開發者許多寶貴的時間。這時候就是PyTorch-Lightning
函式庫大顯身手的好時機了。
PyTorch-Lightning
能帶給我們的好處.to()
丟掉了)。PyTorch
的原生功能,所以能在最大化彈性的情景下刪除大部分樣版程式。PyTorch
更好的運行效率。節錄自
PyTorch-Lightning
的GitHub頁面
PyTorch-Lightning
在瞭解了PyTorch-Lightning
能帶給我們怎樣的好處之後,我們可以開始來動手試試看將劑有訓練流程改寫為基於PyTorch-Lightning
的形式。為此,首先我們需要安裝PyTorch-Lightning
函式庫。
因為PyTorch-Lightning
有發布在Pypi
上,所以我們可以利用pip install pytorch-lightning
來安裝PyTorch-Lightning
函式庫。
PyTorch-Lightning
建立訓練流程利用PyTorch-Lightning
建立訓練流程的過程很簡單,簡單來說就是「將必要的部份補齊」就好了。PyTorch-Lightning
提供了各種已經設定好的類別,使用者只需要透過子類化(Sub-Classing)的方式繼承PyTorch-Lightning
所建立好的類別,並將必要的部份補上/改寫即可。接下來就讓我們來看看如何實作。
基於PyTorch-Lightning
的功能,我們可以將過往的好幾個步驟整合成一個物件,並透過pl.Trainer
來完成對不同裝置的整合以及支援。
在過往的流程中,我們必須要依照以下流程來建立整個模型以及資料管線:
在導入了PyTorch-Lightning
之後,以上繁瑣的的部份都不再需要。你只需要在繼承了pl.LightningModule
的物件中設定以下部份:
training_step
以及validatation_step
方法)trainer.fit()
中導入或是在物件中建立prepare_data
或xxxx_dataloader
方法)configure_optimizers
方法)就可以了。在準備好物件之後,只需要透過pl.Trainer
以及trainer.fit()
函數的協助,就能透無痛的將你的訓練流程佈署在GPU、TPU以及其他可協助加速運算的硬體設備上進行訓練以及推論了。
以下是一個利用繼承了pl.LightningModule
的物件來建立的MNIST模型物件。其包含了以下幾個元素:
__init__
:整個物件的基本設定。forward
:模型如何向前傳播。training_step
:定義訓練的運算流程。configure_optimizers
:定義所使用的優化器。在此之上,若有需要也可以自行添加validation_step
來定義驗證的運算流程。
我們在training_step
中利用self.log
來對準確率以及損失值進行了紀錄,但我們在這裡不會進行介紹,有興趣的人可以先前往瀏覽相關文件來了解詳情。
在設定好模型物件後,我們就可以開始設定pl.Trainer()
並利用它來進行訓練了。
在進行訓練之前,我們必須先建立一個pl.Trainer
物件,並告知我們所希望使用的硬體加速設備、要跑幾個週期進行訓練,以及其他的設定。在建立pl.Trainer
物件後,我們可以利用trainer.fit()
搭配模型以及相關參數來開始我們的訓練。
因為我們上方有利用pl.LightningModule
的self.log
功能對準確率以及損失值進行紀錄,所以我們可以透過TensorBoard
來了解經由這樣的訓練流程設計,我們是否能成功對的對模型進行訓練。
我們可以發現,PyTorch-Lightning
很順利的依照我們所設定的流程進行了訓練。
藉由PyTorch-Lightning
的幫助,我們省下了許多不必要且重複的的工程部份,以及節省了很大篇幅的程式編寫,並且很大的程度提昇了整個程式碼的可讀性。下方的組圖中,左方是舊有的訓練流程,而又方是藉由PyTorch-Lightning
來編寫的核心部份。
我們省去了to()
、backward
以及step
等不必要的部份,並獲得了專心在設計模型以及調整架構的時間以及機會,並且也無須在安排變數應該在哪一個裝置上費心思。這些就是藉由導入PyTorch-Lightning
所帶來的好處。
PyTorch-Lightning
機制介紹在前面的部份,我們介紹了如何利用PyTorch-Lightning
來建立訓練流程。接下來我們就來詳細了解PyTorch-Lightning
是如何運作,又是如何以上方的機制來簡化流程的建立的。
PyTorch-Lightning
的設核心為:以基於PyTorch
的架構為基礎,建構一個具有高度彈性以及可擴充性的函式庫。PyTorch-Lightning
所提供的所有主要函式,都是基於PyTorch
原本就有的功能。以LightningModule
為例,LightningModule
是基於nn.Module
來建構的,也就是在原生PyTorch
中我們透過模型子類化建立模型時,必須繼承的對象,所以過往所有的模型設計可以無縫接軌直接改寫成使用LightningModule
來建立。
PyTorch-Lightning
的架構之所有能有極高的彈性,就在於其設計上均以「Hook」的方式來將各個功能擴充到主要的功能之中,讓使用者不管在建立模型、建立數據管線、建立驗證以及測試邏輯、甚至是設計預測函式,都能夠被包裝在一個主要的物件之中,不需要在建立額外的物件。若要舉例的話,就類似於tf.keras.Callback
所提供的on_epoch_end
以及on_epoch_start
等在自定義回測函數時,所用到的各個部份。使用者只需要將繼承對象原有的函式進行覆寫,就能夠隨心所欲的自訂一所想要的功能。
LightningModule
是在PyTorch-Lightning
的架構中,最核心的一部分。無論是建立模型、設定超參數、建立數據管線、設定優化器以及處理訓練狀態等,只要是能想到的功能都能往繼承了LightningModule
的物件裡面塞,最後在外面套一個pl.Trainer()
結束這一回合。可以說是要多優雅就有多優雅,也不需要管變數要放在哪一個硬體上,更不用管資料要怎要在分佈式系統上處理,基本上交給LightningModule
加上pl.Trainer()
的組合就沒問題。
怎麼做到的?因為所有在PyTorch-Lightning
中的Hook以及延伸功能都與LightningModule
有掛勾,所以才能提供這樣極具彈性的功能。無論是訓練及測試用的xxxx_step
也好,處理數據的xxxx_dataloader
也罷。都與LightningModule
緊緊相連。使用者只需要將必要的部份改寫成自己的設計,剩下的都可以交由PyTorch-Lightning
所預先設計好的架構來處理。
對PyTorch-Lightning
所提供的Hook有興趣的話,可以參考他們的網站,這裡就不一一介紹了。
在本章節中,我們介紹了如何利用PyTorch-Lightning
所帶來的強大功能來最佳化我們的各項流程,也介紹了PyTorch-Lightning
的核心設計理念以及架構的精隨所在。接下來我們會介紹如何利用PyTorch-Lightning
的功能來一步一步讓整個流程更加的有彈性以及組織。
Machine Learning
Notebook
技術隨筆
機器學習
Python
PyTorch
PyTorch-Lightning