当前位置: 首页 > article >正文

人工神经网络知识点讲解

人工神经网络知识点讲解知识导图人工神经网络 ├── 基础认知 │ ├── 神经网络的核心概念 │ ├── 神经元的工作机制 │ └── 网络的层级结构 ├── 激活函数 │ ├── 激活函数的作用 │ ├── 常见激活函数sigmoid/tanh/ReLU/Softmax │ └── 激活函数的选择 ├── 参数初始化 │ ├── 7种初始化方法 │ └── 初始化方法的选择 ├── 损失函数 │ ├── 分类任务损失 │ └── 回归任务损失 ├── 网络优化 │ ├── 优化算法 │ └── 学习率衰减 ├── 正则化方法 │ ├── 正则化的作用 │ ├── Dropout 随机失活 │ └── 批量归一化 └── 实战案例 └── 手机价格分类案例核心名词解释人工神经网络 (ANN)也简称为神经网络 (NN)是一种模仿生物神经网络结构和功能的计算模型用来拟合复杂的非线性关系。神经元神经网络的基本单元接收输入后进行加权求和再通过激活函数输出结果模拟生物神经元的工作方式。输入层 (Input Layer)神经网络的输入层负责接收原始的输入数据每个输入特征对应一个神经元。隐藏层 (Hidden Layers)输入层和输出层之间的层负责对输入数据进行特征提取和变换神经网络的深度由隐藏层的数量决定。输出层 (Output Layer)神经网络的输出层负责生成最终的预测结果根据任务的不同分类 / 回归有不同的设计。全连接层相邻层的所有神经元都相互连接的层也叫稠密层每个连接都有对应的权重和偏置。内部状态值神经元的加权求和结果公式为z W⋅x\b是激活函数的输入。激活值激活函数对内部状态值进行非线性变换后得到的结果是神经元的最终输出。激活函数为神经网络引入非线性因素的函数让网络可以拟合复杂的非线性函数。sigmoid将输入映射到 (0,1) 区间的激活函数常用于二分类的输出层。tanh将输入映射到 (-1,1) 区间的激活函数是 sigmoid 的平移版本解决了 sigmoid 的输出非零均值的问题。ReLU修正线性单元是目前最常用的隐藏层激活函数计算简单缓解了梯度消失问题。Softmax多分类任务的输出激活函数将输出转换为概率所有输出的概率和为 1。参数初始化对神经网络的权重和偏置进行初始赋值的过程合适的初始化可以让网络更快收敛避免梯度消失 / 爆炸。Xavier 初始化也叫 Glorot 初始化用来平衡输入和输出的方差适合 sigmoid、tanh 这类激活函数。Kaiming 初始化也叫 HE 初始化针对 ReLU 这类激活函数设计考虑了 ReLU 的半正则特性让深层网络更容易训练。损失函数用来衡量模型预测值和真实值之间差异的函数是网络训练的优化目标。交叉熵损失分类任务中常用的损失函数衡量预测概率分布和真实分布的差异。MAE 损失也叫 L1 损失回归任务的损失计算预测和真实的绝对误差。MSE 损失也叫 L2 损失回归任务的损失计算预测和真实的均方误差。优化器用来更新神经网络参数最小化损失函数的算法。学习率衰减随着训练进行逐渐降低学习率的策略让模型训练更稳定。Dropout随机失活正则化训练时随机让部分神经元失活防止过拟合。批量归一化 (BN)对批量数据进行标准化和重构的层缓解梯度消失加速训练。正则化用来防止模型过拟合的方法通过限制模型的复杂度提升模型的泛化能力。一、神经网络基础认知本章节学习目标知道什么是人工神经网络了解神经网络的构成理解内部状态和激活值的概念1.1 什么是人工神经网络人工神经网络 Artificial Neural Network 简写为 ANN也简称为神经网络NN是一种模仿生物神经网络结构和功能的计算模型。人脑可以看做是一个生物神经网络由众多的神经元连接而成。各个神经元传递复杂的电信号树突接收到输入信号然后对信号进行处理通过轴突输出信号。当电信号通过树突进入到细胞核时会逐渐聚集电荷。达到一定的电位后细胞就会被激活通过轴突发出电信号。1.2 神经元的工作机制神经网络是由多个神经元组成构建神经网络就是在构建神经元。这个过程就像来源不同树突 (树突都会有不同的权重) 的信息进行的加权计算输入到细胞中做加和再通过激活函数输出细胞值。1.3 神经网络的层级结构神经网络中信息只向一个方向移动即从输入节点向前移动通过隐藏节点再向输出节点移动。其中的基本部分是:输入层Input Layer即输入 x 的那一层如图像、文本、声音等。每个输入特征对应一个神经元。输入层将数据传递给下一层的神经元。输出层Output Layer即输出 y 的那一层。输出层的神经元根据网络的任务回归、分类等生成最终的预测结果。隐藏层Hidden Layers输入层和输出层之间的层负责对输入数据进行特征提取和变换神经网络的深度由隐藏层的数量决定。网络的特点同一层的神经元之间没有连接第 N 层的每个神经元和第 N-1 层 的所有神经元相连这就是全连接神经网络全连接神经网络接收的样本数据是二维的数据在每一层之间需要以二维的形式传递第 N-1 层神经元的输出就是第 N 层神经元的输入每个连接都有一个权重值w 系数和 b 系数1.4 内部状态值和激活值每一个神经元工作时会产生 4 个值:前向传播会产生内部状态值加权求和值和激活值反向传播时会产生激活值梯度和内部状态值梯度。内部状态值:z W⋅x\bW权重矩阵x输入值b偏置激活值:af\(z\)f激活函数z内部状态值二、激活函数本章节学习目标知道常见的激活函数了解激活函数的作用掌握激活函数的选择方法2.1 激活函数的作用激活函数用于对每层的输出数据进行变换进而为整个网络注入了非线性因素。此时神经网络就可以拟合各种曲线。没有引入非线性因素的网络等价于使用一个线性模型来拟合。通过给网络输出增加激活函数实现引入非线性因素使得网络模型可以逼近任意函数提升网络对复杂问题的拟合能力。2.2 常见的激活函数2.2.1 sigmoid 激活函数sigmoid 激活函数可以将输入映射到 (0,1) 的区间它的公式和导数公式如下对应的绘制代码# 解决OMP冲突的代码 import os os.environ[KMP_DUPLICATE_LIB_OK]True # 加这行切换Matplotlib的后端绕过PyCharm的兼容bug import matplotlib matplotlib.use(TkAgg) # 导包 import torch import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [Microsoft YaHei] # 指定用Windows自带的微软雅黑支持中文 plt.rcParams[axes.unicode_minus] False # 顺便解决负号显示成方框的问题 # 准备数据 # 准备 -2020的等差张量1000点 -- x x torch.linspace(start-20,end20,steps1000,requires_gradFalse) print(x.shape,x.ndim) y torch.sigmoid(x) print(y.shape,y.ndim) # 绘制图像 # **todo 为了把值域图像和导数图像画到一张画布上创建一个一行两列的画布** fig,axs plt.subplots(1,2) axs[0].plot(x,y) axs[0].grid() axs[0].set_title(sigmoid 值域图像) # plt.show() print(1) # 准备数据 # # 准备x,y数据 - **todo 注意此处的x开启自动微分y的本质是梯度** x torch.linspace(start-20,end20,steps1000,requires_gradTrue) print(x.shape,x.ndim) torch.sigmoid(x).sum().backward() # - # backward()触发反向传播PyTorch自动帮你计算Sigmoid对x的导数结果会自动存在 x.grad 里 y x.grad print(y.shape,y.ndim) # 绘制图像 axs[1].plot(x.detach(),x.grad) axs[1].grid() axs[1].set_title(Sigmoid 导数图像) plt.show() print(2)2.2.2 tanh 激活函数tanh 激活函数可以将输入映射到 (-1,1) 的区间解决了 sigmoid 输出非零均值的问题它的公式和导数公式如下对应的绘制代码# 创建画布和坐标轴 _, axes plt.subplots(1, 2) # 函数图像 x torch.linspace(-20, 20, 1000) y torch.tanh(x) axes[0].plot(x, y) axes[0].grid() axes[0].set_title(Tanh 函数图像) # 导数图像 x torch.linspace(-20, 20, 1000, requires_gradTrue) torch.tanh(x).sum().backward() axes[1].plot(x.detach(), x.grad) axes[1].grid() axes[1].set_title(Tanh 导数图像) plt.show()2.2.3 ReLU 激活函数ReLU 是修正线性单元是目前最常用的隐藏层激活函数它的公式和导数公式如下对应的绘制代码# 创建画布和坐标轴 _, axes plt.subplots(1, 2) # 函数图像 x torch.linspace(-20, 20, 1000) y torch.relu(x) axes[0].plot(x, y) axes[0].grid() axes[0].set_title(ReLU 函数图像) # 导数图像 x torch.linspace(-20, 20, 1000, requires_gradTrue) torch.relu(x).sum().backward() axes[1].plot(x.detach(), x.grad) axes[1].grid() axes[1].set_title(ReLU 导数图像) plt.show()2.2.4 SoftMax 激活函数softmax 用于多分类过程中它是二分类函数 sigmoid 在多分类上的推广目的是将多分类的结果以概率的形式展现出来。Softmax 就是将网络输出的 logits 通过 softmax 函数就映射成为 (0,1) 的值而这些值的累和为 1满足概率的性质那么我们将它理解成概率选取概率最大也就是值对应最大的节点作为我们的预测目标类别。对应的使用代码import torch scores torch.tensor([0.2, 0.02, 0.15, 0.15, 1.3, 0.5, 0.06, 1.1, 0.05, 3.75]) # dim 0,按行计算 probabilities torch.softmax(scores, dim-1) print(probabilities) # 输出结果: # tensor([0.0212, 0.0177, 0.0202, 0.0202, 0.0638, 0.0287, 0.0185, 0.0522, 0.0183,0.7392])2.3 其他激活函数还有其他的常见激活函数比如 Leaky ReLU、PReLU、ELU 等2.4 激活函数的选择方法隐藏层的选择优先选择 ReLU 激活函数如果 ReLu 效果不好那么尝试其他激活如 Leaky ReLu 等。如果你使用了 ReLU 需要注意一下 Dead ReLU 问题 避免出现 0 梯度从而导致过多的神经元死亡。少用使用 sigmoid 激活函数可以尝试使用 tanh 激活函数输出层的选择二分类问题选择 sigmoid 激活函数多分类问题选择 softmax 激活函数回归问题选择 identity 激活函数激活函数对比辨析激活函数输出区间特点适用场景sigmoid(0, 1)输出非零均值容易梯度消失二分类输出层tanh(-1, 1)输出零均值缓解了 sigmoid 的部分问题隐藏层早期ReLU[0, ∞)计算简单缓解梯度消失可能出现 Dead ReLU隐藏层主流Softmax(0, 1)总和为 1输出概率分布多分类输出层三、参数初始化本章节学习目标了解常见的参数初始化方法掌握初始化方法的选择3.1 常见的初始化方法参数初始化是对神经网络的权重和偏置进行初始赋值的过程常见的 7 种初始化方法如下基础初始化方法均匀分布初始化权重参数初始化从区间均匀随机取值默认区间为01。可以设置为在 (-1/√d,1/√d) 均匀分布中生成当前神经元的权重其中 d 为神经元的输入数量正态分布初始化随机初始化从均值为 0标准差是 1 的高斯分布中取样使用一些很小的值对参数 W 进行初始化全 0 初始化将神经网络中的所有权重参数初始化为 0全 1 初始化将神经网络中的所有权重参数初始化为 1固定值初始化将神经网络中的所有权重参数初始化为某个固定值进阶初始化方法kaiming 初始化HE 初始化HE 初始化分为正态分布的 HE 初始化、均匀分布的 HE 初始化.正态分布的 he 初始化它是从 [0, std] 中抽取样本的std sqrt\(2 / fan\_in\)均匀分布的 he 初始化它从 [-limitlimit] 中的均匀分布中抽取样本limit是 sqrt\(6 / fan\_in\)fan_in输入层神经元的个数xavier 初始化Glorot 初始化该方法也有两种一种是正态分布的 xavier 初始化、一种是均匀分布的 xavier 初始化.正态化的 Xavier 初始化它是从 [0, std] 中抽取样本的std sqrt\(2 / \(fan\_in \ fan\_out\)\)均匀分布的 Xavier 初始化[-limitlimit] 中的均匀分布中抽取样本limit 是 sqrt\(6 / \(fan\_in \ fan\_out\)\)fan_in输入层神经元的个数 fan_out输出层神经元个数3.2 初始化的代码示例import torch import torch.nn.functional as F import torch.nn as nn # 1. 均匀分布随机初始化 def test01(): linear nn.Linear(5, 3) # 从0-1均匀分布产生参数 nn.init.uniform_(linear.weight) print(linear.weight.data) # 2.固定初始化 def test02(): linear nn.Linear(5, 3) nn.init.constant_(linear.weight, 5) print(linear.weight.data) # 3. 全0初始化 def test03(): linear nn.Linear(5, 3) nn.init.zeros_(linear.weight) print(linear.weight.data) # 4. 全1初始化 def test04(): linear nn.Linear(5, 3) nn.init.ones_(linear.weight) print(linear.weight.data) # 5. 正态分布随机初始化 def test05(): linear nn.Linear(5, 3) nn.init.normal_(linear.weight, mean0, std1) print(linear.weight.data) # 6. kaiming 初始化 def test06(): # kaiming 正态分布初始化 linear nn.Linear(5, 3) nn.init.kaiming_normal_(linear.weight) print(linear.weight.data) # kaiming 均匀分布初始化 linear nn.Linear(5, 3) nn.init.kaiming_uniform_(linear.weight) print(linear.weight.data) # 7. xavier 初始化 def test07(): # xavier 正态分布初始化 linear nn.Linear(5, 3) nn.init.xavier_normal_(linear.weight) print(linear.weight.data) # xavier 均匀分布初始化 linear nn.Linear(5, 3) nn.init.xavier_uniform_(linear.weight) print(linear.weight.data)3.3 初始化方法的选择根据激活函数选择Sigmoid/Tanh选择 Xavier 初始化ReLU/Leaky ReLU选择 kaiming 初始化根据网络深度选择浅层网络随机初始化即可深层网络需要考虑方差平衡如 Xavier 或 kaiming 初始化初始化方法对比辨析初始化方法核心特点适用激活函数适用场景均匀 / 正态随机简单随机初始化浅层网络的激活函数简单的浅层网络全 0 / 全 1 / 固定值固定值初始化不推荐容易导致对称问题仅偏置可以使用权重不推荐Xavier 初始化平衡输入输出方差Sigmoid、Tanh早期的深层网络Kaiming 初始化适配 ReLU 的半正则特性ReLU、Leaky ReLU现代深层网络四、神经网络搭建实战我们来构建一个简单的神经网络模型结合我们学到的激活函数和参数初始化搭建步骤在 pytorch 中定义深度神经网络其实就是层堆叠的过程继承自 nn.Module实现两个方法\_\_init\_\_方法中定义网络中的层结构主要是全连接层并进行初始化forward方法在实例化模型的时候底层会自动调用该函数。该函数中为初始化定义的 layer 传入数据进行前向传播等。代码实现from torch.nn import Module, Linear import torch # TODO 1.自定义模型类继承Module类 class My_Model(Module): # TODO 2.重写init魔法方法和forward前向传播方法 def __init__(self, *args, **kwargs): # 1.调用父类的init初始化方法 super().__init__(*args, **kwargs) # TODO 定义神经网络结构 self.linear1 Linear(3, 3) self.linear2 Linear(3, 2) self.out Linear(2, 2) # 3.参数初始化(生成权重矩阵) # 隐藏层初始化权重矩阵 torch.nn.init.xavier_normal_(self.linear1.weight) torch.nn.init.kaiming_normal_(self.linear2.weight) def forward(self, x): # TODO 前向传播计算(每层都是加权求和激活函数) x torch.sigmoid(self.linear1(x)) x torch.relu(self.linear2(x)) # 下面-1代表最后一维, 也就是按照每个样本概率和为1. x torch.softmax(self.out(x), dim-1) return x # TODO 3.创建模型对象并使用模型对象 # 创建模型对象 model My_Model() # 自动调用init魔法方法 # 准备数据集(正态分布数据) torch.manual_seed(66) data torch.randn(5, 3) # 5个样本,3个特征 # 把数据传入模型对象 output model(data) # 自动调用forward方法 print(output)五、损失函数本章节学习目标知道分类任务的损失函数知道回归任务的损失函数5.1 什么是损失函数在深度学习中损失函数是用来衡量模型参数的质量的函数衡量的方式是比较网络输出和真实输出的差异。损失函数在不同的文献中名称是不一样的主要有以下几种命名方式损失函数Loss Function代价函数Cost Function目标函数Objective Function5.2 分类任务的损失函数5.2.1 多分类任务交叉熵损失在多分类任务通常使用 softmax 将 logits 转换为概率的形式所以多分类的交叉熵损失也叫做 softmax 损失它的计算方法是其中:y 是样本 x 属于某一个类别的真实概率而 f (x) 是样本属于某一类别的预测分数S 是 softmax 激活函数将属于某一类别的预测分数转换成概率L 用来衡量真实值 y 和预测值 f (x) 之间差异性的损失结果从概率角度理解我们的目的是最小化正确类别所对应的预测概率的对数的负值 (损失值最小)上图中的交叉熵损失为从概率角度理解我们的目的是最小化正确类别所对应的预测概率的对数的负值(损失值最小)如下图所示在 pytorch 中使用nn\.CrossEntropyLoss\(\)实现代码如下# 分类损失函数交叉熵损失使用nn.CrossEntropyLoss()实现。nn.CrossEntropyLoss()softmax 损失计算 def test01(): # 设置真实值: 可以是热编码后的结果也可以不进行热编码 # y_true torch.tensor([[0, 1, 0], [0, 0, 1]], dtypetorch.float32) # 注意的类型必须是64位整型数据 y_true torch.tensor([1, 2], dtypetorch.int64) y_pred torch.tensor([[0.2, 0.6, 0.2], [0.1, 0.8, 0.1]], requires_gradTrue, dtypetorch.float32) # 实例化交叉熵损失 loss nn.CrossEntropyLoss() # 计算损失结果 my_loss loss(y_pred, y_true).detach().numpy() print(loss:, my_loss)5.2.2 二分类任务二分类交叉熵损失在处理二分类任务时我们不再使用 softmax 激活函数而是使用 sigmoid 激活函数那损失函数也相应的进行调整使用二分类的交叉熵损失函数其中:y 是样本 x 属于某一个类别的真实概率而 y^ 是样本属于某一类别的预测概率L 用来衡量真实值 y 与预测值 y^ 之间差异性的损失结果。在 pytorch 中实现时使用nn\.BCELoss\(\)代码如下def test02(): # 1 设置真实值和预测值 # 预测值是sigmoid输出的结果 y_pred torch.tensor([0.6901, 0.5459], requires_gradTrue) y_true torch.tensor([0, 1], dtypetorch.float32) # 2 实例化二分类交叉熵损失 loss nn.BCELoss() # 3 计算损失 my_loss loss(y_pred, y_true).detach().numpy() print(loss, my_loss)5.3 回归任务的损失函数5.3.1 MAE 损失函数L1 LossMean absolute loss (MAE) 也被称为 L1 Loss是以绝对误差作为距离。损失函数公式:特点是由于 L1 loss 具有稀疏性为了惩罚较大的值因此常常将其作为正则项添加到其他 loss 中作为约束。L1 loss 的最大问题是梯度在零点不平滑导致会跳过极小值。在 pytorch 中使用nn\.L1Loss\(\)实现代码如下# 计算inputs与target之差的绝对值 def test03(): # 1 设置真实值和预测值 y_pred torch.tensor([1.0, 1.0, 1.9], requires_gradTrue) y_true torch.tensor([2.0, 2.0, 2.0], dtypetorch.float32) # 2 实例化MAE损失 loss nn.L1Loss() # 3 计算损失 my_loss loss(y_pred, y_true).detach().numpy() print(loss, my_loss)5.3.2 MSE 损失函数L2 LossMean Squared Loss (MSE) 也被称为 L2 Loss是以均方误差作为距离。损失函数公式:特点是L2 loss 的梯度会随着误差减小而减小因此更容易收敛到最小值。对异常值更敏感因为它会对大的误差进行平方惩罚。在 pytorch 中使用nn\.MSELoss\(\)实现代码如下# 计算inputs与target之差的平方 def test04(): # 1 设置真实值和预测值 y_pred torch.tensor([1.0, 1.0, 1.9], requires_gradTrue) y_true torch.tensor([2.0, 2.0, 2.0], dtypetorch.float32) # 2 实例化MSE损失 loss nn.MSELoss() # 3 计算损失 my_loss loss(y_pred, y_true).detach().numpy() print(loss, my_loss)损失函数对比辨析损失函数适用任务特点适用场景交叉熵损失CrossEntropy多分类衡量预测概率分布和真实分布的差异梯度稳定多分类任务二分类交叉熵损失BCELoss二分类针对二分类的交叉熵配合 sigmoid 使用二分类任务MAE 损失L1 Loss回归对异常值不敏感零点梯度不平滑回归任务对异常值鲁棒的场景MSE 损失L2 Loss回归梯度随误差减小更容易收敛对异常值敏感回归任务数据质量较好的场景六、网络优化方法本章节学习目标了解常见的优化算法掌握学习率的调整方法6.1 梯度下降优化算法梯度下降是神经网络优化的基础算法常见的梯度下降变种有批量梯度下降BGD使用全部样本计算梯度更新稳定但速度慢随机梯度下降SGD使用单个样本计算梯度速度快但波动大小批量梯度下降MBGD使用小批量样本平衡速度和稳定性是目前的主流6.2 带动量的梯度下降动量Momentum是模拟物理中的动量概念积累之前的梯度方向加速收敛减少震荡6.3 自适应学习率算法6.3.1 AdaGrad自适应调整每个参数的学习率对稀疏数据效果好但学习率会单调递减6.3.2 RMSProp解决 AdaGrad 学习率递减的问题使用指数移动平均来累积梯度6.3.3 Adam结合了动量和 RMSProp 的优点是目前最常用的优化算法自适应调整学习率收敛速度快6.4 学习率衰减随着训练的进行逐渐降低学习率让模型在训练后期更稳定避免震荡6.4.1 等间隔学习率衰减每经过固定的轮次就将学习率乘以一个衰减系数def test_StepLR(): # 0.参数初始化 LR 0.1 # 设置学习率初始化值为0.1 iteration 10 max_epoch 200 # 1 初始化参数 y_true torch.tensor([0]) x torch.tensor([1.0]) w torch.tensor([1.0], requires_gradTrue) # 2.优化器 optimizer optim.SGD([w], lrLR, momentum0.9) # 3.设置学习率下降策略 scheduler_lr optim.lr_scheduler.StepLR(optimizer, step_size50, gamma0.5) # 4.获取学习率的值和当前的epoch lr_list, epoch_list list(), list() for epoch in range(max_epoch): lr_list.append(scheduler_lr.get_last_lr()) # 获取当前lr epoch_list.append(epoch) # 获取当前的epoch for i in range(iteration): # 遍历每一个batch数据 loss ((w*x-y_true)**2)/2.0 # 目标函数 optimizer.zero_grad() # 反向传播 loss.backward() optimizer.step() # 更新下一个epoch的学习率 scheduler_lr.step() # 5.绘制学习率变化的曲线 plt.plot(epoch_list, lr_list, labelStep LR Scheduler) plt.xlabel(Epoch) plt.ylabel(Learning rate) plt.legend() plt.show()6.4.2 指定间隔学习率衰减在指定的轮次进行学习率衰减更灵活def test_MultiStepLR(): torch.manual_seed(1) LR 0.1 iteration 10 max_epoch 200 weights torch.randn((1), requires_gradTrue) target torch.zeros((1)) print(weights---, weights, target---, target) optimizer optim.SGD([weights], lrLR, momentum0.9) # 设定调整时刻数 milestones [50, 125, 160] # 设置学习率下降策略 scheduler_lr optim.lr_scheduler.MultiStepLR(optimizer, milestonesmilestones, gamma0.5) lr_list, epoch_list list(), list() for epoch in range(max_epoch): lr_list.append(scheduler_lr.get_last_lr()) epoch_list.append(epoch) for i in range(iteration): loss torch.pow((weights - target), 2) optimizer.zero_grad() # 反向传播 loss.backward() # 参数更新 optimizer.step() # 更新下一个epoch的学习率 scheduler_lr.step() plt.plot(epoch_list, lr_list, labelMulti Step LR Scheduler\nmilestones:{}.format(milestones)) plt.xlabel(Epoch) plt.ylabel(Learning rate) plt.legend() plt.show()6.4.3 按指数学习率衰减学习率按指数规律衰减def test_ExponentialLR(): # 0.参数初始化 LR 0.1 # 设置学习率初始化值为0.1 iteration 10 max_epoch 200 # 1 初始化参数 y_true torch.tensor([0]) x torch.tensor([1.0]) w torch.tensor([1.0], requires_gradTrue) # 2.优化器 optimizer optim.SGD([w], lrLR, momentum0.9) # 3.设置学习率下降策略 gamma 0.95 scheduler_lr optim.lr_scheduler.ExponentialLR(optimizer, gammagamma) # 4.获取学习率的值和当前的epoch lr_list, epoch_list list(), list() for epoch in range(max_epoch): lr_list.append(scheduler_lr.get_last_lr()) epoch_list.append(epoch) for i in range(iteration): # 遍历每一个batch数据 loss ((w*x-y_true)**2)/2.0 optimizer.zero_grad() # 反向传播 loss.backward() optimizer.step() # 更新下一个epoch的学习率 scheduler_lr.step() # 5.绘制学习率变化的曲线 plt.plot(epoch_list, lr_list, labelMulti Step LR Scheduler) plt.xlabel(Epoch) plt.ylabel(Learning rate) plt.legend() plt.show()优化方法对比辨析优化算法核心特点适用场景SGD简单的随机梯度下降收敛慢容易震荡简单任务数据量小SGDMomentum加入动量加速收敛减少震荡大部分任务稳定训练AdaGrad自适应学习率适合稀疏数据稀疏数据NLP 任务RMSProp解决 AdaGrad 学习率递减问题深度学习任务Adam结合动量和自适应学习率收敛快主流深度学习任务默认首选七、正则化方法本章节学习目标知道正则化的作用掌握随机失活 DropOut 策略知道 BN 层的作用7.1 正则化的作用在设计机器学习算法时希望在新样本上的泛化能力强。许多机器学习算法都采用相关的策略来减小测试误差这些策略被统称为正则化。神经网络强大的表示能力经常遇到过拟合所以需要使用不同形式的正则化策略。7.2 Dropout 正则化在练神经网络中模型参数较多在数据量不足的情况下很容易过拟合。Dropout随机失活是一个简单有效的正则化方法。在训练过程中Dropout 的实现是让神经元以超参数 p 的概率停止工作或者激活被置为 0, 未被置为 0 的进行缩放缩放比例为 1/(1-p)。训练过程可以认为是对完整的神经网络的一些子集进行训练每次基于输入数据只更新子网络的参数。在测试过程中随机失活不起作用。代码示例import torch import torch.nn as nn def test(): # 初始化随机失活层 dropout nn.Dropout(p0.4) # 初始化输入数据:表示某一层的weight信息 inputs torch.randint(0, 10, size[1, 4]).float() layer nn.Linear(4,5) y layer(inputs) print(未失活FC层的输出结果\n, y) y dropout(y) print(失活后FC层的输出结果\n, y)输出结果:未失活FC层的输出结果 tensor([[-0.8369, -5.5720, 0.2258, 3.4256, 2.1919]], grad_fnAddmmBackward0) 失活后FC层的输出结果 tensor([[-1.3949, -9.2866, 0.3763, 0.0000, 3.6531]], grad_fnMulBackward0)7.3 批量归一化Batch Normalization批量归一化是对数据标准化再对数据重构缩放 平移如下所示其中λ 和 β 是可学习的参数它相当于对标准化后的值做了一个线性变换λ 为系数β 为偏置eps 通常指为 1e-5避免分母为 0E (x) 表示变量的均值Var (x) 表示变量的方差批量归一化层在计算机视觉领域使用较多它可以缓解梯度消失 / 爆炸问题允许使用更高的学习率降低对初始化的敏感程度有轻微的正则化效果代码示例import torch import torch.nn as nn m nn.BatchNorm2d(2, eps1e-05, momentum0.1, affineTrue) # affine参数设为True表示weight和bias将被使用 input torch.randn(1, 2, 3, 4) print(input--, input) output m(input) print(output--, output) print(output.size()) print(m.weight) print(m.bias)输出结果:input-- tensor([[[[-0.2751, -1.2183, -0.5106, -0.1540], [-0.4585, -0.5989, -0.6063, 0.5986], [-0.4745, 0.1496, -1.1266, -1.2377]], [[ 0.2580, 1.2065, 1.4598, 0.8387], [-0.4586, 0.8938, -0.3328, 0.1192], [-0.3265, -0.6263, 0.0419, -1.2231]]]]) output-- tensor([[[[ 0.4164, -1.3889, -0.0343, 0.6484], [ 0.0655, -0.2032, -0.2175, 2.0889], [ 0.0349, 1.2294, -1.2134, -1.4262]], [[ 0.1340, 1.3582, 1.6853, 0.8835], [-0.7910, 0.9546, -0.6287, -0.0452], [-0.6205, -1.0075, -0.1449, -1.7779]]]], grad_fnNativeBatchNormBackward0) torch.Size([1, 2, 3, 4]) Parameter containing: tensor([1., 1.], requires_gradTrue) Parameter containing: tensor([0., 0.], requires_gradTrue)八、实战案例手机价格分类本章节学习目标掌握构建分类模型的完整流程动手实践整个训练和评估过程8.1 需求分析小明创办了一家手机公司他不知道如何估算手机产品的价格。为了解决这个问题他收集了多家公司的手机销售数据。该数据为二手手机的各个性能的数据最后根据这些性能得到 4 个价格区间作为这些二手手机售出的价格区间。我们需要帮助小明找出手机的功能例如RAM 等与其售价之间的某种关系。我们可以使用机器学习的方法来解决这个问题也可以构建一个全连接的网络。需要注意的是在这个问题中我们不需要预测实际价格而是一个价格范围它的范围使用 0、1、2、3 来表示所以该问题也是一个分类问题。I在这里插入图片描述8.2 完整流程我们按照四个步骤来完成这个任务准备训练集数据构建要使用的模型模型训练模型预测评估8.2.1 导入工具包# 导入相关模块 import torch from torch.utils.data import TensorDataset from torch.utils.data import DataLoader import torch.nn as nn import torch.optim as optim from sklearn.datasets import make_regression from sklearn.model_selection import train_test_split import matplotlib.pyplot as plt import numpy as np import pandas as pd import time8.2.2 构建数据集数据共有 2000 条其中 1600 条数据作为训练集400 条数据用作测试集。 我们使用 sklearn 的数据集划分工作来完成。并使用 PyTorch 的 TensorDataset 来将数据集构建为 Dataset 对象方便构造数据集加载对象。# 构建数据集 def create_dataset(): # 使用pandas读取数据 data pd.read_csv(data/手机价格预测.csv) # 特征值和目标值 x, y data.iloc[:, :-1], data.iloc[:, -1] # 类型转换特征值目标值 x x.astype(np.float32) y y.astype(np.int64) # 数据集划分 x_train, x_valid, y_train, y_valid train_test_split(x, y, train_size0.8, random_state88) # 构建数据集,转换为pytorch的形式 train_dataset TensorDataset(torch.from_numpy(x_train.values), torch.tensor(y_train.values)) valid_dataset TensorDataset(torch.from_numpy(x_valid.values), torch.tensor(y_valid.values)) # 返回结果 return train_dataset, valid_dataset, x_train.shape[1], len(np.unique(y))输出结果输入特征数 20 分类个数 48.2.3 构建分类网络模型构建全连接神经网络来进行手机价格分类该网络主要由三个线性层来构建使用 relu 激活函数。网络共有 3 个全连接层具体信息如下:第一层输入为维度为 20, 输出维度为: 128第二层输入为维度为 128, 输出维度为: 256第三层输入为维度为 256, 输出维度为: 4# 构建网络模型 class PhonePriceModel(nn.Module): def __init__(self, input_dim, output_dim): super(PhonePriceModel, self).__init__() # 1. 第一层: 输入为维度为 20, 输出维度为: 128 self.linear1 nn.Linear(input_dim, 128) # 2. 第二层: 输入为维度为 128, 输出维度为: 256 self.linear2 nn.Linear(128, 256) # 3. 第三层: 输入为维度为 256, 输出维度为: 4 self.linear3 nn.Linear(256, output_dim) def forward(self, x): # 前向传播过程 x torch.relu(self.linear1(x)) x torch.relu(self.linear2(x)) output self.linear3(x) # 获取数据结果 return output模型实例化的输出8.2.4 模型训练网络编写完成之后我们需要编写训练函数。所谓的训练函数指的是输入数据读取、送入网络、计算损失、更新参数的流程该流程较为固定。我们使用的是多分类交叉生损失函数、使用 SGD 优化方法。最终将训练好的模型持久化到磁盘中。# 模型训练过程 def train(train_dataset,input_dim,class_num,): # 固定随机数种子 torch.manual_seed(0) # 初始化数据加载器 dataloader DataLoader(train_dataset, shuffleTrue, batch_size8) # 初始化模型 model PhonePriceModel(input_dim, class_num) # 损失函数 criterion nn.CrossEntropyLoss() # 优化方法 optimizer optim.SGD(model.parameters(), lr1e-3) # 训练轮数 num_epoch 50 # 遍历每个轮次的数据 for epoch_idx in range(num_epoch): # 训练时间 start time.time() # 计算损失 total_loss 0.0 total_num 0 # 遍历每个batch数据进行处理 for x, y in dataloader: # 将数据送入网络中进行预测 output model(x) # 计算损失 loss criterion(output, y) # 梯度清零 optimizer.zero_grad() # 反向传播 loss.backward() # 参数更新 optimizer.step() # 损失计算 total_num 1 total_loss loss.item() # 打印损失变换结果 print(epoch: %4s loss: %.2f, time: %.2fs %(epoch_idx 1, total_loss / total_num, time.time() - start)) # 模型保存 torch.save(model.state_dict(), model/phone.pth)训练的输出结果8.2.5 模型评估使用训练好的模型对未知的样本的进行预测的过程。我们这里使用前面单独划分出来的验证集来进行评估。def test(valid_dataset,input_dim,class_num): # 加载模型和训练好的网络参数 model PhonePriceModel(input_dim, class_num) model.load_state_dict(torch.load(model/phone.pth)) # 构建加载器 dataloader DataLoader(valid_dataset, batch_size8, shuffleFalse) # 评估测试集 correct 0 # 遍历测试集中的数据 for x, y in dataloader: # 将其送入网络中 output model(x) # 获取类别结果 y_pred torch.argmax(output, dim1) # 获取预测正确的个数 correct (y_pred y).sum() # 求预测精度 print(Acc: %.5f % (correct.item() / len(valid_dataset)))输出结果:Acc: 0.642508.3 调优方向我们前面的网络模型在测试集的准确率为: 0.64250, 我们可以通过以下方面进行调优:优化方法由 SGD 调整为 Adam学习率由 1e-3 调整为 1e-4对数据进行标准化增加网络深度即增加网络参数量调整训练轮次

