• 【深度学习实验】前馈神经网络(五):自定义线性模型:前向传播、反向传播算法(封装参数)


     

    目录

    一、实验介绍

     二、实验环境

    1. 配置虚拟环境

    2. 库版本介绍

    三、实验内容

    0. 导入必要的工具包

    1. 线性模型Linear类

    a. 构造函数__init__

    b. __call__(self, x)方法

    c. 前向传播forward

    d. 反向传播backward

    2. 模型训练

    3. 代码整合


     

     

     

    一、实验介绍

    • 实现线性模型(Linear类)
      • 实现前向传播forward
      • 实现反向传播backward

     

     二、实验环境

        本系列实验使用了PyTorch深度学习框架,相关操作如下:

    1. 配置虚拟环境

    conda create -n DL python=3.7 
    conda activate DL
    pip install torch==1.8.1+cu102 torchvision==0.9.1+cu102 torchaudio==0.8.1 -f https://download.pytorch.org/whl/torch_stable.html
    
    conda install matplotlib
     conda install scikit-learn

    2. 库版本介绍

    软件包本实验版本目前最新版
    matplotlib3.5.33.8.0
    numpy1.21.61.26.0
    python3.7.16 
    scikit-learn0.22.11.3.0
    torch1.8.1+cu1022.0.1
    torchaudio0.8.12.0.2
    torchvision0.9.1+cu1020.15.2

     

    三、实验内容

    ChatGPT:

            前馈神经网络(Feedforward Neural Network)是一种常见的人工神经网络模型,也被称为多层感知器(Multilayer Perceptron,MLP)。它是一种基于前向传播的模型,主要用于解决分类和回归问题。

            前馈神经网络由多个层组成,包括输入层、隐藏层和输出层。它的名称"前馈"源于信号在网络中只能向前流动,即从输入层经过隐藏层最终到达输出层,没有反馈连接。

    以下是前馈神经网络的一般工作原理:

    1. 输入层:接收原始数据或特征向量作为网络的输入,每个输入被表示为网络的一个神经元。每个神经元将输入加权并通过激活函数进行转换,产生一个输出信号。

    2. 隐藏层:前馈神经网络可以包含一个或多个隐藏层,每个隐藏层由多个神经元组成。隐藏层的神经元接收来自上一层的输入,并将加权和经过激活函数转换后的信号传递给下一层。

    3. 输出层:最后一个隐藏层的输出被传递到输出层,输出层通常由一个或多个神经元组成。输出层的神经元根据要解决的问题类型(分类或回归)使用适当的激活函数(如Sigmoid、Softmax等)将最终结果输出。

    4. 前向传播:信号从输入层通过隐藏层传递到输出层的过程称为前向传播。在前向传播过程中,每个神经元将前一层的输出乘以相应的权重,并将结果传递给下一层。这样的计算通过网络中的每一层逐层进行,直到产生最终的输出。

    5. 损失函数和训练:前馈神经网络的训练过程通常涉及定义一个损失函数,用于衡量模型预测输出与真实标签之间的差异。常见的损失函数包括均方误差(Mean Squared Error)和交叉熵(Cross-Entropy)。通过使用反向传播算法(Backpropagation)和优化算法(如梯度下降),网络根据损失函数的梯度进行参数调整,以最小化损失函数的值。

            前馈神经网络的优点包括能够处理复杂的非线性关系,适用于各种问题类型,并且能够通过训练来自动学习特征表示。然而,它也存在一些挑战,如容易过拟合、对大规模数据和高维数据的处理较困难等。为了应对这些挑战,一些改进的网络结构和训练技术被提出,如卷积神经网络(Convolutional Neural Networks)和循环神经网络(Recurrent Neural Networks)等。

    本系列为实验内容,对理论知识不进行详细阐释

    (咳咳,其实是没时间整理,待有缘之时,回来填坑)

    977468b5ae9843c6a88005e792817cb1.png

     

    0. 导入必要的工具包

    import torch

     

    1. 线性模型Linear类

     

    a. 构造函数__init__

    1. def __init__(self, input_size, output_size):
    2. self.params = {}
    3. self.params['W'] = nn.Parameter(torch.randn(input_size, output_size, requires_grad=True))
    4. self.params['b'] = nn.Parameter(torch.randn(1, output_size, requires_grad=True))
    5. self.inputs = None
    6. self.grads = {}
    • 成员变量:

      • params:用于保存模型的参数,包括权重矩阵 W 和偏置向量 b
      • inputs:保存输入数据的变量。
      • grads:保存参数的梯度的变量。

     

    b. __call__(self, x)方法

        __call__(self, x)方法使得该类的实例可以像函数一样被调用。它调用了forward(x)方法,将输入的x传递给前向传播方法。

    1. def __call__(self, x):
    2. return self.forward(x)

     

    c. 前向传播forward

    1. def forward(self, inputs):
    2. self.inputs = inputs
    3. outputs = torch.matmul(self.inputs, self.params['W']) + self.params['b']
    4. return outputs

    在前向传播中,输入数据经过线性变换操作得到输出:

    • 在构造函数中,使用 nn.Parameter 将随机初始化的权重矩阵 W 和偏置向量 b 包装成可训练的参数。
    • 在 forward 方法中,输入数据 inputs 与权重矩阵 W 相乘,然后加上偏置向量 b,得到输出值 outputs
    • forward 方法返回计算得到的输出值。

     

    d. 反向传播backward

    1. def backward(self, grads=None):
    2. if grads == None:
    3. grads = torch.ones(self.params['W'].shape)
    4. self.grads['w'] = torch.matmul(self.inputs.T, grads)
    5. self.grads['b'] = torch.sum(grads, dim=0)
    6. return torch.matmul(grads, self.params['W'].T)

       backward(self, grads=None)方法执行线性变换的反向传播:

    • 它接受一个可选的参数grads,用于传递输出的梯度。
    • 如果没有提供grads,则默认为全1的张量,表示对输出的梯度都为1。
    • 在线性变换中,计算输入的梯度需要使用输出的梯度和当前输入值。这里使用了矩阵乘法和求和操作来计算参数的梯度和输入的梯度
    • 返回计算得到的输入梯度。

     

    2. 模型训练

    1. net = Linear(4, 2)
    2. x = torch.tensor([1,1,1,1], dtype=torch.float32)
    3. y = net(x)
    4. z = net.backward()
    5. print(z)
    • 创建了一个Linear的实例net;
    • 传入输入张量x进行前向传播;
    • 调用net.backward()进行反向传播,得到输入x的梯度
    • 将结果打印输出。
    1. tensor([[-0.8962, -0.9053, -1.5650, -0.3181],
    2. [-0.8962, -0.9053, -1.5650, -0.3181],
    3. [-0.8962, -0.9053, -1.5650, -0.3181],
    4. [-0.8962, -0.9053, -1.5650, -0.3181]], grad_fn=)

     

     

    3. 代码整合

    1. # 导入必要的工具包
    2. import torch
    3. class Linear:
    4. def __init__(self, input_size, output_size):
    5. self.params = {}
    6. self.params['W'] = nn.Parameter(torch.randn(input_size, output_size, requires_grad=True))
    7. self.params['b'] = nn.Parameter(torch.randn(1, output_size, requires_grad=True))
    8. self.inputs = None
    9. self.grads = {}
    10. def __call__(self, x):
    11. return self.forward(x)
    12. def forward(self, inputs):
    13. self.inputs = inputs
    14. outputs = torch.matmul(self.inputs, self.params['W']) + self.params['b']
    15. return outputs
    16. def backward(self, grads=None):
    17. if grads == None:
    18. grads = torch.ones(self.params['W'].shape)
    19. self.grads['w'] = torch.matmul(self.inputs.T, grads)
    20. self.grads['b'] = torch.sum(grads, dim=0)
    21. return torch.matmul(grads, self.params['W'].T)
    22. net = Linear(4, 2)
    23. x = torch.tensor([1,1,1,1], dtype=torch.float32)
    24. y = net(x)
    25. z = net.backward()
    26. print(z)

     

     

    注意:

            本实验仅实现了线性模型的前向传播和反向传播部分,缺少了模型的训练部分,欲知后事如何,请听下回分解。

     

     

  • 相关阅读:
    基于SpringBoot+Vue的超市货物管理系统
    Java集训(算法&&面试题)第八天(栈与队列)
    HSDB工具的使用说明
    github配置ssh密钥
    Wireshark抓包TLS协议栏显示版本不一致问题
    MySQL解决group by分组后未排序问题
    猿创征文 第二季| #「笔耕不辍」--生命不息,写作不止#
    Qt实现文本编辑器(一)
    【夏日成长计划 —— 圆梦游戏开发】—— day01 认识Unity + 相关软件的安装
    面试题6 -- 腐烂的苹果(多源DFS)
  • 原文地址:https://blog.csdn.net/m0_63834988/article/details/133128818