Day 35 训练
环境准备
确保已安装 PyTorch、sklearn、matplotlib、tqdm 等必要的 Python 库。若未安装,可通过以下命令安装:
pip install torch scikit-learn matplotlib tqdm -i https://pypi.tuna.tsinghua.edu.cn/simple
由于网络原因,使用清华大学的镜像源来加速安装过程。如果链接无法访问,请检查网络连接,或更换其他可用的 PyPI 镜像源。
模型训练
数据准备与预处理
import torch
import torch.nn as nn
import torch.optim as optim
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
import time
import matplotlib.pyplot as plt# 设置GPU设备
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print(f"使用设备: {device}")# 加载鸢尾花数据集
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)# 归一化数据
scaler = MinMaxScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)# 将数据转换为PyTorch张量并移至GPU
X_train = torch.FloatTensor(X_train).to(device)
y_train = torch.LongTensor(y_train).to(device)
X_test = torch.FloatTensor(X_test).to(device)
y_test = torch.LongTensor(y_test).to(device)
这里我们使用 torch.device
来检测并使用可用的 GPU 设备,以加速模型训练过程。加载鸢尾花数据集后,将其划分为训练集和测试集,并对特征数据进行归一化处理,使数据分布在 [0, 1] 范围内,有助于模型更快地收敛。最后将数据转换为 PyTorch 张量格式,并传输到指定设备(GPU 或 CPU)上。
定义模型
class MLP(nn.Module):def __init__(self):super(MLP, self).__init__()self.fc1 = nn.Linear(4, 10) # 输入层到隐藏层self.relu = nn.ReLU()self.fc2 = nn.Linear(10, 3) # 隐藏层到输出层def forward(self, x):out = self.fc1(x)out = self.relu(out)out = self.fc2(out)return out# 实例化模型并移至GPU
model = MLP().to(device)
定义了一个简单的多层感知机(MLP)模型,包含一个输入层、一个隐藏层和一个输出层。输入层接收 4 个特征维度的数据,隐藏层有 10 个神经元并使用 ReLU 激活函数,输出层有 3 个神经元,用于对应鸢尾花的 3 个类别。通过 model.to(device)
将模型放置在指定设备上。
损失函数与优化器
# 分类问题使用交叉熵损失函数
criterion = nn.CrossEntropyLoss()# 使用随机梯度下降优化器
optimizer = optim.SGD(model.parameters(), lr=0.01)
对于分类任务,选择交叉熵损失函数(CrossEntropyLoss)作为损失函数,它可以结合 softmax 操作,衡量模型预测结果与真实标签之间的差异。采用随机梯度下降(SGD)优化器来更新模型参数,学习率(lr)设置为 0.01。
模型训练过程
# 训练模型
num_epochs = 20000 # 训练的轮数# 用于存储每100个epoch的损失值和对应的epoch数
losses = []start_time = time.time() # 记录开始时间for epoch in range(num_epochs):# 前向传播outputs = model(X_train) # 隐式调用forward函数loss = criterion(outputs, y_train)# 反向传播和优化optimizer.zero_grad() #梯度清零loss.backward() # 反向传播计算梯度optimizer.step() # 更新参数# 记录损失值if (epoch + 1) % 200 == 0:losses.append(loss.item()) # item()方法返回一个Python数值,loss是一个标量张量print(f'Epoch [{epoch+1}/{num_epochs}, Loss: {loss.item():.4f}')# 打印训练信息if (epoch + 1) % 100 == 0: # 每100个epoch打印一次print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')time_all = time.time() - start_time # 计算训练时间
print(f'Training time: {time_all:.2f} seconds')
设置训练轮数为 20000 次。在每次训练迭代中,首先进行前向传播计算模型输出和损失值,然后执行反向传播计算梯度,并利用优化器更新模型参数。每 100 个 epoch 打印一次训练信息,每 200 个 epoch 记录一次损失值用于后续可视化。训练完成后,输出整个训练过程所花费的时间。
模型结构可视化
使用 torch.nn.Module
内置功能
# 直接输出模型结构
print(model)# 输出模型的可训练参数迭代器
for name, param in model.named_parameters():print(f"Parameter name: {name}, Shape: {param.shape}")
直接打印模型对象可以查看模型的结构,显示各层的名称和参数信息。通过 model.named_parameters()
可以获取模型中可训练参数的名称和形状,有助于我们了解模型的参数细节。
使用 torchsummary
库
from torchsummary import summary# 打印模型摘要
summary(model, input_size=(4,))
需先安装 torchsummary
库。summary
函数会输出模型的详细摘要,包括每层的输出形状、参数数量等信息。input_size
参数指定输入数据的形状,以便推断模型各层的信息。
使用 torchinfo
库
from torchinfo import summary# 打印模型摘要
summary(model, input_size=(4, ))
torchinfo
提供了比 torchsummary
更为详细的模型信息,包括每层的输入输出形状、参数数量、计算量等。
进度条功能实现
使用 tqdm
库可以方便地在训练过程中添加进度条,实时显示训练进度。
from tqdm import tqdm# 创建tqdm进度条
with tqdm(total=num_epochs, desc="训练进度", unit="epoch") as pbar:# 训练模型for epoch in range(num_epochs):# 前向传播outputs = model(X_train) loss = criterion(outputs, y_train)# 反向传播和优化optimizer.zero_grad()loss.backward()optimizer.step()# 记录损失值并更新进度条if (epoch + 1) % 200 == 0:losses.append(loss.item())epochs.append(epoch + 1)# 更新进度条的描述信息pbar.set_postfix({'Loss': f'{loss.item():.4f}'})# 每1000个epoch更新一次进度条if (epoch + 1) % 1000 == 0:pbar.update(1000) # 更新进度条# 确保进度条达到100%if pbar.n < num_epochs:pbar.update(num_epochs - pbar.n) # 计算剩余的进度并更新
通过 tqdm
创建一个进度条对象,并在训练循环中根据设定的步长更新进度条。set_postfix
方法用于在进度条右侧显示实时数据,如当前损失值。这种方式能够更直观地观察模型训练的进展和效果。
模型推理
在完成模型训练后,我们可以在测试集上进行模型推理,评估模型的性能。
# 在测试集上评估模型
model.eval() # 设置模型为评估模式
with torch.no_grad(): # 禁用梯度计算,提高推理速度outputs = model(X_test) # 对测试数据进行前向传播,获得预测结果_, predicted = torch.max(outputs, 1) # 获取预测类别correct = (predicted == y_test).sum().item() # 计算预测正确的样本数accuracy = correct / y_test.size(0)print(f'测试集准确率: {accuracy * 100:.2f}%')
将模型设置为评估模式,此时模型会关闭一些训练时特有的操作(如 dropout 等),以确保输出结果的稳定性和一致性。在推理过程中禁用梯度计算可以提高效率。通过计算预测结果与真实标签的匹配程度,得出模型在测试集上的准确率。
以上就是基于 PyTorch 实现鸢尾花分类模型的完整实践过程,涵盖了数据准备、模型构建、训练、可视化、进度条功能以及推理评估等各个环节,希望对大家学习和应用深度学习技术有所帮助。
浙大疏锦行