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

庙算兵棋推演AI开发初探(7-神经网络训练与评估概述)

前面我们提取了特征做了数据集设计并实现了处理数据集的神经网络,接下来我们需要训练神经网络了,就是把数据对接好灌进去,训练后查看预测的和实际的结果是否一致——也就是训练与评估

数据解析提取

数据编码为数据集

设计神经网络

-->>神经网络训练与评估

神经网络一个重要指标是收敛 ,就是用可以逼近任意函数的神经网络是否可以逼近你数据集中隐含的模式

再重复一遍【特征工程】与【神经网络】的区别:

前者就像人发现了牛顿第二定律F=ma,显式的找到公式并处理数据得到m和a,然后输入得到F

后者是把包含多余的各种参数都放到神经网络中,然后人为的把F作为标签-对应那些参数的数据集中,经过训练得到隐含关系,用到时候把各种参数都输入到神经网络后得到F。

一、神经网络

nn的实现方式使得我一个编码人员看不懂了,根本看不到函数调用的模式了,在初期接触时还以为是之前的人写错了……

(1)神经网络nn

nn.Module 是一切的基础

torch.nn 中,所有神经网络的组成部分(比如一层线性变换、一个激活函数、一个完整的模型)都是一个类,这个类要继承自 nn.Module

比如你定义一个自己的神经网络层:

import torch
import torch.nn as nnclass MyModel(nn.Module):def __init__(self):super(MyModel, self).__init__()self.linear = nn.Linear(10, 5)  # 线性层:输入10维,输出5维def forward(self, x):x = self.linear(x)return x
  • __init__ 里初始化网络的各种

  • forward 定义了前向传播过程。

(2)前向传递函数forword

注意: 你自己不会直接调用 forward(),而是直接让对象“像函数一样”去调用,比如:

model = MyModel()
output = model(input_data)  # 这里实际上是自动调用 model.forward(input_data)

这一点跟 Python 普通类的调用规则有点不一样。
PyTorch 在 nn.Module 里重载了 __call__() 方法:当你 model(input_data) 时,它实际上内部做了

def __call__(self, *args, **kwargs):# 还有别的一些操作return self.forward(*args, **kwargs)

所以你只写 forward(),调用的时候直接用 (),很自然。

nn模块里有很多“层”和“工具”

比如:

  • nn.Linear(in_features, out_features):全连接层(线性变换)

  • nn.Conv2d(in_channels, out_channels, kernel_size):卷积层

  • nn.ReLU()nn.Sigmoid():常用激活函数

  • nn.CrossEntropyLoss():损失函数

  • nn.Sequential(...):顺序搭建一堆层

  • ...

这些都是封装好的,你拿来直接用。

管理参数:所有 nn.Module 都自动帮你管理它的参数,比如 model.parameters() 可以拿到里面所有需要训练的权重。

(3)张量tensor和“层”的输入(训练中经常需要注意的形状tensor.shape() )

这种图是经常在神经网络的学习中会提到的:

.

刚刚提到的“层的输入”in_features, out_features 就是输出特征数, 输入特征数 而继承了nn.Module 的类,就都会自动调用forward函数。

最简版 nn.Linear 实现

  • self.weight 是一个 (输出特征数, 输入特征数) 的矩阵;

  • self.bias 是一个 (输出特征数, ) 的向量;

  • nn.Parameter 包了一下,让这两个变量能被自动识别为需要优化的参数

  • forward 里用的是:

    • x @ self.weight.t():表示矩阵乘法(这里需要对 weight 做转置 .t(),因为 PyTorch标准是(out_features, in_features)存的)

    • + self.bias:加上偏置。

import torch
import torch.nn as nnclass MyLinear(nn.Module):def __init__(self, in_features, out_features):super(MyLinear, self).__init__()# 初始化权重和偏置self.weight = nn.Parameter(torch.randn(out_features, in_features))  # (out, in)self.bias = nn.Parameter(torch.randn(out_features))  # (out, )def forward(self, x):# 线性变换:y = x @ W^T + breturn x @ self.weight.t() + self.bias

x @ self.weight.t():表示矩阵乘法(这里需要对 weight 做转置 .t(),因为 PyTorch标准是(out_features, in_features)存的)

二、梯度更新