相关文章:

人工神经网络知识点讲解

人工神经网络知识点讲解 知识导图 人工神经网络 ├── 基础认知 │ ├── 神经网络的核心概念 │ ├── 神经元的工作机制 │ └── 网络的层级结构 ├── 激活函数 │ ├── 激活函数的作用 │ ├── 常见激活函数:sigmoid/tanh/ReLU/Softmax │ …...

基于MCP协议的AI智能体安全扫描器:架构、部署与实战指南

1. 项目概述:一个为AI智能体设计的“安全门卫”最近在折腾AI智能体(Agent)的落地应用,发现一个挺普遍但容易被忽视的问题:当你的智能体开始联网、调用工具、处理外部数据时,它接收到的信息就像从四面八方涌…...

基于MCP协议构建微信通知服务:解耦业务与通知逻辑的实践

1. 项目概述:一个面向开发者的轻量级通知集成工具最近在折腾一个自动化脚本,需要把运行结果实时推送到手机上,但又不想把各种IM的SDK耦合进代码里,太臃肿了。相信很多做后端服务、运维监控或者自动化脚本的朋友都遇到过类似的需求…...

基于MCP协议构建TikTok趋势分析服务器:架构设计与实战指南

1. 项目概述与核心价值最近在折腾一个挺有意思的项目,叫trendsmcp/tiktok-trends-mcp。乍一看这个名字,你可能觉得这又是一个抓取TikTok数据的工具,市面上这类工具确实不少。但深入用下来,我发现它的定位和设计思路非常独特&#…...

