#import cv2
import cv2 as cv
import numpy as np
import torch as t
import torchvision as tv
from torchvision.datasets import mnist
from torch.utils.data import DataLoader
#1.利用torchvision 将图像数据转为tensor,并进行归一化的预处理
transform=tv.transforms.Compose([tv.transforms.ToTensor(),tv.transforms.Normalize((0.5,),(0.5,))])
train_ts = tv.datasets.MNIST(root='./data', train=True, download=True, transform=transform)
test_ts = tv.datasets.MNIST(root='./data', train=False, download=True, transform=transform)
train_dl = DataLoader(train_ts, batch_size=32, shuffle=True, drop_last=False)
test_dl = DataLoader(test_ts, batch_size=64, shuffle=True, drop_last=False)
#2.模型的读取
model =t.nn.Sequential(t.nn.Linear(784, 100), #隐藏层线性层
t.nn.ReLU(), #隐藏层的激活函数
t.nn.Linear(100, 10), #输出层线性层
t.nn.LogSoftmax(dim=1)#损失计算
)
#3.训练函数
def train_mnist():
loss_fn = t.nn.NLLLoss(reduction='mean') # NLL方式的损失计算
optimizer = t.optim.SGD(model.parameters(), lr=1e-3) #优化器的计算函数,用于根据损失计算参数更新
for s in range(5): #设计为5个epoch
print('run in epoch:%d'%s)
for i ,(x_train,y_train) in enumerate(train_dl):
x_train=x_train.view(x_train.shape[0],-1)
y_pred=model(x_train) #向前传播
train_loss=loss_fn(y_pred,y_train)#计算损失
if(i+1)%100==0:
print(i+1,train_loss.item())
model.zero_grad() #梯度清零
train_loss.backward() # 反向传播
optimizer.step() #更新所有的参数 使用优化器指定的学习率进行优化更新
total=0
correct_count=0
for test_images,test_labels in test_dl:
for i in range (len(test_labels)):
image=test_images[i].view(1,784)
with t.no_grad():
pred_labels=model(image)
plabel=t.exp(pred_labels)
probs=list(plabel.numpy()[0])
pred_labels=probs.index(max(probs))
true_label=test_labels.numpy()[i]
if(pred_labels==true_label):
correct_count+=1
total+=1
print('accuracy: %.2f',correct_count/total)
t.save(model.state_dict(),'./nn_mnist_model.pth')
if __name__=='__main__':
train_mnist()
print('model is state dict')
# 输出模型的结构
for param_tensor in model.state_dict():
print(param_tensor,"\t",model.state_dict()[param_tensor].size())
# 推理
model.load_state_dict(t.load('./nn_mnist_model.pth'))
# model.eval() 是 PyTorch 等深度学习框架中的关键方法,用于将模型切换到 评估模式(Evaluation Mode),
# 直接影响模型中特定层的行为,确保模型在推理/测试阶段的表现稳定可靠。
# 禁用 Dropout 层
# 冻结 BatchNorm 层统计量
# 停止梯度计算(需配合 torch.no_grad() )
model.eval()
#inference by model
image =cv.imread("9_99.png",cv.IMREAD_GRAYSCALE)
cv.imshow('image',image)
img_f=np.float32(image)/255.0-0.5
img_f=img_f/0.5
img_f=np.reshape(img_f,(1,784))
pred_labels=model(t.from_numpy(img_f))
plabels=t.exp(pred_labels)
probs=list(plabels.detach().numpy()[0])
pred_labels=probs.index(max(probs))
print("predict num",pred_labels)
cv.waitKey(0)
cv.destroyWindows()