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

DAY33 简单神经网络

你需要自行了解下MLP的概念。

你需要知道

  1. 梯度下降的思想
  2. 激活函数的作用
  3. 损失函数的作用
  4. 优化器
  5. 神经网络的概念

神经网络由于内部比较灵活,所以封装的比较浅,可以对模型做非常多的改进,而不像机器学习三行代码固定。

1. 神经网络的概念 (The concept of neural networks)

您可以把神经网络想象成一个由许多相互连接的“神经元”(neurons)组成的系统,它模仿了人类大脑处理信息的方式。这些神经元组织成层(layers):

  • 输入层 (Input Layer): 接收原始数据,比如一张图片的像素值,或者鸢尾花数据集中的花瓣、花萼的长度和宽度。
  • 隐藏层 (Hidden Layers): 在输入层和输出层之间,负责进行大部分的计算和特征提取。一个神经网络可以有多个隐藏层。层数越多,网络通常能学习更复杂的模式。
  • 输出层 (Output Layer): 输出最终结果,比如图片的分类(猫或狗),或者鸢尾花的种类。

每个连接都有一个相关的“权重”(weight),这个权重决定了前一个神经元对后一个神经元的影响程度。训练神经网络的过程,就是不断调整这些权重,使得网络能够对输入数据做出正确的预测。

2. 梯度下降的思想 (The idea of gradient descent)

梯度下降是一种优化算法,用于寻找函数(比如损失函数,后面会讲到)的最小值。想象一下你在一座山上,想要走到山谷的最低点,但周围有大雾,你看不清路。梯度下降就像你每走一步都选择当前位置最陡峭的下坡方向,这样就能最快到达谷底。

在神经网络中,“山”就是损失函数,我们要找的“谷底”就是损失函数的最小值点,对应的神经网络参数(主要是权重)就是最优的参数。梯度下降通过计算损失函数对于每个参数的“梯度”(可以理解为斜率或变化率),然后沿着梯度的反方向更新参数,从而逐渐减小损失。学习率(learning rate)是梯度下降中的一个重要超参数,它控制了每一步更新参数的幅度。

3. 损失函数的作用 (The role of loss functions)

损失函数(Loss Function),也叫代价函数(Cost Function),用来衡量神经网络模型预测结果与真实标签之间的差异。它的输出值(损失值)越大,表示模型的预测越不准确;损失值越小,表示模型预测越准确。

训练神经网络的目标就是最小化损失函数。通过梯度下降等优化算法,我们不断调整网络的权重,使得损失值越来越小。

常见的损失函数有:

  • 均方误差 (Mean Squared Error, MSE): 常用于回归问题(预测连续值)。
  • 交叉熵损失 (Cross-Entropy Loss): 常用于分类问题(预测离散类别)。您在代码中看到的 nn.CrossEntropyLoss() 就是这个。

4. 激活函数的作用 (The role of activation functions)

激活函数(Activation Function)被应用于神经网络中每个神经元的输出。它们的主要作用是给神经网络引入非线性(non-linearity)。

如果不用激活函数,或者只用线性激活函数(比如f(x)=x),那么无论神经网络有多少层,它本质上都只是一个线性模型,无法学习复杂的数据模式。而非线性激活函数使得神经网络能够拟合各种复杂的非线性关系。

常见的激活函数有:

  • Sigmoid: 将输出压缩到0和1之间,常用于二分类问题的输出层。
  • Tanh (双曲正切): 将输出压缩到-1和1之间。
  • ReLU (Rectified Linear Unit): 计算公式是 f(x) = max(0, x)。它非常简单高效,是目前最常用的激活函数之一。您在代码中看到的 nn.ReLU() 就是这个。
  • Softmax: 常用于多分类问题的输出层,它能将输出层的原始分数转换成概率分布,使得所有输出类别的概率和为1。

5. 优化器 (Optimizers)