开源集成利器OpenClaw:深度连接Bitrix24与外部系统的PHP解决方案

1. 项目概述:一个为Bitrix24量身定制的开源集成利器如果你正在使用Bitrix24,并且对它的某些功能限制感到束手束脚,或者你厌倦了在不同系统间手动搬运数据的繁琐,那么你很可能已经意识到,一个强大的集成工具是多么必要。…...

Llama 3专用JavaScript分词器:原理、API与实战指南

1. 项目概述:一个为Llama 3量身定制的JavaScript分词器 如果你正在Web端或Node.js环境中折腾大语言模型,特别是Meta家的Llama 3系列,那么处理文本的第一步——分词(Tokenization)——很可能就是你遇到的第一个拦路虎。…...

WorkBuddy清理Claw历史会话指南

🔧 WorkBuddy 清理Claw历史会话指南「有些在Claw上用来做测试的对话一直存在,界面没有删除按钮,就算把文件夹删了,历史记录也还是在,强迫症都犯了!!!」—— 来自一位真实网友的吐槽如…...

基于检索增强生成(RAG)构建专属代码生成器:从原理到工程实践

1. 项目概述:一个为开发者赋能的代码生成与知识管理工具在软件开发的世界里,我们每天都在与代码、文档和碎片化的知识打交道。你有没有遇到过这样的场景:面对一个似曾相识的业务逻辑,却记不清上次是怎么实现的;或者需要…...

