导入必要的库
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets,transforms
print("Pytorch Vision: ",torch.__version__)
import numpy as np
import matplotlib.pyplot as plt
首先定义一个基于ConvNet的简单神经网络
```
class Net(nn.Module):
def __init__(self):
super(Net,self).__init__()
self.conv1=nn.Conv2d(1,20,5,1)
self.conv2=nn.Conv2d(20,50,5,1)
self.fc1=nn.Linear(4*4*50,500)
self.fc2=nn.Linear(500,10)
def forward(self,x):
x=F.relu(self.conv1(x))
x=F.max_pool2d(x,2,2)
x=F.relu(self.conv2(x))
x=F.max_pool2d(x,2,2)
x=x.view(-1,4*4*50) #相当于reshape,展平特征向量
x=F.relu(self.fc1(x))
x=self.fc2(x)
return F.log_softmax(x,dim=1) #得到概率值
```
模型使用类构建,需要定义一个forward方法 模型通过Sequential构建,不需要定义forward方法
读入数据测试
mnist_data=datasets.MNIST("./mnist_data",train=True,download=True,
transform=transforms.Compose([
transforms.ToTensor()
]))
plt.figure()
plt.imshow(mnist_data[0][0].view(28,28).numpy())
tensor转换numpy,使用numpy()方法 如果变量在cuda上,需要先转到cpu上再转为numpy格式,使用.cpu()方法 cuda-cpu-numpy转换
定义训练
def train(model,device,train_loader,optimizer,epoch):
model.train() #模型是训练模型
for idx,(data,target) in enumerate(train_loader): #idx代表第几个batch
data,target=data.to(device),target.to(device) #数据转移到cuda上
#前向传播,计算损失,损失函数采用了nll_loss函数
pred=model(data)
loss=F.nll_loss(pred,target)
#反向传播,梯度下降,这里选用SGD方法
optimizer.zero_grad()
loss.backward() #计算当前梯度
optimizer.step() #反向传递,梯度下降
if idx%100==0:
print("Train Epoch: {},iteration: {},Loss: {}".
format(epoch,idx,loss.item()))
print('train_size',idx)
定义测试
def test(model,device,test_loader,epoch):
model.eval()
total_loss=0
correct=0
with torch.no_grad(): #不计算梯度
for idx,(data,target) in enumerate(test_loader):
data,target=data.to(device),target.to(device)
output=model(data) #batch_size*10
total_loss+=F.nll_loss(output,target,reduction="sum").item() #单个数字的tensor变成纯数字
pred=output.argmax(dim=1) # batch_size*1
correct+=pred.eq(target.view_as(pred)).sum().item()
i=0
i=pred.eq(target.view_as(pred)).sum().item()/len(data)*100
if idx%100==0:
print("Test Epoch: {},iteration: {},Acc: {}".
format(epoch,idx,i))
print('--------------------------------------------')
print('test_size:',idx)
total_loss/=len(test_loader.dataset)
acc=correct/len(test_loader.dataset)*100
print("Test loss: {}.Accuracy: {}".format(total_loss,acc)) #format用法,前面设置好格式,后面输出数字,使用.隔开
print('********************************************')
数据读入
device=torch.device("cuda" if torch.cuda.is_available() else "cpu")
batch_size=32 #一个batch有32张图片
train_dataloader=torch.utils.data.DataLoader(
datasets.MNIST("./mnist_data", train=True, download=True,
transform=transforms.Compose([
transforms.ToTensor(),transforms.Normalize((0.1307,),(0.3081,))
])),
batch_size=batch_size,shuffle=True,
num_workers=1,pin_memory=True
)
test_dataloader=torch.utils.data.DataLoader(
datasets.MNIST("./mnist_data", train=False, download=True,
transform=transforms.Compose([
transforms.ToTensor(),transforms.Normalize((0.1307,),(0.3081,))
])),
batch_size=batch_size,shuffle=True,
num_workers=1,pin_memory=True
)
lr=0.01
momentum=0.5
model=Net().to(device)
optimizer=torch.optim.SGD(model.parameters(),lr=lr,momentum=momentum)
num_epochs=2
for epoch in range(num_epochs):
train(model,device,train_dataloader,optimizer,epoch)
test(model,device,test_dataloader,epoch)
#保存模型
torch.save(model.state_dict(),"fashion_mnist_cnn.pt")
epoch代表对整个训练集 循环的次数 batch,因为硬件限制,不可能整个训练集一口吃进去,所以将其分为batch口吃进去 batch_size,每一口吃多少个数据。比如,2000张图片,batch=4,那么batch_size=500,epoch=1。表示:2000张图片就使用一次,每次训练500张,分4次训练完成。 epoch、batch、batch_size的关系