首先我们下载数据集并查看数据集:
import os
#third-party library
import torch
import torch.nn as nn
from torch.autograd import Variable
import torch.utils.data as Data
import torchvision
import matplotlib.pyplot as plt
%matplotlib inline
torch.manual_seed(1) # reproducible
#Hyper Parameters
EPOCH = 5 # train the training data n times, to save time, we just train 1 epoch
BATCH_SIZE = 50
LR = 0.001 # learning rate
DOWNLOAD_MNIST = False
#Mnist digits dataset
train_data = torchvision.datasets.MNIST(
root='./mnist/',
train=True, # this is training data
transform=torchvision.transforms.ToTensor(), # Converts a PIL.Image or numpy.ndarray to
# torch.FloatTensor of shape (C x H x W) and normalize in the range [0.0, 1.0]
download=True,
)
#plot one example
print(train_data.train_data.size()) # (60000, 28, 28)
print(train_data.train_labels.size()) # (60000)
plt.imshow(train_data.train_data[0].numpy(), cmap='gray')
plt.title('%i' % train_data.train_labels[0])
plt.show()
网络定义如下:
import torch.nn.functional as F
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.conv1 = nn.Conv2d(1, 32, kernel_size=5)
self.conv2 = nn.Conv2d(32, 32, kernel_size=5)
self.conv3 = nn.Conv2d(32,64, kernel_size=5)
self.fc1 = nn.Linear(3*3*64, 256)
self.fc2 = nn.Linear(256, 10)
def forward(self, x):
x = F.relu(self.conv1(x))
#x = F.dropout(x, p=0.5, training=self.training)
x = F.relu(F.max_pool2d(self.conv2(x), 2))
x = F.dropout(x, p=0.5, training=self.training)
x = F.relu(F.max_pool2d(self.conv3(x),2))
x = F.dropout(x, p=0.5, training=self.training)
x = x.view(-1,3*3*64 )
x = F.relu(self.fc1(x))
x = F.dropout(x, training=self.training)
x = self.fc2(x)
return F.log_softmax(x, dim=1)
我将batch_size设置为50,即每50个数据作一次训练,epoch设置为5,即全部数据总共训练五次。
训练数据准备:
train_loader = Data.DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True)
训练:
net=CNN().cuda()
optimizer = torch.optim.Adam(net.parameters(), lr=LR) # optimize all cnn parameters
loss_func = nn.CrossEntropyLoss() # the target label is not one-hotted
def train_mnist(train_loader,net,optimizer,loss_func):
l_his = [] # 记录 training 时不同神经网络的 loss
acc_his = [] # 记录 training 时不同神经网络的 准确率
# training and testing
for epoch in range(5):
right_num=0
print("start!")
for step, (x, y) in enumerate(train_loader): # gives batch data, normalize x when iterate train_loader
v_x=Variable(x).cuda()
v_y=Variable(y).cuda()
out = net(v_x) #这里省略了 mo_net.forward()
loss = loss_func(out,v_y)
#--------------------用于预测对的个数-------------------------#
out_class=torch.max(out.data, 1)[1].data.squeeze()
right_num +=(out_class==v_y).sum().float() #分类对的数值,因为每次对50个数据处理,所以预测对的个数是加起来
#--------------------求预测对的个数结束-------------------------#
optimizer.zero_grad()
loss.backward()
optimizer.step()
if (step + 1) % 50 == 0:
l_his.append(loss.data[0])
acc_his.append(right_num/((step+1)*50))
if (step + 1) % 500 == 0:
print('epoch:{},step : {}, loss: {},precision{},right_num{}'.format(epoch+1,step +1, loss.data[0],right_num/((step+1)*50),right_num))
return l_his,acc_his,net
l_his,acc_his,net=train_mnist(train_loader,net,optimizer,loss_func)
x1=list(range(len(l_his)))
plt.plot(x1, l_his,c='red',label='loss')
plt.plot(x1, acc_his,c='blue',label='precision')
plt.legend()
test_data = torchvision.datasets.MNIST(root='./mnist/', train=False)
test_x = Variable(torch.unsqueeze(test_data.test_data, dim=1), volatile=True).type(torch.FloatTensor)[:2000]/255. # shape from (2000, 28, 28) to (2000, 1, 28, 28), value in range(0,1)
test_y = test_data.test_labels[:2000]
v_x_test=Variable(test_x).cuda()
v_y_test=Variable(test_y).cuda()
def test_mnist(v_x_test,v_y_test,net):
out_test=net(v_x_test)
loss_test = loss_func(out_test, v_y_test)
out_class=torch.max(out_test.data, 1)[1].data.squeeze() #将out矩阵中大于0的转化为1,小于0的转化为0,存入a中
right_num_test =(out_class==v_y_test).sum().float() #分类对的数值
precision_test=right_num_test/out_test.shape[0] #准确率
loss_test=loss_test.data[0]
print('loss_test:{},precision_test:{},right_num_test:{}'.format(loss_test,precision_test,right_num_test))
test_mnist(v_x_test,v_y_test,net)
结果: