深度学习-神经网络基础-网络搭建-损失函数-网络优化-正则化方法

一. 神经网络搭建和参数计算

一个继承(nn.model), 两个方法(init, forward)

简介

在pytorch中定义深度神经网络其实就是层堆叠的过程,继承自nn.Module,实现两个方法:

  • init方法中定义网络中的层结构,主要是全连接层,并进行初始化, 定义层

  • forward方法,在实例化模型的时候,底层会自动调用该函数。该函数中可以定义学习率,为初始化定义的layer传入数据等。将各层连接

案例

需求

编码设计如下:

  1. 第1个隐藏层:权重初始化采用标准化的xavier初始化 激活函数使用sigmoid

  2. 第2个隐藏层:权重初始化采用标准化的He初始化 激活函数采用relu

  3. out输出层线性层 假若二分类,采用softmax做数据归一化

代码演示
import torch
import torch.nn as nn
from torchsummary import summary
​
​
class NnModel(nn.Module):
    def __init__(self):
        super(NnModel, self).__init__()
​
        # Hidden1(3, 3)
        self.linear1 = nn.Linear(3, 3)
        nn.init.xavier_normal_(self.linear1.weight)
​
        # Hidden2(3, 2)
        self.linear2 = nn.Linear(3, 2)
        nn.init.kaiming_uniform_(self.linear2.weight)
​
        # Output(2, 2)
        self.out = nn.Linear(2, 2)
​
    def forward(self, x):
        # 数据经第一层线性层处理
        x = self.linear1(x)
        # 激活函数
        x = torch.sigmoid(x)
​
        # 数据经第二层线性层处理
        x = self.linear2(x)
        # 激活函数
        x = torch.relu(x)
​
        # 数据经输出层
        out = self.out(x)
        # dim=-1: 输出每个样本预测不同类别的概率, 每个样本类别预测和为1
        out = torch.softmax(out, dim=-1)
        return out
​
​
if __name__ == '__main__':
    # 'cuda': 使用GPU, 数据模型等都需要放到一起
    model = NnModel().to('cuda')
    my_data = torch.randn(5, 3).to('cuda')
    output = model(my_data)
    print(output)
​
    # 查看网络结构
    summary(model, (3,), 1, device='cuda')
​
    # 查看网络参数
    for name, param in model.named_parameters():
        print(name, param)
​

模型参数的计算

  1. 以第一个隐层为例:该隐层有3个神经元,每个神经元的参数为:4个(w1,w2,w3,b1),所以一共用3x4=12个参数。

  2. 输入数据和网络权重是两个不同的事儿!对于初学者理解这一点十分重要,要分得清。

总结

神经网络的搭建方

  1. 定义继承自nn.Module的模型类

  2. init方法中定义网络中的层结构

  3. 在forward方法中定义数据传输方式

网络参数量的统计方法

  1. 统计每一层中的权重w和偏置b的数量

优缺点

1. 优点

  1. 精度高,性能优于其他的机器学习算法,甚至在某些领域超过了人类

  2. 可以近似任意的非线性函数随之计算机硬件的发展,

  3. 近年来在学界和业界受到了热捧,有大量的框架和库可供调。

2. 缺点

  1. 黑箱,很难解释模型是怎么工作的

  2. 训练时间长,需要大量的计算资源

  3. 网络结构复杂,需要调整超参数

  4. 部分数据集上表现不佳,容易发生过拟合

二. 损失函数

概念

在深度学习中, 损失函数是用来衡量模型参数的质量的函数, 衡量的方式是比较网络输出和真实输出的差异:

损失函数在不同的文献中名称是不一样的,主要有以下几种命名方式:

多分类损失函数-softmax

loss = nn.CrossEntropyLoss()

概念

在多分类任务通常使用softmax将logits转换为概率的形式,所以多分类的交叉熵损失也叫做softmax损失,它的计算方法是:

公式

其中:

1.y 是样本 x 属于某一个类别的真实概率

2.而 f(x) 是样本属于某一类别的预测分数

3.S 是 softmax 激活函数,将属于某一类别的预测分数转换成概率

4.L 用来衡量真实值 y 和预测值 f(x) 之间差异性的损失结果

举例

