在学习GANs的时候遇到一篇论文DCGANs,说是其中用到了卷积神经网络。
所以,就抽空学习一下,结果,真没想到有那么多的坑。
第一步配置数据的时候就贼坑了。。。
import torch
import torch.nn as nn
import torchvision
import torch.utils.data as Data
DOWNLOAD_MNIST = True # 已经下载好的话,会自动跳过的
# Mnist 手写数字
train_data = torchvision.datasets.MNIST(
root='./mnist/', # 保存或者提取位置
train=True, # this is training data
transform=torchvision.transforms.ToTensor(), # 转换 PIL.Image or numpy.ndarray 成
# torch.FloatTensor (C x H x W), 训练的时候 normalize 成 [0.0, 1.0] 区间
download=DOWNLOAD_MNIST, # 没下载就下载, 下载了就不用再下了
)
test_data = torchvision.datasets.MNIST(
root='./mnist/',
train=False
)
BATCH_SIZE
设置为了50,所以,也有1200次的训练了。所以,只用一次就好了。BATCH_SIZE
就是每一次训练的那个块中的数据数量LR
学习率这些参数在建立GANs的时候也用到了。
# Hyper Parameters
EPOCH = 1 # 训练整批数据多少次, 为了节约时间, 我们只训练一次
BATCH_SIZE = 50
LR = 0.001 # 学习率
# 训练集丢BATCH_SIZE个, 图片大小为28*28
train_loader = Data.DataLoader(
dataset=train_data,
batch_size=BATCH_SIZE,
shuffle=True # 是否打乱顺序
)
其实这里调用出来是没有什么用,但是任然放出来了,主要是为了跟学习的一份代码中保持一致性。找bug的时候,这样很方便。
但是这里有一个重点(对于新手)
torch.unsqueeze()
函数,给数组加上一个维度。dim=1表示在添加的这个维度是再哪?dim=1
时候(10,20)
变成了(10,1,20)
# test_data为 [10000, 28, 28]这样的一个数组,这里就只截取一段就好了
test_x = torch.unsqueeze(test_data.test_data, dim=1).type(torch.FloatTensor)
test_y = test_data.test_labels
nn.Module
非常常见的自定义类,所有模型的基类如果真的是新手的话,会发下这里贼多知识点。
.view(shape(0),-1)
这样的方式,将数据展开为一个一维向量。之后,再通过一个线性函数,转成10个线性函数的结果来。(表示对应10个数字的概率(其实可能是负数的,但是会逐渐的改善,大致上能拟合出结果来))class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.layer1 = nn.Sequential(
# (1, 28, 28)
nn.Conv2d(
in_channels=1,
out_channels=16,
kernel_size=5, # 卷积filter, 移动块长
stride=1, # filter的每次移动步长
padding=2,
groups=1
),
# (16, 28, 38)
nn.ReLU(),
nn.MaxPool2d(kernel_size=2)
# (16, 14, 14)
)
self.layer2 = nn.Sequential(
nn.Conv2d(
in_channels=16,
out_channels=32,
kernel_size=5,
stride=1,
padding=2
),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2)
)
self.layer3 = nn.Linear(32 * 7 * 7, 10)
def forward(self, x):
# print(x.shape)
x = self.layer1(x)
# print(x.shape)
x = self.layer2(x)
# print(x.shape)
x = x.view(x.size(0), -1)
# print(x.shape)
x = self.layer3(x)
# print(x.shape)
return x
cnn = CNN()
optimizer = torch.optim.Adam(cnn.parameters(), lr=LR)
loss_function = nn.CrossEntropyLoss()
for epoch in range(EPOCH):
for step, (b_x, b_y) in enumerate(train_loader):
output = cnn(b_x)
loss = loss_function(output, b_y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
print('finished training')
test_out = cnn(test_x)
predict_y = torch.argmax(test_out, 1).data.numpy()
print('Accuracy in Test : %.4f%%' % (sum(predict_y == test_y.data.numpy()) * 100/ len(predict_y)))
我这里跑的一个结果是
finished training
Accuracy in Test : 98.2000%
然后速度其实是有点慢的。之后会再看看其他的实现。
import torch
import torch.nn as nn
import torchvision
import torch.utils.data as Data
# Hyper Parameters
EPOCH = 1 # 训练整批数据多少次, 为了节约时间, 我们只训练一次
BATCH_SIZE = 50
LR = 0.001 # 学习率
DOWNLOAD_MNIST = True # 已经下载好的话,会自动跳过的
# Mnist 手写数字
train_data = torchvision.datasets.MNIST(
root='./mnist/', # 保存或者提取位置
train=True, # this is training data
transform=torchvision.transforms.ToTensor(), # 转换 PIL.Image or numpy.ndarray 成
# torch.FloatTensor (C x H x W), 训练的时候 normalize 成 [0.0, 1.0] 区间
download=DOWNLOAD_MNIST, # 没下载就下载, 下载了就不用再下了
)
test_data = torchvision.datasets.MNIST(
root='./mnist/',
train=False
)
# 训练集丢BATCH_SIZE个, 图片大小为28*28
train_loader = Data.DataLoader(
dataset=train_data,
batch_size=BATCH_SIZE,
shuffle=True # 是否打乱顺序
)
# test_data为 [10000, 28, 28]这样的一个数组,这里就只截取一段就好了
test_x = torch.unsqueeze(test_data.test_data, dim=1).type(torch.FloatTensor)
test_y = test_data.test_labels
# cnn
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.layer1 = nn.Sequential(
# (1, 28, 28)
nn.Conv2d(
in_channels=1,
out_channels=16,
kernel_size=5, # 卷积filter, 移动块长
stride=1, # filter的每次移动步长
padding=2,
groups=1
),
# (16, 28, 38)
nn.ReLU(),
nn.MaxPool2d(kernel_size=2)
# (16, 14, 14)
)
self.layer2 = nn.Sequential(
nn.Conv2d(
in_channels=16,
out_channels=32,
kernel_size=5,
stride=1,
padding=2
),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2)
)
self.layer3 = nn.Linear(32 * 7 * 7, 10)
def forward(self, x):
# print(x.shape)
x = self.layer1(x)
# print(x.shape)
x = self.layer2(x)
# print(x.shape)
x = x.view(x.size(0), -1)
# print(x.shape)
x = self.layer3(x)
# print(x.shape)
return x
cnn = CNN()
optimizer = torch.optim.Adam(cnn.parameters(), lr=LR)
loss_function = nn.CrossEntropyLoss()
for epoch in range(EPOCH):
for step, (b_x, b_y) in enumerate(train_loader):
output = cnn(b_x)
loss = loss_function(output, b_y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
print('finished training')
test_out = cnn(test_x)
predict_y = torch.argmax(test_out, 1).data.numpy()
print('Accuracy in Test : %.4f%%' % (sum(predict_y == test_y.data.numpy()) * 100/ len(predict_y)))