从零实现MD5算法:C语言详解与工程实践指南

1. 从零开始:为什么我们需要自己实现MD5?在信息安全领域,MD5(Message-Digest Algorithm 5)是一个绕不开的名字。尽管它早已被证明存在碰撞漏洞,不再适用于高安全级别的数字签名或证书场景,但它在…...

深入解析JavaScript光标增强库:原理、实战与性能优化

1. 项目概述:一个被低估的JavaScript光标增强库 在Web前端开发中,我们常常会忽略一个看似微小却直接影响用户体验的细节——光标。无论是文本编辑器、代码IDE,还是富文本应用,光标的样式、行为和状态反馈,都直接关系到…...

权限组(PerGroup)设计:超越RBAC的精细化权限管理核心

1. 从“组”到“权限组”:一个被忽视的系统管理基石在系统管理和软件开发中,我们经常听到“用户组”(Group)这个概念。无论是Linux系统上的/etc/group文件,还是Windows的本地用户和组管理,亦或是各类应用后…...

别再只用AddModuleScore了!用irGSEA包一站式搞定单细胞基因集富集分析与8种可视化

单细胞基因集富集分析进阶指南:告别AddModuleScore,拥抱irGSEA的全能解决方案 在单细胞转录组数据分析中,基因集富集分析(Gene Set Enrichment Analysis, GSEA)是揭示细胞状态和功能特征的关键步骤。然而,许…...

