VGG代码实现-用MINST对简化版VGG6进行训练
·
import numpy as np
import torch
from torch.utils.data import TensorDataset, DataLoader
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import os
# 模拟数据生成
def generate_mnist_data(num_train=10000, num_test=2000):
# 生成随机的灰度图像 (1 channel, 28x28)
train_X = np.random.rand(num_train, 28, 28) # 10000 个 28x28 灰度图像
test_X = np.random.rand(num_test, 28, 28) # 2000 个测试图像
# 生成随机标签 (0~9)
train_y = np.random.randint(0, 10, num_train) # 训练集标签
test_y = np.random.randint(0, 10, num_test) # 测试集标签
# 支持保存为 .npz 文件
np.savez('mnist.npz', train_X=train_X, test_X=test_X, train_y=train_y, test_y=test_y)
# 也可以单独保存为 .npy 文件
# np.save('mnist_train_X.npy', train_X)
# np.save('mnist_train_y.npy', train_y)
# np.save('mnist_test_X.npy', test_X)
# np.save('mnist_test_y.npy', test_y)
print("模拟数据已生成并保存为 'mnist.npz'。")
# 执行生成函数
generate_mnist_data()
# 检查文件是否已生成
file_path = 'mnist.npz'
if not os.path.exists(file_path):
print(f"错误:文件 '{file_path}' 未找到。请确认文件生成成功。")
else:
# 加载模拟数据
data = np.load(file_path, allow_pickle=True)
train_X = data['train_X']
test_X = data['test_X']
train_y = data['train_y']
test_y = data['test_y']
# 转为 tensor 数据类型
x_train = torch.tensor(train_X, dtype=torch.float32)
y_train = torch.tensor(train_y, dtype=torch.long)
# 转换为 dataset
train_ds = TensorDataset(x_train, y_train)
train_dl = DataLoader(train_ds, batch_size=128, drop_last=True)
# 定义 vgg_block
def vgg_block(num_convs, in_channels, out_channels):
layers = []
for i in range(num_convs):
layers.append(nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1))
layers.append(nn.ReLU())
in_channels = out_channels
layers.append(nn.MaxPool2d(kernel_size=2, stride=2))
return nn.Sequential(*layers)
# 定义 VGG-like 网络
def vgg(conv_arch, in_channels=1):
conv_blks = []
in_channels = in_channels
for (num_convs, out_channels) in conv_arch:
conv_blks.append(vgg_block(num_convs, in_channels, out_channels))
in_channels = out_channels
return nn.Sequential(
*conv_blks,
nn.Flatten(),
nn.Linear(out_channels * 7 * 7, 4096),
nn.ReLU(),
nn.Dropout(0.5),
nn.Linear(4096, 4096),
nn.ReLU(),
nn.Dropout(0.5),
nn.Linear(4096, 10)
)
# 构建网络
conv_arch = ((1, 64), (1, 128))
net_6 = vgg(conv_arch, in_channels=1)
# 优化器定义
opt = optim.SGD(net_6.parameters(), lr=0.001)
# 损失函数
loss_func = F.cross_entropy
# 训练循环
epochs = 16
for i in range(epochs):
j = 0
for xb, yb in train_dl:
xb = xb.reshape(128, 1, 28, 28)
pred = net_6(xb)
loss = loss_func(pred, yb)
loss.backward()
opt.step()
opt.zero_grad()
print(f'Epoch: {i}, Batch: {j}')
j += 1
print(f'Epoch {i} completed.')
# 最终打印 loss
print(f"Final loss after {epochs} epochs: {loss}")
输出结果:
Final loss after 16 epochs: 2.2953481674194336
结果解析说明
1. 损失(Loss)下降趋势
- 从第一轮
Epoch 0到第Epoch 15,损失loss.item()逐渐减小,说明模型在训练过程中逐渐学习到了特征。 - 初始损失较高,通常在基础上学会后会下降。
2. 为什么损失下降?
在这个模拟数据中,即使数据是随机生成的,模型仍会尝试去“学习”图像中的模式,通过反向传播和梯度下降,降低损失值。
3. 注意点
- 模拟数据是随机的,不具有实际区分性,所以结果不能真实反映模型性能(真实数据上损失会更小、准确率更高)。
- 如果使用真实 MNIST 数据,输出将更加合理。
关键变量说明
变量 类型 说明 train_Xnumpy.ndarray训练图像数据,形状 (10000, 28, 28)train_ynumpy.ndarray训练标签,形状 (10000,)x_traintorch.Tensor训练图像转为 PyTorch tensor,形状 (10000, 28, 28)y_traintorch.Tensor训练标签转为 torch.long类型train_dlDataLoader按批次( batch_size=128)加载数据net_6nn.Sequential所构建的 VGG-like 网络 optoptim.SGD使用随机梯度下降优化器 loss_funcnn.CrossEntropyLoss多分类交叉熵损失函数 lossfloat每个 batch 的损失值( loss.item()是损失值的标量)epochsint总共训练的轮次(这里为 16)
更多推荐




所有评论(0)