说明:
本例程使用YOLOv3进行昆虫检测。例程分为数据处理、模型设计、损失函数、训练模型、模型预测和测试模型六个部分。本篇为第四部分,使用Momentum优化算法训练YOLOv3网络权重。数据集训练一轮就使用验证集计算验证损失,如果当前为最好验证损失,则保存网络权重。开始学习率如果过大,会导致损失值发散。模型大概训练100轮收敛,150轮已经过拟合。
实验代码:
训练模型:
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