携手创造,一起生长!这是我参加「日新方案 8 月更文挑战」的第6天,点击查看活动概况

原文链接

大家好,我是小寒。

咱们在上一篇文章共享了如何进行手写数字识别。

今天咱们运用 LeNet-5 (它是最早发布的卷积神经⽹络之⼀)来完成 Fashion-MNIST 服装图⽚的分类使命。

读取数据集

Fashion-MNIST 数据会集的图画是一个 28*28 的灰度图画。咱们经过 pytorch 的内置函数将 FashionMNIST 下载并读到内存中。

# 经过ToTensor实例将图画数据从PIL类型变换成32位浮点数格式,
# 并除以255使得所有像素的数值均在0到1之间
trans = transforms.ToTensor()
mnist_train = torchvision.datasets.FashionMNIST(
            root="../data", train=True, transform=trans, download=True)
mnist_test = torchvision.datasets.FashionMNIST(
            root="../data", train=False, transform=trans, download=True)

Fashion-MNIST 由10个类别的图画组成,每个类别由练习数据集(train dataset)中的6000张图画和测试数据集(test dataset)中的1000张图画组成。

len(mnist_train), len(mnist_test)
60000,10000

可视化数据集

咱们来显示看一下数据会集的图画样本是什么样的。

经过如下方法,咱们来可视化的展现练习会集前几个样本。

# 显示数据集
mnist_show = torchvision.datasets.FashionMNIST(root="../data", train=True, transform=torchvision.transforms.ToTensor(), download=True)
images, label = next(iter(data.DataLoader(mnist_show, 20, shuffle=True)))
images=images.reshape(20,28,28)
fig,axes = plt.subplots(2,10,figsize=(15,3))  
axes = axes.flatten()   
for i, (ax, img) in enumerate(zip(axes, images)):
    if torch.is_tensor(img):
        ax.imshow(img.numpy())
    else:
        # PIL图⽚
        ax.imshow(img)
plt.show()

深度学习案例分享 |  Fashion-MNIST 服装数据分类 - PyTorch 实现

LeNet-5 网络结构

整体来看,LeNet-5 由两个部分组成:

  • 两个卷积层。
  • 三个全衔接层。

深度学习案例分享 |  Fashion-MNIST 服装数据分类 - PyTorch 实现

每个卷积块中的根本单元是⼀个卷积层、⼀个 sigmoid 激活函数和平均会聚层。

每个卷积层使⽤ 5 5 卷积核和⼀个 sigmoid 激活函数。

第⼀卷积层有 6 个输出通道,⽽第⼆个卷积层有16个输出通道。

每个 2 2 的池操作(步幅2)经过空间下采样将维数削减4倍。卷积的输出形状由批量⼤⼩、通道数、⾼度、宽度决议。

为了将卷积块的输出传递给稠密块,咱们必须在⼩批量中展平每个样本。换⾔之,咱们将这个四维输⼊转化成全衔接层所希望的⼆维输⼊。这⾥的⼆维表⽰的第⼀个维度索引⼩批量中的样本,第⼆个维度给出每个样本的平⾯向量表⽰。

LeNet-5 的稠密块有三个全衔接层,别离有120、84和10个输出。因为咱们在执⾏分类使命,所以输出层的10维对应于最终输出结果的数量。

下面咱们看一下网络结构的界说。

net = nn.Sequential(
        nn.Conv2d(1, 6, kernel_size=5, padding=2), 
        nn.Sigmoid(),
        nn.AvgPool2d(kernel_size=2, stride=2),
        nn.Conv2d(6, 16, kernel_size=5), 
        nn.Sigmoid(),
        nn.AvgPool2d(kernel_size=2, stride=2),
        nn.Flatten(),
        nn.Linear(16 * 5 * 5, 120), 
        nn.Sigmoid(),
        nn.Linear(120, 84), 
        nn.Sigmoid(),
        nn.Linear(84, 10))

深度学习案例分享 |  Fashion-MNIST 服装数据分类 - PyTorch 实现

X = torch.rand(size=(1, 1, 28, 28), dtype=torch.float32)
for layer in net:
    X = layer(X)
    print(layer.__class__.__name__, 'output shape: \t', X.shape)

输出如下所示:

