深度学习理论基础(二)深度神经网络DNN

目录

  • 一、基础知识点
    • Ⅰ 参数部分
    • Ⅱ 模型部分
  • 二、深度神经网络模型搭建
    • 1. 准备数据集
    • 2. 划分数据集
    • 3. 搭建模型
    • 4. 训练网络
    • 5. 测试网络
    • 6. 保存与导入模型

  神经网络通过学习大量样本的输入与输出特征之间的关系,以拟合出输入与输出之间的方程,学习完成后,只给它输入特征,它便会可以给出输出特征。神经网络可以分为这么几步:准备数据集、划分数据集、搭建网络模型、训练网络、测试网络、使用网络。
  神经网络的训练过程,就是经过很多次前向传播与反向传播的轮回,最终不断调整其内部参数(权重 ω 与偏置 b),以拟合任意复杂函数的过程。内部参数一开始是随机的(如 Xavier 初始值、He 初始值),最终会不断优化到最佳。
  对于整个流程如下:我们先准备好样本数据以及样本对应的标签(一般给模型的输入都是tensor格式的,如果初始数据集不是tensor格式则需要转为tensor格式),将整个样本分为训练集和测试集,一般为8/2或7/3,训练集必须大于测试集,因为我们是训练模型,所以要使用更多的数据去训练优化模型,具体的划分比例按实际情况分析。 训练过程:先定义损失函数、学习率和优化器(具体选择哪个函数和优化器根据情况而定)。将训练集的样本放入网络中去获得预测标签,然后将预测的标签和真实样本的标签放入损失函数中进行计算损失,再将计算的损失进行反向传播,并使用优化器进行优化模型参数。训练优化模型的参数。 测试过程:测试过程和训练过程唯一的区别就是测试网络中不需要回传梯度,即不需要进行反向传播。所以也不需要定义损失函数和优化器,直接将测试集的样本放入模型进行一次前向传播,得出预测标签,然后将预测标签和真实标签进行比较,最终得出准确率。
  神经网络:深度神经网络(DNN)、卷积神经网络(CNN)。

一、基础知识点

Ⅰ 参数部分

  1. 损失函数:计算真实值和预测值差异的一类函数。预测值越接近真实值时,损失越低。我们训练的最终目的就是使得损失函数降到最低。一般用在训练网络中,将样本放入模型中得出预测标签,然后将预测标签和真实标签放入损失函数中计算损失,再将损失进行回传(反向传播),通过优化器进行优化模型的参数。损失函数有很多种,可用于不同的神经网络模型。

  2. 激活函数:引入非线性性,使得神经网络能够学习复杂的模式和函数。激活函数通常被应用在神经网络的每一层的输出上。选择合适的激活函数通常取决于具体的任务和数据集。如果每层网络输出后不加上激活函数进行非线性调整的话,那么就算搭建一百层的网络,其实一层就可以搞定。所以激活函数是很必要的!神经网络各层功能函数详情查看地址。
    在这里插入图片描述
    在这里插入图片描述

  3. 学习率:训练神经网络时的一个关键超参数,它控制模型参数在每次迭代中更新的幅度。一个合适的学习率可以使模型在训练过程中快速收敛到局部最优解或全局最优解,而一个不合适的学习率可能会导致训练过程出现问题,例如收敛速度过慢、陷入局部最优解等。

