---
# System prepended metadata

title: Yolov7 說明書

---

# Yolov7 說明書

## **準備材料**
### 1. 資料集
資料集中應該包含:
    * 圖片檔 
    * label檔
![圖片](https://hackmd.io/_uploads/rk1nGkPN0.png)
且圖片與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檔做決定。
![圖片](https://hackmd.io/_uploads/BJF_LywNA.png)
為了方便只截重要的部分
其中
* nc=你所需要辨別物體的數量，假設我要辨別 1.安全帽 2.安全背心
  則nc=2，其他不動
![圖片](https://hackmd.io/_uploads/H1mWwkDE0.png)

### 3. 設定data.yaml
使yolo訓練時能讀取你所自訂的資料集，以下為我所創造的data.yaml
![圖片](https://hackmd.io/_uploads/HyMHdkP4R.png)

內容如下:

![圖片](https://hackmd.io/_uploads/HyFcuJP4R.png)

1. 須將train、val、test的路徑改為之前所生成的train.txt、test.txt、val.txt的路徑
2. 更改 nc 及 names，其中names為標註之物體的名稱

### 3. 下載預訓練權重(pre_train_weight)

從官網下載權重檔，並放置於主目錄下
![圖片](https://hackmd.io/_uploads/Hy93c1v4R.png)

**以上設定完成便可開始訓練!**

## **開始訓練**
1. 首先檢查train.py中的參數，可以看到以下內容
![圖片](https://hackmd.io/_uploads/SJjLi1w4C.png)
這部分需要修的只有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





