Day 33 方便的神经网络

1. 写在前面

从今天开始,我们将正式进入深度学习的领域。虽然机器学习只需要三行代码就能调用模型,但神经网络的灵活性更高,我们可以对模型结构、训练过程做非常多的定制。

在开始写代码之前,你需要先明确几个核心概念:

  1. 神经网络:它就像一个复杂的函数,输入数据,输出预测结果。
  2. 梯度下降:这是让模型"学习"的方法,通过不断调整参数来减少误差。
  3. PyTorch:这是目前最流行的深度学习框架之一,我们接下来的项目都会基于它来开发。

2. 环境配置与检查

深度学习通常需要独立的Python环境,以避免包版本冲突。

如果你不知道环境如何配置,这里推荐一个B站的教程:【2025年最新版】手把手教你安装PyTorch,用最简单的方式教你安装PyTorch_哔哩哔哩_bilibili

基本上很多环境配置的问题都可以得到解决。

创建环境

建议创建一个名为 DL (Deep Learning) 的新环境:

conda create -n DL python=3.8
conda activate DL
# 安装PyTorch(具体命令需参考PyTorch官网,根据你的显卡版本选择)
# pip install torch torchvision torchaudio ...

检查显卡 (CUDA)

深度学习主要是矩阵运算,GPU(显卡)的并行计算能力比CPU强得多。我们可以通过代码检查CUDA是否可用:

import torch
# 检查CUDA是否可用
if torch.cuda.is_available():
    print("CUDA可用!")
    # 查看设备数量
    print(f"设备数量: {torch.cuda.device_count()}")
    # 查看当前设备名称
    print(f"显卡名称: {torch.cuda.get_device_name(0)}")
else:
    print("CUDA不可用,将使用CPU训练")

如果是NVIDIA显卡且安装了正确的驱动,通常能看到显卡信息。如果没有显卡,用CPU也能跑今天的简单例子。

安装torch成功可以在终端输入以下命令验证,出现“True”就是成功了

3. 数据准备:从Numpy到Tensor

神经网络对输入数据比较挑剔,通常需要做两步处理:

  1. 归一化:将数据缩放到0-1之间,这样模型收敛更快。
  2. 转为Tensor:PyTorch无法直接处理Numpy数组,必须转换成张量(Tensor)。
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
import torch
import numpy as np
# 1. 加载数据
iris = load_iris()
X = iris.data
y = iris.target
# 2. 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 3. 数据归一化(非常重要)
scaler = MinMaxScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
# 4. 转换为PyTorch张量
# 特征转为FloatTensor(浮点型),标签转为LongTensor(长整型,分类任务要求)
X_train = torch.FloatTensor(X_train)
y_train = torch.LongTensor(y_train)
X_test = torch.FloatTensor(X_test)
y_test = torch.LongTensor(y_test)

4. 搭建神经网络模型

在PyTorch中定义模型主要有三个固定步骤:

  1. 继承 nn.Module 父类。
  2. __init__ 中定义层(如全连接层、激活函数)。
  3. forward 中定义前向传播的路径(数据怎么流)。
import torch.nn as nn
class MLP(nn.Module):
    def __init__(self):
        super(MLP, self).__init__() # 必须调用父类初始化
        # 定义网络层
        # 输入层到隐藏层:输入4个特征,输出10个神经元
        self.fc1 = nn.Linear(4, 10)
        # 激活函数
        self.relu = nn.ReLU()
        # 隐藏层到输出层:输入10个神经元,输出3个分类
        self.fc2 = nn.Linear(10, 3)
    def forward(self, x):
        # 定义数据流向
        out = self.fc1(x)
        out = self.relu(out)
        out = self.fc2(out)
        return out
        # 注意:输出层不需要加Softmax,因为后续的交叉熵损失函数自带了
# 实例化模型
model = MLP()

5. 训练的"三件套"

在开始训练循环前,需要准备好工具:

  1. 损失函数 (Criterion):衡量模型预测得准不准。
  2. 优化器 (Optimizer):根据误差来更新模型参数。
import torch.optim as optim
# 分类任务常用交叉熵损失
criterion = nn.CrossEntropyLoss()
# 随机梯度下降优化器 (SGD)
# lr是学习率,控制每次更新的步长
optimizer = optim.SGD(model.parameters(), lr=0.01)

6. 训练循环 (Training Loop)

这是深度学习代码中最核心的部分,逻辑非常固定,俗称"五步走":

num_epochs = 20000 # 训练轮数
losses = []        # 记录损失值用于画图
for epoch in range(num_epochs):
    # 1. 前向传播:计算预测值
    outputs = model(X_train)
    # 2. 计算损失:预测值 vs 真实值
    loss = criterion(outputs, y_train)
    # 3. 梯度清零:清除上一步的残留梯度(必须做!)
    optimizer.zero_grad()
    # 4. 反向传播:计算新的梯度
    loss.backward()
    # 5. 更新参数:根据梯度调整权重
    optimizer.step()
    # 记录和打印
    losses.append(loss.item())
    if (epoch + 1) % 100 == 0:
        print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')

新手易错点

  • optimizer.zero_grad() 千万别忘了,否则梯度会累积,导致模型训练失败。
  • model(X_train) 等价于 model.forward(X_train),是Python的魔法方法调用。

7. 结果可视化

训练完成后,我们可以画出 Loss 的变化曲线。如果曲线一直在下降并趋于平稳,说明模型学到了东西。

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()
posted @ 2026-01-10 18:43  gccbuaa  阅读(2)  评论(0)    收藏  举报