优化器(Optimizer)是实现梯度下降思想的具体算法。它根据损失函数计算出的梯度来更新神经网络的权重,目标是最小化损失函数。

除了基本的随机梯度下降(Stochastic Gradient Descent, SGD,您代码中用的 optim.SGD),还有许多更高级的优化器,它们在SGD的基础上做了一些改进,试图更快、更稳定地找到损失函数的最小值。

常见的优化器有:

  • SGD (Stochastic Gradient Descent): 基本的梯度下降。
  • Momentum: 在SGD的基础上引入了动量,可以加速收敛并减少震荡。
  • AdaGrad (Adaptive Gradient): 对不同参数使用不同的学习率。
  • RMSprop (Root Mean Square Propagation): 也是自适应学习率的一种。
  • Adam (Adaptive Moment Estimation): 结合了Momentum和RMSprop的优点,是目前非常流行和常用的优化器之一。您代码中注释掉的 optim.Adam 就是这个。

简单来说,神经网络通过损失函数来衡量预测的好坏,通过梯度下降的思想,在优化器的帮助下,不断调整神经元之间的连接权重,而激活函数则赋予了网络学习复杂模式的能力。

数据的准备

# 仍然用4特征,3分类的鸢尾花数据集作为我们今天的数据集
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
import numpy as np# 加载鸢尾花数据集
iris = load_iris()
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(y_train.shape)
print(X_test.shape)
print(y_test.shape)

归一化数据

# 归一化数据,神经网络对于输入数据的尺寸敏感,归一化是最常见的处理方式
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)

模型架构定义

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

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

class MLP(nn.Module): # 定义一个多层感知机(MLP)模型,继承父类nn.Moduledef __init__(self): # 初始化函数super(MLP, 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# 实例化模型
model = MLP()

或者

    # def forward(self,x): #前向传播#     x=torch.relu(self.fc1(x)) #激活函数#     x=self.fc2(x) #输出层不需要激活函数,因为后面会用到交叉熵函数cross_entropy#     return x

定义损失函数和优化器

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

开始循环训练

实际上在训练的时候,可以同时观察每个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: # range是从0开始,所以epoch+1是从当前epoch开始,每100个epoch打印一次print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')

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

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

在这里插入图片描述
浙大疏锦行-CSDN博客

相关文章:

  • Leetcode 1651. Hopper 公司查询 III
  • 【NIPS 2024】Towards Robust Multimodal Sentiment Analysis with Incomplete Data
  • quill 富文本多张图片排序
  • 大语言模型的完整训练周期从0到1的体系化拆解
  • CS学习网站-geeksforgeeks介绍
  • 历年安徽大学保研上机真题
  • 原生php单元测试
  • Kafka 的日志清理策略:delete 和 compact
  • 决策引擎与规则引擎在交易所业务风控中的建设思路、架构设
  • 历年北京理工大学保研上机真题
  • 使用 Hyperlane 实现 WebSocket广播
  • MIT 6.S081 2020Lab5 lazy page allocation 个人全流程
  • 《技术择时,价值择股》速读笔记
  • [论文品鉴] DeepSeek V3 最新论文 之 MTP
  • 历年北京邮电大学保研上机真题
  • 嵌入式硬件篇---Ne555定时器
  • 私有知识库 Coco AI 实战(七):摄入本地 PDF 文件
  • WORD 转 PDF 工具:排版 / 图片 / 表格批量转换提升办公效率
  • 分布式缓存:ZSET → MGET 跨槽(cross‐slot)/ 并发 GET解决思路
  • Android自定义View学习总结
  • 一个服务器可以做两个网站/沧州网站建设推广
  • 郑州公司企业网站建设/百度推广查询
  • 万网主机 wordpress/关键词优化好
  • 南昌网站建设品牌/写软文赚钱的平台都有哪些
  • 跨境独立站建站公司/360搜索推广官网
  • php网站怎么做静态化/宁德市人民医院