import torch
from torch import nn
​
# 多分类交叉熵损失,使用nn.CrossEntropyLoss()实现。nn.CrossEntropyLoss()=softmax + 损失计算
def test1():
    # 设置真实值: 可以是热编码后的结果也可以不进行热编码
    # y_true = torch.tensor([[0, 1, 0], [0, 0, 1]], dtype=torch.float32)
    # 注意的类型必须是64位整型数据
    y_true = torch.tensor([1, 2], dtype=torch.int64)
    y_pred = torch.tensor([[0.2, 0.6, 0.2], [0.1, 0.8, 0.1]], dtype=torch.float32)
    # 实例化交叉熵损失
    loss = nn.CrossEntropyLoss()
    # 计算损失结果
    my_loss = loss(y_pred, y_true).numpy()
    print('loss:', my_loss)
​

二分类损失函数-sigmoid

criterion = nn.BCELoss()

概念

在处理二分类任务时,我们不再使用softmax激活函数,而是使用sigmoid激活函数,那损失函数也相应的进行调整,使用二分类的交叉熵损失函数

公式

其中:

  1. y 是样本x属于某一个类别的真实概率

  2. 而 y^ 是样本属于某一类别的预测概率

  3. L 用来衡量真实值y与预测值y^之间差异性的损失结果。

举例
import torch
from torch import nn
​
def test2():
    # 1 设置真实值和预测值
    # 预测值是sigmoid输出的结果
    y_pred = torch.tensor([0.6901, 0.5459, 0.2469], requires_grad=True)
    y_true = torch.tensor([0, 1, 0], dtype=torch.float32)
    # 2 实例化二分类交叉熵损失
    criterion = nn.BCELoss()
    # 3 计算损失
    my_loss = criterion(y_pred, y_true).detach().numpy()
    print('loss:', my_loss)
​

回归-MAE损失函数

loss = nn.L1Loss()

概念

Mean absolute loss(MAE)也被称为L1 Loss,是以绝对误差作为距离。损失函数公式:

特点

  1. 由于L1 loss具有稀疏性,为了惩罚较大的值,因此常常将其作为正则项添加到其他loss中作为约束。

  2. L1 loss的最大问题是梯度在零点不平滑,导致会跳过极小值。

举例
import torch
from torch import nn
​
def test3():
    # 1 设置真实值和预测值
    y_pred = torch.tensor([1.0, 1.0, 1.9], requires_grad=True)
    y_true = torch.tensor([2.0, 2.0, 2.0], dtype=torch.float32)
    # 2 实例MAE损失对象
    loss = nn.L1Loss()
    # 3 计算损失
    my_loss = loss(y_pred, y_true).detach().numpy()
    print('loss:', my_loss)
​

回归-MSE损失函数

loss = nn.MSELoss()

概念

Mean Squared Loss/ Quadratic Loss(MSE loss)也被称为L2 loss,或欧氏距离,它以误差的平方和的均值作为距离

特点

  1. L2 loss也常常作为正则项。

  2. 当预测值与目标值相差很大时, 梯度容易爆炸。

举例
import torch
from torch import nn
​
def test4():
    # 1 设置真实值和预测值
    y_pred = torch.tensor([1.0, 1.0, 1.9], requires_grad=True)
    y_true = torch.tensor([2.0, 2.0, 2.0], dtype=torch.float32)
    # 2 实例MSE损失对象
    loss = nn.MSELoss()
    # 3 计算损失
    my_loss = loss(y_pred, y_true).detach().numpy()
    print('myloss:', my_loss)
​

回归-SmoothL1损失

loss = nn.SmoothL1Loss()

概念

smooth L1说的是光滑之后的L1。损失函数公式:

解释

其中:𝑥 = f(x) − y 为真实值和预测值的差值。

从下图中可以看出,该函数实际上就是一个分段函数

  1. 在[-1,1]之间实际上就是L2损失,这样解决了L1的不光滑问题

  2. 在[-1,1]区间外,实际上就是L1损失,这样就解决了离群点梯度爆炸的问题

举例
import torch
from torch import nn
​
def test5():
    # 1 设置真实值和预测值
    y_true = torch.tensor([0, 3])
    y_pred = torch.tensor([0.6, 0.4], requires_grad=True)
    # 2 实例化smoothL1损失对象
    loss = nn.SmoothL1Loss()
    # 3 计算损失
    my_loss = loss(y_pred, y_true).detach().numpy()
    print('loss:', my_loss)
​

三. 网络优化方法

