当前位置: 首页 > news >正文

day33 MLP神经网络的训练

目录

神经网络

神经网络的概念

神经网络的核心组成与结构

神经网络的工作原理:从输入到输出

神经网络的学习能力和特点

神经网络和深度学习的关系

准备工作

数据准备

模型架构定义

模型训练(CPU版本)

定义损失函数和优化器

开始循环训练

可视化结果


神经网络

神经网络的概念

神经网络(Neural Network),全称为人工神经网络(Artificial Neural Network, ANN),是一种受生物大脑神经元结构启发的计算模型。其核心思想是通过多层相互连接的“人工神经元”(节点)传递和处理信息,模拟生物神经系统的学习和决策过程。

神经网络的核心组成与结构

  1. 人工神经元(节点)

    • 输入层:接收原始数据(如图像像素、文本特征)。
    • 隐藏层:处理和转换输入信息,提取抽象特征(层数和节点数根据任务调整)。
    • 输出层:生成最终结果(如分类标签、回归值)。
  2. 网络连接与权重

    • 神经元之间通过 “权重(Weight)” 连接,权重决定信息传递的强度,是模型学习的核心参数。
    • 每个神经元的输出通过激活函数(如 ReLU、Sigmoid)引入非线性变换,使网络能处理复杂问题。
  3. 典型网络结构示例

    • 多层感知机(MLP):全连接网络,适用于简单分类任务。
    • 卷积神经网络(CNN):通过卷积层提取空间特征,擅长图像处理。
    • 循环神经网络(RNN):通过记忆单元处理序列数据,适用于自然语言处理。

神经网络的工作原理:从输入到输出

  1. 前向传播(Forward Propagation)

    • 输入数据经过各层神经元的加权求和与激活函数计算,逐层传递至输出层。
    • 数学表达式:

      其中 wi 为权重,b为偏置,f为激活函数,a为神经元输出。
    • 激活函数的作用:赋予神经网络“思考”的灵魂。它是神经网络中对神经元输入进行变换的函数,其核心作用是为网络引入非线性映射能力。若没有激活函数,多层神经网络将退化为线性模型,只能处理线性问题(如简单的线性回归),无法拟合现实世界中的复杂非线性关系(如图像识别、语言理解等)。
  2. 反向传播(Backpropagation)

    • 计算预测结果与真实值的误差(损失函数),通过链式法则将误差反向传播至各层,更新权重以减小误差。
    • 优化目标:通过梯度下降等算法最小化损失函数(如交叉熵、均方误差)。
    • 损失函数的作用:衡量模型“对错”的标尺与优化方向的指引它是神经网络中用于度量模型预测结果和标签差异的函数,其核心作用是将“模型预测的准确性”转化为可计算的数值——数值越小,代表预测与真实越接近。从优化角度看,损失函数为模型训练提供了明确的“目标”:通过调整参数使损失值最小化,从而让模型不断逼近真实规律。
    • 梯度下降的思想:从“下山寻谷”到神经参数的优化。本质是“局部最优驱动全局优化”:不追求一步到位,而是通过每一步的“最优局部选择”逐步逼近目标。这种思想在现实中也有映射 —— 如企业管理中通过每日迭代优化流程,最终实现整体效率提升。在深度学习中,尽管存在非凸优化、梯度消失等挑战,但梯度下降仍是目前最有效、最易实现的参数优化方法,其与反向传播的结合,构成了现代神经网络训练的基石。理解梯度下降,就是理解机器学习 “从数据中学习” 的动态过程。
    • 优化器:负责更新模型参数、最小化损失函数的算法框架。不同的优化器采用不同的策略来更新参数,直接影响模型的训练速度、稳定性和最终性能。

神经网络的学习能力和特点

  1. 强大的表征能力

    • 多层网络可近似任意复杂函数(通用近似定理),能捕捉数据中的非线性关系。
    • 示例:CNN 通过多层卷积提取图像中的边缘、纹理等特征,最终实现物体识别。
  2. 数据驱动的学习方式

    • 无需手动设计特征,直接从数据中学习模式(如自动驾驶通过海量图像数据学习路况识别)。
  3. 局限性

    • 需大量标注数据,训练计算成本高(如 GPT-4 训练需数千块 GPU 协作)。
    • 模型可解释性较差(“黑箱” 特性),难以直观理解决策逻辑。

