1 import torch
2 import torchvision
3 import torch.nn as nn
4 import torch.utils.data as Data
5 import matplotlib.pyplot as plt
6 from torch.autograd import Variable
7
8 # 超参数定义
9 EPOCH = 5 #定义太大的话CPU计算时间会太长 train the training data n times
10 LR = 0.01
11 BATCH_SIZE = 50
12
13 DOWNLOAD_MNIST = True #没下载好的时候是True 下载好了改成 False
14
15 # 下载MNIST数据集
16 train_data = torchvision.datasets.MNIST(
17 root = './mnist/',
18 # 是否是训练数据
19 train = True,
20 # 数据变换(0, 255) -> (0, 1) 把下载的数据改成TENSOR
21 transform = torchvision.transforms.ToTensor(),
22 # 是否下载MNIST数据
23 download = DOWNLOAD_MNIST
24 )
25
26 test_data = torchvision.datasets.MNIST(
27 root = './mnist/',
28 # 是否是训练数据
29 train = False,
30 # 数据变换(0, 255) -> (0, 1)
31 transform = torchvision.transforms.ToTensor(),
32 # 是否下载MNIST数据
33 download = DOWNLOAD_MNIST
34 )
35 # 查看图像
36 plt.imshow(train_data.train_data[0].numpy(), cmap = 'gray')
37 plt.title('%i' % train_data.train_labels[0])
38 plt.show()
39
40 plt.imshow(test_data.test_data[0].numpy(), cmap = 'gray')
41 plt.title('%i' % test_data.test_labels[0])
42 plt.show()
43 # 数据加载
44 train_loader = Data.DataLoader(dataset = train_data, batch_size = BATCH_SIZE, shuffle = True, num_workers = 2)
45 #test_x = Variable(torch.unsqueeze(test_data.test_data,dim=1),volatile=True).type(torch.FloatTensor)[:2000]/255.
46 #test_y = test_data.test_lable[:2000] #测试只取了前两千个 为了节省时间 这里和莫烦视频里的不一样
47 test_loader = Data.DataLoader(dataset = test_data, batch_size = BATCH_SIZE, shuffle = False, num_workers = 1)
48
49
50
51 print(train_data.__len__)
52 print(test_data.__len__)
53 print(train_loader.__len__)
54 print(test_loader.__len__)
55
56
57 # 定义卷积神经网络 (重点)
58 class CNN(nn.Module):
59 def __init__(self):
60 super(CNN, self).__init__()
61 self.conv1 = nn.Sequential( #卷积层
62 nn.Conv2d( #(1,28,28) #卷积层相当于一个三维过滤器(有高度)(高度用来提取的特征属性)
63 in_channels = 1, #图片有多少个层 黑白图:1层 彩图:RGB 3层
64 out_channels = 16, #16个过滤器 同时提取16个特征
65 kernel_size = 5, #过滤器的大小 5*5
66 stride = 1, #每隔一步跳一下
67 padding = 2 #扫到边缘过滤器超出范围时,多加一圈为0的信息
68 #padding 的值的计算 if stride=1,padding=(kernel_size-1)/2=(5-1)/2=2
69 ),#-->(16,28,28)
70 nn.ReLU(), #-->(16,28,28) #神经网络
71 nn.MaxPool2d(kernel_size = 2)#池化层
72 #-->(16,14,14) #使用了一个2*2的过滤器,选择2*2区域中的最大值,相当于把原始图片裁剪了一下,
73 #换成长宽变小,高度不变
74 )
75 # conv1输出为(16, 14, 14)
76 self.conv2 = nn.Sequential(
77 nn.Conv2d(16, 32, 5, 1, 2), #-->(32,14,14)
78 nn.ReLU(), #-->(32,14,14)
79 nn.MaxPool2d(2) #-->(32,7,7)
80 #Pooling 有两种MaxPool2d,AvgPool2d(平均值) 一般选MAX的
81 )
82 # conv2输出为(32, 7, 7)
83 self.output = nn.Linear(32 * 7 * 7, 10)
84
85 def forward(self, x):
86 x = self.conv1(x)
87 x = self.conv2(x) #(batch,32,7,7) 考虑了batch
88 x = x.view(x.size(0), -1) #(batch,32*7*7)
89 prediction = self.output(x) #这样就有了上面的参数值
90 return prediction
91
92 cnn = CNN()
93 print (cnn)
94 # 定义优化器
95 optimizer = torch.optim.Adam(cnn.parameters(), lr = LR, betas= (0.9, 0.999))
96
97 # 定义损失函数
98 loss_func = nn.CrossEntropyLoss()
99
100 # 训练
101 for epoch in range(EPOCH):
102 for step, (x, y) in enumerate(train_loader):
103
104 # print('Epoch: ', epoch, 'Step: ', step)
105 x_var = Variable(x)
106 y_var = Variable(y)
107
108 prediction = cnn(x_var)
109 loss = loss_func(prediction, y_var)
110 # print(loss)
111
112 optimizer.zero_grad() # 清空上一步的残余更新参数值
113 loss.backward() # 误差反向传播, 计算参数更新值
114 optimizer.step() # 将参数更新值施加到 net 的 parameters 上
115
116 if step % 50 == 0:
117 correct = 0.0
118 for step_test, (test_x, test_y) in enumerate(test_loader):
119 # print(step_test)
120
121 test_x = Variable(test_x)
122 test_output = cnn(test_x)
123
124 pred_y = torch.max(test_output, 1)[1].data.squeeze()
125 correct += sum(pred_y == test_y)
126
127 accuracy = correct / test_data.test_data.size(0)
128 print ('epoch: ', epoch, '| train loss: %.4f' % loss.data, '| accuracy: ', accuracy)
129
130