【pytorch+全连接层】mnist分类问题【尽可能的高准确率,99%以上】 您所在的位置:网站首页 mnist数据集准确率099 【pytorch+全连接层】mnist分类问题【尽可能的高准确率,99%以上】

【pytorch+全连接层】mnist分类问题【尽可能的高准确率,99%以上】

2024-07-04 19:28| 来源: 网络整理| 查看: 265

要求

使用pytorch,使用全连接层,而不是用卷积层,要求有两层隐含层尽可能提高准确率本博客要求使用GPU,否则CPU可能需要半天时间才能运行出来结果要求下载CSV格式的mnist数据(可以在我上一篇博客里面下载)

写在前面:运用各种方法来尽可能提高准确率,对理解深度学习及其各种技巧有很大好处。

注意:全连接层也是可以将准确率训练到99%以上的,不要以为只有卷积层才可以。毕竟mnist是一个简单的数据集。

在上一篇博客中,我用纯python写了mnist的分类,在小心的调试参数之后,终于能够达到96左右的准确率。 但是速度有点慢,不利于调参,所以改变到这个pytorch和CUDA环境方便调参,也为了巩固自己所学的pytorch知识。 如果没有先自己尝试写反向传播,建议看上一篇博客,会比较清楚的告诉你,怎么去反向传播的。直接进行pytorch编程,会对某些概念不理解。

结果展示,最终结果也可以达到99%以上吧。在这里插入图片描述

这里,我也尝试分析一下参数的影响吧, 条件:要注意这些条件,基于这些条件我们才好分析。如果你理解这些条件的意义最好。 1)使用了sigmoid激活函数,这个激活函数有饱和值,饱和之后梯度就比较小。 2)就只使用全批次梯度下降的方式,不使用momentum等。虽然这个也有助于提高收敛速度。 3)不使用任何正规化方法,如batch normalization,以及L2正则。 评价指标:损失曲线,正确率曲线 影响因素: 1)隐含层数量 2)参数的初始化方式 3)输入值的统计值(均值和方差) 4)学习率

我们说说,设置的不合适会导致什么问题。 1)首先我们先说隐含层数量的影响。如果数量太大,我们知道 o u t = s i g m o i d ( w x + b ) out=sigmoid(wx+b) out=sigmoid(wx+b),在这里,wx+b就会比较大,(其他情况不变的情况下),因此就越有可能接近sigmoid函数的饱和值。这样在初期可能导致梯度较小,损失就难以降下去,要花很多时间在初始阶段,特别是学习率也比较小的时候。当然,隐层数量比较小,网络能力较差,这个大家都熟知,我就不分析了。 2)参数的初始化。第一,我们可以选择正态分布或者均匀分布。有两个方式需要注意:大小是否合适,是否是关于0对称的。如果初始化值比较大的话, o u t = s i g m o i d ( w x + b ) out=sigmoid(wx+b) out=sigmoid(wx+b),在这里,wx+b也就会比较大。也就越可能接近sigmoid的饱和区域,导致前期梯度较小。再来说是否关于0对称,或者说是否只有正值。假如使用均匀分布,且所有的值都大于0,你会碰到麻烦的。另外,你要使得参数的变化范围不能太小,假如你所有的参数都等于一个值或许也有很多麻烦。 3)实际上,我们需要联合参数的初始化和隐层数量,比如在同样的参数初始化环境下,不同隐层数量最好保证 w x + b wx+b wx+b的值都不会很大,常见的方法,可以将每一层参数除以每一个隐层的数量。 3)我这里不多解释对输入值需要进行怎样的处理了。 4)学习率设置不好的话,梯度的更新也可能比较大,可能导致刚开始损失不变。太大的话,导致后期一定的震荡。

改进版:增加BatchNorm1d. 结果瞬间好很多,可以看见batch normalization 对于提高训练速度有很大的帮助。 最终这个版本提供下载地址(jupyter版本,使用CUDA):下载地址 在这里插入图片描述

第一步:处理数据

import numpy as np import csv train = csv.reader(open('mnist_train.csv', 'r')) train_content = [] for line in train: train_content.append(line) test = csv.reader(open('mnist_test.csv', 'r')) test_content = [] for line in test: test_content.append(line) train_content = np.array(train_content, dtype=np.float32) test_content = np.array(test_content, dtype=np.float32) train_label = np.array(train_content[:, 0], dtype=np.int) train_x = train_content[:,1 :] test_label = np.array(test_content[:, 0], dtype=np.int) test_x = test_content[:, 1:] assert train_x.shape[1] == test_x.shape[1] print('Number of input is %d' % train_x.shape[1]) num_input = train_x.shape[1] train_x = (train_x - 255/2) / 255 test_x = (test_x - 255/2) / 255 import torch train_x = torch.from_numpy(train_x) train_label = torch.from_numpy(train_label)

第二步:建立模型框架

import torch import torch.nn as nn import torch.optim as optim import os os.environ['CUDA_VISIBLE_DEVICES'] = '0' class nn_XML(nn.Module): def __init__(self, num_in=784, num_out=10, hidden=[100, 30]): super().__init__() self.linear = nn.Sequential(nn.Linear(num_in, hidden[0], bias=True), nn.Sigmoid(), nn.Linear(hidden[0], hidden[1], bias=True), nn.Sigmoid(), nn.Linear(hidden[1], num_out, bias=True)) def forward(self, input): out = self.linear(input) return out def init_weight(m): name = m.__class__.__name__ if name.find('Linear') != -1: m.weight.data.normal_(0.01, 0.1) # 0.01这个参数需要注意 nn.init.constant_(m.bias.data, 0.0)

第三步:进行训练,训练前定义好优化器,损失函数

epoch = 50000 lr = 0.1 device = torch.device("cuda:0" if (torch.cuda.is_available()) else "cpu") model = nn_XML().to(device) model.apply(init_weight) # print(model) # print(device) creation = nn.CrossEntropyLoss() optimizer = optim.SGD(model.parameters(), lr=lr) for i in range(epoch): model.zero_grad() train_x = train_x.to(device) train_label = train_label.to(device) output = model(train_x) loss = creation(output, train_label) # 顺序不要反了,否则出错 loss.backward() loss_ = loss.mean().item() optimizer.step() if i % 300 == 0: predict = torch.argmax(output, dim=1) assert predict.size() == train_label.size() sum = 0.0 for j in range(predict.size()[0]): if int(predict[j]) == int(train_label[j]): sum += 1 print('Epoch: {:d}, Loss: {:0.5f}, Acc: {:0.3f}%'.format(i, loss_, sum / len(predict) * 100))


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有