forked from ffzs/ml_pytorch
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ml_pytorch_cnn.py
134 lines (127 loc) · 4.84 KB
/
ml_pytorch_cnn.py
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
125
126
127
128
129
130
131
132
133
134
"""
ffzs
2018.1.11
win10
i7-6700HQ
gtx965m
"""
import torch
from torch import nn, optim # nn 神经网络模块 optim优化函数模块
from torch.utils.data import DataLoader
from torch.autograd import Variable
from torchvision import transforms, datasets
from visdom import Visdom # 可视化处理模块
import time
import numpy as np
# 可视化app
viz = Visdom()
# 超参数
BATCH_SIZE = 40
LR = 1e-3
EPOCHS = 2
# 判断是否使用gpu
USE_GPU = True
if USE_GPU:
gpu_status = torch.cuda.is_available()
else:
gpu_status = False
# 数据引入
train_dataset = datasets.MNIST('./mnist', True, transforms.ToTensor(), download=False)
test_dataset = datasets.MNIST('./mnist', False, transforms.ToTensor())
train_loader = DataLoader(train_dataset, BATCH_SIZE, True)
# 为加快测试,把测试数据从10000缩小到2000
test_data = torch.unsqueeze(test_dataset.test_data, 1)[:1500]
test_label = test_dataset.test_labels[:1500]
# visdom可视化部分数据
viz.images(test_data[:100], nrow=10)
# 为防止可视化视窗重叠现象,停顿0.1秒
time.sleep(0.5)
if gpu_status:
test_data = test_data.cuda()
test_data = Variable(test_data, volatile=True).float()
# 创建线图可视化窗口
line = viz.line(np.arange(10))
# 创建cnn神经网络
class CNN(nn.Module):
def __init__(self, in_dim, n_class):
super(CNN, self).__init__()
self.conv = nn.Sequential(
# channel 为信息高度 padding为图片留白 kernel_size 扫描模块size(5x5)
nn.Conv2d(in_channels=in_dim, out_channels=16,kernel_size=5,stride=1, padding=2),
nn.ReLU(),
# 平面缩减 28x28 >> 14*14
nn.MaxPool2d(kernel_size=2),
nn.Conv2d(16, 32, 3, 1, 1),
nn.ReLU(),
# 14x14 >> 7x7
nn.MaxPool2d(2)
)
self.fc = nn.Sequential(
nn.Linear(32*7*7, 120),
nn.Linear(120, n_class)
)
def forward(self, x):
out = self.conv(x)
out = out.view(out.size(0), -1)
out = self.fc(out)
return out
net = CNN(1,10)
if gpu_status :
net = net.cuda()
print("#"*26, "使用gpu", "#"*26)
else:
print("#" * 26, "使用cpu", "#" * 26)
# loss、optimizer 函数设置
loss_f = nn.CrossEntropyLoss()
optimizer = optim.Adam(net.parameters(), lr=LR)
# 起始时间设置
start_time = time.time()
# 可视化所需数据点
time_p, tr_acc, ts_acc, loss_p = [], [], [], []
# 创建可视化数据视窗
text = viz.text("<h1>convolution Nueral Network</h1>")
for epoch in range(EPOCHS):
# 由于分批次学习,输出loss为一批平均,需要累积or平均每个batch的loss,acc
sum_loss, sum_acc, sum_step = 0., 0., 0.
for i, (tx, ty) in enumerate(train_loader, 1):
if gpu_status:
tx, ty = tx.cuda(), ty.cuda()
tx = Variable(tx)
ty = Variable(ty)
out = net(tx)
loss = loss_f(out, ty)
sum_loss += loss.data[0]*len(ty)
pred_tr = torch.max(out,1)[1]
sum_acc += sum(pred_tr==ty).data[0]
sum_step += ty.size(0)
# 学习反馈
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 每40个batch可视化一下数据
if i % 40 == 0:
if gpu_status:
test_data = test_data.cuda()
test_out = net(test_data)
# 如果用gpu运行out数据为cuda格式需要.cpu()转化为cpu数据 在进行比较
pred_ts = torch.max(test_out, 1)[1].cpu().data.squeeze()
acc = sum(pred_ts==test_label)/float(test_label.size(0))
print("epoch: [{}/{}] | Loss: {:.4f} | TR_acc: {:.4f} | TS_acc: {:.4f} | Time: {:.1f}".format(epoch+1, EPOCHS,
sum_loss/sum_step, sum_acc/sum_step, acc, time.time()-start_time))
# 可视化部分
time_p.append(time.time()-start_time)
tr_acc.append(sum_acc/sum_step)
ts_acc.append(acc)
loss_p.append(sum_loss/sum_step)
viz.line(X=np.column_stack((np.array(time_p), np.array(time_p), np.array(time_p))),
Y=np.column_stack((np.array(loss_p), np.array(tr_acc), np.array(ts_acc))),
win=line,
opts=dict(legend=["Loss", "TRAIN_acc", "TEST_acc"]))
# visdom text 支持html语句
viz.text("<p style='color:red'>epoch:{}</p><br><p style='color:blue'>Loss:{:.4f}</p><br>"
"<p style='color:BlueViolet'>TRAIN_acc:{:.4f}</p><br><p style='color:orange'>TEST_acc:{:.4f}</p><br>"
"<p style='color:green'>Time:{:.2f}</p>".format(epoch, sum_loss/sum_step, sum_acc/sum_step, acc,
time.time()-start_time),
win=text)
sum_loss, sum_acc, sum_step = 0., 0., 0.
torch.save(net.state_dict(), 'save/cnn.pth')