网格优化, 使得损失函数最小, 快速找到预测值和真实值更接近的方法

梯度下降算法

寻找使损失函数最小化

原理

梯度下降法是一种寻找使损失函数最小化的方法。从数学上的角度来看,梯度的方向是函数增长速度最快的方向,那么梯度的反方向就是函数减少最快的方向,所以有:

其中,η是学习率,如果学习率太小,那么每次训练之后得到的效果都太小,增大训练的时间成本。如果,学习率太大,那就有可能直接跳过最优解,进入无限的训练中。解决的方法就是,学习率也需要随着训练的进行而变化。

相关概念

在进行模型训练时,有三个基础的概念:

  1. Epoch: 使用全部数据对模型进行以此完整训练,训练轮次

  2. Batch_size: 使用训练集中的小部分样本对模型权重进行以此反向传播的参数更新,每次训练每批次样本数量

  3. Iteration: 使用一个 Batch 数据对模型进行一次参数更新的过程, 等于Batch

假设数据集有 50000 个训练样本,现在选择 Batch Size = 256 对模型进行训练。

  • 每个 Epoch 要训练的图片数量:50000

  • 训练集具有的 Batch 个数:50000/256+1=196

  • 每个 Epoch 具有的 Iteration 个数:196

  • 10个 Epoch 具有的 Iteration 个数:1960

分类

在深度学习中,梯度下降的几种方式的根本区别就在于 Batch Size不同,如下表所示:

注:上表中 Mini-Batch 的 Batch 个数为 N / B + 1 是针对未整除的情况。整除则是 N / B。

反向传播算法

从后往前,结合梯度下降算法,依次求各个参数的偏导,并进行参数更新

原理

前向传播:指的是数据输入的神经网络中,逐层向前传输,一直到运算到输出层为止。

反向传播(Back Propagation):利用损失函数 ERROR,从后往前,结合梯度下降算法,依次求各个参数的偏导,并进行参数更新

举例

反向传播对神经网络中的各个节点的权重进行更新。一个简单的神经网络用来举例:激活函数为sigmoid

网络

前向传播

反向传播

接下来是反向传播,我们先来求最简单的,求误差E对w5的导数。要求误差E对w5的导数,需要先求误差E对out o1的导数,再求out o1对net o1的导数,最后再求net o1对w5的导数,经过这个处理,我们就可以求出误差E对w5的导数(偏导),如下图所示:

参数更新

导数(梯度)已经计算出来了,下面就是反向传播与参数更新过程

如果要想求误差E对w1的导数,误差E对w1的求导路径不止一条,这会稍微复杂一点,但换汤不换药,计算过程如下所示:

代码演示
import torch
from torch import nn
from torch import optim
​
# 创建神经网络类
class Model(nn.Module):
    # 初始化参数
    def __init__(self):
        # 调用父类方法
        super(Model, self).__init__()
        # 创建网络层
        self.linear1 = nn.Linear(2, 2)
        self.linear2 = nn.Linear(2, 2)
        # 初始化神经网络参数
        self.linear1.weight.data = torch.tensor([[0.15, 0.20], [0.25, 0.30]])
        self.linear2.weight.data = torch.tensor([[0.40, 0.45], [0.50, 0.55]])
        self.linear1.bias.data = torch.tensor([0.35, 0.35])
        self.linear2.bias.data = torch.tensor([0.60, 0.60])
​
    # 前向传播方法
    def forward(self, x):
        # 数据经过第一层隐藏层
        x = self.linear1(x)
        # 计算第一层激活值
        x = torch.sigmoid(x)
        # 数据经过第二层隐藏层
        x = self.linear2(x)
        # 计算第二层激活值
        x = torch.sigmoid(x)
        return x    
    
    
if __name__ == '__main__':
    # 定义网络输入值和目标值
    inputs = torch.tensor([[0.05, 0.10]])
    target = torch.tensor([[0.01, 0.99]])
    # 实例化神经网络对象
    model = Model()
    output = model(inputs)
    print("output-->", output)
    loss = torch.sum((output - target) ** 2) / 2    # 计算误差
    print("loss-->", loss)
    # 优化方法和反向传播算法
    optimizer = optim.SGD(model.parameters(), lr=0.5)
    optimizer.zero_grad()
    loss.backward()
    print("w1,w2,w3,w4-->", model.linear1.weight.grad.data)
    print("w5,w6,w7,w8-->", model.linear2.weight.grad.data)
    optimizer.step()
    # 打印神经网络参数
    print(model.state_dict())
