【深度学习实验】前馈神经网络(三):自定义两层前馈神经网络(激活函数logistic、线性层算子Linear)

2024-07-30 08:25:06 浏览数 (1)

一、实验介绍

  • 本实验实现了一个简单的两层前馈神经网络
    • 激活函数logistic
    • 线性层算子Linear

二、实验环境

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

1. 配置虚拟环境

代码语言:javascript复制
conda create -n DL python=3.7 
代码语言:javascript复制
conda activate DL
代码语言:javascript复制
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
代码语言:javascript复制
conda install matplotlib
代码语言:javascript复制
 conda install scikit-learn

2. 库版本介绍

软件包

本实验版本

目前最新版

matplotlib

3.5.3

3.8.0

numpy

1.21.6

1.26.0

python

3.7.16

scikit-learn

0.22.1

1.3.0

torch

1.8.1 cu102

2.0.1

torchaudio

0.8.1

2.0.2

torchvision

0.9.1 cu102

0.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)等。

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

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

0. 导入必要的工具包

代码语言:javascript复制
import torch
from torch import nn

1. 构建数据集

代码语言:javascript复制
input = torch.ones((1, 10))

创建了一个输入张量`input`,大小为(1, 10)。

2. 激活函数logistic

代码语言:javascript复制
def logistic(z):
    return 1.0 / (1.0   torch.exp(-z))

logistic函数的特点是将输入值映射到一个介于0和1之间的输出值,可以看作是一种概率估计。当输入值趋近于正无穷大时,输出值趋近于1;当输入值趋近于负无穷大时,输出值趋近于0。因此,logistic函数常用于二分类问题,将输出值解释为概率值,可以用于预测样本属于某一类的概率。在神经网络中,logistic函数的引入可以引入非线性特性,使得网络能够学习更加复杂的模式和表示。

3. 线性层算子 Linear

代码语言:javascript复制
class Linear(nn.Module):
    def __init__(self, input_size, output_size):
        super(Linear, self).__init__()
        self.params = {}
        self.params['W'] = nn.Parameter(torch.randn(input_size, output_size, requires_grad=True))
        self.params['b'] = nn.Parameter(torch.randn(1, output_size, requires_grad=True))
        self.grads = {}
        self.inputs = None

    def forward(self, inputs):
        self.inputs = inputs
        outputs = torch.matmul(inputs, self.params['W'])   self.params['b']
        return outputs
  • Linear类是一个自定义的线性层,继承自nn.Module
    • 它具有两个参数:input_sizeoutput_size,分别表示输入和输出的大小。
  • 在初始化时,创建了两个参数:Wb,分别代表权重和偏置,都是可训练的张量,并通过nn.Parameter进行封装。
    • paramsgrads是字典类型的属性,用于存储参数和梯度;
    • inputs是一个临时变量,用于存储输入。
  • forward方法实现了前向传播的逻辑,利用输入和参数计算输出。

4. 两层的前馈神经网络MLP

代码语言:javascript复制
class MLP(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(MLP, self).__init__()
        self.fc1 = Linear(input_size, hidden_size)
        self.fc2 = Linear(hidden_size, output_size)

    def forward(self, x):
        z1 = self.fc1(x)
        a1 = logistic(z1)
        z2 = self.fc2(a1)
        a2 = logistic(z2)
        return a2
  • 初始化时创建了两个线性层Linear对象:fc1fc2
  • forward方法实现了整个神经网络的前向传播过程:
    • 输入x首先经过第一层线性层fc1
    • 然后通过logistic函数进行激活,
    • 再经过第二层线性层fc2
    • 最后再经过一次logistic函数激活,
    • 并返回最终的输出。

5. 模型训练

代码语言:javascript复制
input_size, hidden_size, output_size = 10, 5, 2
net = MLP(input_size, hidden_size, output_size)
output = net(input)
print(output)
  • 定义了三个变量input_sizehidden_sizeoutput_size,分别表示输入大小、隐藏层大小和输出大小。
  • 创建了一个MLP对象net,并将输入input传入模型进行前向计算,得到输出output。最后将输出打印出来。

6. 代码整合

代码语言:javascript复制
# 导入必要的工具包
import torch
from torch import nn


# 线性层算子,请一定注意继承自 nn. Module, 这会帮你解决许多细节上的问题
class Linear(nn.Module):
    def __init__(self, input_size, output_size):
        super(Linear, self).__init__()
        self.params = {}
        self.params['W'] = nn.Parameter(torch.randn(input_size, output_size, requires_grad=True))
        self.params['b'] = nn.Parameter(torch.randn(1, output_size, requires_grad=True))
        self.grads = {}
        self.inputs = None

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


# 实现一个两层的前馈神经网络
class MLP(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(MLP, self).__init__()
        self.fc1 = Linear(input_size, hidden_size)
        self.fc2 = Linear(hidden_size, output_size)

    def forward(self, x):
        z1 = self.fc1(x)
        a1 = logistic(z1)
        z2 = self.fc2(a1)
        a2 = logistic(z2)
        return a2


# Logistic 函数
def logistic(z):
    return 1.0 / (1.0   torch.exp(-z))

input = torch.ones((1, 10))
input_size, hidden_size, output_size = 10, 5, 2
net = MLP(input_size, hidden_size, output_size)
output = net(input)
print(output)

0 人点赞