WechatDecrypt终极指南:4步快速解密微信加密数据库的技术原理与实战

WechatDecrypt终极指南:4步快速解密微信加密数据库的技术原理与实战 【免费下载链接】WechatDecrypt 微信消息解密工具 项目地址: https://gitcode.com/gh_mirrors/we/WechatDecrypt 在数字隐私保护日益重要的今天,微信作为全球最大的即时通讯工具…...

K8s 日志治理:EFK 集群进阶配置 + 日志分片、归档、清理自动化方案

K8s 日志治理:EFK 集群进阶配置 + 日志分片、归档、清理自动化方案 前言:在Kubernetes(以下简称K8s)集群运维中,日志是问题排查、性能监控、合规审计的核心依据。EFK(Elasticsearch + Fluentd/Fluent Bit + Kibana)作为K8s日志收集与分析的主流架构,基础部署仅能满足“…...

容器存储进阶:PersistentVolume(PV)_PVC 底层原理 + 动态供应踩坑 + 数据备份恢复实战

容器存储进阶:PersistentVolume(PV)/PVC 底层原理 + 动态供应踩坑 + 数据备份恢复实战 前言:在Kubernetes容器集群中,PersistentVolume(PV)与PersistentVolumeClaim(PVC)是实现容器持久化存储的核心组件,但生产环境中,多数运维人员往往卡在基础配置层面,而忽略了动…...