​
​
>>> output--> tensor([[0.7514, 0.7729]], grad_fn=<SigmoidBackward0>)
​
loss--> tensor(0.2984, grad_fn=<DivBackward0>)
​
w1,w2,w3,w4--> tensor([[0.0004, 0.0009],
                       [0.0005, 0.0010]])
​
w5,w6,w7,w8--> tensor([[ 0.0822,  0.0827],
                       [-0.0226, -0.0227]])
​
OrderedDict([('linear1.weight', tensor([[0.1498, 0.1996],
                                      [0.2498, 0.2995]])), 
             ('linear1.bias', tensor([0.3456, 0.3450])), 
             ('linear2.weight', tensor([[0.3589, 0.4087],
                                        [0.5113, 0.5614]])), 
             ('linear2.bias', tensor([0.5308, 0.6190]))])
​

总结

前向传播:指的是数据输入的神经网络中,逐层向前传输,一直到运算到输出层为止。

反向传播(Back Propagation):利用损失函数 ERROR,从后往前,结合梯度下降算法,依次求各个参数的偏导,并进行参数更新

梯度下降优化方法

  1. 碰到平缓区域,梯度值较小,参数优化变慢

  2. 碰到 “鞍点” ,梯度为 0,参数无法优化

  3. 碰到局部最小值,参数不是最优

对梯度下降算法的优化方法,例如:Momentum、AdaGrad、RMSprop、Adam 等

指数加权平均

用于动量算法和RMSProp算法的更新步骤

指数移动加权平均则是参考各数值,并且各数值的权重都不同,距离越远的数字对平均数计算的贡献就越小(权重较小),距离越近则对平均数的计算贡献就越大(权重越大)。

  • St 表示指数加权平均值;

  • Yt 表示 t 时刻的值;

  • β 调节权重系数,该值越大平均数越平缓。

momentum-梯度

动量算法调整梯度

公式

梯度计算公式:Dt = β * St-1 + (1- β) * Wt

  1. St-1 表示历史梯度移动加权平均值

  2. Wt 表示当前时刻的梯度值

  3. Dt 为当前时刻的指数加权平均梯度值

  4. β 为权重系数

举例

假设:权重 β 为 0.9,例如:

  • 第一次梯度值:D1 = S1 = W1

  • 第二次梯度值:D2=S2 = 0.9 * S1 + W2 * 0.1

  • 第三次梯度值:D3=S3 = 0.9 * S2 + W3 * 0.1

  • 第四次梯度值:D4=S4 = 0.9 * S3 + W4 * 0.1

梯度下降公式中梯度的计算,就不再是当前时刻 t 的梯度值,而是历史梯度值的指数移动加权平均值。公式修改为:grad2 = grad1 * A + grad2 * B

优缺点
  1. 当处于鞍点位置时,由于当前的梯度为 0,参数无法更新。但是 Momentum 动量梯度下降算法已经在先前积累了一些梯度值,很有可能使得跨过鞍点。克服鞍点问题

  2. 由于 mini-batch 普通的梯度下降算法,每次选取少数的样本梯度确定前进方向,可能会出现震荡,使得训练时间变长。Momentum 使用移动加权平均,平滑了梯度的变化,使得前进方向更加平缓,有利于加快训练过程。

代码演示
import torch
import matplotlib.pyplot as plt
​
def test03():
    # 1 初始化权重参数
    w = torch.tensor([1.0], requires_grad=True, dtype=torch.float32)
    y = ((w ** 2) / 2.0).sum()
    # 2 实例化优化方法,SGD指定参数beta=0.9
    optimizer = torch.optim.SGD([w], lr=0.01, momentum=0.9)
    # 3 第一次更新计算梯度,并对参数进行更新
    optimizer.zero_grad()
    y.backward()
    optimizer.step()
    print('第1次: 梯度w.grad: %f,更新后的权重:%f' % (w.grad.numpy(), w.detach().numpy()))
    # 4 第2次更新 计算梯度,并对参数进行更新
    # 使用更新后的参数机选输出结果
    y = ((w ** 2) / 2.0).sum()
    optimizer.zero_grad()
    y.backward()
    optimizer.step()
    print('第2次: 梯度w.grad: %f, 更新后的权重:%f' % (w.grad.numpy(), w.detach().numpy()))