Ⅱ 模型部分

  1. 模型的输入:模型的输入通常需要是张量(tensor)的形式。这是因为深度学习模型是基于张量运算构建的,张量提供了一种有效的方式来表示和处理数据。在深度学习模型中使用输入数据,你通常需要将原始数据转换为张量的形式。
  2. 训练集和测试集:训练集是用来训练模型的数据集,它包含了模型需要学习的样本和对应的标签。在训练过程中,模型通过训练集中的样本进行学习,调整参数以最小化损失函数。在模型训练完成后,使用测试集来评估模型在未知数据上的泛化能力。测试集的目的是检查模型是否能够正确地推广到新的、未见过的数据上,以验证模型的性能和有效性。
  3. 训练网络和测试网络:训练网络和测试网络的区别就在于,训练网络需要回传梯度,即反向传播。而测试网络不需要回传梯度。
  4. 前向传播:在前向传播过程中,输入数据通过神经网络的各个层,经过权重和偏置的线性组合,然后通过激活函数得到输出。前向传播的目的是计算模型的预测值(或者说输出值),然后将预测值与实际标签进行比较以计算损失函数。这一过程沿着网络的正向进行,从输入层到输出层。
  5. 反向传播 :反向传播是训练神经网络的关键步骤,它通过计算损失函数关于网络参数(权重和偏置)的梯度,来调整参数使得损失函数减小。反向传播利用链式法则从输出层向输入层计算梯度,将损失沿着网络反向传播。反向传播过程可以分为两个阶段:首先计算损失函数对网络输出的梯度,然后逐层反向传播这些梯度以计算损失函数对各层参数的梯度。计算得到的梯度可以用于更新模型参数,通常使用梯度下降等优化算法进行参数更新。这个过程很复杂,原理不必掌握。我们直接使用函数即可。
  6. 梯度下降优化器
    (1)optim.SGD: 随机梯度下降(Stochastic Gradient Descent),是最基础的优化器之一,通过梯度的方向进行参数的更新。
    (2)optim.Adam: Adam 优化器结合了动量梯度下降和 RMSProp 算法,对学习率进行自适应调整,适用于大多数深度学习任务。
    (3)optim.Adagrad: 自适应梯度算法(Adaptive Gradient Algorithm),根据参数的历史梯度调整学习率。
    (4)optim.RMSprop: RMSProp 优化器使用指数加权移动平均来调整学习率,有效地解决了 AdaGrad 学习率下降过快的问题。
    (5)optim.Adadelta: AdaDelta 优化器也是自适应学习率算法,类似于 RMSProp,但没有学习率超参数。
    (6)optim.AdamW: 在 Adam 优化器的基础上添加了权重衰减(Weight Decay)的选项,用于对权重进行正则化。
    (7)optim.LBFGS: 拟牛顿法的一种,适用于较小的数据集和参数较少的情况。
      这些优化器类提供了不同的优化算法和超参数选项,可以根据具体任务的需求选择合适的优化器来进行模型训练。
  7. batch_size: 每次训练投入模型的样本个数。
  8. epochs:全部样本训练的轮次。1 个 epoch 就是指全部样本进行 1 次前向传播与反向传播。

二、深度神经网络模型搭建

以该神经网络框架为例:
在这里插入图片描述

1. 准备数据集

  无论是任何模型,第一步都是先要准备好进行训练的数据集。为了演示,我们这里自己通过代码生成数据集。如上述模块框架,输入特征x个数为3,输出特征y个数也为3。

"""随机生成10000行1列的输入数据。使用torch.rand生成的数据已经是tensor格式了"""X1 = torch.rand(10000, 1)  # 输入特征 1X2 = torch.rand(10000, 1)  # 输入特征 2X3 = torch.rand(10000, 1)  # 输入特征 3"""将输入特征的各行逐行相加,并与1比较。<1为1,否则为0."""    Y1 = ((X1 + X2 + X3) < 1).float()  # 输出特征1。Y2 = ((1 < (X1 + X2 + X3)) & ((X1 + X2 + X3) < 2)).float()  # 输出特征2。Y3 = ((X1 + X2 + X3) > 2).float()  # 输出特征3"""整合数据集,合并为10000行6列的数据列表"""    
"""axis=1,在第二个维度上合并数据,也就是列的维度上。axis=0,则在行的维度上合并,合并后为60000行1列"""Data = torch.cat([X1, X2, X3, Y1, Y2, Y3], axis=1) 

2. 划分数据集

将数据集进行划分,划分为训练集和测试集。下面代码中包含列表的切片操作,详情查看这里。

