[ML] Pytorch自学实战项目其3:神经网络RNN,学习的方法估算车辆yawrate,超参数调优学习。 不断更新中。。。

写在前面

本文为Pytorch自学实战项目其2和1的后续。1 https://blog.csdn.net/weixin_46479223/article/details/133316914中建立了简单的全连接网络学习yawrate,2https://blog.csdn.net/weixin_46479223/article/details/134054330中将数据集和模型改为rnn的形式,使用历史信息。都做了对应的训练和验证。
本节是针对rnn网络来调节超参数以及优化网络结构来获取更好的学习估计结果。

更新

Outline

  • 增加模型复杂度,移动到GPU
  • 超参数调整方法,超参数相关笔记
  • hyperopt && tensorboard&&加入 Earlystop Flag可视化
  • tensorRT

使用GPU

之前一直在cpu上搞,为了学习BEV,618整了块显卡,现在使用显卡训练。显卡驱动安装,cuda按照,pytorch安装均可见https://blog.csdn.net/h904798869/article/details/131719404

分别验证cuda工具包版本,显卡驱动情况(注意这显示的是可使用的最高版本的cuda而不是你安装好的),和torch版本。conda是因为我在使用anaconda虚拟环境

nvcc-V  
nvidia-smi 
conda list | grep torch

使用

import torch

print('CUDA 可用:', torch.cuda.is_available())
if torch.cuda.is_available():
    print('可用的 CUDA 设备数:', torch.cuda.device_count())
    print('当前 CUDA 设备索引:', torch.cuda.current_device())
    print('当前 CUDA 设备名称:', torch.cuda.get_device_name(torch.cuda.current_device()))
else:
    print('CUDA 不可用')

print(torch.__version__, torch.cuda.is_available())
# Pytorch 实际使用的运行时的 cuda 目录
import torch.utils.cpp_extension
print(torch.utils.cpp_extension.CUDA_HOME)

我这段代码也可以作出如下验证
在这里插入图片描述

开始调整超参数

首先这里,根据书《深度学习入门》的第6章开始一节一节尝试优化方法

同时 这篇文章里表达的很好,调参数主要是过拟合和找最优之间的对抗在这里插入图片描述

参数的更新&& 权重初始值

其实在1、2节中已经尝试过,具体不同梯度下降的处理方式按照上图中的目录可以自行搜索。

以下为本次对RNN网络结构的更新后的结构,具体修改解释见代码后的文章

成功跑起来版20231130 修改了batch的变形方法,我在对BN层用法的研究记录在了https://blog.csdn.net/weixin_46479223/article/details/134721806

class MyRNN(nn.Module):
    def __init__(self):
        super().__init__()
        self.linear_in = nn.Linear(9,32)
        self.relu = nn.ReLU()
        self.linear_32=nn.Linear(32,32)
        self.rnn = nn.RNN(input_size=32, hidden_size=32, num_layers=1, batch_first=True) 
        self.linear_out=nn.Linear(32,7)
        # 创建 Batch Normalization 层
        self.batch_norm_layer = nn.BatchNorm1d(num_features=32)
        self.dropout = nn.Dropout(p=0.5)  # 添加 Dropout 层,丢弃率0.5
        for name, param in self.named_parameters():
            if 'weight' in name:
                nn.init.normal_(param, mean=0.0, std=0.01)
            elif 'bias' in name:
                nn.init.constant_(param, 0)         
    def forward(self, x,hidden_prev):
        batch_size,sequence_length,num_features=x.shape
        temp1=self.linear_in(x)# temp1 (16,5,32)
        #temp1 = temp1.unsqueeze(2)  # 增加一个维度,变成 (batch_size, sequence_length, 1, input_size)
        temp1 = temp1.view(-1, 32)  # 将形状从 (batch_size, sequence_length, num_features) 改为 (batch_size*sequence_length, num_features) 
        temp11 = self.batch_norm_layer(temp1)
        temp11 = temp11.view(batch_size,sequence_length, 32)  # 再次变换形状回到原来的状态
        #temp1 = temp11.squeeze(2)  # 移除添加的维度
        temp2=self.relu (temp11)
        temp3=self.linear_32(temp2)# temp3 (16,5,32)
        out, hidden_prev = self.rnn(temp3,hidden_prev)# out (16,5,32) #hidden(1,16,32)        
        # Get output from the last time step
        last_output = out[:, -1, :]#last_output(16,32)   
        last_output = last_output.unsqueeze(1)# let (16,32)to(16,1,32)     
        # Feed into linear layer and apply activation
        temp4 = self.linear_32(last_output)#temp4 (16,1,32)
        #temp4 = temp4.unsqueeze(2)
        temp4 = temp4.view(-1, 32) 
        temp41 = self.batch_norm_layer(temp4)
        temp4 = temp41.view(batch_size,1, 32)  
        #temp4 = temp41.squeeze(2)
        temp5 = self.relu(temp41)#temp5(16,1,32)  
        # 应用 Dropout 层
        temp5 = self.dropout(temp5)
        output =self.linear_out(temp5)#output(16,1,7)
        return output,hidden_prev