​
    
>>> 
第1次: 梯度w.grad: 1.0000000000, 更新后的权重:0.9900000095
第2次: 梯度w.grad: 0.9900000095, 更新后的权重:0.9711000323

AdaGrad-学习率

累计平方梯度优化学习率

步骤

AdaGrad 通过对不同的参数分量使用不同的学习率,AdaGrad 的学习率总体会逐渐减小

其计算步骤如下:

1.初始化学习率 α、初始化参数 θ、小常数 σ = 1e-6

2.初始化梯度累积变量 s = 0

3.从训练集中采样 m 个样本的小批量,计算梯度 g

4.累积平方梯度 s = s + g ⊙ g,⊙ 表示各个分量相乘

公式

学习率 α 的计算公式如下:

参数更新公式如下:

累计平方梯度:

累积平方梯度 s = s + g ⊙ g,⊙ 表示各个分量相乘

用梯度平方惩罚学习率

优缺点

AdaGrad 缺点是可能会使得学习率过早、过量的降低,导致模型训练后期学习率太小,较难找到最优解。

导致学习率过低, 容易陷入局部极小值点

代码演示
import torch
import matplotlib.pyplot as plt
​
def test04():
    # 1 初始化权重参数
    w = torch.tensor([1.0], requires_grad=True, dtype=torch.float32)
    y = ((w ** 2) / 2.0).sum()
    # 2 实例化优化方法:adagrad优化方法
    optimizer = torch.optim.Adagrad([w], lr=0.01)
    # 3 第1次更新 计算梯度,并对参数进行更新
    optimizer.zero_grad()
    y.backward()
    optimizer.step()
    print('第1次: 梯度w.grad: %f, 更新后的权重:%f' % (w.grad.numpy(), w.detach().numpy()))
    # 4 第2次更新 计算梯度,并对参数进行更新
    # 使用更新后的参数机选输出结果
    y = ((w ** 2) / 2.0).sum()
    optimizer.zero_grad()
    y.backward()
    optimizer.step()
    print('第2次: 梯度w.grad: %f, 更新后的权重:%f' % (w.grad.numpy(), w.detach().numpy()))
​
    
>>>
第1次: 梯度w.grad: 1.000000, 更新后的权重:0.990000 
第2次: 梯度w.grad: 0.990000, 更新后的权重:0.982965

RMSProp-学习率

使用指数移动加权平均累计历史梯度优化AdaGrad

步骤

RMSProp 优化算法是对 AdaGrad 的优化. 最主要的不同是,其使用指数移动加权平均梯度替换历史梯度的平方和。其计算过程如下:

  1. 初始化学习率 α、初始化参数 θ、小常数 σ = 1e-6

  2. 初始化参数 θ

  3. 初始化梯度累计变量 s

  4. 从训练集中采样 m 个样本的小批量,计算梯度 g

  5. 使用指数移动平均累积历史梯度,公式如下:

公式

学习率 α 的计算公式如下:

参数更新公式如下:

指数移动加权平均累积历史梯度,公式如下:

代码演示
import torch
import matplotlib.pyplot as plt
​
def test05():
    # 1 初始化权重参数
    w = torch.tensor([1.0], requires_grad=True, dtype=torch.float32)
    y = ((w ** 2) / 2.0).sum()
    # 2 实例化优化方法:RMSprop算法,其中alpha对应β
    optimizer = torch.optim.RMSprop([w], lr=0.01, alpha=0.9)
    # 3 第1次更新 计算梯度,并对参数进行更新
    optimizer.zero_grad()
    y.backward()
    optimizer.step()
    print('第1次: 梯度w.grad: %f, 更新后的权重:%f' % (w.grad.numpy(), w.detach().numpy()))
    # 4 第2次更新 计算梯度,并对参数进行更新
    # 使用更新后的参数机选输出结果
    y = ((w ** 2) / 2.0).sum()
    optimizer.zero_grad()
    y.backward()
    optimizer.step()
    print('第2次: 梯度w.grad: %f, 更新后的权重:%f' % (w.grad.numpy(), w.detach().numpy()))
​
    
>>>
第1次: 梯度w.grad: 1.000000, 更新后的权重:0.968377 
第2次: 梯度w.grad: 0.968377, 更新后的权重:0.945788

