CNN 训练模型时,需要调优,与哪些因素有关
学习率(Learning Rate):
学习率决定了参数在每次迭代中的更新幅度。过大的学习率可能导致震荡或发散,而过小的学习率可能导致训练过慢。通常需要通过尝试不同的学习率来找到最佳值。
批量大小(Batch Size):
批量大小定义了每次更新模型参数时使用的样本数量。较大的批量大小可能加速训练,但会增加内存需求。较小的批量大小可能提高模型的泛化能力,但可能导致训练过程更加不稳定。
迭代次数(Epochs):
迭代次数表示整个训练数据集被模型处理的次数。增加迭代次数通常可以提高模型性能,但过多的迭代可能导致过拟合。
权重初始化(Weight Initialization):
初始化权重的方式可能影响模型的收敛速度和性能。一些常见的初始化方法包括随机初始化、Xavier/Glorot初始化等。
优化器的选择:
不同的优化器对模型的性能有显著影响。常见的优化器包括随机梯度下降(SGD)、Adam、RMSprop等。每个优化器都有其优点和缺点,因此选择合适的优化器非常重要。
正则化(Regularization):
正则化方法,如L1正则化和L2正则化,可以帮助防止过拟合。它们通过向损失函数添加正则化项来对模型参数进行惩罚。
数据增强(Data Augmentation):
数据增强是通过对训练数据进行随机变换来扩充数据集。这有助于提高模型的泛化能力,减轻过拟合问题。
网络架构:
CNN的网络架构包括卷积层、池化层、全连接层等。调整网络深度、卷积核大小、池化方式等超参数可能对性能产生重要影响。
学习率调度(Learning Rate Scheduling):
逐渐降低学习率可以帮助模型更好地收敛。学习率调度方法包括按步骤调整、余弦退火等。
批量归一化(Batch Normalization):
批量归一化可以加速训练过程并提高模型的泛化能力。它在每个批次的数据上进行归一化,有助于缓解梯度消失和爆炸问题。
在调优过程中,往往需要进行反复尝试和实验,以找到最佳的超参数组合,从而获得性能良好的CNN模型。
根据参数调优的类别,分析调优效果
先对上一篇文章的代码做如下修改
创建数据生成器
import time
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
import numpy as np
import matplotlib.pyplot as plt
# 数据生成器
class DataGenerator(object):
def __init__(self):
super(DataGenerator, self).__init__()
self.trainData = []
self.trainLabels = []
self.valData = []
self.valLabels = []
# 检查tx,ty坐标象限分类
def check_quadrant(self, tx, ty):
if (tx > 0) and (ty > 0):
return 0 # 第一象限
if (tx < 0) and (ty > 0):
return 1 # 第二象限
if (tx < 0) and (ty < 0):
return 2 # 第三象限
if (tx > 0) and (ty < 0):
return 3 # 第四象限
# 浮点数比较
if (abs(tx) > 0) and (abs(ty) < 0.000001):
return 4 # x轴
# 浮点数比较
if (abs(tx) < 0.000001) and (abs(ty) > 0):
return 5 # y轴
return 6 # 原点
# 随机整数
def random_int(self, low, high):
return np.random.randint(low, high)
# 随机生成训练和验证数据
# train(low, high, count)
# val(low, high, count)
def generateData(self, train: tuple[int, int, int], val: tuple[int, int, int]):
self.trainData.clear()
self.trainLabels.clear()
self.valData.clear()
self.valLabels.clear()
low = train[0]
high = train[1]
count = train[2]
for i in range(count):
tx = self.random_int(low, high)
ty = self.random_int(low, high)
tl = self.check_quadrant(tx, ty)
self.trainData.append([tx, ty])
self.trainLabels.append(tl)
low = val[0]
high = val[1]
count = val[2]
for i in range(count):
tx = self.random_int(low, high)
ty = self.random_int(low, high)
tl = self.check_quadrant(tx, ty)
self.valData.append([tx, ty])
self.valLabels.append(tl)
# 转化为Numpy数据格式
def toNumpyObj(self):
return np.array(self.trainData, dtype=np.float32), np.array(self.trainLabels, dtype=np.int64), \
np.array(self.valData, dtype=np.float32), np.array(self.valLabels, dtype=np.int64)
# 转化为张量对象
def toTensorObj(self):
td, tl, vd, vl = self.toNumpyObj()
return torch.from_numpy(td), torch.from_numpy(tl), torch.from_numpy(vd), torch.from_numpy(vl)
构建神经网络模型
class QuadrantClassifier(nn.Module):
def __init__(self):
super(QuadrantClassifier, self).__init__()
# 输入层,中间层,输出层列表
self.mLayers = []
# 设置输入层,中间层,输出层(用于层数量的多少对结果性能的比较)
# 输入层,中间层,输出层特别数要一一对应起来(否则会出错)
# 至少要有两层(一个输入层,一个输出层)
def setLayers(self, layers: list[tuple[int, int]]):
self.mLayers.clear()
layerCnt = 0
for tmpLL in layers:
layerCnt += 1
tmpLayer = nn.Linear(tmpLL[0], tmpLL[1])
# 这里需要动态设置性值(否则创建优化器时,会报模型的参数为空,不知是何原因)
setattr(self, "layer_%d" % layerCnt, tmpLayer)
self.mLayers.append(tmpLayer)
# 神经网络每次调用时都需要执行的前向传播计算(使用ReLU激活函数)
def forward(self, x):
layerSize = len(self.mLayers)
# 输入层和中间层都采用ReLU激活函数
for tl in range(layerSize - 1):
x = torch.relu(self.mLayers[tl](x))
# 最后一层为输出层(输出层不使用激活函数)
x = self.mLayers[layerSize - 1](x)
return x
模型处理类
class ModelProcessor(object):
def __init__(self):
super(ModelProcessor, self).__init__()
# 训练数据和验证数据
self.mTrainData = None
self.mTrainLabels = None
self.mValData = None
self.mValLabels= None
# 模型对象
self.mQmodel = None
# 输入层,中间层,输出层列表
self.mLayers = None
# 损失函数
self.mCriterion = None
# 优化器
self.mOptimizer = None
# 数据加载器
self.mDataloader = None
# 学习率
self.mLr = 0.001
# 训练次数
self.mEpochs = 100
# 模型保存的路径
self.mQmodelPath = "./model/quadrant_v2.pt"
# 模型的准确率
self.mSucRatio = 0.0
# 训练所花费的总时间(s)
self.mTrainTime = 0.0
def setTrainValData(self, trainData, trainLabels, valData, valLabels):
self.mTrainData = trainData
self.mTrainLabels = trainLabels
self.mValData = valData
self.mValLabels = valLabels
# 设置输入层,中间层,输出层(用于层数量的多少对结果性能的比较)
# 输入层,中间层,输出层特别数要一一对应起来(否则会出错)
# 至少要有两层(一个输入层,一个输出层)
def setLayers(self, layers: list[tuple[int, int]]):
self.mLayers = layers
def setEpochs(self, epochs: int):
self.mEpochs = epochs
def setLr

本文围绕CNN训练模型调优展开,介绍了学习率、批量大小、迭代次数等多个影响调优的因素,强调需反复尝试找最佳超参数组合。还通过修改代码,分析了调节迭代次数和改变训练数据分布范围对模型泛化能力的影响,如调节迭代次数准确率提升不明显,扩大样本范围准确率有提高。
最低0.47元/天 解锁文章
1067

被折叠的 条评论
为什么被折叠?