"""传入参数为:总数据集"""
def train_test_split(Data):train_size = int(len(Data) * 0.7)  # 训练集的样本数量test_size = len(Data) - train_size  # 测试集的样本数量""" Data.size(0) 为数据的行数,Data.size(1)的列数 """""" Data[第一个维度,第二个维度] ,' : '表示该维度全要 """Data = Data[ torch.randperm(Data.size(0)),  :]  # 按行进行打乱样本的顺序,第二个维度不变train_Data = Data[: train_size, :]  # 训练集样本test_Data = Data[train_size: , :]  # 测试集样本return train_Data,test_Datatrain_Data,test_Data=train_test_split(Data)

在这里插入图片描述

3. 搭建模型

  搭建神经网络时,以 nn.Module 作为父类,我们自己的神经网络可直接继承父类的方法与属性,nn.Module 中包含网络各个层的定义。每个模型都必须包含forward(前向传播)方法。
  不同模型可以查看模型的框图进行搭建。

class DNN(nn.Module):def __init__(self):''' 搭建神经网络各层 '''super(DNN,self).__init__()self.net = nn.Sequential( 			# 按顺序搭建各层,每一个隐藏层后都使用了 RuLU 激活函数nn.Linear(3, 5), nn.ReLU(), 	# 第 1 层:全连接层nn.Linear(5, 5), nn.ReLU(), 	# 第 2 层:全连接层nn.Linear(5, 5), nn.ReLU(), 	# 第 3 层:全连接层nn.Linear(5, 3)				    # 第 4 层:全连接层)def forward(self, x):''' 前向传播 '''y = self.net(x) # x 即输入数据return y # y 即输出数据model = DNN().to('cuda:0')  #创建子类的实例,并搬到 GPU 上
"""model = DNN()    #在cpu上"""
print(model)                #查看该实例的各层

查看模型层数情况:

print(model)                #查看该实例的各层

在这里插入图片描述

4. 训练网络

def train_net():loss_fn = nn.MSELoss() """选择损失函数"""learning_rate = 0.01   """设置学习率""""""定义优化器"""""" torch.optim.SGD 是 PyTorch 提供的 SGD 优化器类,用于实现随机梯度下降算法。""""""	model.parameters() 是一个迭代器,它会返回模型中所有需要训练的参数。""""""	lr=learning_rate 设置了学习率(learning rate),即 SGD 算法中用于控制参数更新步长的超参数。""" optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate) """ 训练网络"""epochs = 1000   losses = []           #记录损失函数变化的列表"""给训练集划分输入与输出"""X = train_Data[:, :3]     #前3列为输入特征Y = train_Data[:, -3:]    #后3列为输出特征for epoch in range(epochs):"""前向传播写法一:"""Pred = model.forward(X)  # 一次前向传播(批量),获得预测值"""前向传播写法二:这是因为torch中对模型输入时,自动调用forward方法,不需要显示调用forward方法"""""" Pred = model(X)  """loss = loss_fn(Pred, Y)  # 将预测值和真实值传入损失函数,计算损失。losses.append(loss.item())  # 记录损失函数的变化optimizer.zero_grad()  # 清理上一轮滞留的梯度loss.backward()  # 将损失进行一次反向传播optimizer.step()  # 优化内部参数print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch + 1, epochs, loss.item()))"""对loss损失进行画图"""    Fig = plt.figure()plt.plot(range(epochs), losses)plt.ylabel('loss'), plt.xlabel('epoch')plt.show()

查看模型内部参数

 for name, param in model.named_parameters():print(f"参数:{name}\n 形状:{param.shape}\n 数值:{param}\n")

在这里插入图片描述
在这里插入图片描述

5. 测试网络

  在测试网络时,通常不需要定义损失函数和优化器。在测试阶段,我们主要关注模型在新的、未见过的数据上的性能表现,而不是在训练集上的表现。因此,不需要对模型进行参数更新,也就不需要定义优化器。