Adam-学习率+梯度

  1. Momentum 使用指数加权平均计算当前的梯度值

  2. AdaGrad、RMSProp 使用自适应的学习率

  3. Adam优化算法(Adaptive Moment Estimation,自适应矩估计)将 Momentum 和 RMSProp 算法结合在一起。

  4. 修正梯度: 使⽤梯度的指数加权平均

  5. 修正学习率: 使⽤梯度平⽅的指数加权平均。

import torch
import matplotlib.pyplot as plt
​
def test06():
    # 1 初始化权重参数
    w = torch.tensor([1.0], requires_grad=True)
    y = ((w ** 2) / 2.0).sum()
    # 2 实例化优化方法:Adam算法,其中betas是指数加权的系数, 一个梯度, 一个学习率
    optimizer = torch.optim.Adam([w], lr=0.01, betas=[0.9, 0.99])
    # 3 第1次更新 计算梯度,并对参数进行更新
    optimizer.zero_grad()
    y.backward()
    optimizer.step()
    print('第1次: 梯度w.grad: %f, 更新后的权重:%f' % (w.grad.numpy(), w.detach().numpy()))
    # 4 第2次更新 计算梯度,并对参数进行更新
    # 使用更新后的参数机选输出结果
    y = ((w ** 2) / 2.0).sum()
    optimizer.zero_grad()
    y.backward()
    optimizer.step()
    print('第2次: 梯度w.grad: %f, 更新后的权重:%f' % (w.grad.numpy(), w.detach().numpy()))
​
    
>>> 
第1次: 梯度w.grad: 1.000000, 更新后的权重:0.990000 
第2次: 梯度w.grad: 0.990000, 更新后的权重:0.980003

总结

学习率衰减方法

等间隔学习率衰减

设置调整学习率的间隔, 训练指定间隔数后调整学习率

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_grad=True)
    # 2.优化器
    optimizer = optim.SGD([w], lr=LR, momentum=0.9)
    # 3.设置学习率下降策略
    scheduler_lr = optim.lr_scheduler.StepLR(optimizer, step_size=50, gamma=0.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, label="Step LR Scheduler")
    plt.xlabel("Epoch")
    plt.ylabel("Learning rate")
    plt.legend()
    plt.show()

指定间隔学习率衰减

def test_MultiStepLR():
    torch.manual_seed(1)
    LR = 0.1
    iteration = 10
    max_epoch = 200
    weights = torch.randn((1), requires_grad=True)
    target = torch.zeros((1))
    print('weights--->', weights, 'target--->', target)
    optimizer = optim.SGD([weights], lr=LR, momentum=0.9)
    # 设定调整时刻数
    milestones = [50, 125, 160]
    # 设置学习率下降策略
    scheduler_lr = optim.lr_scheduler.MultiStepLR(optimizer, milestones=milestones, gamma=0.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, label="Multi Step LR Scheduler\nmilestones:{}".format(milestones))
    plt.xlabel("Epoch")
    plt.ylabel("Learning rate")
    plt.legend()
    plt.show()

指数学习率衰减

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_grad=True)
    # 2.优化器
    optimizer = optim.SGD([w], lr=LR, momentum=0.9)
    # 3.设置学习率下降策略
    gamma = 0.95
    scheduler_lr = optim.lr_scheduler.ExponentialLR(optimizer, gamma=gamma)
    # 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, label="Multi Step LR Scheduler")
    plt.xlabel("Epoch")
    plt.ylabel("Learning rate")
    plt.legend()
    plt.show()

四. 正则化方法

缓解过拟合, 减小测试集误差

Dropout正则化

神经元随机失活

发生在训练阶段, 不在测试阶段, 网络结构不变, 测试阶段还会用到失活的神经元

策略

让神经元以超参数p的概率停止工作或者被激活置为为0, 未被置为0的按比例1/(1-p)缩放

代码演示
import torch
import torch.nn as nn
​
def test():
    # 初始化随机失活层
    dropout = nn.Dropout(p=0.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_fn=<AddmmBackward0>)
​
失活后FC层的输出结果:
 tensor([[-1.3949, -9.2866,  0.3763,  0.0000,  3.6531]], grad_fn=<MulBackward0>)

批量归一化-(BN层)

批量归一化层在计算机视觉领域使用较多