import torch
import torch.nn as nn
import torch.optim as optim# 定义一个简单的模型
model = nn.Linear(10, 2)  # 输入维度为10,输出维度为2
criterion = nn.CrossEntropyLoss()  # 损失函数
optimizer = optim.SGD(model.parameters(), lr=0.01)  # 使用随机梯度下降优化器# 模拟输入数据和标签
inputs = torch.randn(5, 10)  # batch size 为 5,输入维度为 10
labels = torch.tensor([0, 1, 0, 1, 0])  # 对应的标签# 前向传播
outputs = model(inputs)  # 计算模型输出
loss = criterion(outputs, labels)  # 计算损失# 反向传播
optimizer.zero_grad()  # 清空梯度
loss.backward()  # 计算梯度
optimizer.step()  # 更新模型参数# 打印损失值
print(f"Loss: {loss.item()}")

(1)loss 损失函数-反向传播

在机器学习/深度学习中,损失(loss)的作用是:

  • 衡量模型输出真实标签 之间的差距有多大。

  • 差距越大,loss越大,训练目标就是让loss变小。

这部分是继承自torch.nn的,继承了在反向传播时就可以自动执行了——loss 是一个函数,它根据模型的输出(预测)和真实答案(标签)算出“错了多少”。而且——PyTorch 已经帮你写好了很多常见的损失函数,所以可以自动计算损失值

举例:

outputs = torch.tensor([[0.8], [0.2]])  # 模型预测
targets = torch.tensor([[1.0], [0.0]])  # 真实答案loss_fn = nn.MSELoss()
loss = loss_fn(outputs, targets)
print(loss)

 用 MSELoss(均方误差),计算出来的是:

MSE= 2 (0.8−1.0) 2 +(0.2−0.0) 2 ​ = 2 (0.04+0.04) ​ =0.04

PyTorch中,常见的 loss 都是封装成了一个,比如 nn.MSELossn.CrossEntropyLoss,使用起来就像调用一个函数一样。

损失函数适用情况计算公式(简略版)
nn.MSELoss回归问题均方误差 (初中学的方差)
nn.CrossEntropyLoss多分类问题交叉熵
nn.BCELoss二分类问题(sigmoid后输出)二元交叉熵
nn.L1Loss有时用于回归,鲁棒性更好绝对值误差 

(2)optimizer 优化器-反向传播

Optimizer 是用来:

  • 根据梯度(.grad)调整模型参数,让模型的损失 (loss) 变小。

也就是说:优化器就是根据 .grad 去真正“更新”权重的人。

在 PyTorch 里,常见的优化器有:

  • torch.optim.SGD(随机梯度下降)

  • torch.optim.Adam(自适应动量优化)

  • torch.optim.RMSprop(更适合处理稀疏数据)

  • 等等等等

举例: 

optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

 意思是:

  • 随机梯度下降法(SGD)

  • 学习率 lr=0.01

  • 优化model里面所有可以训练的参数。

 套路——每一轮训练时需要:

loss.backward()      # 计算梯度,填到 param.grad
optimizer.step()     # 用 param.grad 来更新 param
optimizer.zero_grad()# 清空梯度,准备下一轮

小结比较一下自动化调用 

步骤说明自动吗?
1前向传播 (forward) 计算输出
2计算损失 (loss)
3反向传播 (loss.backward()) 计算梯度你需要手动调用 .backward()
4用优化器 (optimizer.step()) 更新参数你需要手动调用 .step()

(3)scheduler 学习率调度器

Scheduler 是用来:

  • 动态调整学习率 (learning rate) 的。(scheduler是用来让学习率“聪明变化”的。)

因为:

  • 一开始训练时需要大学习率快速接近目标;

  • 后面训练细节时需要小学习率慢慢收敛到最优。

PyTorch提供了各种学习率调度器(scheduler),比如:

  • StepLR(每隔几步降低一次)

  • ExponentialLR(指数下降)

  • ReduceLROnPlateau(如果验证集loss不下降,就降低学习率)

  • CosineAnnealingLR(余弦退火,非常热门)

用法举例:

optimizer = torch.optim.SGD(model.parameters(), lr=0.1)
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=30, gamma=0.1)

