Docker 27监控告警实战:5分钟部署CPU/内存/IO异常自动钉钉/企微推送(附13个关键指标阈值调优清单)
2026/5/6 17:47:30
MNIST是一个经典的手写数字识别数据集,包含:
我们将构建一个全连接神经网络(Fully Connected Neural Network):
输入层(784) → 隐藏层1(64) → 隐藏层2(64) → 隐藏层3(64) → 输出层(10)安装命令:
pipinstalltorch torchvision matplotlib我们先看一下整个项目的结构,然后分块详细讲解:
# 导入必要的库importtorchfromtorch.utils.dataimportDataLoaderfromtorchvisionimporttransformsfromtorchvision.datasetsimportMNISTimportmatplotlib.pyplotasplt逐行解释:
import torch:导入PyTorch核心库from torch.utils.data import DataLoader:数据加载器,用于批量加载数据from torchvision import transforms:数据预处理工具from torchvision.datasets import MNIST:MNIST数据集import matplotlib.pyplot as plt:绘图库,用于可视化# 神经网络模型定义classNet(torch.nn.Module):def__init__(self):super().__init__()# 定义四个全连接层self.fc1=torch.nn.Linear(28*28,64)# 输入层→隐藏层1self.fc2=torch.nn.Linear(64,64)# 隐藏层1→隐藏层2self.fc3=torch.nn.Linear(64,64)# 隐藏层2→隐藏层3self.fc4=torch.nn.Linear(64,10)# 隐藏层3→输出层defforward(self,x):# 前向传播过程x=torch.nn.functional.relu(self.fc1(x))# 第一层 + ReLU激活x=torch.nn.functional.relu(self.fc2(x))# 第二层 + ReLU激活x=torch.nn.functional.relu(self.fc3(x))# 第三层 + ReLU激活x=torch.nn.functional.log_softmax(self.fc4(x),dim=1)# 输出层 + log_softmaxreturnx原理拆解:
torch.nn.Module:
init()方法:
torch.nn.Linear(in_features, out_features):定义全连接层forward()方法:
torch.nn.functional.relu():ReLU激活函数torch.nn.functional.log_softmax():log_softmax函数,用于多分类问题dim=1:在第一个维度(每行的10个输出)上计算softmax💡为什么使用log_softmax?
- 数值稳定性更好
- 与NLLLoss(负对数似然损失)配合使用,计算交叉熵损失更高效
# 数据加载函数defget_data_loader(is_train):# 定义数据预处理:将PIL图像转换为Tensorto_tensor=transforms.Compose([transforms.ToTensor()])# 加载MNIST数据集data_set=MNIST("",# 数据集保存路径(空表示当前目录)is_train,# True=训练集,False=测试集transform=to_tensor,# 应用预处理download=True# 如果本地没有则下载)# 创建DataLoaderreturnDataLoader(data_set,# 数据集batch_size=15,# 每批15个样本shuffle=True# 打乱数据顺序)逐行解释:
transforms.Compose:
transforms.ToTensor():将PIL图像或numpy数组转换为PyTorch Tensor,并自动归一化到[0,1]MNIST类参数:
is_train:是否为训练集transform:数据预处理管道download=True:自动下载数据集DataLoader参数:
batch_size=15:每批加载15张图片shuffle=True:打乱数据顺序,避免模型学习到顺序信息⚠️注意:训练集需要shuffle,测试集通常不需要,但这里统一设置为True
# 评估函数:计算模型在测试集上的准确率defevaluate(test_data,net):n_correct=0# 正确预测的数量n_total=0# 总样本数量withtorch.no_grad():# 关闭梯度计算,节省内存for(x,y)intest_data:# 遍历测试集# 前向传播outputs=net.forward(x.view(-1,28*28))# 统计正确预测数fori,outputinenumerate(outputs):iftorch.argmax(output)==y[i]:n_correct+=1n_total+=1returnn_correct/n_total# 返回准确率原理拆解:
torch.no_grad():
x.view(-1, 28*28):
-1表示自动计算该维度大小torch.argmax(output):
# 训练函数defmain():# 加载数据train_data=get_data_loader(is_train=True)test_data=get_data_loader(is_train=False)# 创建模型实例net=Net()# 初始准确率(随机权重)print("初始准确率:",evaluate(test_data,net))# 定义优化器optimizer=torch.optim.Adam(net.parameters(),lr=0.001)# 训练3个epochforepochinrange(3):# 遍历训练集for(x,y)intrain_data:# 梯度清零net.zero_grad()# 前向传播output=net.forward(x.view(-1,28*28))# 计算损失loss=torch.nn.functional.nll_loss(output,y)# 反向传播loss.backward()# 更新权重optimizer.step()# 每个epoch结束后评估print("epoch",epoch,"准确率:",evaluate(test_data,net))# 保存模型参数torch.save(net.state_dict(),'MNIST_model_params.pt')print("模型已保存为 MNIST_model_params.pt")# 可视化前4个测试样本的预测结果for(n,(x,_))inenumerate(test_data):ifn>3:break# 预测predict=torch.argmax(net.forward(x[0].view(-1,28*28)))# 绘制图像plt.figure(n)plt.imshow(x[0].view(28,28),cmap="gray")plt.title("预测结果: "+str(int(predict)))plt.show()plt.close()训练过程详解:
优化器设置:
optimizer=torch.optim.Adam(net.parameters(),lr=0.001)lr=0.001:学习率,控制权重更新的步长训练循环:
关键步骤:
net.zero_grad():梯度清零,防止梯度累积loss.backward():反向传播,计算梯度optimizer.step():更新权重损失函数:
loss=torch.nn.functional.nll_loss(output,y)# 预测函数:加载已训练的模型并进行预测defpredict():# 创建模型实例net=Net()# 加载训练好的权重net.load_state_dict(torch.load('MNIST_model_params.pt',weights_only=True))# 加载测试数据test_data=get_data_loader(is_train=False)# 创建3×3的子图显示9个预测结果plt.figure(figsize=(10,8))# 预测前9个测试样本for(n,(x,_))inenumerate(test_data):ifn>8:break# 预测predict=torch.argmax(net.forward(x[0].view(-1,28*28)))# 在子图中显示plt.subplot(3,3,n+1)plt.imshow(x[0].view(28,28),cmap="gray")plt.title("预测: "+str(int(predict)))plt.axis('off')# 关闭坐标轴plt.tight_layout()plt.show()plt.close()# 运行训练(注释掉,避免重复运行)# main()# 运行预测predict()A: 初始权重是随机的,模型还没有学习到任何规律。随着训练进行,准确率会逐渐提高。
A: 通常建议使用2的幂次(如16、32、64)。太小训练不稳定,太大内存可能不够。这里使用15是为了演示。
A: 0.001是常用初始值。如果训练不稳定(损失震荡),可以调小;如果收敛太慢,可以适当调大。
A: PyTorch会累积梯度。如果不清零,每次backward()的梯度会加到之前的梯度上,导致错误更新。
A: 使用torch.save(net, 'model.pth'),加载时使用net = torch.load('model.pth')
修改网络结构:尝试增加或减少隐藏层的数量,观察对准确率的影响
# 尝试修改为:self.fc1=torch.nn.Linear(28*28,128)self.fc2=torch.nn.Linear(128,64)self.fc3=torch.nn.Linear(64,10)调整超参数:修改学习率和batch_size,观察训练效果
# 尝试:optimizer=torch.optim.Adam(net.parameters(),lr=0.0005)# 或returnDataLoader(data_set,batch_size=32,shuffle=True)扩展功能:添加验证集,在每个epoch后同时计算训练集和验证集的准确率