补充知识1

37 阅读4分钟

神经网络模型

首先,我们知道pytorch的任何网络net,都是torch.nn.Module的子类,都算是module,也就是模块。

  • model.apply(fn):
    pytorch中的model.apply(fn)会递归地将函数fn应用到父模块的每个子模块submodule,也包括model这个父模块自身。
  • isinstance:
    isinstance是一个函数。它用于检查一个对象是否属于指定的类或类型。
    isinstance(object, classinfo)接受两个参数:
    - object:要检查的对象。
    - classinfo:可以是类、类型或由类或类型组成的元组。
    如果object是classinfo的实例或子类的实例,则返回True;否则返回False。
  • torch.nn.Module设定模式:
    函数train和函数eval的作用是将Module及其SubModule分别设置为training modeevaluation mode
  • torch.optim.Optimizer
    torch.optim.Optimizer的实例是指通过torch.optim模块创建的优化器对象。torch.optim模块提供了各种常用的优化器类,这些类都是torch.optim.Optimizer的子类。
...
 for X, y in train_iter:
        # 计算梯度并更新参数
        y_hat = net(X)
        l = loss(y_hat, y)
        if isinstance(updater, torch.optim.Optimizer):
            # torch.optim.Optimizer是用来优化模型权重的类
            # 使用PyTorch内置的优化器和损失函数
            updater.zero_grad() # 先清零梯度
            # 求梯度
            l.backward()
            updater.step()
            metric.add(
                # 训练损失乘len(y)是因为,pytorch会自动对loss取均值
                float(l) * len(y), accuracy(y_hat, y),
                y.size().numel()
            )
        else:
            # 使用定制的优化器和损失函数
            # l是向量
            l.sum().backward()
            updater(X.shape[0])
        metric.add(float(l.sum()), accuracy(y_hat, y), y.numel())
    # 返回训练损失和训练精度
    ...
    def updater(batch_size):
    return d2l.sgd([W, b], lr, batch_size)
    ...

代码通过if isinstance(updater, torch.optim.Optimizer):检查updater是否是torch.optim.Optimizer的实例,并分别设定操作。
在PyTorch中,可以使用torch.optim.SGD类来创建SGD优化器的实例。通过实例化torch.optim.SGD类并传入相应的参数,可以创建一个SGD优化器对象。然后,可以使用该对象的step()方法来更新模型的参数,该方法会根据梯度和学习率自动执行参数更新操作。

import torch
import torch.optim as optim

# 创建模型和损失函数
model = ...
loss_fn = ...

# 创建SGD优化器
learning_rate = 0.01
optimizer = optim.SGD(model.parameters(), lr=learning_rate)

# 在每个训练步骤中执行以下操作
optimizer.zero_grad()  # 清零梯度
output = model(input)
loss = loss_fn(output, target)
loss.backward()  # 计算梯度
optimizer.step()  # 更新参数

在上述代码中,model.parameters()用于获取模型的参数。

nn.Sequential()介绍

一个序列容器,用于搭建神经网络的模块被按照被传入构造器的顺序添加到nn.Sequential()容器中。利用nn.Sequential()搭建好模型架构。nn.Sequential()可以视为将多个模块封装成一个模块,用forward()接收输入后,nn.Sequential()按照内部模块顺序自动一次计算并输出结果。
nn.Sequential()和torch.nn.ModuleList的区别在于:torch.nn.ModuleList只是一个储存网络模块的list,其中的网络模块之间没有连接关系和顺序关系。而nn.Sequential()内的网络模块之间是按照添加的顺序级联的。


nn.Linear()基本用法

nn.Linear()定义一个神经网络的线性层:

torch.nn.Linear(in_features,  # 输入的神经元个数
           out_features,  # 输出神经元个数
           bias=True  # 是否包含偏置
           )

Linear就是对输入Xn×iX_{n{\times}i}执行了一次线性变换:
假设输入i个样本,样本特征数为n。定义线性层,我们输入特征值为n,即in_feature=n我们想让下一层输出为o,所以out_feature=o

 Yi×o=Xi×nWn×0+b\ Y_{i{\times}o}=X_{i{\times}n}*W_{n{\times}0}+b

经过线性层后,我们最终得到了i×oi{\times}o维矩阵,即输入i个样本,每个样本维度为n,输出i个样本,将每个样本扩展成了o维


nn.Flatten()

torch.nn.Flatten(start_dim=1, end_dim=- 1)
作用:将连续的维度范围展平为张量。 经常在nn.Sequential()中出现,一般写在某个神经网络模型之后,用于对神经网络模型的输出进行处理,得到tensor类型的数据。


  • torch.init.normal_(tensor,mean=,std=): mean表示均值,std表示正态分布标准差
  • assert:python中当表达式为真时,程序继续往下执行,只是判断,不做任何处理; 当表达式为假时,抛出AssertionError错误,并将 [参数] 输出

如果将W1和W2初始化为全0,会导致神经网络在训练过程中出现一种现象叫做"对称权重"(Symmetric Weights)问题。这意味着每个神经元在同一层的权重会保持相同的值,因为它们会收到相同的梯度更新。
初始化为全0会导致以下问题:

  1. 梯度消失:所有权重相同导致梯度更新也相同,神经网络在反向传播过程中可能无法学习到有意义的表示。
  2. 缺乏多样性:对于隐藏层神经元,如果它们的权重都相同,那么它们在计算过程中会学习到相同的特征,无法捕捉输入数据中的多样性。
    为了避免这些问题,通常使用一种称为“权重初始化”(Weight Initialization)的方法来初始化权重。通过给网络的权重矩阵赋予随机的初始值(通常是很小的值),可以打破对称性,使得每个神经元在训练过程中能学习到不同的特征。权重初始化有很多种方法,比如使用正态分布、均匀分布或者特定的初始化策略(如Xavier初始化、He初始化等)。

参考资料: blog.csdn.net/zhaohongfei… blog.csdn.net/Just_do_mys… blog.csdn.net/gx19990824/… blog.csdn.net/weixin_2943…