Python协程与异步模式进阶

Python协程与异步模式进阶 一、协程的本质 协程是可以暂停和恢复执行的函数。Python中协程经历了三代演进: - 基于生成器的协程(Python 2.5,已废弃) - yield from协程(Python 3.3) - async/await原生协程…...

终极指南:无需Office软件,3秒预览Word、Excel、PPT文件

终极指南:无需Office软件,3秒预览Word、Excel、PPT文件 【免费下载链接】QuickLook.Plugin.OfficeViewer Word, Excel, and PowerPoint plugin for QuickLook. 项目地址: https://gitcode.com/gh_mirrors/qu/QuickLook.Plugin.OfficeViewer 还在为…...

ArcMap打开别人发来的mxd文件,图层全是红叉?别慌,5分钟教你修复数据源链接

ArcMap打开mxd文件图层全是红叉?5步急救与3种预防方案 收到同事发来的ArcMap项目文件,满屏红色感叹号像交通信号灯一样刺眼——这是GIS从业者最熟悉的"心跳加速时刻"。这种数据源断裂问题每年困扰着全球超过60%的ArcMap用户,尤其在…...

如何破解Wallpaper Engine资源文件:终极RePKG工具指南

如何破解Wallpaper Engine资源文件:终极RePKG工具指南 【免费下载链接】repkg Wallpaper engine PKG extractor/TEX to image converter 项目地址: https://gitcode.com/gh_mirrors/re/repkg 想要修改Wallpaper Engine动态壁纸却打不开PKG资源包?…...