batch normalization &&增加网络结构复杂度

这里我对2中的RNN 类作出两处修改

  • 加入对数据分布进行正规化的层batch_norm_layer
  • 增加全连接网络层数让网络学习到更复杂的结果。

关于细节这篇文章讲的很好,以及有关于数据特征的缩放处理
BatchNormalization
特征缩放
以下附上书中的解释,我理解这个还是对同一个特征 在批次维度上正规化,而不是同一个样本不同特征之间的样本标准化
同时,这个层带有可学习参数,要注意使用model.train() 和eval()改变其学习计算的方式。
在这里插入图片描述
在这里插入图片描述

扩展 gpt对batch normalization的解释
(更多可以见https://blog.csdn.net/weixin_46479223/article/details/132784268
Batch Normalization(批归一化)是一种用于加速深度神经网络训练过程、提高模型性能的技术。它在神经网络的每一层对输入进行归一化,使得每个特征的均值接近0,标准差接近1。这一操作通常在激活函数之前进行。

以下是Batch Normalization的一些关键思想和操作步骤:

思想:
    在神经网络中,每一层的输入分布可能会随着训练的进行而发生变化,这被称为“Internal Covariate Shift”问题。Batch Normalization的目标是通过标准化输入,减少这种分布变化,从而加速训练。

操作步骤:
    对于每个mini-batch(一小批样本),计算该批次中每个特征的均值和标准差。 # 我这里目前是16一批
    使用批次的均值和标准差对批次中的每个样本进行归一化,得到零均值和单位方差的样本。# 归一、L1、L2正则、标准化是不同的概念,归一还有批和层归一的区别
    引入可学习的参数(缩放和平移)进行线性变换,使得网络可以恢复其表达能力。
    在激活函数之前应用上述操作,确保输出的每个特征都被标准化。

Batch Normalization的优势包括:

加速收敛: 由于输入被标准化,神经网络更容易学到适当的权重,因此收敛速度更快。
降低对权重初始化的敏感性: Batch Normalization减少了对权重初始化的依赖,允许使用更大的学习率。
正则化效果: 类似于Dropout,Batch Normalization在一定程度上有正则化效果,可以减轻过拟合问题。

在实际应用中,Batch Normalization已经成为深度学习中的标配技术,被广泛应用于各种类型的神经网络。

正则化

在我2的结果中,发现已经出现了训练集准确度大于测试集合的效果,即过拟合。

书中提到权值衰减、L1 L2 范式(针对输出,BN是),但我这里不展开,可以根据书中提纲自行开展搜索,我这里使用dropout。

#init
self.dropout = nn.Dropout(p=0.5) 
#forward
temp5 = self.dropout(temp5)

扩展 gpt总结应对过拟合的方式

更多的数据: 提供更多的训练数据是减轻过拟合的有效方法。更多的数据有助于模型学到更一般的模式,从而提高在未见过的数据上的泛化能力。

数据增强: 对训练数据进行增强,通过对图像进行随机旋转、翻转、缩放等操作,可以生成更多样本,有助于模型更好地学习数据的不变性。

简化模型: 减少模型的复杂度,可以通过减少网络的层数、每层的神经元数目等方式来降低模型的容量,从而减少过拟合的风险。

正则化:
    L1和L2正则化: 在损失函数中加入L1或L2正则化项,限制权重的大小,防止模型学习过于复杂的特征。
    Dropout: 在训练过程中随机丢弃一部分神经元,防止神经元之间建立过于强烈的依赖关系,有助于泛化。

交叉验证: 使用交叉验证来评估模型的性能,确保模型在不同的数据划分上都有良好的表现,而不是只依赖于单一的训练-验证划分。

集成方法: 使用集成学习方法,如bagging和boosting,可以降低过拟合的风险。

早停: 监控模型在验证集上的性能,当性能不再提升时停止训练,以防止过拟合。

特征选择: 仔细选择与任务相关的特征,避免使用过多无关或冗余的特征。

对抗训练: 引入对抗样本训练,使模型对输入的微小扰动具有更好的鲁棒性。

注意力机制: 使用注意力机制帮助模型集中注意力于关键的部分,减少对噪声的过度关注。

超参数的调整作为本文下一次大更新

附上 GPT 所回答的超参数的调整项总结

学习率(Learning Rate):
    影响: 学习率决定了权重更新的步长,过大的学习率可能导致不稳定的训练,而过小的学习率可能导致训练速度过慢。
    调整方法: 使用学习率调度(learning rate schedule)、自适应学习率算法(如Adam、Adagrad)或者手动调整学习率。

权重衰减(Weight Decay):
    影响: 控制正则化项的大小,有助于防止过拟合。
    调整方法: 尝试不同的权重衰减系数,通常通过交叉验证或验证集的性能来选择最佳值。

批量大小(Batch Size):
    影响: 影响训练的速度和稳定性,较大的批量大小通常会提高训练速度,但也可能导致内存不足。
    调整方法: 通常通过实验来选择适当的批量大小,可以尝试不同的批量大小并监视性能。

迭代次数(Epochs):
    影响: 控制整个训练数据集被遍历的次数。
    调整方法: 通过观察模型在验证集上的性能,选择适当的迭代次数,过多的迭代可能导致过拟合。

隐藏层神经元数量和层数:
    影响: 影响模型的容量和复杂性。
    调整方法: 通过交叉验证或验证集性能选择合适的神经元数量和层数。

激活函数(Activation Function):
    影响: 不同的激活函数对梯度传播和模型的表达能力有影响。
    调整方法: 选择适合任务的激活函数,ReLU是常用的激活函数,但在某些情况下,tanh或sigmoid也可能更合适。

初始化方法(Weight Initialization):
    影响: 初始权重的选择可能影响模型的训练速度和性能。
    调整方法: 使用合适的初始化方法,如Xavier/Glorot初始化,或者使用预训练模型的权重。

优化器(Optimizer):
    影响: 不同的优化算法可能导致不同的训练速度和性能。
    调整方法: 尝试不同的优化算法,如Adam、SGD等,并调整其超参数。

Dropout率:
    影响: Dropout可以减少过拟合。
    调整方法: 尝试不同的Dropout率,通常在0.2到0.5之间,通过验证集性能选择最佳值。

学习率衰减和调度:

影响: 在训练的不同阶段使用不同的学习率,有助于稳定训练。
调整方法: 使用学习率衰减策略,如按指数衰减、按阶梯衰减等。

梯度裁剪(Gradient Clipping):

影响: 防止梯度爆炸问题。
调整方法: 设置梯度裁剪的阈值,通常在1.0附近,以确保梯度的大小在可控范围内。
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值