意思是:

  • 用SGD,初始学习率是0.1

  • 每30个epoch,学习率乘0.1(变成原来的十分之一)

训练套路:

for epoch in range(100):train()  # 自己定义的训练过程validate()  # 验证scheduler.step()  # 记得每个epoch后,scheduler自己去调整学习率

三、训练模式与评估模式

所以,最后所谓保存的“模型”是什么?就是各种权重的一个字典,包括了继承自torch的那些【nn、loss、optimizer】

训练的时候是【修改梯度】的,就像人学新东西时要保持接受的状态。

评估的时候是【禁止修改梯度】的,就像人考试的时候一样,知识不能再根据考卷摇摆

import torch
import torch.nn as nn# 定义一个简单的模型
model = nn.Linear(2, 1)  # 输入维度为2,输出维度为1
criterion = nn.MSELoss()  # 损失函数
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)# 模拟训练数据
train_inputs = torch.tensor([[1.0, 2.0], [3.0, 4.0]])
train_targets = torch.tensor([[5.0], [7.0]])# 模拟评估数据
eval_inputs = torch.tensor([[5.0, 6.0]])
eval_targets = torch.tensor([[11.0]])# 训练模式
model.train()  # 切换到训练模式
for epoch in range(10):optimizer.zero_grad()outputs = model(train_inputs)loss = criterion(outputs, train_targets)loss.backward()optimizer.step()print(f"Epoch {epoch+1}, Loss: {loss.item()}")# 评估模式
model.eval()  # 切换到评估模式
with torch.no_grad():  # 禁用梯度计算eval_outputs = model(eval_inputs)eval_loss = criterion(eval_outputs, eval_targets)print(f"Evaluation Loss: {eval_loss.item()}")
  1. model.train():

    • 启用训练模式。
    • 影响某些层(如 Dropout 和 BatchNorm),使它们在训练时正常工作。
  2. model.eval():

    • 启用评估模式。
    • 禁用 Dropout 和固定 BatchNorm 的均值和方差,使模型在评估时表现稳定。
  3. torch.no_grad():

    • 在评估模式下,禁用梯度计算以节省内存和加速推理。

总结流程:

  • outputs = model(inputs)

  • loss = criterion(outputs, targets)

  • loss.backward()计算出每个参数的.grad

  • optimizer.step()根据.grad更新参数

  • optimizer.zero_grad()清空上一次的梯度

http://www.xdnf.cn/news/198433.html

相关文章:

  • FTP-网络文件服务器
  • 使用 Vue3 + Webpack 和 Vue3 + Vite 实现微前端架构(基于 Qiankun)
  • iVX 图形化编程如何改写后端开发新范式
  • EXCEL中跨行匹配两组数据
  • 流域生态系统碳排放、碳循环模拟与评估技术应用
  • 【基础篇】static_config采集配置详解
  • Vue 3 中通过 createApp 创建的 app 实例的所有核心方法,包含完整示例、使用说明及对比表格
  • 深入解析 PyTorch 中的 torch.distributions模块与 Categorical分布
  • 2025吃鸡变声器软件推荐
  • 【Vue3 组合式 API 在大型项目中的实践:useOperatorData 封装与应用】
  • 如何开发动态贴纸功能?一体化美颜SDK的技术实现思路与实战方案
  • Java 入门宝典--注释、关键字、数据类型、变量常量、类型转换
  • 服务器部署,Nginx安装和配置
  • 思维链理解汇总
  • 美团社招一面
  • 2025天津二类医疗器械经营备案攻略
  • AI 边缘盒子:智能与效率的边缘先锋
  • 生成对抗网络(Generative Adversarial Nets,GAN)
  • 知识付费平台推荐及对比介绍
  • Nacos源码—1.Nacos服务注册发现分析一
  • Coding Practice,48天强训(26)
  • 空间计算:开启人机交互新纪元的下一代技术范式
  • 安卓主题换肤功能
  • 安卓基础(强制转换)
  • 社交电商和泛娱乐平台出海南美市场支付方式与策略
  • ASP.NET MVC​ 入门指南四
  • 【quantity】3 Unit 物理量计算库(quantity.rs)
  • c语言的指针详解
  • js补环境工具使用技巧、补环境实例、重点环境检测点详解
  • Qt开发:XML文件的写入与读取