神经网络和深度学习的关系

  • 深度学习是神经网络的延伸,特指具有多层隐藏层的复杂神经网络(如 10 层以上的 CNN 或 Transformer)。
  • 深度学习通过增加网络深度和复杂度,结合大数据和算力,在图像识别、语音处理、自然语言生成等领域实现了突破性进展(如 AlphaGo、ChatGPT)。

准备工作

# 安装pytorch
%pip install torch torchvision torchaudio -i https://pypi.tuna.tsinghua.edu.cn/simpleimport torch
# 检查CUDA是否可用 (因为我是macos所以不可用)if torch.cuda.is_available():print("CUDA可用!")# 获取可用的CUDA设备数量device_count = torch.cuda.device_count()print(f"可用的CUDA设备数量: {device_count}")# 获取当前使用的CUDA设备索引current_device = torch.cuda.current_device()print(f"当前使用的CUDA设备索引: {current_device}")# 获取当前CUDA设备的名称device_name = torch.cuda.get_device_name(current_device)print(f"当前CUDA设备的名称: {device_name}")# 获取CUDA版本cuda_version = torch.version.cudaprint(f"CUDA版本: {cuda_version}")
else:print("CUDA不可用。")

数据准备

# 仍然使用4特征,3分类的鸢尾花数据集
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
import numpy as np# 加载鸢尾花数据集
X = iris.data # 特征数据
y = iris.target # 标签数据
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)# 打印尺寸
print(X_train.shape)
print(X_test.shape)
print(y_train.shape)
print(y_test.shape)

(120, 4)

(120,)

(30, 4)

(30,)

# 归一化数据,神经网络对于输入数据的尺寸敏感,归一化湿最常见的处理方式
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test) # 确保训练集和测试集是相同的缩放# 将数据转换为 PyTorch 张量,因为 PyTorch 使用张量进行训练
# y_train和y_test是整数,所以需要转化为long整型,如果是float32,会输出1.0 0.0
X_train = torch.FloatTensor(X_train)
y_train = torch.LongTensor(y_train)
X_test = torch.FloatTensor(X_test)
y_test = torch.LongTensor(y_test)

注意事项:

1. 分类任务中,若标签是整数(如 0/1/2 类别),需转为long类型(对应 PyTorch 的torch.long),否则交叉熵损失函数会报错。

2. 回归任务中,标签需转为float类型(如torch.float32)。

模型架构定义

定义一个简单的全连接神经网络模型,包含一个输入层、一个隐藏层和一个输出层。

定义层数+定义前向传播顺序

import torch.nn as nn    # 神经网络模块
import torch.optim as optim    # 优化器模块class MLP(nn.Module): # 定义一个多层感知机(MLP)模型,继承父类nn.Moduledef __init__: # 初始化函数super(MPL, self).__init__() # 调用父类的初始化函数# 前三行是八股文,后面是自定义的self.fc1 = nn.Linear(4, 10) # 输入层到隐藏层self.relu = nn.ReLU()    # 激活函数self.fc2 = nn.Linear(10, 3) # 隐藏层到输出层# 输出层不需要激活函数,因为后面会用到交叉熵函数cross_entropy,交叉熵函数内部有softmax函数,会把输出转化为概率def forward(self, x):out = self.fc1(x)out = self.relu(out)out = self.fc2(out)return out# 其实模型层的写法又很多,relu也可以不写,在后面前向出传播的时候计算下即可,因为relu其实不算一个层,只是一个计算而已
#   def forward(self, x):
#       out = torch.relu(self.fc1(x))
#       out = self.fc2(out)
#       return out# 实例化模型
model = MLP()

模型训练(CPU版本)

定义损失函数和优化器

# 分类问题使用交叉熵损失函数
criterion = nn.CrossEntropyLoss()# 使用随机梯度下降优化器
optimizer = optim.SGD(model.parameters(), lr=0.01)# 使用自适应学习率优化器 
# optimizer = optim.Adam(model.parameter(), lr=0.01)

