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

news2024/11/16 21:44:03

目录

  • 一、基础知识点
    • Ⅰ 参数部分
    • Ⅱ 模型部分
  • 二、深度神经网络模型搭建
    • 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)  # 输入特征 1
    X2 = torch.rand(10000, 1)  # 输入特征 2
    X3 = 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_Data
    
train_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)] = 1
	    Pred[Pred != 1] = 0
	    correct = 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)
        
        # 将非最大值位置的值设置为 0
        Pred = 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)
        
        # 将非最大值位置的值设置为 0
        Pred = 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.coloradmin.cn/o/1568075.html

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

相关文章

ndk ffmpeg

报错&#xff1a; 解决办法&#xff1a; 报错 解决办法&#xff1a;

js猜拳游戏

文章目录 1. 演示效果2. 分析思路3. 代码实现3.1. 方式一3.2. 方式二 1. 演示效果 2. 分析思路 获取玩家的出拳(获取按钮的标签体)获取电脑的出拳(随机数)比较二者的出拳&#xff0c;将比较的结果设置到对应的 span 标签中 3. 代码实现 3.1. 方式一 将点击事件进行动态绑定…

Python网络爬虫(四):b站评论

首先来看一下采集的数据格式: 本文不对数据采集的过程做探讨,直接上代码。首先要在程序入口处bvids列表内替换成自己想要采集的视频bvid号,然后将self.cookies替换成自己的(需要字典格式),代码可以同时爬取多个视频的评论,且爬取的评论较为完整,亲测有效: im…

股权激励和期权激励对比辨析

文章目录 概念定义 收益方式 风险评估 应用和分析 股权激励和期权激励&#xff0c;两者的区别是什么&#xff0c;本文就来梳理对比一下。 概念定义 股权激励&#xff0c;是指上市公司以本公司股票为标的&#xff0c;对其董事、高级管理人员及其他员工进行的长期性激励。取得…

二维相位解包理论算法和软件【全文翻译- 简单的路径依赖检验(2.6)】

将公式 2.33 【见前面的文章中】代入公式 2.2,可得 其中积分 代表与路径无关的解,只捕捉 φ 的非旋转成分,以及 代表包含 φ 旋转部分的路径依赖成分。 需要强调的是,F(r)(或 φ(r))中的旋转分量是二维相位解包中路径依赖的唯一来源。相位中的旋转成分是残差的原因。可…

C++从入门到精通——入门知识

1. C关键字(C98) C总计63个关键字&#xff0c;C语言32个关键字 2. 命名空间 在C/C中&#xff0c;变量、函数和后面要学到的类都是大量存在的&#xff0c;这些变量、函数和类的名称都将存在于全局作用域中&#xff0c;可能会导致很多冲突。使用命名空间的目的就是对标识符的名…

【Python系列】 yaml中写入数据

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

680.验证回文串II-力扣

680.验证回文串II-力扣 给你一个字符串 s&#xff0c;最多可以从中删除一个字符。 请你判断 s 是否能成为回文字符串&#xff1a;如果能&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false。 示例1&#xff1a; 输入&#xff1a;s “aba” 输出&#xff1a;true示…

自定义树形筛选选择组件

先上效果图 思路&#xff1a;刚开始最上面我用了el-input&#xff0c;选择框里面内容用了el-inputel-tree使用&#xff0c;但后面发现最上面那个可以输入&#xff0c;那岂不是可以不需要下拉就可以使用&#xff0c;岂不是违背了写这个组件的初衷&#xff0c;所以后面改成div自定…

STM32中启用 UART 的特定中断( __HAL_UART_ENABLE_IT函数)开机立即进入中断问题(HAL库)

学习过程中发现启用 UART 的特定中断功能之后&#xff0c;原本应该是等到空闲中断的标志位变化了再进入中断&#xff0c;结果MCU开机就会进入中断&#xff0c;不符合逻辑&#xff0c;所以尝试解决这个问题。 DMA空闲中断 处理 串口接收不定长数据 的文章见以下 原文链接&#…

把标注数据导入到知识图谱