CubeMX默认配置的坑:STM32 LPUART的ORE溢出错误如何彻底解决(从寄存器到HAL库的避坑指南)

STM32 LPUART的ORE溢出错误:从硬件机制到HAL库的深度解决方案 当你在深夜调试STM32的LPUART接口时,突然发现串口"神秘"地停止了响应——这种场景对于经验丰富的嵌入式工程师来说并不陌生。问题的根源往往指向那个容易被忽视的Overrun Error&am…...

从零构建XV-15倾转旋翼机:X-Plane飞行模拟与模型调校实战

1. 认识XV-15与倾转旋翼机 XV-15是美国贝尔直升机公司在1970年代研发的实验性倾转旋翼机,它完美结合了直升机的垂直起降能力和固定翼飞机的高速巡航特性。这种独特的飞行器通过旋转发动机舱实现旋翼倾转,在起飞时像直升机一样垂直升空,达到一…...

【DeepSeek大模型Azure部署黄金方案】:20年架构师亲授5大避坑指南与性能调优实战

更多请点击: https://intelliparadigm.com 第一章:DeepSeek大模型Azure部署黄金方案全景概览 在 Azure 上高效部署 DeepSeek 系列大模型(如 DeepSeek-V2、DeepSeek-Coder)需兼顾性能、成本与可运维性。微软 Azure 提供了从 GPU 实…...

