# Yolov7 說明書
## **準備材料**
### 1. 資料集
資料集中應該包含:
* 圖片檔
* label檔

且圖片與label檔的檔名必須相同
並分成以下三個類別:
* train (占資料集照片的60%,訓練模型的數據集)
* test (占資料集照片的20%,評估模型性能的數據集)
* val (占資料集照片的20%,調整模型超參數和進行模型選擇)
以上比例可自行調整
以下為分檔程式,可以自行調整train、test、val的比例,且會生成train.txt、test.txt、val.txt,這三個txt將會再設定data.yaml時使用
```
import shutil
import random
import os
# 原始資料集路徑,通常只須改這裡
image_original_path = "./mydataset/fall_image/"
label_original_path = "./mydataset/fall_label/"
cur_path = os.getcwd()
# 訓練集路徑
train_image_path = os.path.join(cur_path, "datasets/images/train/")
train_label_path = os.path.join(cur_path, "datasets/labels/train/")
# 驗證集路徑
val_image_path = os.path.join(cur_path, "datasets/images/val/")
val_label_path = os.path.join(cur_path, "datasets/labels/val/")
# 測試集路徑
test_image_path = os.path.join(cur_path, "datasets/images/test/")
test_label_path = os.path.join(cur_path, "datasets/labels/test/")
# 訓練集目錄
list_train = os.path.join(cur_path, "datasets/train.txt")
list_val = os.path.join(cur_path, "datasets/val.txt")
list_test = os.path.join(cur_path, "datasets/test.txt")
#更改三個資料集的比例
train_percent = 0.8
val_percent = 0.1
test_percent = 0.1
# 刪除文件的函數
def del_file(path):
for i in os.listdir(path):
file_data = path + "\\" + i
os.remove(file_data)
# 建立目錄的函數
def mkdir():
if not os.path.exists(train_image_path):
os.makedirs(train_image_path)
else:
del_file(train_image_path)
if not os.path.exists(train_label_path):
os.makedirs(train_label_path)
else:
del_file(train_label_path)
if not os.path.exists(val_image_path):
os.makedirs(val_image_path)
else:
del_file(val_image_path)
if not os.path.exists(val_label_path):
os.makedirs(val_label_path)
else:
del_file(val_label_path)
if not os.path.exists(test_image_path):
os.makedirs(test_image_path)
else:
del_file(test_image_path)
if not os.path.exists(test_label_path):
os.makedirs(test_label_path)
else:
del_file(test_label_path)
# 清理文件的函數
def clearfile():
if os.path.exists(list_train):
os.remove(list_train)
if os.path.exists(list_val):
os.remove(list_val)
if os.path.exists(list_test):
os.remove(list_test)
# 主函數
def main():
mkdir()
clearfile()
file_train = open(list_train, 'w')
file_val = open(list_val, 'w')
file_test = open(list_test, 'w')
total_txt = os.listdir(label_original_path)
num_txt = len(total_txt)
list_all_txt = range(num_txt)
num_train = int(num_txt * train_percent)
num_val = int(num_txt * val_percent)
num_test = num_txt - num_train - num_val
train = random.sample(list_all_txt, num_train)
# 從list_all_txt中取出num_train個元素作為訓練集
val_test = [i for i in list_all_txt if not i in train]
# 再從val_test取出num_val個元素,val_test剩下的元素就是測試集
val = random.sample(val_test, num_val)
print("訓練集數目:{}, 驗證集數目:{}, 測試集數目:{}".format(len(train), len(val), len(val_test) - len(val)))
for i in list_all_txt:
name = total_txt[i][:-4]
srcImage = image_original_path + name + '.jpg'
srcLabel = label_original_path + name + ".txt"
if i in train:
dst_train_Image = train_image_path + name + '.jpg'
dst_train_Label = train_label_path + name + '.txt'
shutil.copyfile(srcImage, dst_train_Image)
shutil.copyfile(srcLabel, dst_train_Label)
file_train.write(dst_train_Image + '\n')
elif i in val:
dst_val_Image = val_image_path + name + '.jpg'
dst_val_Label = val_label_path + name + '.txt'
shutil.copyfile(srcImage, dst_val_Image)
shutil.copyfile(srcLabel, dst_val_Label)
file_val.write(dst_val_Image + '\n')
else:
dst_test_Image = test_image_path + name + '.jpg'
dst_test_Label = test_label_path + name + '.txt'
shutil.copyfile(srcImage, dst_test_Image)
shutil.copyfile(srcLabel, dst_test_Label)
file_test.write(dst_test_Image + '\n')
file_train.close()
file_val.close()
file_test.close()
if __name__ == "__main__":
main()
```
### 2. 設定cfg.yaml
在cfg/training中可以找到yolov7.yaml,而其他的選擇則是依照你所選之weight檔做決定。

為了方便只截重要的部分
其中
* nc=你所需要辨別物體的數量,假設我要辨別 1.安全帽 2.安全背心
則nc=2,其他不動

### 3. 設定data.yaml
使yolo訓練時能讀取你所自訂的資料集,以下為我所創造的data.yaml

內容如下:

1. 須將train、val、test的路徑改為之前所生成的train.txt、test.txt、val.txt的路徑
2. 更改 nc 及 names,其中names為標註之物體的名稱
### 3. 下載預訓練權重(pre_train_weight)
從官網下載權重檔,並放置於主目錄下

**以上設定完成便可開始訓練!**
## **開始訓練**
1. 首先檢查train.py中的參數,可以看到以下內容

這部分需要修的只有Batch_size,將其從16改成8,除非顯卡夠好
接著在終端機輸入以下內容:
```
python3 train.py --weights /home/k900/yolov7_defect/weights/yolov7.pt --cfg /home/k900/yolov7_defect/cfg/training/yolov7.yaml --data /home/k900/yolov7_defect/data/defect.yaml --epochs 100 --device 0
```
* --weights : 預訓練權重檔的路徑
* --cfg : cfg檔的位置
* --data : data檔的位置
* --epochs : 訓練回數
* --device 0 : 使用GPU訓練,預設為使用cpu