• pytorch——关于拟合训练的demo代码解析


    自动求导机制——autograd

    torch.autograd为用户方便使用,而专门开发的一套自动求导引擎,可以根据输入和前向传播过程自动构建计算图,并执行反向传播。

    计算图:现代深度学习框架如PyTorch和TensorFlow等的核心,其为高效自动求导算法——反向传播提供理论支持。

    autograd包为张量上的所有操作提供了自动求导。它是一个在运行时定义的框架,这意味着反向传播是根据你的代码来确定如何运行,并且每次迭代可以是不同的。

    张量(Tensor)

    torch.Tensor是这个包的核心类。如果设置.requires_grad为True,那么将会追踪该张量的操作。

    • backward:当完成计算后通过调用 .backward(),自动计算所有的梯度, 这个张量的所有梯度将会自动积累到 .grad 属性。

    • detach:要阻止张量跟踪历史记录,可以调用.detach()方法将其与计算历史记录分离,并禁止跟踪它将来的计算记录。

    • grad:为了防止跟踪历史记录(和使用内存),可以将代码块包装在with torch.no_grad():中。 在评估模型时特别有用,因为模型可能具有requires_grad = True的可训练参数,但是我们不需要梯度计算。

    训练模型过程

    model = nn.Linear(1, 1)  # w * input + b
    loss_fn = nn.MSELoss()  # 损失函数
    opt = torch.optim.SGD(model.parameters(), lr=0.0001)  # 随机梯度下降
    # 开始训练
    for epoch in range(1000):
        for x, y in zip(X, Y):
            # step1:使用模型预测
            y_pred = model(x) 
            # step2:根据预测结果计算损失
            loss = loss_fn(y, y_pred) 
            # step3:把变量梯度清0
            opt.zero_grad()  
            # step4:求解梯度
            loss.backward() 
            # step5:优化模型参数
            opt.step()  
    # 输出结果
    print(model.weight, model.bias)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    step1——model预测

    这里利用nn.Linear()函数进行计算。nn.Linear()是用于设置网络中的全连接层。

    import torch
    
    in_features = torch.tensor([1, 2, 3, 4], dtype=torch.float32)
    weight_matrix = torch.tensor([
        [1, 2, 3, 4],
        [2, 3, 4, 5],
        [3, 4, 5, 6]
    ], dtype=torch.float32)
    out_features = weight_matrix.matmul(in_features)
    print(out_features)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    这就是Linear层的工作原理。使用权重矩阵(相当于上面代码的weight_matrix二维矩阵)将一个in_feature空间映射到一个out_feature空间。

    下面来看看如何创建一个Pytorch的Linear层来完成上述相同的操作。

    fc = nn.Linear(in_features = 4, out_features = 3, bias = False)
    
    • 1

    上面代码定义了一个线性层,它接受4个输入特征并把它们转化成3个输出特征。即从四维空间转换到三维空间。 PyTorch LinearLayer类使用传递给构造函数的数字4和3创建了一个3 x 4的权重矩阵。

        def __init__(self, in_features: int, out_features: int, bias: bool = True,
                     device=None, dtype=None) -> None:
            factory_kwargs = {'device': device, 'dtype': dtype}
            super(Linear, self).__init__()
            self.in_features = in_features
            self.out_features = out_features
            self.weight = Parameter(torch.empty((out_features, in_features), **factory_kwargs))
            if bias:
                self.bias = Parameter(torch.empty(out_features, **factory_kwargs))
            else:
                self.register_parameter('bias', None)
            self.reset_parameters()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    当用一个3×4矩阵乘以一个4×1矩阵时,结果是一个3×1矩阵。这就是PyTorch以这种方式构建权重矩阵的原因。

    Parameter(torch.empty((out_features, in_features), **factory_kwargs))生成out_features × in_features大小的矩阵。并将值放入parameter中。

    model = torch.nn.Linear(1, 1)
    for x,y in zip(X,Y):
        ans = model1(x)  # 相当于ans = x * model.weight + model.bias
        # 这里的 model.weight 和 model.bias 是随机生成的
    
    • 1
    • 2
    • 3
    • 4
    step2——loss计算损失

    创建损失函数nn.MSELoss()平均方差

    loss = loss_fn(y, y_pred)
    l o s s = ( y − y p r e d ) 2 loss = (y-y_{pred})^2 loss=(yypred)2
    其它损失函数:

    • L1Loss 取预测值和真实值的绝对误差的平均数,用于回归。

    l o s s = 1 N ∑ n N ∣ x n − y n ∣ loss = \frac{1}{N} \sum_n^N |x_n-y_n| loss=N1nNxnyn

    • SmoothL1Loss 也叫作 Huber Loss,误差在 (-1,1) 上是平方损失,其他情况是 L1 损失,应用于回归。
    step3——opt.zero_grad梯度清0

    optimizer.zero_grad()函数会遍历模型的所有参数,通过p.grad.detach_()方法截断反向传播的梯度流,再通过p.grad.zero_()函数将每个参数的梯度值设为0,即上一次的梯度记录被清空。

    即本来上一次梯度求导为n,当前为m,如果不设置梯度清0,则这一次的值会与之前的累加,即n+m

    step4——loss.backward()求解梯度

    torch.tensor是autograd包的基础类,如果你设置tensor的requires_grads为True,就会开始跟踪这个tensor上面的所有运算,如果你做完运算后使用tensor.backward(),所有的梯度就会自动运算,tensor的梯度将会累加到它的.grad属性里面去

    具体的说,损失函数loss是由模型的所有权重w经过一系列运算得到的,若某个w的requires_grads为True,则w的所有上层参数的.grad_fn属性中保存了对应的运算,在使用loss.backward()后,会一层层的反向传播计算每个w的梯度值,并保存到该w的.grad属性中。

    如果没有进行tensor.backward()的话,梯度值将会是None,因此loss.backward()要写在optimizer.step()之前。

    step5——opt.step()优化模型参数

    step()函数的作用是执行一次优化步骤,通过梯度下降法来更新参数(w,b)的值,因为梯度下降是基于梯度的。所以在执行opt.step()函数前应该先执行loss.backward()函数来计算梯度。

  • 相关阅读:
    仿真与烧录程序有哪几种方式?(包含常用工具与使用方式)
    详解 Springboot 中使用 Aop
    Prompts(二)
    菜单栏-JS防抖
    第三章:人工智能深度学习教程-基础神经网络(第三节-Tensorflow 中的多层感知器学习)
    7(第六章,数据存储和操作)
    Unity的IPostprocessBuildWithReport:深入解析与实用案例
    node中package解析、npm 命令行npm详解,node中的common模块化,npm、nrm两种方式查看源和切换镜像
    Nginx反向代理与负载均衡
    9.7 校招 内推 面经
  • 原文地址:https://blog.csdn.net/VinciB/article/details/126732369