# yolor操作手冊
## Colab
- 照這個colab執行: https://colab.research.google.com/drive/1e1Uk9SjxBaagu7aoGZ4oTcqePhnMLM23?usp=sharing#scrollTo=cy8NlkoKg9lC
- 流程:
### step1.創環境跟下載yolor模型結構
git clone yolor跟相關套件mish cuda、pytorch-wavelets(不一定要載相關套件),yolor官網的installation有寫

```
git clone https://github.com/WongKinYiu/yolor
cd yolor
# pip install required packages
pip install -qr requirements.txt
# install mish-cuda if you want to use mish activation
# https://github.com/thomasbrandon/mish-cuda
# https://github.com/JunnYu/mish-cuda
git clone https://github.com/JunnYu/mish-cuda
cd mish-cuda
python setup.py build install
cd ..
# install pytorch_wavelets if you want to use dwt down-sampling module
# https://github.com/fbcotter/pytorch_wavelets
git clone https://github.com/fbcotter/pytorch_wavelets
cd pytorch_wavelets
pip install .
cd ..
```
->
### step2.prepare training data & `.yaml`
將想要train的資料分割成訓練(train)及測試(valid)資料
下載dataset放到yolor資料夾裡,如果是用Roboflow就繼續照著執行(要先到Roboflow網站下載)


