git log規範_deepvac-PyTorch訓練模型專案的工程化規範
技術標籤:git log規範
deepvac提供了PyTorch訓練模型專案的工程化規範。專案地址:
DeepVAC/deepvacgithub.com歡迎star
為了達到這一目標,deepvac包含了:
- 專案組織規範
- 程式碼規範
- deepvac庫
諸多PyTorch訓練模型專案的內在邏輯都大同小異,因此deepvac致力於把更通用的邏輯剝離出來,從而使得工程程式碼的準確性、易讀性、可維護性上更具優勢。
專案組織規範
定義PyTorch訓練模型專案的組織規範,包含:
- 訓練測試的程式碼目錄/檔案規範;
- git分支規範;
- 配置規範;
訓練測試的程式碼目錄/檔案規範
每一個符合deepvac規範的PyTorch模型訓練專案,都包含下面這些目錄和檔案:
目錄/檔案 | 說明 |
---|---|
README.md | 專案的說明、git分支數量及其介紹、原始資料的存放路徑說明 |
train.py | 訓練和驗證的入口檔案,繼承DeepvacTrain類體系(來自deepvac/syszux_deepvac.py)的擴充套件實現 |
test.py | 測試的入口檔案, 繼承Deepvac類體系(來自deepvac/syszux_deepvac.py)的擴充套件實現 |
config.py | 使用者訓練和測試的配置檔案,syszux_config模組(來自deepvac/syszux_config)的擴充套件實現 |
modules/model.py | 模型、Loss的定義檔案,PyTorch Module類的擴充套件實現 |
modules/utils.py | 工具類/方法的定義檔案(可省略) |
data/train.txt | 訓練集清單檔案(可省略) |
data/val.txt | 驗證集清單檔案(可省略) |
output/model* | 輸出或輸入的模型檔案 |
output/optimizer* | 輸出或輸入的checkpoint檔案 |
synthesis/synthesis.py | 資料合成或清洗程式碼(可省略) |
synthesis/config.py | synthesis.py的配置檔案(可省略) |
aug/aug.py | 資料增強的程式碼 |
aug/config.py | aug.py的配置檔案 |
log/*.log | 日誌輸出目錄 |
這些檔案覆蓋了一個PyTorch模型訓練的整個生命週期:
- 原始資料,在README.md中描述;
- 資料清洗、合成,在synthesis/synthesis.py中定義;
- 資料增強,在aug/aug.py中定義;
- 資料輸入,在data中定義;
- 模型訓練,在train.py中定義;
- 模型驗證,在train.py中定義;
- 模型測試,在test.py中定義;
- 模型輸出,在output目錄中存放;
- 日誌輸出,在log目錄中存放;
git分支規範
每一個符合deepvac規範的PyTorch專案,都會面臨一個問題:如何並行的進行多種實驗? deepvac採用的是git branch的解決方案。deepvac規定:
- 每一種實驗都有對應的git branch;
- deepvac規定了兩種git branch,長期執行分支和臨時分支;
- 長期執行分支的名字以LTS_開頭,臨時分支的名字以PROTO_開頭;
- 分支的名字要準確表達當前訓練的上下文,使用變數名的程式碼規範,小寫字母,以下劃線分割;如:LTS_ocr_train_on_5synthesis_9aug_100w;
- 因此,deepvac在檢測不到當前程式碼所在的合法git branch時,將會終止執行;
配置規範
- 相較於維護程式碼的不同版本,deepvac中的配置規範更傾向於維護不同的config.py版本;
- 使用者介面層面的配置均在config.py中;
- 內部開發定義的配置均在類的auditConfig方法中;
- 所有臨時除錯的配置均在類的建構函式中,或者由argparse.ArgumentParser模組來傳遞;
- DeepvacTrainDDP類的--rank和--gpu引數為程序級別,由argparse.ArgumentParser模組來傳遞;
- 類的建構函式輸入為config;
deepvac庫
deepvac庫對使用層面提供以下模組:
模組 | 目錄/檔案 | 說明 |
---|---|---|
SynthesisFactory | deepvac/syszux_synthesis_factory.py | 用於資料合成或者清洗 |
AugFactory | deepvac/syszux_aug_factory.py | 用於資料增強 |
DatasetFactory | deepvac/syszux_loader_factory.py | Dataset的擴充套件實現,torch.utils.data.Dataset的子類們 |
LoaderFactory | deepvac/syszux_loader_factory.py | 用於資料裝載 |
Deepvac{,Train,DDP} | deepvac/syszux_deepvac.py | Deepvac類體系,用於訓練、驗證、測試程式碼的基類 |
{,Face,Ocr}Report | deepvac/syszux_report.py | Report類體系,用於列印測試報告 |
{,*Aug}Executor | deepvac/syszux_executor.py | Executor類體系,用於資料增強邏輯的抽象封裝 |
LOG | deepvac/syszux_log.py | 日誌模組 |
AttrDict | deepvac/syszux_config.py | 配置模組 |
專案依賴
- Python3。不支援Python2,其已被廢棄;
- 依賴包:torch, torchvision, tensorboard, scipy, numpy, cv2, Pillow;
- 字型檔案(可選):如果使用text synthesis,請安裝字型檔案:https://github.com/CivilNet/SYSZUXfont;
如何基於deepvac構建自己的pytorch專案
1. 安裝依賴
參考
專案依賴github.com2. 安裝deepvac
可以使用pip來進行安裝:pip3 install deepvac
或者python3 -m pip install deepvac
如果你需要使用deepvac在gitlab上的最新程式碼,就需要使用如下的開發者模式:
開發者模式
- 克隆該專案到本地:
git clone https://github.com/DeepVAC/deepvac
- 在你的入口檔案中新增:
import sys
#replace with your local deepvac directory
sys.path.append('/home/gemfield/github/deepvac')
3. 建立自己的PyTorch專案
- 初始化自己專案的git倉庫;
- 在倉庫中建立第一個研究分支,比如分支名為 LTS_b1_aug9_movie_video_plate_130w;
- 切換到上述的LTS_b1分支中,開始coding;
4. 編寫配置檔案
配置檔案的檔名均為 config.py,在程式碼開始處新增from deepvac.syszux_config import *
;
所有使用者的配置都存放在這個檔案裡。 有些配置是全域性唯一的,則直接配置如下:
config.device = "cuda"
config.output_dir = "output"
config.log_dir = "log"
config.log_every = 10
......
有些配置在train、val、test上下文中有不同的值,比如batch_size,則配置在對應的上下文中:
#in train context
config.train.batch_size = 128
#in val context
config.val.batch_size = 32
......
一個完整的config.py例子可以參考 config.py例子
然後用下面的方式來使用 config.py檔案:
from config import config as conf
vac = Deepvac(conf)
之後,程式碼中一般通過如下方式來讀寫配置項
#通過conf模組來訪問
print(conf.log_dir)
#在類中可以通過self.conf成員訪問配置
print(self.conf.train.batch_size)
5. 編寫synthesis/synthesis.py
編寫該檔案,用於產生資料集和data/train.txt,data/val.txt (待完善)
6. 編寫aug/aug.py
編寫該檔案,用於實現資料增強策略; 繼承syszux_executor模組中的Executor類體系,比如:
class MyAugExecutor(Executor):
def __init__(self, deepvac_config):
super(MyAugExecutor, self).__init__(deepvac_config)
ac1 = AugChain('[email protected] => [email protected]',deepvac_config)
ac2 = AugChain('MotionAug || GaussianAug',deepvac_config)
self.addAugChain('ac1', ac1, 1)
self.addAugChain('ac2', ac2, 0.5)
(待完善)
7. 編寫Dataset類
程式碼編寫在train.py檔案中。 繼承syszux_loader模組中的Dataset類體系,比如FileLineDataset類提供了對如下train.txt對裝載封裝:
#train.txt,第一列為圖片路徑,第二列為label
img0/1.jpg 0
img0/2.jpg 0
...
img1/0.jpg 1
...
img2/0.jpg 2
...
有時第二列是字串,並且想把FileLineDataset中使用Image讀取圖片對方式替換為cv2,那麼可以通過如下的繼承方式來重新實現:
class FileLineCvStrDataset(FileLineDataset):
def _buildLabelFromLine(self, line):
line = line.strip().split(" ")
return [line[0], line[1]]
def _buildSampleFromPath(self, abs_path):
#we just set default loader with Pillow Image
sample = cv2.imread(abs_path)
if self.transform is not None:
sample = self.transform(sample)
return sample
哦,FileLineCvStrDataset也已經是syszux_loader模組中提供的類了。
再比如,在例子a_resnet_project 中,NSFWTrainDataset就繼承了deepvac庫中的ImageFolderWithTransformDataset類:
class NSFWTrainDataset(ImageFolderWithTransformDataset):
def __init__(self, nsfw_config):
super(NSFWTrainDataset, self).__init__(nsfw_config)
8. 編寫訓練和驗證指令碼
程式碼寫在train.py檔案中,繼承syszux_deepvac模組中的DeepvacTrain類,或者DeepvacDDP類(用於分散式訓練)。繼承DeepvacTrain類的子類必須(重新)實現以下方法才能夠開始訓練:
類的方法(*號表示必需重新實現) | 功能 | 備註 |
---|---|---|
* initNetWithCode | 初始化http://self.net成員 | 用於初始化網路,在此方法中手動將網路載入到device裝置上 |
* initCriterion | 初始化self.criterion成員 | 用於初始化損失/評價函式 |
initOptimizer | 初始化self.optimizer成員 | 用於初始化優化器,預設初始化為SGD |
initScheduler | 初始化self.scheduler成員 | 預設初始化為torch.optim.lr_scheduler |
* initTrainLoader | 初始化self.train_loader成員 | 初始化用於訓練的DataLoader |
* initValLoader | 初始化self.val_loader成員 | 初始化用於驗證的DataLoader |
preEpoch | 每輪Epoch之前的操作 | 預設啥也不做 |
preIter | 每個batch迭代之前的操作 | 預設會將資料載入到device上,並初始化self.sample、self.target,並對上一個迭代計算得到的梯度進行zero_grad操作 |
postIter | 每個batch迭代之後的操作 | 預設啥也不做 |
postEpoch | 每輪Epoch之後的操作 | 預設會呼叫self.scheduler.step() |
doForward | 網路前向推理過程 | 預設會將推理得到的值賦值給self.output成員 |
doLoss | 計算loss的過程 | 預設會使用self.output和self.target進行計算得到此次迭代的loss |
doBackward | 網路反向傳播過程 | 預設呼叫self.loss.backward() |
doOptimize | 網路權重更新的過程 | 預設呼叫self.optimizer.step() |
一個train.py的例子 train.py。
(DDP類待完善)
9. 編寫測試指令碼
程式碼寫在test.py檔案中,繼承syszux_deepvac模組中的Deepvac類。和train.py中的train/val的本質不同在於:
- 捨棄train/val上下文;
- 不再使用DataLoader裝載資料,開始使用OpenCV等三方庫來直接讀取圖片樣本;
- 網路不再使用autograd上下文;
- 不再計算loss、acc等;取而代之的是使用Deepvac的*Report模組來進行準確度、速度方面的衡量;
- 程式碼更便於生產環境的部署;
繼承Deepvac類的子類必須(重新)實現以下方法才能夠開始測試:
類的方法(*號表示必需重新實現) | 功能 | 備註 |
---|---|---|
* initNetWithCode | 初始化http://self.net成員 | 用於初始化網路,在此方法中手動將網路轉移到device裝置中 |
* process | 網路的推理計算過程 | 在該過程中,通過report.add(gt, pred)新增測試結果,生成報告 |
一個test.py的小例子 test.py。開始測試前,必須在config.py中配置config.model_path
。
10. 再談配置檔案
基於deepvac的PyTorch專案,可以通過在config.py中新增一些特殊配置項來自動實現特定的功能。
- 輸出TorchScript;
- 輸出ONNX;
- 輸出NCNN;
- 輸出CoreML;
- 啟用自動混合精度訓練;
- 啟用分散式訓練;
- 啟用量化;
- 啟用tensorboard;
- (待完善)