您的位置:首页 > 房产 > 建筑 > 移动端网站怎么制作_中国室内设计师网首页_视频号视频下载助手app_中国足球世界排名

移动端网站怎么制作_中国室内设计师网首页_视频号视频下载助手app_中国足球世界排名

2025/1/22 12:43:00 来源:https://blog.csdn.net/Kiradzy/article/details/145068099  浏览:    关键词:移动端网站怎么制作_中国室内设计师网首页_视频号视频下载助手app_中国足球世界排名
移动端网站怎么制作_中国室内设计师网首页_视频号视频下载助手app_中国足球世界排名

系列文章目录

Pytorch基础篇

01-PyTorch新手必看:张量是什么?5 分钟教你快速创建张量!
02-张量运算真简单!PyTorch 数值计算操作完全指南
03-Numpy 还是 PyTorch?张量与 Numpy 的神奇转换技巧
04-揭秘数据处理神器:PyTorch 张量拼接与拆分实用技巧
05-深度学习从索引开始:PyTorch 张量索引与切片最全解析
06-张量形状任意改!PyTorch reshape、transpose 操作超详细教程
07-深入解读 PyTorch 张量运算:6 大核心函数全面解析,代码示例一步到位!
08-自动微分到底有多强?PyTorch 自动求导机制深度解析

Pytorch实战篇

09-从零手写线性回归模型:PyTorch 实现深度学习入门教程
10-PyTorch 框架实现线性回归:从数据预处理到模型训练全流程
11-PyTorch 框架实现逻辑回归:从数据预处理到模型训练全流程
12-PyTorch 框架实现多层感知机(MLP):手写数字分类全流程详解


文章目录

  • 系列文章目录
  • 前言
  • 一、简单全连接神经网络的搭建
    • 1.1 什么是全连接神经网络?
    • 1.2 使用 PyTorch 搭建简单网络
      • 1.2.1 示例代码:构建两层全连接网络
      • 1.2.2 输出结果
      • 1.2.3 代码解析
  • 二、激活函数的引入
    • 2.1 为什么需要激活函数?
    • 2.2 在网络中引入激活函数
      • 2.2.1 示例代码:为网络添加 ReLU 激活函数
      • 2.2.2 输出结果
      • 2.2.3 代码解析
    • 2.3 不同激活函数的对比
    • 2.4 激活函数的注意事项
  • 三、多层感知机(MLP)的结构与实现
    • 3.1 什么是多层感知机?
      • 3.1.1 MLP 的基本特点
    • 3.2 使用 PyTorch 实现多层感知机
      • 3.2.1 示例代码:构建多层感知机
      • 3.2.2 输出结果
      • 3.2.3 代码解析
    • 3.3 数据输入形状
    • 3.4 模型训练的必要组件
      • 3.4.1 示例代码:定义损失函数和优化器
    • 3.5 注意事项
    • 3.6 多层感知机的优化方向
  • 四、实际案例:手写数字分类
    • 4.1 数据加载与预处理
      • 4.1.1 下载 MNIST 数据集
      • 4.1.2 数据处理说明
    • 4.2 定义模型结构
      • 4.2.1 模型代码
      • 4.2.2 模型结构解释
    • 4.3 定义训练过程
      • 4.3.1 训练函数
      • 4.3.2 代码说明
    • 4.4 模型测试与评估
      • 4.4.1 测试函数
      • 4.4.2 测试流程
    • 4.5 完整运行流程
    • 4.6 运行结果
    • 4.7 进一步优化
  • 五、总结


前言

在人工智能和深度学习领域,PyTorch 以其灵活性和简洁性,迅速成为研究人员和开发者们的首选工具。然而,对于许多初学者而言,深度学习的入门看似门槛颇高:神经网络的结构、数学公式的理解、代码实现的细节……每一环都可能让人望而却步。

本文以经典的 MNIST 手写数字分类问题 为例,通过 从零开始的方式,带领你逐步实现一个多层感知机(MLP),从最基础的全连接网络开始,逐渐引入激活函数和多层结构,最终完成一个完整的训练与测试流程。本文不仅提供详细的代码示例,更注重背后的原理解析与实践指导,力求让你在最短的时间内掌握 PyTorch 的核心用法。

无论你是深度学习的初学者,还是希望深入了解 PyTorch 实战的开发者,这篇文章都将是你学习的绝佳起点。

一、简单全连接神经网络的搭建

1.1 什么是全连接神经网络?

全连接神经网络(Fully Connected Neural Network, FCNN)是深度学习中最基础的网络结构之一。它的特点是:网络中的每一层神经元与下一层的每个神经元都存在连接。全连接网络的核心是矩阵运算,可以表示为以下公式:

