pytorch入门笔记05

  1. 1. pytorch实现CNN
  2. 2. 测试训练结果

pytorch实现CNN

这部分是根据深度学习入门里面的简单的卷积网络CNN写的。写了之后会发现pytorch真香

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
import numpy as np
import matplotlib.pyplot as plt
import torch.utils.data as Data
import torchvision
import torchvision.transforms as transforms
import time

# 超参
batch_size = 100
learning_rate = 0.01
momentum = 0.9
epoch_loop = 10

############数据加载#############
transform = transforms.Compose(
[transforms.ToTensor(), # ToTensor方法作用是0-255的值变换为0-1之间
transforms.Normalize((0.1307,), (0.3081,))] # Normalize的作用是把0-1转为(-1,1)之间。image = (image - mean) / std
)
trainSet = torchvision.datasets.MNIST(
root='./mnist',
train=True,
download=True,
transform=transform
)
trainLoader = Data.DataLoader(trainSet,
batch_size=batch_size,
shuffle=True,
num_workers=0)
testSet = torchvision.datasets.MNIST(
root='./mnist',
train=False,
download=True,
transform=transform
)
testLoader = Data.DataLoader(testSet,
batch_size=batch_size,
shuffle=True,
num_workers=0)
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')


def imshow(img):
img = img / 2 + 0.5
npimg = img.numpy()
plt.imshow(np.transpose(npimg, (1, 2, 0)))
plt.show()

# images, labels = next(iter(trainLoader))
# img = torchvision.utils.make_grid(images) #将若干张图片拼成一张图
# imshow(img)
###########网络############
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1,1,5)
self.pool = nn.MaxPool2d(2,2)
self.fc1 = nn.Linear(144,100)
self.fc2 = nn.Linear(100,10)

def forward(self, x):
x = self.conv1(x)
x = F.relu(x)
x = self.pool(x)
x = x.view(batch_size, -1)
x = self.fc1(x)
x = F.relu(x)
x = self.fc2(x)
return x

net = Net()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=learning_rate, momentum=0.9)
net.to(device) # 网络扔到GPU中
startTime = time.time()
for epoch in range(epoch_loop):
running_loss = 0.0
for step, data in enumerate(trainLoader):
inputs, labels = data[0].to(device), data[1].to(device)
# inputs, labels = data
optimizer.zero_grad()

outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()

running_loss += loss.item()
if step % 200 == 199:
print('[%d, %5d] loss: %.3f' % (epoch + 1, step + 1, running_loss / 2000))
running_loss = 0.0

# 每个Epoch之后检查一下精度
test_acc = 0
test_count = 0
train_acc = 0
train_count = 0
with torch.no_grad():
for data in iter(testLoader):
images, labels = data[0].to(device), data[1].to(device) # 转GPU Tensor
# images, labels = data # 喂CPU Tensor
outputs = net(images)
_, predictions = torch.max(outputs, 1)
test_acc += torch.sum(predictions == labels)
test_count += len(labels)
for data in iter(trainLoader):
images, labels = data[0].to(device), data[1].to(device)
# images, labels = data
outputs = net(images)
_, predictions = torch.max(outputs, 1)
train_acc += torch.sum(predictions == labels)
train_count += len(labels)

test_acc = float(test_acc) / test_count
train_acc = float(train_acc) / train_count
print(f'Epoch step: {epoch + 1} | train acc: {train_acc} | test acc: {test_acc}')
endTime = time.time()
print("用时:", (endTime - startTime))
# 保存网络
torch.save(net, "mnistCNNTrain.pkl")
torch.save(net.state_dict(), "mnistCNNTrainDict.pth")

需要注意的点:就是官网说过的,想用GPU跑的话,需要将网络放到GPU中,还有数据也要放到GPU中。就是训练时候的inputs和labels。否则会报错,网络是GPU但是给的数据是CPU Tensor,是常见错误。

下面是对比CPU和GPU训练MNIST训练集速度。

CPU耗时

GPU耗时

测试训练结果

用的Opencv对自己画的图像进行处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import cv2 as cv
import numpy as np
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
import torch
import os, sys

sys.path.append(os.pardir)


loadPic = []
ans = []
batch_size = 100


class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 1, 5)
self.pool = nn.MaxPool2d(2, 2)
self.fc1 = nn.Linear(144, 100)
self.fc2 = nn.Linear(100, 10)

def forward(self, x):
x = self.conv1(x)
x = F.relu(x)
x = self.pool(x)
x = x.view(1, -1)
x = self.fc1(x)
x = F.relu(x)
x = self.fc2(x)
return x


net = Net()
net.load_state_dict(torch.load("mnistCNNTrainDict.pth"))
for picitem in range(11):
src = cv.imread('../pic' + str(picitem) + '.jpg')
if src is None:
print("读取失败")
break
dst = cv.cvtColor(src, cv.COLOR_RGB2GRAY)
ret, dst = cv.threshold(src, 127, 255, cv.THRESH_BINARY_INV)
cv.imshow('pic' + str(picitem), dst)
b, g, r = cv.split(dst)
a = np.array(b) / 255
a = (a - 0.1307) / 0.3081
test = torch.FloatTensor(a)
test = test.view(1, 1, 28, 28)
out = net(test)
predict = torch.max(out, 1)
ans.append(predict[1].item())
print(ans)

cv.waitKey(0)
cv.destroyAllWindows()

效果: