- 🍨 本文為🔗365天深度學習訓練營中的學習記錄博客
- 🍖 原作者:K同學啊
一、配置環境
1.官網下載源碼
2.安裝需要環境
二、準備好自己的數據
目錄結構:
·主目錄
? ? ? ? ·data
? ? ? ? ? ? ? ? ·images(存放圖片)
? ? ? ? ? ? ? ? ·annotations(放置.xml文件)
? ? ? ? ? ? ? ? ·imagesets
? ? ? ? ? ? ? ? ? ? ? ? ·main(會在該文件夾內自動生成train.txt、val.txt、test.txt、trainval.txt文件,? 存放訓練集、驗證集、測試集圖片的名字)
? ? ? ? ? ? ? ? ·split_train_val.py(劃分訓練集、驗證集與測試集)
? ? ? ? ? ? ? ? ·voc_label.py(獲取劃分訓練集、驗證集與測試集路徑)
? ? ? ? ? ? ? ? ·ab.yaml(數據集及數據類別聲明文件)
? ? ? ? ·trainByK.py(代碼運行文件)
1.運行split_train_val.py文件
文件代碼:
import os,random,argparseparser=argparse.ArgumentParser()# 添加命令行參數,用于指定XML文件的路徑,默認為‘Annotation'文件夾
parser.add_argument('--xml_path',default='Annotations',type=str,help='input xml label path')#添加命令行參數,用于指定輸出txt標簽文件的路徑,默認為'ImageSets/Main'文件
parser.add_argument('--txt_path',default='ImageSets/Main',type=str,help='output txt label path')#解析命令行參數
opt=parser.parse_args()#定義訓練驗證集和測試集的劃分比例
trainval_percent=1.0 # 使用全部數據
train_percent=0.9 # 訓練集占訓練驗證集的90%# 設置XML文件夾的路徑,根據命令行參數指定
xmlfilepath=opt.xml_path# 設置輸出txt標簽文件的路徑,根據命令行參數指定
txtsavepath=opt.txt_path# 獲取XML文件夾中的所有XML文件列表
total_xml=os.listdir(xmlfilepath)# 如果輸出txt標簽文件的文件夾不存在,創建它
if not os.path.exists(txtsavepath):os.makedirs(txtsavepath)# 獲取XML文件的總數
num=len(total_xml)# 創建一個包含所有XML文件索引的列表
list_index=range(num)# 計算訓練驗證集的數量
tv=int(num*trainval_percent)# 計算訓練集的數量
tr=int(tv*train_percent)# 從所有XML文件索引中隨機選擇出訓練驗證集的索引
trainval=random.sample(list_index,tv)# 從訓練驗證集的索引中隨機選擇出訓練集的索引
train=random.sample(trainval,tr)# 打開要寫入的訓練驗證集、測試集、訓練集、驗證集的txt文件
file_trainval=open(txtsavepath+'/trainval.txt','w')
file_test=open(txtsavepath+'/test.txt','w')
file_train=open(txtsavepath+'/train.txt','w')
file_val=open(txtsavepath+'/val.txt','w')#遍歷所有XML文件的索引
for i in list_index:name = total_xml[i][:-4] + '\n' #獲取XML文件的名稱(去掉后綴.xml),并添加換行符#如果該索引在訓練驗證集中if i in trainval:file_trainval.write(name) #寫入訓練驗證集txt文件if i in train:file_train.write(name)else:file_val.write(name)else:file_test.write(name)file_trainval.close()
file_train.close()
file_val.close()
file_test.close()
運行后得到四個文件:
注:如何修改數據集中訓練集、驗證集、測試集的比例?
2.運行voc_label.py文件(將label格式轉換為VOC格式)
文件代碼:
#-*- coding:utf-8 -*-import xml.etree.ElementTree as ET
import os
from os import getcwd#定義數據集的名稱
sets =['train','val','test']#請根據您的數據集修改這些類別名稱
# classes =['Banana','Snake fruit','Dragon fruit','Pineapple']
classes = ["banana","snake fruit","dragon fruit","pineapple"]#獲取當前工作目錄的絕對路徑
abs_path = os.getcwd()
print(abs_path)#定義一個函數,將邊界框的坐標從絕對值轉換為相對于圖像大小的比例
def convert(size,box):dw = 1./(size[0]) #計算圖像寬度的倒數dh = 1./(size[1]) #計算圖像高度的倒數x = (box[0]+box[1])/2.0-1 #計算中心點的x坐標y = (box[2]+box[3])/2.0-1 # 計算中心點的y坐標w= box[1]- box[0] # 計算邊界框的寬度h = box[3] - box[2] # 計算邊界框的高度x = x * dw # 縮放x坐標w = w * dw # 縮放寬度y = y * dh # 縮放y坐標h=h*dh #縮放高度return x, y, w, h# 定義一個函數,將標注文件從XML格式轉換為YOLO格式
def convert_annotation(image_id):in_file = open('./Annotations/%s.xml' % (image_id),encoding='UTF-8') # 打開XML標注文件out_file = open('./labels/%s.txt'%(image_id),'w') # 打開要寫入的YOL0格式標簽文件tree =ET.parse(in_file) #解析XML文件root = tree.getroot()filename = root.find('filename').text # 獲取圖像文件名filenameFormat=filename.split(".")[1] # 獲取文件格式size = root.find('size') # 獲取圖像尺寸信息w= int(size.find('width').text) # 獲取圖像寬度h=int(size.find('height').text) #獲取圖像高度for obj in root.iter('object'):difficult = obj.find('difficult').text # 獲取對象的難度標志cls= obj.find('name').text #獲取對象的類別名稱if cls not in classes or int(difficult)== 1:continuecls_id = classes.index(cls) # 獲取類別的索引xmlbox = obj.find('bndbox') # 獲取邊界框坐標信息b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),float(xmlbox.find('ymax').text))b1,b2,b3,b4 = b# 標注越界修正if b2 > w:b2 = wif b4 > h:b4 = hb=(b1,b2,b3,b4)bb=convert((w,h),b) #調用convert函數,將邊界框坐標轉換為Y0OLO格式out_file.write(str(cls_id)+" "+" ".join([str(a) for a in bb])+'\n') #寫入YOLO格式標簽文件return filenameFormat#獲取當前工作目錄
wd = getcwd()#遍歷每個數據集(train、val、test)
for image_set in sets:#如果labels目錄不存在,創建它if not os.path.exists('./labels/'):os.makedirs('./labels/')#從數據集文件中獲取圖像ID列表image_ids = open('./ImageSets/Main/%s.txt'%(image_set)).read().strip().split()#打開要寫入的文件,寫入圖像的文件路徑和格式list_file =open('./%s.txt'%(image_set),'w')for image_id in image_ids:filenameFormat=convert_annotation(image_id)list_file.write(abs_path +'/images/%s.%s\n'%(image_id,filenameFormat)) #注意你的圖片格式,如果是.jpg記得修改list_file.close()
運行voc_label.py,獲得三個文件
3.創建ab.yaml文件
train:D:\learn\data\train.txt #絕對路徑
val:D:\learn\data\val.txt #絕對路徑nc: 4 # number of classesnames: ["banana", "snake fruit", "dragon fruit", "pineapple"]
三、開始用自己數據集訓練模型
自建train.py文件運行
from ultralytics import YOLOif __name__ == '__main__':model = YOLO("yolov8s.pt")model.train(data=r"D:\learn\ultralytics-main\data\ab.yaml",seed=0,epoches=10,batch=4,workes=2)
修改了很久,可能環境方面出了問題,依舊連接不到我的數據文件夾里。
四、訓練參數設置(defalult.yaml)
# Ultralytics YOLO 🚀, AGPL-3.0 許可證,由K同學啊注解
# 默認的訓練設置和超參數,用于中度增強 COCO 訓練task: detect # (str) YOLO 任務,例如 detect、segment、classify、pose
mode: train # (str) YOLO 模式,例如 train、val、predict、export、track、benchmark# 訓練設置 -------------------------------------------------------------------------------------------------------
model: # (str, 可選) 模型文件路徑,例如 yolov8n.pt、yolov8n.yaml
data: #./paper_data/ab.yaml # (str, 可選) 數據文件路徑,例如 coco128.yamlepochs: 100 # (int) 訓練的輪次數
patience: 50 # (int) 提前停止訓練的等待周期數,如果沒有明顯的改進
batch: 1 # (int) 每批處理的圖像數量(-1 表示自動批處理)
imgsz: 640 # (int | list) 輸入圖像的大小,以像素為單位,用于訓練和驗證模式,或以列表[w,h]形式用于預測和導出模式
save: True # (bool) 保存訓練檢查點和預測結果
save_period: -1 # (int) 每隔 x 個周期保存一個檢查點(如果 < 1 則禁用)
cache: False # (bool) 使用緩存加載數據(True/ram、disk 或 False)
device: 0 # (int | str | list, 可選) 運行模型的設備,例如 cuda device=0 或 device=0,1,2,3 或 device=cpu
workers: 4 # (int) 數據加載的工作線程數(每個 DDP 會有一個)
project: # (str, 可選) 項目名稱
name: # (str, 可選) 實驗名稱,結果保存在 'project/name' 目錄下
exist_ok: False # (bool) 是否覆蓋現有的實驗
pretrained: True # (bool | str) 是否使用預訓練模型(True 或加載權重的模型路徑字符串)
optimizer: auto # (str) 優化器選擇,選項=[SGD、Adam、Adamax、AdamW、NAdam、RAdam、RMSProp、auto]
verbose: True # (bool) 是否打印詳細輸出
seed: 0 # (int) 隨機種子,用于可重復性
deterministic: True # (bool) 是否啟用確定性模式
single_cls: False # (bool) 是否將多類數據訓練為單一類別
rect: False # (bool) 如果模式='train',則進行矩形訓練;如果模式='val',則進行矩形驗證
cos_lr: False # (bool) 是否使用余弦學習率調度器
close_mosaic: 10 # (int) 在最后幾個周期內禁用馬賽克增強(0 表示禁用)
resume: False # (bool) 是否從上次檢查點恢復訓練
amp: True # (bool) 是否啟用自動混合精度(AMP)訓練,選項=[True, False],True 表示運行 AMP 檢查
fraction: 1.0 # (float) 訓練集數據分數(默認為 1.0,使用訓練集中的所有圖像)
profile: False # (bool) 在訓練期間記錄 ONNX 和 TensorRT 速度以供記錄器使用
freeze: None # (int | list, 可選) 凍結前 n 層,或在訓練期間凍結的層索引列表
# 分割
overlap_mask: True # (bool) 訓練期間是否允許蒙版重疊(僅適用于分割訓練)
mask_ratio: 4 # (int) 蒙版下采樣比率(僅適用于分割訓練)
# 分類
dropout: 0.0 # (float) 是否使用 dropout 正則化(僅適用于分類訓練)# 驗證/測試設置 ----------------------------------------------------------------------------------------------------
val: True # (bool) 訓練期間是否進行驗證/測試
split: val # (str) 用于驗證的數據集分割,例如 'val'、'test' 或 'train'
save_json: False # (bool) 是否將結果保存為 JSON 文件
save_hybrid: False # (bool) 是否保存標簽的混合版本(標簽 + 額外的預測)
conf: # (float, 可選) 用于檢測的對象置信度閾值(默認 0.25 用于預測,0.001 用于驗證)
iou: 0.7 # (float) NMS 的交并比(IoU)閾值
max_det: 300 # (int) 每張圖像的最大檢測數
half: False # (bool) 是否使用半精度(FP16)
dnn: False # (bool) 是否使用 OpenCV DNN 進行 ONNX 推理
plots: True # (bool) 在訓練/驗證期間保存圖形# 預測設置 --------------------------------------------------------------------------------------------------
source: # (str, 可選) 圖像或視頻的源目錄
show: False # (bool) 如果可能的話是否顯示結果
save_txt: False # (bool) 是否將結果保存為 .txt 文件
save_conf: False # (bool) 是否保存帶有置信度分數的結果
save_crop: False # (bool) 是否保存裁剪后的帶有結果的圖像
show_labels: True # (bool) 是否在圖形中顯示對象標簽
show_conf: True # (bool) 是否在圖形中顯示對象置信度分數
vid_stride: 1 # (int) 視頻幀率跨度
stream_buffer: False # (bool) 是否緩存所有流式幀(True)或返回最新的幀(False)
line_width: # (int, 可選) 邊界框的線寬,如果缺失則自動設置
visualize: False # (bool) 是否可視化模型特征
augment: False # (bool) 是否對預測源應用圖像增強
agnostic_nms: False # (bool) 是否進行類別無關的 NMS
classes: # (int | list[int], 可選) 按類別篩選結果,例如 classes=0,或 classes=[0,2,3]
retina_masks: False # (bool) 是否使用高分辨率分割蒙版
boxes: True # (bool) 在分割預測中顯示邊界框# 導出設置 ------------------------------------------------------------------------------------------------------
format: torchscript # (str) 導出格式,可選項請查看 https://docs.ultralytics.com/modes/export/#export-formats
keras: False # (bool) 是否使用 Kera=s
optimize: False # (bool) TorchScript:優化為移動設備
int8: False # (bool) CoreML/TF INT8 量化
dynamic: False # (bool) ONNX/TF/TensorRT:動態軸
simplify: False # (bool) ONNX:簡化模型
opset: # (int, 可選) ONNX:opset 版本
workspace: 4 # (int) TensorRT:工作空間大小(GB)
nms: False # (bool) CoreML:添加 NMS# 超參數 ------------------------------------------------------------------------------------------------------
lr0: 0.01 # (float) 初始學習率(例如,SGD=1E-2,Adam=1E-3)
lrf: 0.01 # (float) 最終學習率(lr0 * lrf)
momentum: 0.937 # (float) SGD 動量/Adam beta1
weight_decay: 0.0005 # (float) 優化器權重衰減 5e-4
warmup_epochs: 3.0 # (float) 預熱周期數(分數也可以)
warmup_momentum: 0.8 # (float) 預熱初始動量
warmup_bias_lr: 0.1 # (float) 預熱初始偏置 lr
box: 7.5 # (float) 目標框損失增益
cls: 0.5 # (float) 類別損失增益(與像素一起縮放)
dfl: 1.5 # (float) DFL 損失增益
pose: 12.0 # (float) 姿勢損失增益
kobj: 1.0 # (float) 關鍵點 obj 損失增益
label_smoothing: 0.0 # (float) 標簽平滑化(分數)
nbs: 64 # (int) 名義批次大小
hsv_h: 0.015 # (float) 圖像 HSV-Hue 增強(分數)
hsv_s: 0.7 # (float) 圖像 HSV-Saturation 增強(分數)
hsv_v: 0.4 # (float) 圖像 HSV-Value 增強(分數)
degrees: 0.0 # (float) 圖像旋轉(+/- 度)
translate: 0.1 # (float) 圖像平移(+/- 分數)
scale: 0.5 # (float) 圖像縮放(+/- 增益)
shear: 0.0 # (float) 圖像剪切(+/- 度)
perspective: 0.0 # (float) 圖像透視變換(+/- 分數),范圍 0-0.001
flipud: 0.0 # (float) 圖像上下翻轉(概率)
fliplr: 0.5 # (float) 圖像左右翻轉(概率)
mosaic: 1.0 # (float) 圖像馬賽克增強(概率)
mixup: 0.0 # (float) 圖像混合增強(概率)
copy_paste: 0.0 # (float) 段復制粘貼(概率)# 自定義 config.yaml ---------------------------------------------------------------------------------------------------
cfg: # (str, 可選) 用于覆蓋默認.yaml 的自定義配置# 跟蹤器設置 ------------------------------------------------------------------------------------------------------
tracker: botsort.yaml # (str) 跟蹤器類型,選項=[botsort.yaml, bytetrack.yaml]
五、總結
閱讀代碼能力比之前強了,但是還是缺少連接所有知識的能力。有的時候總會忘記之前出現問題的解決辦法,導致實驗無法進行。?