y = W x + b \ y = Wx + b  y=Wx+b

其中:

  • ( W ) 是权重矩阵;
  • ( b ) 是偏置;
  • ( x ) 是输入;
  • ( y ) 是输出。

简单的全连接网络通常由输入层、一个或多个隐藏层和输出层组成,每一层通过线性变换对输入数据进行处理。以下是全连接网络的基本结构示意图:

输入层 -> 隐藏层 -> 输出层

1.2 使用 PyTorch 搭建简单网络

在 PyTorch 中,神经网络的构建通常通过继承 torch.nn.Module 来完成。我们可以定义网络的结构并实现前向传播。

1.2.1 示例代码:构建两层全连接网络

以下是一个使用 PyTorch 构建两层全连接网络的简单示例:

import torch
import torch.nn as nn# 定义简单的全连接神经网络
class SimpleNN(nn.Module):def __init__(self, input_size, hidden_size, output_size):super(SimpleNN, 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 = self.fc2(x)  # 输入通过第二层return x# 定义模型参数
input_size = 10  # 输入特征数
hidden_size = 5  # 隐藏层神经元个数
output_size = 2  # 输出类别数# 初始化模型
model = SimpleNN(input_size, hidden_size, output_size)# 打印模型结构
print(model)

1.2.2 输出结果

运行以上代码后,你将看到模型的结构:

SimpleNN((fc1): Linear(in_features=10, out_features=5, bias=True)(fc2): Linear(in_features=5, out_features=2, bias=True)
)

1.2.3 代码解析

  1. nn.Linear:PyTorch 提供的全连接层类,用于实现输入到输出的线性变换。
  2. forward 方法:定义了数据的前向传播路径,规定输入数据如何流经网络层。

二、激活函数的引入

2.1 为什么需要激活函数?

全连接网络中的线性层只能实现输入和输出之间的线性变换。为了让网络具备非线性建模能力,我们需要引入激活函数。

激活函数的主要作用是:

  • 引入非线性,使网络能够学习复杂的模式;
  • 控制神经元的输出范围,避免梯度爆炸或梯度消失。

常见的激活函数包括:

  • ReLU (Rectified Linear Unit)
    • 定义: f ( x ) = max ⁡ ( 0 , x ) \ f(x) = \max(0, x)  f(x)=max(0,x)
    • 特点:简单高效,对正值保持线性,对负值置零。
  • Sigmoid
    • 定义: f ( x ) = 1 1 + e − x \ f(x) = \frac{1}{1 + e^{-x}}  f(x)=1+ex1
    • 特点:输出范围为 (0, 1),常用于二分类任务。
  • Tanh (双曲正切函数)
    • 定义: f ( x ) = e x − e − x e x + e − x \ f(x) = \frac{e^x - e^{-x}}{e^x + e^{-x}}  f(x)=ex+exexex
    • 特点:输出范围为 (-1, 1),常用于归一化数据的建模。

2.2 在网络中引入激活函数

在 PyTorch 中,激活函数可以通过 torch.nn 模块中的函数类实现,也可以直接使用 torch 提供的操作符。

2.2.1 示例代码:为网络添加 ReLU 激活函数

以下是为之前的两层全连接网络添加 ReLU 激活函数的代码:

class SimpleNNWithActivation(nn.Module):def __init__(self, input_size, hidden_size, output_size):super(SimpleNNWithActivation, self).__init__()# 定义两层全连接层self.fc1 = nn.Linear(input_size, hidden_size)self.relu = nn.ReLU()  # 添加 ReLU 激活函数self.fc2 = nn.Linear(hidden_size, output_size)def forward(self, x):x = self.fc1(x)  # 输入通过第一层x = self.relu(x)  # 应用 ReLU 激活函数x = self.fc2(x)  # 输入通过第二层return x# 初始化网络
model_with_activation = SimpleNNWithActivation(input_size, hidden_size, output_size)# 打印模型结构
print(model_with_activation)

2.2.2 输出结果

运行后打印的模型结构如下:

SimpleNNWithActivation((fc1): Linear(in_features=10, out_features=5, bias=True)(relu): ReLU()(fc2): Linear(in_features=5, out_features=2, bias=True)
)

2.2.3 代码解析

  1. __init__ 方法中,定义了 ReLU 激活函数对象(self.relu = nn.ReLU())。
  2. forward 方法中,激活函数被插入到第一层和第二层之间,用于对第一层的输出进行非线性变换。

2.3 不同激活函数的对比

以下是三种常见激活函数的对比表:

激活函数数学公式输出范围优势缺点
ReLU f ( x ) = max ⁡ ( 0 , x ) \ f(x) = \max(0, x)  f(x)=max(0,x)[0, ∞)计算简单,收敛速度快对负值不敏感,可能导致神经元失活
Sigmoid f ( x ) = 1 1 + e − x \ f(x) = \frac{1}{1 + e^{-x}}  f(x)=1+ex1(0, 1)输出平滑,适合概率预测梯度消失,计算开销较大
Tanh f ( x ) = e x − e − x e x + e − x \ f(x) = \frac{e^x - e^{-x}}{e^x + e^{-x}}  f(x)=ex+exexex(-1, 1)输出对称,适合归一化数据梯度消失,计算开销较大

通过这些对比,ReLU 是目前最常用的激活函数,尤其是在深层神经网络中。


2.4 激活函数的注意事项

  1. 避免梯度消失问题:在使用 Sigmoid 和 Tanh 时,当输入过大或过小时,梯度可能趋近于 0。
  2. ReLU 的“神经元失活”问题:如果输入总是负值,某些神经元可能永远无法被激活。
  3. 选择激活函数的依据
    • ReLU 常用于隐藏层;
    • Sigmoid 常用于输出层的二分类任务;
    • Tanh 在数据归一化的场景下表现更好。

三、多层感知机(MLP)的结构与实现

3.1 什么是多层感知机?

多层感知机(Multilayer Perceptron, MLP)是深度学习中一种重要的神经网络结构。它由多层全连接层组成,并通过激活函数引入非线性,能够学习并拟合复杂的非线性关系。

3.1.1 MLP 的基本特点

  1. 多层结构:包括输入层、一个或多个隐藏层和输出层。
  2. 激活函数:隐藏层通常使用非线性激活函数(如 ReLU)。
  3. 全连接层:每个神经元与下一层的所有神经元相连。
  4. 前向传播和反向传播:前向传播计算输出,反向传播通过梯度下降优化权重。

MLP 的基本结构如下:

输入层 -> 隐藏层1 -> 激活函数 -> 隐藏层2 -> 激活函数 -> 输出层

相较于简单的单层全连接网络,MLP 通过多个隐藏层和非线性激活函数,能够表示更复杂的函数关系,是神经网络的基础模型。


3.2 使用 PyTorch 实现多层感知机

以下是实现一个具有两层隐藏层的 MLP 的代码示例。

3.2.1 示例代码:构建多层感知机

import torch
import torch.nn as nn# 定义多层感知机
class MLP(nn.Module):def __init__(self, input_size, hidden_sizes, output_size):super(MLP, self).__init__()# 定义第一层全连接层self.fc1 = nn.Linear(input_size, hidden_sizes[0])  # 定义第二层全连接层self.fc2 = nn.Linear(hidden_sizes[0], hidden_sizes[1])  # 定义输出层self.fc3 = nn.Linear(hidden_sizes[1], output_size)  # 定义 ReLU 激活函数self.relu = nn.ReLU()def forward(self, x):# 数据通过第一层x = self.fc1(x)x = self.relu(x)  # 应用 ReLU 激活# 数据通过第二层x = self.fc2(x)x = self.relu(x)  # 再次应用 ReLU 激活# 数据通过输出层x = self.fc3(x)return x# 定义模型参数
input_size = 784  # 输入层节点数(如28x28图像展开为784维向量)
hidden_sizes = [128, 64]  # 两个隐藏层,节点数分别为128和64
output_size = 10  # 输出层节点数(如10个分类)# 初始化模型
mlp_model = MLP(input_size, hidden_sizes, output_size)# 打印模型结构
print(mlp_model)

3.2.2 输出结果

运行以上代码后,会打印出模型结构:

MLP((fc1): Linear(in_features=784, out_features=128, bias=True)(fc2): Linear(in_features=128, out_features=64, bias=True)(fc3): Linear(in_features=64, out_features=10, bias=True)(relu): ReLU()
)

3.2.3 代码解析

  1. 层的定义
    • 第一层全连接层:self.fc1,输入维度为 784,输出维度为 128;
    • 第二层全连接层:self.fc2,输入维度为 128,输出维度为 64;
    • 输出层:self.fc3,输入维度为 64,输出维度为 10。
  2. 激活函数
    • 在每一层全连接层后使用 ReLU 激活函数,增加非线性建模能力。
  3. 前向传播
    • forward 方法定义了输入数据流经网络的路径。

3.3 数据输入形状

多层感知机通常需要将输入数据展平为一维向量(即 flatten 操作),以符合全连接层的输入要求。例如,对于 MNIST 数据集,输入是 28x28 的灰度图像,需要将其展平成大小为 ( 28 \times 28 = 784 ) 的向量。

# 示例:将 28x28 图像展平成一维向量
images = torch.randn(64, 1, 28, 28)  # 假设 64 个批量的 MNIST 数据
flattened_images = images.view(images.size(0), -1)  # 展平成 (64, 784)
print(flattened_images.shape)  # 输出形状:(64, 784)

3.4 模型训练的必要组件

为了训练多层感知机,需要以下组件:

  1. 损失函数:计算预测结果与真实值之间的误差。
  2. 优化器:调整模型参数以最小化损失函数。
  3. 数据加载器:批量加载数据,支持随机抽样和迭代。

3.4.1 示例代码:定义损失函数和优化器

import torch.optim as optim# 定义交叉熵损失函数(适合分类任务)
criterion = nn.CrossEntropyLoss()# 定义随机梯度下降优化器
optimizer = optim.SGD(mlp_model.parameters(), lr=0.01)print("Loss function and optimizer defined!")

3.5 注意事项

  1. 隐藏层的数量和节点数
    • 隐藏层越多,网络的表达能力越强,但计算复杂度也会增加;
    • 节点数的选择需要平衡模型性能和计算开销,可根据经验或通过交叉验证调整。
  2. 过拟合问题
    • 多层感知机可能容易过拟合,特别是在隐藏层过多或节点数过大时;
    • 可以引入正则化技术(如 Dropout)来缓解过拟合。
  3. 初始化权重
    • 默认的权重初始化方式通常表现良好,但在某些复杂任务中,可以考虑使用自定义初始化方法。

3.6 多层感知机的优化方向

为了进一步优化多层感知机的性能,可以尝试以下方法:

  1. 更复杂的激活函数
    • 除了 ReLU,还可以尝试 Leaky ReLU、ELU 或 GELU 等更高级的激活函数。
  2. 正则化技术
    • 添加 Dropout 层随机丢弃部分神经元,防止过拟合;
    • 在损失函数中加入 L2 正则化项(权重惩罚)。
  3. 使用 GPU
    • 通过将模型和数据加载到 GPU 上,显著加速训练过程:
      device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
      mlp_model.to(device)
      

四、实际案例:手写数字分类

在本节中,将结合经典的 MNIST 数据集,使用多层感知机(MLP)完成手写数字分类任务。MNIST 数据集包含 28x28 的灰度图像,共 10 个类别(数字 0 到 9)。


4.1 数据加载与预处理

4.1.1 下载 MNIST 数据集

使用 torchvision 提供的工具,可以轻松下载并加载 MNIST 数据集。

from torchvision import datasets, transforms
from torch.utils.data import DataLoader# 数据预处理
transform = transforms.Compose([transforms.ToTensor(),  # 转换为 Tensortransforms.Normalize((0.5,), (0.5,))  # 归一化到 [-1, 1]
])# 加载 MNIST 数据集
train_dataset = datasets.MNIST(root='./data', train=True, transform=transform, download=True
)
test_dataset = datasets.MNIST(root='./data', train=False, transform=transform, download=True
)# 定义数据加载器
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)print("MNIST 数据集加载完成!")

