2.1 神经网络基础


文档摘要

2.1 神经网络基础 第二章:PyTorch 模型构建领域 - 2.1 神经网络基础详解 2.1.1 神经网络的起源与基本概念 神经网络的灵感来源于生物神经系统,尤其是大脑的工作方式。大脑由数百万个神经元相互连接组成,这些神经元通过传递电信号来处理信息。人工神经网络试图模拟这种结构,通过构建由相互连接的“人工神经元”组成的网络来完成各种任务。 基本组成单元:神经元 (Neuron) 神经网络的基本组成单元是神经元,也称为感知器 (Perceptron)。一个人工神经元接收多个输入信号,对这些信号进行加权求和,并加上一个偏置项,最后通过一个激活函数进行非线性转换,输出最终结果。 可以用以下公式来描述一个神经元的工作过程: 其中: 是神经元的输入信号。

2.1 神经网络基础

第二章:PyTorch 模型构建领域 - 2.1 神经网络基础详解

2.1.1 神经网络的起源与基本概念

神经网络的灵感来源于生物神经系统,尤其是大脑的工作方式。大脑由数百万个神经元相互连接组成,这些神经元通过传递电信号来处理信息。人工神经网络试图模拟这种结构,通过构建由相互连接的“人工神经元”组成的网络来完成各种任务。

基本组成单元:神经元 (Neuron)

神经网络的基本组成单元是神经元,也称为感知器 (Perceptron)。一个人工神经元接收多个输入信号,对这些信号进行加权求和,并加上一个偏置项,最后通过一个激活函数进行非线性转换,输出最终结果。

可以用以下公式来描述一个神经元的工作过程:

z = (w1 * x1) + (w2 * x2) + ... + (wn * xn) + b a = activation_function(z)

其中:

  • x1, x2, ..., xn 是神经元的输入信号。

  • w1, w2, ..., wn 是每个输入信号对应的权重 (weights)。权重决定了每个输入信号对神经元输出的重要性。

  • b 是偏置 (bias)。偏置项允许神经元在没有输入信号时也能被激活,增加了模型的灵活性。

  • z 是加权输入信号的总和加上偏置项,也称为神经元的线性输出。

  • activation_function 是激活函数,它对线性输出 z 进行非线性转换,得到神经元的最终输出 a

  • a 是神经元的输出,也作为下一层神经元的输入。

图示:神经元结构

神经网络的结构:层 (Layer)

多个神经元可以组合成层 (layer)。神经网络通常由多个层组成,包括:

  • 输入层 (Input Layer): 接收原始输入数据,每个神经元对应输入数据的一个特征。

  • 隐藏层 (Hidden Layer): 位于输入层和输出层之间,执行复杂的特征提取和模式识别。神经网络可以有一个或多个隐藏层。深度神经网络拥有多个隐藏层,使其能够学习更抽象和复杂的特征。

  • 输出层 (Output Layer): 产生最终的预测结果。输出层的神经元数量和激活函数取决于具体的任务类型(例如,分类任务、回归任务)。

连接方式:前馈神经网络 (Feedforward Neural Network)

最常见的神经网络结构是前馈神经网络 (Feedforward Neural Network),也称为多层感知器 (Multilayer Perceptron, MLP)。在前馈神经网络中,信息单向流动,从输入层经过隐藏层,最终到达输出层,没有循环或反馈连接。

图示:前馈神经网络结构

2.1.2 激活函数 (Activation Functions)