def test_net():"""给测试集划分输入与输出"""X = test_Data[:, :3]     #前3列为输入特征Y = test_Data[:, -3:]    #后3列为输出特征with torch.no_grad():     """该局部关闭梯度计算功能"""Pred = model(X)     #一次前向传播(批量),获得预测值"""torch.argmax(Pred, axis=1) 返回每行中最大值的索引,然后使用这些索引来将对应位置的值设置为1,其他位置的值保持不变。"""Pred[:, torch.argmax(Pred, axis=1)] = 1Pred[Pred != 1] = 0correct = torch.sum((Pred == Y).all(1))  # 预测正确的样本total = Y.size(0)        #全部的样本数量print(f'测试集精准度: {100 * correct / total} %')

6. 保存与导入模型

(1)保存和导入整个模型
  通常用于在 PyTorch 中保存训练好的模型。当你在训练神经网络模型时,可能会花费很多时间和计算资源。为了避免每次使用模型时都重新训练,你可以使用 torch.save() 将模型保存到磁盘上,以便稍后加载和使用。比如将模型部署到生产环境或与其他人共享模型。
  模型文件通常以.pth或.pt为后缀。

"""保存已经训练好的模型文件"""    
old_model=DNN()
train_net()  """在保存模型文件前要先训练模型"""
torch.save(old_model, 'old_model.pth')"""新模型加载已经训练好的模型文件,不需要进行实例化模型""" 
new_model = torch.load('old_model.pth')
test_net()   #测试网络中前向传播的模型要改为new_model。

(2)只保存模型参数文件 (推荐使用,更加轻量化)
  可将保存的模型数据导入新的网络中使用。

"""只保存模型参数"""
old_model=DNN()
train_net()  """在保存模型文件前要先训练模型"""
torch.save(old_model.state_dict(), 'old_model_params.pth')"""将加载的参数状态字典加载到模型实例new_model中"""
new_model=DNN()
model_state_dict = torch.load('old_model_params.pth')
new_model.load_state_dict(model_state_dict)
test_net()   #测试网络中前向传播的模型要改为new_model。

(3)导入模型到测试网络
  模型导入后可以直接去跑测试集。因为保存的模型里面各类参数已经训练好,所以不需要再训练。
new_model使用了原有模型文件,我们就需要在测试网络的前向传播中的模型修改为new_model去进行测试。如下:
<1> 导入整个模型

""" 假设原模型已经被保存为: 'old_model.pth' """def test_net():"""给测试集划分输入与输出"""X = test_Data[:, :3]     #前3列为输入特征Y = test_Data[:, -3:]    #后3列为输出特征with torch.no_grad():  # 该局部关闭梯度计算功能Pred = new_model(X)  # 一次前向传播(批量),获得预测值"""使用 torch.argmax() 获取每行最大值的索引,并根据索引设置对应位置的值为 1"""Pred_onehot = torch.zeros_like(Pred)Pred_onehot.scatter_(1, torch.argmax(Pred, dim=1).unsqueeze(1), 1)# 将非最大值位置的值设置为 0Pred = Pred_onehot# 计算预测正确的样本数量correct = torch.sum(torch.all(Pred == Y, dim=1))total = Y.size(0)  # 全部的样本数量print(f'测试集精准度: {100 * correct / total} %')if __name__ == '__main__':new_model = torch.load('old_model.pth')test_net()

<2> 导入模型参数

""" 假设原模型已经被保存为: 'old_model_params.pth' """def test_net():"""给测试集划分输入与输出"""X = test_Data[:, :3]     #前3列为输入特征Y = test_Data[:, -3:]    #后3列为输出特征with torch.no_grad():  # 该局部关闭梯度计算功能Pred = new_model(X)  # 一次前向传播(批量),获得预测值"""使用 torch.argmax() 获取每行最大值的索引,并根据索引设置对应位置的值为 1"""Pred_onehot = torch.zeros_like(Pred)Pred_onehot.scatter_(1, torch.argmax(Pred, dim=1).unsqueeze(1), 1)# 将非最大值位置的值设置为 0Pred = Pred_onehot# 计算预测正确的样本数量correct = torch.sum(torch.all(Pred == Y, dim=1))total = Y.size(0)  # 全部的样本数量print(f'测试集精准度: {100 * correct / total} %')if __name__ == '__main__':new_model=DNN()model_state_dict = torch.load('old_model_params.pth')new_model.load_state_dict(model_state_dict)  #新模型加载保存好的模型参数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/797844.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