Conv2d output shape: 	 torch.Size([1, 6, 28, 28])
Sigmoid output shape: 	 torch.Size([1, 6, 28, 28])
AvgPool2d output shape: 	 torch.Size([1, 6, 14, 14])
Conv2d output shape: 	 torch.Size([1, 16, 10, 10])
Sigmoid output shape: 	 torch.Size([1, 16, 10, 10])
AvgPool2d output shape: 	 torch.Size([1, 16, 5, 5])
Flatten output shape: 	 torch.Size([1, 400])
Linear output shape: 	 torch.Size([1, 120])
Sigmoid output shape: 	 torch.Size([1, 120])
Linear output shape: 	 torch.Size([1, 84])
Sigmoid output shape: 	 torch.Size([1, 84])
Linear output shape: 	 torch.Size([1, 10])

初始化模型参数

这里咱们运用 Xavier 来进行参数的初始化。

def init_weights(m):
    if type(m) == nn.Linear or type(m) == nn.Conv2d:
        nn.init.xavier_uniform_(m.weight)
net.apply(init_weights)

界说丢失函数和优化器

#穿插熵作为丢失函数
loss = nn.CrossEntropyLoss()
#界说优化器
optimizer = torch.optim.SGD(net.parameters(), lr=0.1)

练习及预测

让咱们看看 LeNet-5 在 Fashion-MNIST 数据集上的表现吧。

def train_ch6(net, train_iter, test_iter, num_epochs, lr, device):
    """⽤GPU练习模型"""
    #初始化权重
    def init_weights(m):
        if type(m) == nn.Linear or type(m) == nn.Conv2d:
            nn.init.xavier_uniform_(m.weight)
    net.apply(init_weights)
    print('training on', device)
    #net复制到相应的设备上
    net.to(device)
    #界说优化器
    optimizer = torch.optim.SGD(net.parameters(), lr=lr)
    #穿插熵作为丢失函数
    loss = nn.CrossEntropyLoss()
    num_batches = len(train_iter)
    train_loss=[]
    train_accs=[]
    starttime = datetime.datetime.now()
    for epoch in range(num_epochs):
        #练习丢失之和,练习正确数之和,样本数
        metric = Accumulator(3)
        net.train()
        for i, (X, y) in enumerate(train_iter):
            optimizer.zero_grad()
            X, y = X.to(device), y.to(device)
            y_hat = net(X)
            l = loss(y_hat, y)
            l.backward()
            optimizer.step()
            with torch.no_grad():
                metric.add(l * X.shape[0], accuracy(y_hat, y), X.shape[0])
            #练习丢失、练习正确率
            train_l = metric[0] / metric[2]
            train_acc = metric[1] / metric[2]
        train_loss.append(train_l)
        train_accs.append(train_acc)
        print(f'ecoch {epoch+1}, loss {train_l:.3f}, train acc {train_acc:.3f}')
    endtime = datetime.datetime.now()
    time_second= (endtime - starttime).seconds
    print(f'总耗时 {time_second}')
    show_image(num_epochs, train_loss, train_accs)
    test_acc = evaluate_accuracy_gpu(net, test_iter)
    print(f'test acc {test_acc:.3f}')
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print(device)
lr, num_epochs = 0.5, 50
train_ch6(net, train_iter, test_iter, num_epochs, lr, device)

咱们在 GPU 上进行 50 轮的迭代练习,测试集的正确率能够达到89%。

cuda:0
training on cuda:0
ecoch 1, loss 2.320, train acc 0.100
ecoch 2, loss 2.079, train acc 0.219
ecoch 3, loss 1.058, train acc 0.589
ecoch 4, loss 0.859, train acc 0.670
ecoch 5, loss 0.751, train acc 0.709
ecoch 6, loss 0.691, train acc 0.729
ecoch 7, loss 0.648, train acc 0.746
ecoch 8, loss 0.611, train acc 0.762
ecoch 9, loss 0.581, train acc 0.777
ecoch 10, loss 0.556, train acc 0.786
ecoch 11, loss 0.531, train acc 0.797
ecoch 12, loss 0.510, train acc 0.806
ecoch 13, loss 0.491, train acc 0.815
ecoch 14, loss 0.478, train acc 0.821
ecoch 15, loss 0.463, train acc 0.827
ecoch 16, loss 0.452, train acc 0.832
ecoch 17, loss 0.441, train acc 0.837
ecoch 18, loss 0.434, train acc 0.839
ecoch 19, loss 0.425, train acc 0.843
ecoch 20, loss 0.420, train acc 0.845
ecoch 21, loss 0.408, train acc 0.851
ecoch 22, loss 0.403, train acc 0.851
ecoch 23, loss 0.396, train acc 0.855
...
ecoch 48, loss 0.303, train acc 0.888
ecoch 49, loss 0.305, train acc 0.886
ecoch 50, loss 0.300, train acc 0.889
总耗时 378
test acc 0.890

深度学习案例分享 |  Fashion-MNIST 服装数据分类 - PyTorch 实现