激活函数在神经网络中扮演着至关重要的角色,它们为神经元引入了非线性特性。如果没有激活函数,无论神经网络有多少层,都只能进行线性变换,其表达能力将非常有限。常见的激活函数包括:

  1. Sigmoid 函数:

    • 公式:σ(x) = 1 / (1 + exp(-x))

    • 输出范围:(0, 1)

    • 特点:将输入值压缩到 0 和 1 之间,常用于二分类问题的输出层,可以解释为概率。但存在梯度消失问题,尤其在输入值远离 0 时。

  2. ReLU (Rectified Linear Unit) 函数:

    • 公式:ReLU(x) = max(0, x)

    • 输出范围:[0, ∞)

    • 特点:当输入为正时,输出等于输入;当输入为负时,输出为 0。ReLU 函数计算简单,收敛速度快,是目前最常用的激活函数之一。但ReLU函数在负数区域梯度为0,可能导致神经元“死亡”。

  3. Tanh (Hyperbolic Tangent) 函数:

    • 公式:tanh(x) = (exp(x) - exp(-x)) / (exp(x) + exp(-x))

    • 输出范围:(-1, 1)

    • 特点:将输入值压缩到 -1 和 1 之间,输出以 0 为中心。与 Sigmoid 函数相比,Tanh 函数在原点附近的梯度更大,收敛速度更快。但也存在梯度消失问题。

  4. Leaky ReLU 函数:

    • 公式:LeakyReLU(x) = max(αx, x) (其中 α 是一个很小的常数,例如 0.01)

    • 输出范围:(-∞, ∞)

    • 特点:是 ReLU 函数的改进版本,解决了 ReLU 函数在负数区域梯度为 0 的问题。当输入为负时,Leaky ReLU 输出一个很小的负斜率,避免神经元“死亡”。

  5. Softmax 函数:

    • 公式:Softmax(xi) = exp(xi) / Σj exp(xj) (对一个向量 x 的每个元素 xi 计算)

    • 输出范围:(0, 1),且所有输出之和为 1

    • 特点:常用于多分类问题的输出层,将输出值转化为概率分布。

PyTorch 代码实践:激活函数

在 PyTorch 中,我们可以使用 torch.nn.functional 模块来调用各种激活函数。

import torch import torch.nn.functional as F # Sigmoid 激活函数 sigmoid_output = F.sigmoid(torch.tensor([1.0, 2.0, -1.0])) print("Sigmoid Output:", sigmoid_output) # ReLU 激活函数 relu_output = F.relu(torch.tensor([1.0, -2.0, 0.5])) print("ReLU Output:", relu_output) # Tanh 激活函数 tanh_output = F.tanh(torch.tensor([1.0, -1.0, 0.0])) print("Tanh Output:", tanh_output) # Leaky ReLU 激活函数 leaky_relu_output = F.leaky_relu(torch.tensor([1.0, -2.0]), negative_slope=0.01) print("Leaky ReLU Output:", leaky_relu_output) # Softmax 激活函数 (通常用于输出层,需要指定维度) softmax_output = F.softmax(torch.tensor([[1.0, 2.0, 0.5], [0.1, 0.2, 0.3]]), dim=1) # dim=1 表示对每一行进行 Softmax print("Softmax Output:", softmax_output)

代码详解:

  • torch.tensor([...]) 创建 PyTorch 张量 (Tensor),用于表示输入数据。

  • F.sigmoid(), F.relu(), F.tanh(), F.leaky_relu(), F.softmax() 调用 torch.nn.functional 模块中的激活函数。

  • negative_slope=0.01F.leaky_relu() 函数的参数,用于设置负数区域的斜率。

  • dim=1F.softmax() 函数的参数,指定对哪个维度进行 Softmax 计算。在多分类问题中,通常对最后一维(类别维度)进行 Softmax。

2.1.3 前向传播 (Forward Propagation)

前向传播是指将输入数据通过神经网络逐层传递,直到得到输出结果的过程。在前向传播过程中,每一层的神经元接收上一层的输出作为输入,经过加权求和、加上偏置项,并应用激活函数,得到本层的输出,然后传递给下一层。

步骤详解:

  1. 输入层接收输入数据: 输入数据被送入输入层。

  2. 逐层计算: 从输入层开始,逐层向前计算每一层的输出。对于每一层:

    • 线性变换: 将上一层的输出与本层的权重矩阵进行矩阵乘法,并加上偏置向量。

    • 激活函数: 将线性变换的结果输入激活函数,得到本层的输出。

  3. 输出层输出结果: 最终,数据到达输出层,输出层神经元的输出即为神经网络的预测结果。

数学公式表示 (以两层神经网络为例):

  • 输入层到隐藏层:

    z1 = W1 * x + b1

    a1 = activation_function1(z1)

    其中,x 是输入向量,W1 是输入层到隐藏层的权重矩阵,b1 是隐藏层的偏置向量,activation_function1 是隐藏层的激活函数,a1 是隐藏层的输出。

  • 隐藏层到输出层:

    z2 = W2 * a1 + b2

    a2 = activation_function2(z2)

    其中,a1 是隐藏层的输出(作为输出层的输入),W2 是隐藏层到输出层的权重矩阵,b2 是输出层的偏置向量,activation_function2 是输出层的激活函数,a2 是输出层的最终输出。

