相关视频:
PyTorch 动态神经网络 (莫烦 Python 教学)
目录
一、导入库、设置超参数
若没有下载好MNIST数据集,则将DOWNLOAD设为True
若已经下载好MNIST数据集,则将DOWNLOAD设为False
二、下载、读取MNIST数据集
一张图片的尺寸为(1, 28, 28)。
第一次运行代码没有下载成功,第二次运行代码下载成功了,大概花了五分钟不到。
将保存路径设置为同一级路径下的data文件夹中(即./data),下载好的内容如下:
data
└─MNIST
├─processed
│ test.pt
│ training.pt
│
└─raw
t10k-images-idx3-ubyte
t10k-images-idx3-ubyte.gz
t10k-labels-idx1-ubyte
t10k-labels-idx1-ubyte.gz
train-images-idx3-ubyte
train-images-idx3-ubyte.gz
train-labels-idx1-ubyte
train-labels-idx1-ubyte.gz
三、DataLoader
四、读取测试集
五、设计、创建网络
1.设计网络
2.创建网络
有注释版本:
# 创建神经网络(有注释)
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.layer1 = nn.Sequential(
# (1, 28, 28)
nn.Conv2d(
in_channels=1, # 灰度图的通道数为1
out_channels=16, # 16个filter
kernel_size=5, # filter的边长为5
stride=1, # 步长为1
padding=2, # 因为filter的边长为5,所以padding设为(5-1)/2=2
),
# (16, 28, 28)
nn.ReLU(),
# (16, 28, 28)
nn.MaxPool2d(
kernel_size=2,
),
# (16, 14, 14)
)
self.layer2 = nn.Sequential(
# (16, 14, 14)
nn.Conv2d(16, 32, kernel_size=5, stride=1, padding=2),
# (32, 14, 14)
nn.ReLU(),
# (32, 14, 14)
nn.MaxPool2d(kernel_size=2)
# (32, 7, 7)
)
self.output_layer = nn.Linear(32*7*7, 10)
def forward(self, x):
# (batch, 1, 28, 28)
x = self.layer1(x)
# (batch, 16, 14, 14)
x = self.layer2(x)
# (batch, 32, 7, 7)
x = x.reshape(x.size(0), -1) # 将x展开为(batch, 32*7*7)
# (batch, 32*7*7)
output = self.output_layer(x)
# (batch, 10)
return output
无注释版本:
# 创建神经网络(无注释)
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.layer1 = nn.Sequential(
nn.Conv2d(1, 16, kernel_size=5, stride=1, padding=2),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2),
)
self.layer2 = nn.Sequential(
nn.Conv2d(16, 32, kernel_size=5, stride=1, padding=2),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2)
)
self.output_layer = nn.Linear(32*7*7, 10)
def forward(self, x):
x = self.layer1(x)
x = self.layer2(x)
x = x.reshape(x.size(0), -1)
output = self.output_layer(x)
return output
3.新建网络
可以使用torchsummary.summary查看网络的结构:
六、优化器、损失函数
七、准备测试集数据
八、训练神经网络
九、预测
十、完整代码
import torch
import torch.nn as nn
from torch.autograd import Variable
import torch.utils.data as Data
from torchvision import datasets, transforms
import matplotlib.pyplot as plt
from torchsummary import summary
# 创建神经网络(有注释)
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.layer1 = nn.Sequential(
# (1, 28, 28)
nn.Conv2d(
in_channels=1, # 灰度图的通道数为1
out_channels=16, # 16个filter
kernel_size=5, # filter的边长为5
stride=1, # 步长为1
padding=2, # 因为filter的边长为5,所以padding设为(5-1)/2=2
),
# (16, 28, 28)
nn.ReLU(),
# (16, 28, 28)
nn.MaxPool2d(
kernel_size=2,
),
# (16, 14, 14)
)
self.layer2 = nn.Sequential(
# (16, 14, 14)
nn.Conv2d(16, 32, kernel_size=5, stride=1, padding=2),
# (32, 14, 14)
nn.ReLU(),
# (32, 14, 14)
nn.MaxPool2d(kernel_size=2)
# (32, 7, 7)
)
self.output_layer = nn.Linear(32*7*7, 10)
def forward(self, x):
# (batch, 1, 28, 28)
x = self.layer1(x)
# (batch, 16, 14, 14)
x = self.layer2(x)
# (batch, 32, 7, 7)
x = x.reshape(x.size(0), -1) # 将x展开为(batch, 32*7*7)
# (batch, 32*7*7)
output = self.output_layer(x)
# (batch, 10)
return output
# # 创建神经网络(无注释)
# class CNN(nn.Module):
# def __init__(self):
# super(CNN, self).__init__()
# self.layer1 = nn.Sequential(
# nn.Conv2d(1, 16, kernel_size=5, stride=1, padding=2),
# nn.ReLU(),
# nn.MaxPool2d(kernel_size=2),
# )
# self.layer2 = nn.Sequential(
# nn.Conv2d(16, 32, kernel_size=5, stride=1, padding=2),
# nn.ReLU(),
# nn.MaxPool2d(kernel_size=2)
# )
# self.output_layer = nn.Linear(32*7*7, 10)
# def forward(self, x):
# x = self.layer1(x)
# x = self.layer2(x)
# x = x.reshape(x.size(0), -1)
# output = self.output_layer(x)
# return output
# 超参数
EPOCH = 2
BATCH_SIZE = 100
LR = 0.001
DOWNLOAD = False # 若已经下载mnist数据集则设为False
# 下载mnist数据
train_data = datasets.MNIST(
root='./data', # 保存路径
train=True, # True表示训练集,False表示测试集
transform=transforms.ToTensor(), # 将0~255压缩为0~1
download=DOWNLOAD
)
# 旧的写法
print(train_data.train_data.size())
print(train_data.train_labels.size())
# 新的写法
print(train_data.data.size())
print(train_data.targets.size())
# 打印部分数据集的图片
for i in range(2):
print(train_data.targets[i].item())
plt.imshow(train_data.data[i].numpy(), cmap='gray')
plt.show()
# DataLoader
train_loader = Data.DataLoader(
dataset=train_data,
batch_size=BATCH_SIZE,
shuffle=True,
num_workers=2
)
# 如果train_data下载好后,test_data也就下载好了
test_data = datasets.MNIST(
root='./data',
train=False
)
print(test_data.data.size())
print(test_data.targets.size())
# 新建网络
cnn = CNN()
print(cnn)
# 查看网络的结构
model = CNN()
if torch.cuda.is_available():
model.cuda()
summary(model, input_size=(1,28,28))
# 优化器
optimizer = torch.optim.Adam(cnn.parameters(), lr=LR)
# 损失函数
loss_func = nn.CrossEntropyLoss()
# 为了节约时间,只使用测试集的前2000个数据
test_x = Variable(
torch.unsqueeze(test_data.data, dim=1),
volatile=True
).type(torch.FloatTensor)[:2000]/255 # 将将0~255压缩为0~1
test_y = test_data.targets[:2000]
# # 使用所有的测试集
# test_x = Variable(
# torch.unsqueeze(test_data.test_data, dim=1),
# volatile=True
# ).type(torch.FloatTensor)/255 # 将将0~255压缩为0~1
# test_y = test_data.test_labels
# 训练神经网络
for epoch in range(EPOCH):
for step, (batch_x, batch_y) in enumerate(train_loader):
output = cnn(batch_x)
loss = loss_func(output, batch_y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 每隔50步输出一次信息
if step%50 == 0:
test_output = cnn(test_x)
predict_y = torch.max(test_output, 1)[1].data.squeeze()
accuracy = (predict_y == test_y).sum().item() / test_y.size(0)
print('Epoch', epoch, '|', 'Step', step, '|', 'Loss', loss.data.item(), '|', 'Test Accuracy', accuracy)
# 预测
test_output = cnn(test_x[:100])
predict_y = torch.max(test_output, 1)[1].data.numpy().squeeze()
real_y = test_y[:100].numpy()
print(predict_y)
print(real_y)
# 打印预测和实际结果
for i in range(10):
print('Predict', predict_y[i])
print('Real', real_y[i])
plt.imshow(test_data.data[i].numpy(), cmap='gray')
plt.show()