每日一题(leetcode31):下一个排列-思维

思路&#xff1a;从后往前找到第一个nums[i-1]>nums[i] 然后从后往前(len-1 -->i(包含))找到第一个大于nums[i-1]的数&#xff0c;与nums[i-1]交换&#xff0c;然后对下标区间为[i,len-1]的元素进行排序。 class Solution { public:void nextPermutation(vector<in…

[深度学习] 无人车环境准备

1. 安装过程基本遵循以下步骤 电脑端环境配置 - OriginBot智能机器人开源套件 需要注意以下两点&#xff1a; 1> 由于深度学习需要的包和镜像体积都比较大&#xff0c;所以虚拟机硬盘大小建议120GB 2> 虚拟机的网络适配器应该设置为桥接模式&#xff0c;如果使用NAT模…

vivado 使用网表插入调试探测流程

使用网表插入调试探测流程 在 Vivado 工具中插入调试核的过程以分层方式来演示 &#xff0c; 以应对多样化的 Vivado 用户组的不同需求 &#xff1a; • 最高层是根据选定调试的一组信号线来自动创建并配置 Integrated Logic Analyzer (ILA) 核的简单向导。 • 下一层是“…

File,IO流,递归详解

File类 介绍 java.io.File类是Java语言提供了用来描述文件和目录(文件夹)的 构造 方法 注意&#xff1a; 构造方法中通常用的是第一个方法文件和目录可以通过File封装成对象File封装的对象仅仅是一个路径名&#xff0c;它是可以存在的&#xff0c;也可以不存在 绝对路径…

【二分查找】Leetcode x 的平方根

题目解析 69. x 的平方根 这道题表面是没有顺序性&#xff0c;但是我们可以发现如果使用枚举策略&#xff0c;它是包含顺序性质的&#xff0c;因此我们将枚举算法改进成二分算法 算法讲解 我们让left指针指向1&#xff0c; right指针指向x 如果当前的mid计算出来的平方 &g…

什么是商家转账到零钱

商家转账到零钱是什么&#xff1f; 通过商家转账到零钱这个功能&#xff0c;如果我们系统需要对用户支付费用&#xff0c;比如发放佣金、提成、退款之类的&#xff0c;可以直接转账到用户的微信零钱。 【商家转账到零钱】是【企业付款到零钱】的升级版&#xff0c;2022年5月1…

怀俄明探空站数据解算PWV和Tm

1. Matlab 获取代码可关注公众号WZZHHH回复&#xff08;怀俄明探空站数据解算PWV和Tm&#xff09;&#xff0c;或者咸鱼关注&#xff1a;WZZHHH123 怀俄明探空站数据解算PWV和Tm&#xff1a; 有关 Matlab 获取代码可关注公众号WZZHHH回复&#xff08;怀俄明多线程下载&#…

语音助手背后的魔法:一文揭秘NLP在智能助手中的应用

自然语言处理&#xff08;NLP&#xff09;正逐渐渗透到我们生活的每一个角落。在今天的大盘点中&#xff0c;我们将深入探索NLP在实际生活场景中的多样化应用&#xff0c;以及它在各个案例中所展现出的强大能力。 NLP技术如今已成为智能生活的关键驱动力&#xff0c;它让机器能…

wordpress全站开发指南-面向开发者及深度用户(全中文实操)--php数组与基本循环

php数组与基本循环 <?php$myName"xixi";$namesarray(xixi1,xixi2,xixi3); ?> <p> Hi ,my name is <?php echo $myName; ?> </p> <p> Hi,my name is <?php echo $names[0] ?> </p> <p> Hi,my name is <?…

Open CASCADE学习|放样建模