BN层: 对数据标准化,再对数据重构(缩放+平移)

先对数据标准化,再对数据重构(缩放+平移),如下所示:

  1. λ 和 β 是可学习的参数,它相当于对标准化后的值做了一个线性变换λ 为系数,β 为偏置;

  2. eps 通常指为 1e-5,避免分母为 0;

  3. E(x) 表示变量的均值;

  4. Var(x) 表示变量的方差;

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

全彩LED显示屏有几种安装方式?

全彩LED显示屏的安装方式多样&#xff0c;根据不同的使用场景和安装环境&#xff0c;可以选择最合适的安装方法。以下是一些常见的全彩LED显示屏安装方式&#xff1a; 室内显示屏安装方式 吊装&#xff1a;适用于室内承重混凝土顶&#xff0c;可以使用标准吊件&#xff0c;吊杆…

ZISUOJ 2024算法基础公选课练习二

一、前言 先把代码丢上来&#xff0c;后续再补上思路 二、题目总览 三、具体题目 3.1 问题 A: 成绩排序1 参考代码 简单排序 #include <bits/stdc.h> using i64 long long;int main() {std::cin.tie(nullptr)->sync_with_stdio(false);int t 1;std::cin >&g…

阿里云智能语音交互产品试用,基于语音识别、语音合成、自然语言理解

VER&#xff1a;2024年1月25日 17:29:33 智能语音交互产品基于语音识别、语音合成、自然语言理解 新开通智能语音交互服务用户&#xff0c;可享有3个月免费试用期&#xff0c;试用期间将不会产生费用 智能语音交互产品基于语音识别、语音合成、自然语言理解等技术&#xff0c…

服务器被攻击排查记录

起因 我的深度学习的所有进程突然被killed&#xff0c;我以为是检修&#xff0c;后面发现好像简单的python代码可以正常运行。但是我的训练进程一启动就会被killed 第一时间没有用htop查看cpu&#xff0c;用top看着挺正常的&#xff0c;但是后面看htop&#xff0c;全是绿的&a…

安卓好软-----电脑端查看apk全部信息的工具 查看包名 名称以及权限等等

有时候从网络下载的应用很多是英文。时间久了会忘记到底是什么apk应用。这款工具可以方便的查看apk应用的名称 包名以及各种权限 图标 大小版本号等等。方便用户随时查看 APK Helper能够详细地获得安装包名、软件名称、APK证书、真实版本号、要求的手机版本、系统权限、以及证书…

算法每日双题精讲——双指针(移动零,复写零)

&#x1f31f;快来参与讨论&#x1f4ac;&#xff0c;点赞&#x1f44d;、收藏⭐、分享&#x1f4e4;&#xff0c;共创活力社区。 &#x1f31f; 别再犹豫了&#xff01;快来订阅我们的算法每日双题精讲专栏&#xff0c;一起踏上算法学习的精彩之旅吧&#xff01;&#x1f4aa;…

【SQL】在 SQL Server 中创建数据源是 MySQL 数据表的视图

背景&#xff1a;Windows系统已安装了mysql5.7和sqlServer数据库&#xff0c;现在需要在sqlServer创建视图或者查询来自mysql的数据&#xff0c;视图的数据来源mysql数据库。下面进行实现在sqlserver实现获取mysql数据表数据构建视图。 1、打开 ODBC 数据源管理器&#xff0c;…

Git 入门篇(一)

前言 操作系统&#xff1a;win11 64位 与gitee搭配使用 Git 入门篇&#xff08;一&#xff09; Git 入门篇&#xff08;二&#xff09; Git 入门篇&#xff08;三&#xff09; 目录 git下载、安装与配置 下载 安装 配置 git下载、安装与配置 下载 官网&#xff1a;git-…

【React】条件渲染——逻辑与运算符

条件渲染——逻辑与&&运算符 你会遇到的另一个常见的快捷表达式是 JavaScript 逻辑与&#xff08;&&&#xff09;运算符。在 React 组件里&#xff0c;通常用在当条件成立时&#xff0c;你想渲染一些 JSX&#xff0c;或者不做任何渲染。 function Item({ nam…

Ubuntu 的 ROS 操作系统安装与测试

