1. 程式人生 > 實用技巧 >[Paddle學習筆記][11][基於YOLOv3的昆蟲檢測-訓練模型]

[Paddle學習筆記][11][基於YOLOv3的昆蟲檢測-訓練模型]

說明:

本例程使用YOLOv3進行昆蟲檢測。例程分為資料處理、模型設計、損失函式、訓練模型、模型預測和測試模型六個部分。本篇為第四部分,使用Momentum優化演算法訓練YOLOv3網路權重。資料集訓練一輪就使用驗證集計算驗證損失,如果當前為最好驗證損失,則儲存網路權重。

實驗程式碼:

訓練模型:

from source.train import train

# 訓練模型
# train(epoch_numb=1,
#       learning_rate=[0.001, 0.0005, 0.00025, 0.00002, 0.00001],
#       lr_iterations=[4250, 8500, 12750, 17000],
# model_path='./output/darknet53-yolov3', # train_path='./dataset/train/', # valid_path='./dataset/val/') # train(epoch_numb=100, # learning_rate=[0.001, 0.0005, 0.00025, 0.00002, 0.00001], # lr_iterations=[8500, 17000, 25500, 34000], # model_path='./output/darknet53-yolov3', # train_path='./dataset/train/',
# valid_path='./dataset/val/') train(epoch_numb=150, learning_rate=[0.001, 0.0005, 0.00025, 0.00002, 0.00001], lr_iterations=[12750, 25500, 38250, 51000], model_path='./output/darknet53-yolov3', train_path='./dataset/train/', valid_path='./dataset/val/')

結果:

valid - iter: 63601, epoch: 149, loss: 95.885

best - epoch: 74, loss:92.725, time: 43219s

訓練結果

loss_cls + loss_obj + loss_loc + ignore + wtloc: base lr:0.001, epoch:50, best loss: 100.772

loss_cls + loss_obj + loss_loc + ignore + wtloc: base lr:0.001, epoch:100, best loss: 93.092

loss_cls + loss_obj + loss_loc + ignore + wtloc: base lr:0.001, epoch:150, best loss: 92.725

train.py檔案

import time
import numpy as np

import paddle.fluid as fluid
from paddle.fluid.dygraph.base import to_variable
from paddle.utils.plot import Ploter

from source.data import multip_thread_reader
from source.model import YOLOv3
from source.loss import get_sum_loss

num_classes = 7                                                                              # 類別數量
anchor_size = [10, 13, 16, 30, 33, 23, 30, 61, 62, 45, 59, 119, 116, 90, 156, 198, 373, 326] # 錨框大小
anchor_mask = [[6, 7, 8], [3, 4, 5], [0, 1, 2]]                                              # 錨框掩碼
ignore_threshold = 0.7                                                                       # 忽略閾值
downsample_ratio = 32                                                                        # 下采樣率

def train(epoch_numb=50,
          learning_rate=[0.001, 0.0005, 0.00025, 0.00002, 0.00001],
          lr_iterations=[4250, 8500, 12750, 17000],
          model_path='./output/darknet53-yolov3',
          train_path='./dataset/train/',
          valid_path='./dataset/val/'):
    """
    功能:
        訓練模型
    輸入:
        epoch_numb    - 迭代週期
        learning_rate - 學習率
        lr_iterations - 學習率迭代數
        model_path    - 模型儲存路徑
        train_path    - 訓練資料路徑
        valid_path    - 驗證資料路徑
    輸出:
    """
    with fluid.dygraph.guard(): # 動態圖域
        # 準備資料
        train_reader = multip_thread_reader(train_path, 4, 'train') # 讀取訓練資料
        valid_reader = multip_thread_reader(valid_path, 2, 'valid') # 讀取驗證資料

        # 宣告模型
        model = YOLOv3(num_classes=num_classes, anchor_mask=anchor_mask)

        # 優化演算法
        optimizer = fluid.optimizer.Momentum(
            learning_rate=fluid.layers.piecewise_decay(boundaries=lr_iterations, values=learning_rate),
            momentum=0.9,
            parameter_list=model.parameters())

        # 開始訓練
        train_prompt = "Train loss"                 # 訓練標籤
        valid_prompt = "Valid loss"                 # 驗證標籤
        ploter = Ploter(train_prompt, valid_prompt) # 損失影象
        
        iterator = 1                                # 迭代次數
        iter_time = time.time()                     # 迭代時間
        best_epoch = 0                              # 最好週期
        best_loss = 100000.0                        # 最好損失
        
        for epoch_id in range(epoch_numb):
            # 訓練模型
            model.train() # 設定訓練
            for batch_id, train_data in enumerate(train_reader()):
                # 讀取資料
                image, gtbox, gtcls, image_size = train_data # 讀取一條資料
                image = to_variable(image)                   # 轉換資料格式

                # 前向傳播
                infer = model(image)

                # 計算損失
                loss = get_sum_loss(
                    infer, gtbox, gtcls, num_classes, anchor_size, anchor_mask, ignore_threshold, downsample_ratio)

                # 反向傳播
                loss.backward()          # 反向傳播
                optimizer.minimize(loss) # 更新權重
                model.clear_gradients()  # 清除梯度
                
                # 顯示損失
                if iterator % 10 == 0:                                  # 顯示損失次數
                    ploter.append(train_prompt, iterator, loss.numpy()) # 新增損失數值
                    ploter.plot()                                       # 顯示損失影象
                    print("train - iter: {:5d}, epoch: {:3d}, loss: {[0]:.3f}, best loss:{:.3f}".format(
                        iterator, epoch_id, loss.numpy(), best_loss))
                iterator += 1 # 增加損失次數

            # 驗證模型
            loss_list = [] # 損失列表
            model.eval()   # 設定驗證
            for batch_id, valid_data in enumerate(valid_reader()):
                # 讀取資料
                image, gtbox, gtcls, image_size = valid_data # 讀取一條資料
                image = to_variable(image)                   # 轉換資料格式

                # 前向傳播
                infer = model(image)

                # 計算損失
                loss = get_sum_loss(
                    infer, gtbox, gtcls, num_classes, anchor_size, anchor_mask, ignore_threshold, downsample_ratio)

                # 記錄損失
                loss_list.append(loss.numpy())

            # 顯示損失
            mean_loss = np.mean(loss_list)                   # 計算驗證損失
            ploter.append(valid_prompt, iterator, mean_loss) # 新增損失數值
            ploter.plot()                                    # 顯示損失影象
            print("valid - iter: {:5d}, epoch: {:3d}, loss: {:.3f}".format(iterator, epoch_id, mean_loss))

            # 儲存模型
            if mean_loss < best_loss:
                fluid.save_dygraph(model.state_dict(), model_path) # 儲存模型
                best_loss = mean_loss                              # 更新損失
                best_epoch = epoch_id                              # 更新迭代

        # 顯示時間
        iter_time = time.time() - iter_time # 總的時間
        print("best - epoch:{:4d}, loss:{:.3f}, time: {:.0f}s".format(best_epoch ,best_loss, iter_time))

參考資料:

https://blog.csdn.net/litt1e/article/details/88814417

https://blog.csdn.net/litt1e/article/details/88852745

https://blog.csdn.net/litt1e/article/details/88907542

https://aistudio.baidu.com/aistudio/projectdetail/742781

https://aistudio.baidu.com/aistudio/projectdetail/672017

https://aistudio.baidu.com/aistudio/projectdetail/868589

https://aistudio.baidu.com/aistudio/projectdetail/122277