在CAD软件中&#xff0c;Loft&#xff08;放样&#xff09;功能则是用于创建三维实体或曲面的重要工具。通过选取两个或多个横截面&#xff0c;并沿这些横截面进行放样&#xff0c;可以生成复杂的三维模型。在CAD放样功能的操作中&#xff0c;用户可以选择不同的选项来定制放样…

创新数智化全场景福利解决方案,打造极致员工体验

众所周知&#xff0c;企业面临两个市场&#xff0c;一个是前端的产品&#xff08;服务&#xff09;市场&#xff0c;面对的是客户&#xff0c;另一个便是后端市场&#xff0c;即愈来愈烈的人才市场。在风云变幻、人潮涌动的知识经济时代&#xff0c;员工已成为企业未来的竞争关…

Linux_进程通信_管道_system V共享内存_6

文章目录 一、进程通信分类二、管道1.什么是管道1.原理2.管道的特点 2.匿名管道3.命名管道1.创建命名管道文件 - mkfifo (命令)2.创建命名管道文件 - mkfifo (函数) 三、system V共享内存1.原理2.共享内存函数1.fotk2.shmget1.如何知道有哪些IPC资源 - ipcs &#xff08;命令&a…

河海大学-海洋学院2024年硕士研究生调剂通知

一、调剂专业及计划具体调剂专业及计划可参见河海大学研究生院官网《河海大学2024年硕士研究生调剂通知》和附件。 二、调剂报名与复试要求 1.报名条件&#xff1a;调剂原则见《河海大学202 4年硕士研究生调剂通知》&#xff0c;详细要求见中国研究生招生信息网“全国硕士研究…

Mysql密码修改问题

docker安装mysql&#xff0c;直接拉取镜像&#xff0c;挂载关键目录即可启动&#xff0c;默认3306端口。此时无法直接连接&#xff0c;需要配置密码。docker进入mysql容器中 docker exec -it mysql bash #mysq是容器名称&#xff0c;也可以用容器id通过修改mysql的配置进行免密…

Unity类银河恶魔城学习记录12-7-1 p129 Craft UI - part 1源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili UI_CraftList.cs using System.Collections; using System.Collections.Gen…

Vue基础知识:Vue路由——重定向,以及?(可选符)的使用

当网页打开时&#xff0c;url默认是/路径&#xff08;根路径&#xff09;&#xff0c;未匹配到组件时&#xff0c;会出现空白&#xff0c;为了解决这个问题 就要利用重定向 重定向&#xff1a;匹配path后&#xff0c;强制跳转path路径 重定向的语法&#xff1a; {path:匹配…

【Linux】使用cloudreve搭建个人网盘并传输文件

Cloudreve 是一个开源的个人网盘系统&#xff0c;能够帮助用户搭建属于自己的私有云存储服务。它支持多种存储后端&#xff0c;包括本地存储、远程FTP/SFTP存储、以及云存储服务如阿里云OSS、腾讯云COS和Amazon S3等。Cloudreve具有友好的用户界面和丰富的功能&#xff0c;比如…

如何使用开源情报跟踪一个人?在线访问网站以及使用方法介绍

如何使用开源情报跟踪一个人&#xff1f;在线访问网站以及使用方法介绍。 开源情报&#xff08;OSINT&#xff09;是一门关于收集和分析公开可用信息的独特技艺&#xff0c;它致力于构建个人或团体的详尽档案。 这一过程中&#xff0c;信息搜集者会利用多元化的信息源&#xff…

SQLite 查询优化器概述(九)

返回&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;SQLite中的隔离(八&#xff09; 下一篇&#xff1a;SQLite下一代查询规划器(十&#xff09; 1. 引言 本文档概述了查询规划器和优化器如何 用于 SQLite 工作。 给定一个 SQL 语句&#xff0c;可能有几十个、几百…

Java: LinkedList的模拟实现

一、双向链表简介 上一篇文章我介绍了单向链表的实现&#xff0c;单向链表的特点是&#xff1a;可以根据上一个节点访问下一个节点&#xff01;但是&#xff0c;它有个缺点&#xff0c;无法通过下一个节点访问上一个节点&#xff01;这也是它称为单向链表的原因。 那么&#x…