PyTorch 代码实践:前向传播

import torch import torch.nn as nn import torch.nn.functional as F class SimpleNet(nn.Module): def __init__(self, input_size, hidden_size, output_size): super(SimpleNet, self).__init__() # 定义线性层 (全连接层) self.fc1 = nn.Linear(input_size, hidden_size) # 输入层到隐藏层 self.fc2 = nn.Linear(hidden_size, output_size) # 隐藏层到输出层 def forward(self, x): # 前向传播过程 x = self.fc1(x) # 线性变换 x = F.relu(x) # ReLU 激活函数 x = self.fc2(x) # 线性变换 (输出层) return x # 定义网络参数 input_size = 10 # 输入特征维度 hidden_size = 5 # 隐藏层神经元数量 output_size = 2 # 输出维度 (例如,二分类) # 创建网络实例 net = SimpleNet(input_size, hidden_size, output_size) # 创建随机输入数据 input_data = torch.randn(1, input_size) # batch_size=1, input_size 维度的输入 # 进行前向传播 output = net(input_data) print("Input Data:", input_data) print("Output:", output)

代码详解:

  • class SimpleNet(nn.Module): 定义一个简单的神经网络类,继承自 nn.Module。在 PyTorch 中,所有的神经网络模型都应该继承 nn.Module

  • __init__(self, ...) 构造函数,用于定义网络的结构。

    • self.fc1 = nn.Linear(input_size, hidden_size) 创建第一个线性层 fc1,输入维度为 input_size,输出维度为 hidden_sizenn.Linear 代表全连接层。

    • self.fc2 = nn.Linear(hidden_size, output_size) 创建第二个线性层 fc2,输入维度为 hidden_size,输出维度为 output_size

  • forward(self, x): 定义前向传播过程的函数。

    • x = self.fc1(x) 将输入 x 通过第一个线性层 fc1 进行线性变换。

    • x = F.relu(x) 将线性变换后的结果应用 ReLU 激活函数。

    • x = self.fc2(x) 将激活函数后的结果通过第二个线性层 fc2 进行线性变换。

    • return x 返回最终的输出结果。

  • net = SimpleNet(...) 创建 SimpleNet 类的实例,即创建了一个神经网络模型。

  • input_data = torch.randn(1, input_size) 创建随机的输入数据,torch.randn 生成服从标准正态分布的随机数。

  • output = net(input_data) 将输入数据 input_data 输入到网络 net 中,进行前向传播,得到输出结果 output

2.1.4 反向传播 (Backpropagation) 与梯度下降 (Gradient Descent)

神经网络的学习过程主要通过反向传播和梯度下降算法来完成。

1. 损失函数 (Loss Function):

首先,我们需要定义一个损失函数 (Loss Function) 或目标函数 (Objective Function),用来衡量模型预测结果与真实标签之间的差距。常见的损失函数包括:

  • 均方误差损失 (Mean Squared Error Loss, MSE): 用于回归问题,计算预测值与真实值之间差的平方的平均值。

  • 交叉熵损失 (Cross-Entropy Loss): 用于分类问题,衡量预测概率分布与真实标签分布之间的差距。

2. 反向传播 (Backpropagation):

反向传播是一种计算神经网络参数梯度的方法。梯度指示了损失函数在参数空间中下降最快的方向。反向传播利用链式法则,从输出层开始,逐层向后计算每一层参数的梯度。

步骤详解:

  1. 前向传播: 输入数据通过网络进行前向传播,得到预测输出。

  2. 计算损失: 根据预测输出和真实标签,计算损失函数的值。

  3. 反向传播梯度: 从输出层开始,向后计算每一层参数的梯度。梯度计算过程依赖于链式法则,将损失函数对输出层的梯度反向传播到每一层,并计算每一层参数的梯度。

  4. 参数更新: 使用梯度下降算法,根据计算得到的梯度,更新网络参数(权重和偏置)。参数更新的目标是沿着梯度的负方向调整参数,从而减小损失函数的值。

3. 梯度下降 (Gradient Descent):

梯度下降是一种优化算法,用于寻找损失函数的最小值。在神经网络训练中,梯度下降算法利用反向传播计算得到的梯度,迭代更新网络参数,使损失函数逐渐减小,从而提高模型的预测精度。

