#基于pytorch的数字识别
#作者:申炜 2023.03
#所用库————用ALT+ENTER引入
import torchvision.datasets
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
from model_number import *
#GPU运行
device=torch.device('cuda' if torch.cuda.is_available() else 'cpu')
#准备数据集MNIST
train_data=torchvision.datasets.MNIST(root='./data', train=True,transform=torchvision.transforms.ToTensor(),download=True)
test_data=torchvision.datasets.MNIST(root='./data', train=False,transform=torchvision.transforms.ToTensor(),download=True)
#数据集长度
train_data_size=len(train_data)
test_data_size=len(test_data)
print('训练数据集的长度为:{},测试数据集的长度为:{}'.format(train_data_size,test_data_size))
#加载数据集
train_dataloader=DataLoader(train_data,batch_size=100,shuffle=True)
test_dataloader=DataLoader(test_data,batch_size=100,shuffle=True)
#深度学习网络
#图片大小为1*28*28,batch_size=100
import torch
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Sequential, Flatten, Linear, ReLU, Dropout, Softmax
class Shen(nn.Module):
def __init__(self):
super(Shen,self).__init__()
self.model=Sequential(
Conv2d(1,16,kernel_size=3,padding=1),#100*16*28*28
ReLU(),
Conv2d(16,16,kernel_size=3,padding=1),#100*16*28*28
ReLU(),
MaxPool2d(2),#100*16*14*14
Conv2d(16,32,kernel_size=3,padding=1),#100*32*14*14
ReLU(),
Conv2d(32,32,kernel_size=3,padding=2),#100*32*16*16
ReLU(),
MaxPool2d(2),#100*32*8*8
Conv2d(32,64,kernel_size=3,padding=1),#100*64*8*8
ReLU(),
Conv2d(64,64,kernel_size=3,padding=1),#100*64*8*8
ReLU(),
MaxPool2d(2),#100*64*4*4
Flatten(),
Linear(1024,50),#64*4*4
ReLU(),
Dropout(0.5),
Linear(50,10),
Dropout(0.5),
Softmax(-1)
)
def forward(self,x):
x=self.model(x)
return x
pass
if __name__=='__main__':
shen=Shen()
input=torch.ones((100,1,28,28))
output=shen(input)
print(output.shape)
#创建网络模型
shen=Shen()
shen.to(device)#GPU
#损失函数
loss_function=nn.CrossEntropyLoss()
loss_function.to(device)#GPU
#优化器
learning_rate=0.0005
optimizer=torch.optim.Adam(shen.parameters(),lr=learning_rate,betas=(0.9,0.99),eps=1e-8)
#设置网络参数
total_train_step=0
total_test_step=0
epoch=20
#可视化————用Tensorboard --logdir=logs_number --port=6007打开
writer=SummaryWriter('logs_number')
for i in range(epoch):
print('——————第{}轮训练开始——————'.format(i+1))
#训练步骤
shen.train()
for data in train_dataloader:
imgs,targets=data
imgs = imgs.to(device)#GPU
targets = targets.to(device)#GPU
output=shen(imgs)
loss=loss_function(output,targets)
#优化器
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_train_step += 1
if total_train_step % 100 == 0:
print('训练次数:{},Loss:{}'.format(total_train_step, loss.item()))
writer.add_scalar('train_loss', loss.item(), total_train_step)
pass
pass
#测试步骤
shen.eval()
total_test_loss=0
total_accuracy=0
with torch.no_grad():
for data in test_dataloader:
imgs,targets=data
imgs = imgs.to(device) # GPU
targets = targets.to(device) # GPU
output=shen(imgs)
loss=loss_function(output,targets)
total_test_loss += loss.item()
accuracy=(output.argmax(1)==targets).sum()
total_accuracy += accuracy
pass
pass
print('测试集上的Loss:{}'.format(total_test_loss))
print('测试集上的准确率:{:.4f}%'.format(total_accuracy/test_data_size*100))
writer.add_scalar('test_loss',total_test_loss,total_test_step)
writer.add_scalar('test_accuracy',total_accuracy/test_data_size,total_test_step)
total_test_step += 1
torch.save(shen,'shen_{}.pth'.format(i))
print('模型已保存!')
pass
writer.close()
#斋藤康毅所写的《深度学习入门》中的网络构架与b站up主小土堆的视频讲解的pytorch方法结合进行的一次练手
#所用数据集为MNIST
#困惑:发生了过拟合现象,与理论上99.38%的精度不符,最高只有98.60%的精度,loss函数到一定程度后不再下降