如果不是用Roboflow就直接上傳放到yolor的資料夾裡(記得要有`.yaml`檔,可以用[https://codebeautify.org/yaml-validator](https://)確認格式對不對)
->
非必要:prepare pre-trained weights(也是照官網的Installation裡有寫)


但目前試起來有error,下載不了
->
### step3.`.cfg檔`
改`.cfg`配置檔裡面的head裡面四個[yolo]下的`classes=`和neck後面、head前面的`files=`的數量:

下面這個部分有四組:

可以手動改或是用colab裡的方式用程式直接改:

要加`/`
其他照著執行就能讀取.yaml檔知道classes數、算files數(`(classes數+5)*3)`)然後改.cfg檔
->
### step4.train
用已經有的yolor模型結構和剛剛準備的訓練資料,進行模型訓練
也是照官網,這個colab是執行一個GPU的版本


- 沒權重時:`--weights ''`
- --cfg [路徑],eg.`--cfg cfg/yolor_p6_waymo.cfg`
- 多gpu:`--nproc_per_node 8`搭配`--device 0,1,2,3,4,5,6,7`
- `--img`要配合訓練資料的照片大小,eg.`--img 1920 1920`
- `--name [name]`預設會存到`/yolor/runs/train/[name]`
執行結果:

->
### step5.Score Model
train完的結果會在`/yolor/runs/train/yolor_p6`之類的資料夾裡面,會有`results.png`檔(precision, recall, mAP等圖表)和`train_batch0.jpg`檔(train完框的結果?)可以看
->
### step6.存取最佳模型
可以用`runs/train/yolor_p6/weights`裡的`best_overall.pt`當新的權重Run或Train YOLOR
也可以把train完產生的權重存下來,以便之後使用
->
### step7.尋找最佳模型和參數
可以再用新資料去test(可參考yolor github官網的Testing),或是調校相關超參數(hyperparameter)跟`.cfg檔`裡的參數,尋找最佳模型和參數
## 國網
整體步驟差不多:
step1.創環境跟下載yolor模型結構->
step2.prepare training data & `.yaml`->
step3.`.cfg檔`->
step4.train->
step5.Score Model->
step6.存取最佳模型->
step7.尋找最佳模型和參數
只是step1和step4有些在國網的注意事項:
### 1.(step1):環境
先用minicinda3創一個python環境,再在裡面git clone yolor,和pytorch等相關需要的東東
```!
pip install torch==1.9.0+cu111 torchvision==0.10.0+cu111 torchaudio===0.9.0 -f https://download.pytorch.org/whl/torch_stable.html
pip install -U cython
pip install "git+https://github.com/philferriere/cocoapi.git#egg=pycocotools&subdirectory=PythonAPI"
```
*在國網下載相關套件(mish cuda、pytorch-wavelets)和pre-trained weight時有很多error,可以選擇不載
並寫一個開啟環境的`env.sh`
```!
module load miniconda3
conda activate yolor
#for Importerror
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/nckuhpclab11/.conda/envs/yolor/lib/
```
### 2.(step4):Importerror
如果遇到Importerror

解法:
在開啟環境的`env.sh`裡加`export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/nckuhpclab11/.conda/envs/yolor/lib/`
### 3.(step4):job
在國網上是要用提交job的方式執行train的那行指令
可參考的`job.sh`:
```shell=
#!/bin/bash
#SBATCH -p gp2d
#SBATCH -A ACD110038
#SBATCH --nodes=1
#SBATCH -J jocelin
#SBATCH --time=0-40:00:00
#SBATCH --nodelist=gn1215
#SBATCH --gres=gpu:8
#SBATCH --ntasks-per-node=1
#SBATCH --output=/home/nckuhpclab11/tzuyu/yolor/best_result/job_train_result_32
echo "Test start"
date
hostname
free -h
source /home/nckuhpclab11/jocelin/env.sh
cd /home/nckuhpclab11/tzuyu/yolor/
echo "gpu run"
echo "=============================="
python -m torch.distributed.launch --nproc_per_node 8 --master_port 9527 train.py --batch-size 32 --img 1920 1920 --data /home/nckuhpclab11/waymo_data/waymo_pytorch/pytorch_dataset/data.yaml --cfg cfg/yolor_p6_waymo.cfg --weights '' --device 0,1,2,3,4,5,6,7 --sync-bn --name yolor_p6_32 --hyp /home/nckuhpclab11/tzuyu/yolor/data/hyp.scratch.1280.yaml --epochs 1
echo "=============================="
date
echo "Test end"
```
### 4.(step4):batch-size & gpu
batch-size大小和gpu大概要介於1:1~8:1,batch-size大跑比較快,但太大會有error(CUDA out of memory)

(gpu=8
整個waymo dataset跑20小時
batch-size=4, 20hr => 不是gpu數的倍數,所以沒法跑
batch-size=64, => 做完前置後RuntimeError: CUDA out of memory.

### 5.(step4):資料大小跟時間
(還沒研究完)
- train/imags和labels裡的檔案數量分別是:**19701**
(waymo_jump_40;每四十幀取一次的dataset)
batch-size32, gpu=8:**3.157 hours**
- train/imags和labels裡的檔案數量分別是:**78736**
(waymo_jump;每十幀取一次的dataset)
batch-size32, gpu=8:**12.594 hours**
- train/imags和labels裡的檔案數量分別是:**99911**
(waymo_partof_small)
batch-size16, gpu=8: **27.337 hours**
batch-size32, gpu=8: **15.900 hours**
- train/imags和labels裡的檔案數量分別是:**396471**
(waymo_partof)
batch-size32, gpu=8:**64.065 hours**
### 6.(step4):多機(節點)多gpu
https://pytorch-ignite.ai/tutorials/intermediate/01-cifar10-distributed/#run-with-torchdistributedlaunch-recommended-1
主要概念:
`torch.distributed.launch`的參數要多加
```
--nnodes=2 \ #要用的節點數eg.2
--master_addr=master \ #eg1.gn1222 eg2.gn1222.twcc.ai (這個是hostname) eg3.$SLURM_JOB_NODELIST
--node_rank=0 #進程的序號 eg.$SLURM_PROCID
```
因為是用SLURM,所以大邏輯是用第一個job script(A) srun另一個script(B),然後在B scripy 來train
在A job script 設定SBATCH,其中會設到`#SBATCH --nodes=2`,所以srun會啟動兩個B script,一個B script裡會啟動8個`train.py`,所以最後能啟動16個`train.py`
*注意batch-size要是總gpu數的倍數
`job.sh`(A job script)
```=
#!/bin/bash
#SBATCH -p gp2d
#SBATCH -A ACD110038
#SBATCH --nodes=2
#SBATCH --wait-all-nodes=1
#SBATCH -J jocelin
#SBATCH --time=0-40:00:00
#SBATCH --nodelist=gn1225
#SBATCH --gres=gpu:8
#SBATCH --cpus-per-task=32
#SBATCH --ntasks-per-node=1
#SBATCH --output=/home/nckuhpclab11/tzuyu/yolor/best_result/job_train_result_56_light_96hr_ep6_Wep6_16gpu_5
date
srun /home/nckuhpclab11/tzuyu/a.sh
```
a.sh(B script)
```=
#!/bin/bash
echo "Test start"
date
hostname
free -h
source /home/nckuhpclab11/jocelin/env.sh
cd /home/nckuhpclab11/tzuyu/yolor/
echo rank $SLURM_PROCID
RANK=$SLURM_PROCID
echo "gpu run"
cho "=============================="
python -m torch.distributed.launch\
--nproc_per_node=8\
--nnodes=2\
--node_rank=$SLURM_PROCID\
--master_addr="gn1225.twcc.ai"\
--master_port 9527\
train.py --batch-size 56 \
--img 1920 1920\
--data /home/nckuhpclab11/tzuyu/waymo_partof_small/data.yaml\
--cfg cfg/yolor_p6_waymo.cfg \
--weights /home/nckuhpclab11/tzuyu/yolor/runs/train/yolor_p6_32_light_ep6_96hr_Wep1/weights/best_overall.pt \
--device 0,1,2,3,4,5,6,7 \
--sync-bn \
--name yolor_p6_32_light_96hr_ep6_Wep6_16gpu_node1_2 \
--hyp /home/nckuhpclab11/tzuyu/yolor/data/hyp.scratch.1280.yaml \
--epochs 8
echo "=============================="
date
echo "Test end"
```