参数更新公式:

parameter = parameter - learning_rate * gradient

其中:

  • parameter 是需要更新的参数(权重或偏置)。

  • learning_rate 是学习率,控制参数更新的步长。学习率太小,收敛速度慢;学习率太大,可能导致震荡或无法收敛。

  • gradient 是损失函数对参数的梯度。

优化器 (Optimizer):

在 PyTorch 中,我们使用优化器 (Optimizer) 来实现参数更新。PyTorch 提供了多种优化器,例如:

  • SGD (Stochastic Gradient Descent): 随机梯度下降,是最基本的优化器。

  • Adam (Adaptive Moment Estimation): 自适应矩估计,是一种常用的优化器,通常比 SGD 收敛更快。

  • RMSprop (Root Mean Square Propagation): 均方根反向传播,也是一种自适应学习率的优化器。

PyTorch 代码实践:反向传播与梯度下降

import torch import torch.nn as nn import torch.optim as optim # ... (SimpleNet 网络定义与之前代码相同) ... # 创建网络实例 net = SimpleNet(input_size, hidden_size, output_size) # 定义损失函数 (例如,交叉熵损失,用于分类问题) criterion = nn.CrossEntropyLoss() # 定义优化器 (例如,Adam 优化器) optimizer = optim.Adam(net.parameters(), lr=0.01) # lr: learning rate # 假设我们有真实标签 (target) target = torch.tensor([1]) # 假设真实类别是 1 (索引) # 训练循环 num_epochs = 100 # 训练轮数 for epoch in range(num_epochs): # 1. 前向传播 output = net(input_data) # 2. 计算损失 loss = criterion(output, target) # 3. 清空之前的梯度 (重要!) optimizer.zero_grad() # 4. 反向传播 (计算梯度) loss.backward() # 5. 参数更新 (梯度下降) optimizer.step() if (epoch+1) % 10 == 0: # 每 10 轮打印一次损失值 print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}') print("Training finished.") print("Final Output:", net(input_data))

代码详解:

  • criterion = nn.CrossEntropyLoss() 创建交叉熵损失函数实例。

  • optimizer = optim.Adam(net.parameters(), lr=0.01) 创建 Adam 优化器实例。net.parameters() 返回网络中所有可学习的参数(权重和偏置)。lr=0.01 设置学习率为 0.01。

  • target = torch.tensor([1]) 创建真实标签,假设类别索引为 1。

  • 训练循环:

    • output = net(input_data) 前向传播,得到预测输出。

    • loss = criterion(output, target) 计算损失函数值。

    • optimizer.zero_grad() 重要步骤! 在每次反向传播之前,需要将优化器中存储的梯度清零,否则梯度会累积。

    • loss.backward() 执行反向传播,计算损失函数对网络参数的梯度。

    • optimizer.step() 使用优化器更新网络参数,执行梯度下降步骤。

    • print(...) 每 10 轮打印一次当前的 epoch 数和损失值。

2.1.5 总结与展望

本篇文章详细介绍了神经网络的基础概念,包括神经元、激活函数、前向传播、反向传播和梯度下降等核心组成部分,并结合 PyTorch 代码进行了实践演示。理解这些基础知识是深入学习和应用深度学习技术的关键。

核心要点回顾:

  • 神经元: 神经网络的基本单元,模拟生物神经元的信息处理过程。

  • 激活函数: 为神经网络引入非线性特性,增强模型的表达能力。

  • 前向传播: 数据在神经网络中逐层传递,得到预测输出的过程。

  • 反向传播: 计算损失函数对网络参数梯度的算法。

  • 梯度下降: 利用梯度迭代更新参数,优化模型性能的算法。

  • PyTorch 实践: 使用 PyTorch 提供的 nn.Module, nn.Linear, torch.nn.functional, torch.optim 等模块,可以方便地构建和训练神经网络。

掌握神经网络的基础知识后,我们可以进一步学习更复杂的神经网络结构,例如卷积神经网络 (CNN)、循环神经网络 (RNN) 等,并将其应用于图像识别、自然语言处理等更广泛的领域。PyTorch 作为一个灵活且强大的深度学习框架,为我们提供了丰富的工具和接口,帮助我们探索和创新深度学习技术。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U