开始循环训练

实际上在训练的时候,可以同时观察每个epoch训练完后的测试集的表现:测试集的loss和准确度

# 训练模型
num_epochs = 20000 # 训练的论数# 用于存储每个 epoch 的损失值
losses = []for epoch in range(num_epochs): # range从0开始,所以epoch从0开始# 向前传播outputs = model.forward(X_train)    # 显式调用forward函数# outputs = model(X_train)  # 常见写法隐式调用forward函数,其实是用了model类的__call__方法  loss = criterion(outputs, y_train)    # output是模型预测值,y_train是真实标签# 反向传播和优化optimizer.zero_grad()    # 梯度清零,因为PyTorch会累积梯度,所以每次迭代需要清零,梯度累积是那种小的bitchsize模拟大的bitchsizeloss.backward()    # 反向传播计算梯度optimizer.step()    # 根据学习学习率和梯度更新参数# 记录损失值losses.append(loss.item())# 打印训练信息if (epoch + 1) % 100 == 0: # 每100次训练打印一次print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')

Epoch [100/20000], Loss: 1.0599

Epoch [200/20000], Loss: 1.0205

Epoch [300/20000], Loss: 0.9727

Epoch [400/20000], Loss: 0.9150

Epoch [500/20000], Loss: 0.8493

Epoch [600/20000], Loss: 0.7800

Epoch [700/20000], Loss: 0.7141

Epoch [800/20000], Loss: 0.6562

Epoch [900/20000], Loss: 0.6078

Epoch [1000/20000], Loss: 0.5677

Epoch [1100/20000], Loss: 0.5343

...

Epoch [19600/20000], Loss: 0.0622

Epoch [19700/20000], Loss: 0.0620

Epoch [19800/20000], Loss: 0.0619

Epoch [19900/20000], Loss: 0.0618

Epoch [20000/20000], Loss: 0.0617 

如果你重新运行上面这段训练循环,模型参数、优化器状态和梯度会继续保留, 导师训练结果叠加,模型参数和优化器状态(如动量、学习率等)不会被重置。这会导致训练从之前的状态继续,而不是从头开始

可视化结果

import matplotlib.pyplot as plt
# 可视化损失曲线
plt.plot(range(num_epochs), losses)
plt_xlabel('Epoch')
plt_ylabel('Loss')
plt.title('Train Loss over Epochs')
plt.show()

@浙大疏锦行

相关文章:

  • FPGA基础 -- Verilog HDL 结构风格的描述
  • 企业级 Vue3 项目 iframe 封装方案
  • Excel单元格数值统计 - 华为OD机试真题(Python题解)
  • 宇宙尽头是WPS之——【Excel】一个自动重新排序的宏
  • Vivaldi浏览器6.4.3160.42安装教程 - 64位下载安装步骤详解(包含历史版本)
  • “贴身日记”购物网站的设计与实现
  • Matlab自学笔记五十九:符号变量的代入和替代subs精讲
  • Flutter中将bytes转换成XFile对象上传
  • 8.TCP Server端实现
  • AWS ELB 可观测性最佳实践
  • 34. 在排序数组中查找元素的第一个和最后一个位置
  • 力扣刷题——长度最小的子数组
  • 在 Qt 开发中,.toLocal8Bit().constData() 和 .toUtf8()有什么区别
  • 【React源码解析】初识JSX
  • You Only Look Once Unified, Real-Time Object Detection论文笔记
  • django ReturnDict 如何修改内容
  • C++(从C到C++)
  • Java系统开发:前端与后端的协同开发实践
  • 老项目重构难题破解:飞算 JavaAI 如何实现技术升级突围
  • 数字ic后端设计从入门到精通7(含fusion compiler, tcl教学)sta时序分析
  • 电子商务网站开发技术有哪些/竞价托管一般要多少钱
  • 海口网站建设网站制作/游戏推广平台有哪些
  • 城乡建设部统计网站/产品推广策划方案
  • 做网站f12的用处/seo百度快速排名
  • 做公司网站应准备什么材料/游戏优化是什么意思?
  • 网站建设流程心得/直通车官网