4.1.2 数据处理说明

  1. ToTensor():将 PIL 图像转换为 PyTorch 张量,并将像素值从 [0, 255] 缩放到 [0, 1]。
  2. Normalize((0.5,), (0.5,)):将数据标准化到 [-1, 1] 区间,加速训练收敛。
  3. 数据加载器DataLoader 支持批量加载数据,并通过 shuffle 打乱训练集,增加模型的泛化能力。

4.2 定义模型结构

我们使用一个多层感知机模型,包含两层隐藏层和 ReLU 激活函数。每层的节点数根据 MNIST 数据特性选择。

4.2.1 模型代码

import torch.nn as nnclass MLP(nn.Module):def __init__(self, input_size, hidden_sizes, output_size):super(MLP, self).__init__()self.fc1 = nn.Linear(input_size, hidden_sizes[0])  # 第一层全连接self.fc2 = nn.Linear(hidden_sizes[0], hidden_sizes[1])  # 第二层全连接self.fc3 = nn.Linear(hidden_sizes[1], output_size)  # 输出层self.relu = nn.ReLU()  # 激活函数def forward(self, x):x = self.fc1(x)x = self.relu(x)x = self.fc2(x)x = self.relu(x)x = self.fc3(x)return x# 定义模型参数
input_size = 28 * 28  # MNIST 图像展平成一维向量,28x28 = 784
hidden_sizes = [128, 64]  # 两个隐藏层,节点数分别为 128 和 64
output_size = 10  # 输出层(10 个分类)# 初始化模型
model = MLP(input_size, hidden_sizes, output_size)print(model)