别再让‘01’和‘470.00’坑了你:Python int()类型转换的深度避坑指南

Python类型转换避坑指南:从ValueError到健壮代码的进阶之路 在数据处理和清洗过程中,类型转换是最基础却又最容易出错的环节之一。特别是当面对非标准格式的数字字符串时,即使是经验丰富的开发者也会偶尔掉入int()函数的陷阱。本文将深入剖析…...

Mediapipe手势识别踩坑实录:解决Python 3.10+和OpenCV版本兼容性问题

Mediapipe手势识别实战:Python高版本环境兼容性全指南 当你在Python 3.10或更高版本中尝试运行Mediapipe手势识别项目时,可能会遇到各种令人沮丧的错误。从模块导入失败到函数弃用警告,再到依赖冲突,这些问题往往让开发者陷入无休…...

【51单片机】直流电机PWM调速实战:从驱动电路到闭环控制

1. 直流电机驱动基础与硬件选型 第一次玩直流电机时,我直接拿杜邦线把电机接在51单片机的IO口上,结果电机纹丝不动,还差点烧了芯片。这个教训让我明白:驱动电路是电机控制的第一道门槛。常见的直流电机工作电压通常在3-6V&#xf…...

自动化设计循环:用Figma API与CI/CD打通设计与开发协作

1. 项目概述:从“设计循环”到高效协作的范式转变如果你是一名产品设计师、前端工程师,或者任何需要频繁与设计稿打交道的开发者,那么“设计循环”这个概念你一定不陌生。它指的是从设计稿产出,到开发实现,再到设计走查…...

GPT模型评估实战:开源工具gpt-stats构建多维度能力评测体系

1. 项目概述:一个为GPT模型“体检”的开源利器如果你和我一样,日常工作中经常和各类GPT模型打交道,无论是调用OpenAI的官方API,还是部署、微调开源的Llama、Qwen等模型,心里总会萦绕着一个问题:这个模型到底…...

光波导技术在高速PCB设计中的关键应用与挑战

1. 光波导技术在现代PCB设计中的核心价值2008年那个看似平常的十二月,当Mentor Graphics发布那份关于印刷电路板光波导技术的白皮书时,恐怕很少有人能预见这项技术会在今天成为5G基站和数据中心的核心支撑。作为在高速PCB设计领域摸爬滚打十五年的老工程…...

Overleaf从入门到精通:在线LaTeX编辑器的核心功能与实战指南

1. Overleaf入门:为什么选择在线LaTeX编辑器 第一次接触LaTeX时,我被它复杂的本地环境配置劝退了。直到发现了Overleaf这个在线编辑器,才真正体会到科研写作的流畅感。作为一款零配置的云端LaTeX平台,它解决了传统LaTeX最让人头疼…...

Signaldb CLI 实战指南:快速构建响应式前端应用

1. 项目概述与核心价值 最近在折腾一个前后端分离的项目,涉及到大量的数据同步和状态管理,尤其是离线场景下的数据一致性,简直让人头大。就在我准备自己动手造轮子的时候,偶然在GitHub上看到了 jiridudekusy/signaldb-cli 这个项…...