文章目录 简介数据导入Doccano标注数据&#xff0c;导入到Neo4j寻求帮助 简介 团队成员使用 Doccano 标注了一些数据&#xff0c;包括 命名实体识别、关系和文本分类 的标注的数据&#xff1b; 工作步骤如下&#xff1a; 首先将标注数据导入到Doccano&#xff0c;查看一下标注…

LeetCode每日一题之专题一:双指针 ——复写零

复写零OJ链接&#xff1a;1089. 复写零 - 力扣&#xff08;LeetCode&#xff09; 题目&#xff1a; 解法&#xff08;原地复写-双指针&#xff09;&#xff1a; 算法思路&#xff1a; 如果「从前向后」进⾏原地复写操作的话&#xff0c;由于 0 的出现会复写两次&#xff0c;导致…

鸿蒙开发之ArkTs开发布局之层叠布局(Stack)和弹性布局(Flex)

层叠布局&#xff08;Stack&#xff09; 层叠布局&#xff08;StackLayout&#xff09;用于在屏幕上预留一块区域来显示组件中的元素&#xff0c;提供元素可以重叠的布局。层叠布局通过Stack容器组件实现位置的固定定位与层叠&#xff0c;容器中的子元素&#xff08;子组件&…

技术揭秘:如何打造完美互动的充电桩硬件与服务平台?

充电桩平台全套源码地址 https://gitee.com/chouleng/cdzkjjh.git 这张图像是一个系统或服务的架构图。以下是对图中各个部分的描述&#xff1a; 前端&#xff1a; 位于图像的顶部&#xff0c;颜色为浅绿色。用户服务端&#xff1a; 紧邻前端&#xff0c;颜色为淡黄色。设备服…

【初阶数据结构】——leetcode:160. 相交链表

文章目录 1. 题目介绍2. 思路1&#xff1a;暴力求解算法思想代码实现 3. 思路2&#xff1a;快慢指针算法思想代码实现 1. 题目介绍 链接: link 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&…

OpenAI劲敌出手!Claude 3正式发布,全面超越GPT-4。Claude3模型特点和使用教程分享

已有GPT官方账号不会升级GPT4请参考&#xff1a;【国内如何用gpt4&#xff1f;如何升级gpt4&#xff1f;保姆级教程】 一、Claude震撼发布焦点分析 1.Claude震撼发布 北京时间2024年3月4日晚间&#xff0c;Anthropic&#xff0c;毫无预警地发布了最新一代大模型Claude 3&…

RuoYi-Vue若依框架-集成mybatis-plus报错Unknown column ‘search_value‘ in ‘field list‘

报错信息 ### Error querying database. Cause: java.sql.SQLSyntaxErrorException: Unknown column search_value in field list ### The error may exist in com/ruoyi/sales/mapper/ZcSpecificationsMapper.java (best guess) ### The error may involve defaultParameter…

32-2 APP渗透 - 移动APP架构

前言 app渗透和web渗透最大的区别就是抓包不一样 一、客户端: 反编译: 静态分析的基础手段,将可执行文件转换回高级编程语言源代码的过程。可用于了解应用的内部实现细节,进行漏洞挖掘和算法分析等。调试: 排查软件错误的一种手段,用于分析应用内部原理和行为。篡改/重打…

【python实战】--提取所有目录下所有Excel文件指定列数据

系列文章目录 文章目录 系列文章目录前言一、问题描述二、python代码1.引入库 总结 前言 一、问题描述 需要提取指定路径下所有excel文件中指定一列数据&#xff0c;汇总到新文件&#xff0c;&#xff08;逐列汇总&#xff09; 二、python代码 1.引入库 代码如下&#xff08…

66toolkit终极网络工具系统:470+强大Web工具,助力您的网络运营与开发

一、产品介绍 66toolkit&#xff0c;被誉为“终极网络工具系统”&#xff08;SAAS&#xff09;&#xff0c;是一款功能强大的PHP脚本。它集合了超过470种快速且易用的Web工具&#xff0c;为日常任务处理和开发人员提供了极大的便利。作为一款综合性的网络工具系统&#xff0c;…