引言 机器人操作系统&#xff08;ROS, Robot Operating System&#xff09;是一个用于开发机器人应用的开源框架&#xff0c;它提供了一系列功能丰富的库和工具&#xff0c;能够帮助开发者构建和控制机器人。 当前&#xff0c;ROS1的最新版本为Noetic Ninjemys&#xff0c;专为…

无人驾驶汽车——AI技术在交通领域的进展与未来展望

文章目录 前言什么是无人驾驶汽车?特斯拉的无人驾驶愿景无人驾驶的技术进程:从DARPA挑战赛到特斯拉中国无人驾驶技术的现状谷歌的加入与优步的竞争深度学习的到来与特斯拉的独特优势无人驾驶的未来:机遇与挑战总结前言 今天,我想通过讲一个故事,帮助大家更好地理解无人驾…

MCU面试题

面试题 1、Crotex-M 处理器才用的架构是"v7" Cortex-M3处理器是基于ARMv7-M架构的处理器&#xff0c;支持更丰富的指令集&#xff0c;包括许多32位指令&#xff0c;这些指令可以高效的使用高位寄存器。另外&#xff0c;M3还支持&#xff1a; 查表跳转指令和条件执行&…

基于多设计模式下的同步异步日志系统

目录 一、项目介绍 1.1 项目功能 1.2 开发环境 1.3 核心技术 1.4 环境搭建 二、日志系统介绍 2.1 日志系统存在的必要性 2.2 日志系统的技术实现 三、相关技术知识的补充 3.1 不定参函数的使用 3.2 设计模式 四、日志系统框架设计 4.1 模块划分 4.2 模块关系图 …

C# 选择导入文件的路径、导出文件的路径

通过C#代码&#xff0c;调出windows风格的文件选择对话框和存储文件对话框。提供界面来选择文件的位置&#xff0c;并将完整路径以字符串形式返回。 1、选择导入文件&#xff0c;获取其路径 C#通过这段代码将弹出一个文件选择对话框&#xff0c;允许用户选择一个文件&#xff…

【Hadoop实训】Hive 数据操作①

目录 一、准备文件 1、创建表 2、 数据映射 二、HIVE的数据操作 1、基本查询 a、全表查询 b、选择特定字段查询 c、查询员工表总人数 d、查询员工表总工资额 e、查询5条员工表的信息 2、Where条件查询 a、查询工资等于5000的所有员工 b、查询工资在500到1000的员工信息 …

Kylin Server V10 下自动安装并配置Kafka

Kafka是一个分布式的、分区的、多副本的消息发布-订阅系统&#xff0c;它提供了类似于JMS的特性&#xff0c;但在设计上完全不同&#xff0c;它具有消息持久化、高吞吐、分布式、多客户端支持、实时等特性&#xff0c;适用于离线和在线的消息消费&#xff0c;如常规的消息收集、…

goroutine 介绍

引子&#xff1a; 线程比如打开腾讯视频然后开始下载多个视频&#xff0c;下载任务就是线程 但是这并不是同时进行的&#xff0c;只是时间片比较短切换的比较快 进程和线程的关系 有些程序可以多进程有些可能不支持 并发和并行 并发和并行的根本区别是&#xff1a;并发在同一时…

AlphaProof IMO 2024 P1 in LEAN 之 简介

AlphaProof 是用于进行数学证明的人工智能&#xff0c;其中&#xff0c;对于 IMO 2024 中的6道题中的 4 道。本系列博文&#xff0c;就 AlphaProof 对于 IMO 2024 P1 给出的答案进行详细讲述。这里是此系列的第一篇。 IMO 2024 P1 题目如下&#xff1a; IMO 2024 P1 答案 α 为…

Android Framework AMS(11)广播组件分析-2(注册/注销流程解读)

该系列文章总纲链接&#xff1a;专题总纲目录 Android Framework 总纲 本章关键点总结 & 说明&#xff1a; 说明&#xff1a;本章节主要解读广播组件的动态注册/注销过程及静态注册过程。关注思维导图中左上侧部分即可。 有了前面startActivity流程和service组件启动流程分…

Llamaindex RAG 实践

大模型支持的最强大的应用程序之一是复杂的问答聊天机器人。这些应用程序可以回答有关特定源信息的问题。这些应用程序使用一种称为检索增强生成 &#xff08;RAG&#xff09; 的技术。 1. 什么是RAG&#xff1f; 当你需要给模型注入新的知识时&#xff0c;有两种方法&#xf…