4.2.2 模型结构解释

  • 输入层为 784(28x28 展开后),输出层为 10(对应 10 个数字类别)。
  • 两个隐藏层分别包含 128 和 64 个神经元,通过 ReLU 激活函数引入非线性。
  • 模型的参数(权重和偏置)会在训练中自动更新。

4.3 定义训练过程

模型训练包括前向传播、损失计算、反向传播和优化步骤。

4.3.1 训练函数

import torch
import torch.optim as optim# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()  # 适合分类任务的交叉熵损失
optimizer = optim.SGD(model.parameters(), lr=0.01)  # 随机梯度下降优化器# 训练函数
def train(model, train_loader, criterion, optimizer, epochs=5):for epoch in range(epochs):model.train()  # 切换到训练模式running_loss = 0.0for images, labels in train_loader:# 展平图像为向量images = images.view(images.size(0), -1)# 清零梯度optimizer.zero_grad()# 前向传播outputs = model(images)loss = criterion(outputs, labels)# 反向传播和优化loss.backward()optimizer.step()running_loss += loss.item()print(f"Epoch [{epoch+1}/{epochs}], Loss: {running_loss/len(train_loader):.4f}")

4.3.2 代码说明

  1. 损失函数CrossEntropyLoss 计算预测值与真实标签之间的误差。
  2. 优化器SGD(随机梯度下降)更新模型参数。
  3. 训练流程
    • 数据通过模型的前向传播计算输出;
    • 通过损失函数计算误差;
    • 反向传播计算梯度;
    • 使用优化器更新权重。

