-
Notifications
You must be signed in to change notification settings - Fork 0
/
ex_09.py
127 lines (96 loc) · 3.74 KB
/
ex_09.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
# 利用MNIST 手写数字识别数据集 实现一个完善的 多分类任务的 全连接神经网络
# 不需要划分 validation_set ,直接有一个test_dataset 可以测试准确率
# 我的实验结果准确率达到了了97%,与老师的实验结果相符合
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
import numpy as np
import random
from torch.utils.data import Dataset, DataLoader
from torchvision import datasets, transforms
# 初始化并固定随机种子
def setup_seed(seed):
torch.manual_seed(seed)
torch.cuda.manual_seed_all(seed)
np.random.seed(seed)
random.seed(seed)
torch.backends.cudnn.deterministic = True
setup_seed(1012)
# prepare dataset
batch_size = 64
transform = transforms.Compose(
[transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))])
# 处理图像数据的一个转换类 将pillow类转化为tensor, 并将值归一化: 0.1307 和 0.3081 为该数据集的均值和标准差
train_dataset = datasets.MNIST(
root='./dataset/mnist/', train=True, download=True, transform=transform)
train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size)
test_dataset = datasets.MNIST(
root='./dataset/mnist/', train=False, download=True, transform=transform)
test_loader = DataLoader(test_dataset, shuffle=False,
batch_size=len(test_dataset)) # 测试肯定是
# 此时dataset中的每一个元素仍然是一个28*28的矩阵,若使用全连接神经网络线性层,需要将其转化为[1,28*28(784)]的形状
# design model
class Net(nn.Module):
def __init__(self) -> None:
super(Net, self).__init__()
self.l1 = nn.Linear(784, 512)
self.l2 = nn.Linear(512, 256)
self.l3 = nn.Linear(256, 128)
self.l4 = nn.Linear(128, 64)
self.l5 = nn.Linear(64, 10)
self.layers = nn.Sequential(
self.l1,
nn.ReLU(),
self.l2,
nn.ReLU(),
self.l3,
nn.ReLU(),
self.l4,
nn.ReLU(),
self.l5
# 最后一层softmax之后会自动接在损失函数之上
)
def forward(self, x):
x = x.view(-1, 784) # 把minibatch reshape to [N, 784], 784是每个图像的特征维度
return self.layers(x)
model = Net()
# construct loss and optimiter
# 包含了softmax层,并且会根据标签类别(即使是多类),自动构建one-hot计算交叉熵,需要LongTensor类标签
criterion = nn.CrossEntropyLoss(reduction='mean')
optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
# training and test
loss_list = []
accuracy_list = []
def train(epoch):
'''某一轮epoch上的训练'''
epoch_loss = [] # 记录该轮epoch上每个batch的loss
for batch_idx, batch_data in enumerate(train_loader, 1):
X, y_label = batch_data
y_pred = model(X)
loss = criterion(y_pred, y_label)
epoch_loss.append(loss.item())
optimizer.zero_grad()
loss.backward()
optimizer.step()
average_loss = sum(epoch_loss)/len(epoch_loss)
loss_list.append(average_loss)
print(f'[epoch]:{epoch}, [average_loss]: {average_loss}')
def test():
'''在全集合上测试一次准确率'''
correct_num = 0
num = len(test_dataset)
with torch.no_grad():
for batch_data in test_loader:
X, y = batch_data
y_pred = model(X)
y_pred = torch.argmax(y_pred, dim=1)
correct_num += torch.sum(y_pred == y).item()
accuracy = correct_num/num
accuracy_list.append(accuracy)
print(f'Current accuracy on the test set is {accuracy}')
# start training now!
num_epochs = 10
for epoch in range(1, num_epochs+1):
train(epoch)
test()