4.4 模型测试与评估

训练完成后,我们需要在测试集上评估模型的性能,计算分类准确率。

4.4.1 测试函数

def test(model, test_loader):model.eval()  # 切换到评估模式correct = 0total = 0with torch.no_grad():  # 测试时不需要计算梯度for images, labels in test_loader:# 展平图像为向量images = images.view(images.size(0), -1)# 前向传播outputs = model(images)_, predicted = torch.max(outputs, 1)  # 获取最大值对应的类别total += labels.size(0)correct += (predicted == labels).sum().item()accuracy = 100 * correct / totalprint(f"Test Accuracy: {accuracy:.2f}%")

4.4.2 测试流程

  1. 模式切换model.eval() 将模型设置为评估模式,关闭 Dropout 和 BatchNorm 的动态行为。
  2. 无梯度计算:通过 torch.no_grad() 节省内存和计算开销。
  3. 准确率计算:通过比较预测类别与真实标签,计算准确率。

4.5 完整运行流程

将训练和测试结合在一起,完成整个流程。

# 训练模型
train(model, train_loader, criterion, optimizer, epochs=5)# 测试模型
test(model, test_loader)

4.6 运行结果

经过 5 轮训练,模型在 MNIST 测试集上的分类准确率通常可以达到 90% 以上

Epoch [1/5], Loss: 0.5204
Epoch [2/5], Loss: 0.3198
Epoch [3/5], Loss: 0.2712
Epoch [4/5], Loss: 0.2397
Epoch [5/5], Loss: 0.2163
Test Accuracy: 92.58%

4.7 进一步优化

如果想进一步提升模型性能,可以尝试以下方法:

  1. 增加隐藏层:引入更多隐藏层或增加隐藏层的节点数。
  2. 使用更复杂的优化器:如 Adam 优化器 (optim.Adam)。
  3. 学习率调整:引入学习率调度器,动态调整学习率。
  4. 正则化:添加 Dropout 层,减少过拟合风险。
# 替换优化器为 Adam
optimizer = optim.Adam(model.parameters(), lr=0.001)

五、总结

在本文中,我们从零开始实现了一个完整的多层感知机(MLP)模型,用于 MNIST 手写数字分类问题。通过这一过程,你应该已经掌握了以下关键知识点:

  1. 全连接神经网络的基本结构:如何通过 nn.Linear 搭建最基础的神经网络;
  2. 激活函数的引入:如何通过非线性激活函数(如 ReLU)提升模型的学习能力;
  3. 多层感知机的实现:如何设计一个包含多层隐藏层的深度学习模型;
  4. 完整的训练与测试流程:从数据加载、前向传播、反向传播到模型性能的评估。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com