PyTorch实践系列(一):MNIST 手写体分类

写在开头:其实我现在还不太懂PyTorch的过多操作,因为是先上手一个项目,那我就尽量将这个项目讲明白,讲不明白的我会在学习一段时间之后回来进行补充。

内容安排

       本次内容我们通过使用PyTorch来进行MNIST手写体分类的一个CNN训练,因为今天花费了一些时间来安装这个PyTorch和TensorFlow,于是兴奋的开始了第一个项目,我们将一边运行代码一边解释的模式进行,在必要部分我们将认真的讲解一下。

开始上手

1.加载包
       首先需要加载torch和torchvision包因为涉及到可视化在后面,顺便我们通过torch.__version__来查看一下我们的PyTorch的一个版本,

import torch
import torchvision
torch.__version__
'1.2.0+cu92'

       这里我们是一个1.2.0版的,其实版本有点之前了,但能正常运行我已经很欣慰了,细节后面再继续补充。
2.参数设置

#重要参数
n_epochs = 3 #迭代轮数
batch_size_train = 64 #训练集规模
batch_size_test = 1000 #测试集规模
learning_rate = 0.01 #学习率

#一般参数
momentum = 0.5 #动量系数
log_interval = 10 #控制可视化输出间隔

random_seed = 1 
#是否使用非确定性算法,True时会自动寻找适合当前的高效算法。
torch.backends.cudnn.enabled = False 
torch.manual_seed(random_seed) #设置随机种子

首先来对上面的参数分别进行讨论与分析,
参数1:n_epochs
       就是所谓的迭代轮数,也可以理解为整个卷积要轮回的次数,关于一些基本概念的说明可以点击这里查看。

Q1:为什么需要n_epochs多次轮回?
       不是使用k折交叉验证就能得到较好的参数了吗?我们可以简单的理解为如果只进行一次训练,可能尚未寻找到最优解就停止了迭代,也就是对于权重 w = w + Δ w ( t ) w=w+\Delta w(t) w=w+Δw(t)的更新还达到最终的值,因此需要多次的轮回来保证对训练数据的完整性。可以点击这里查看参考文献。

Q2:如果n_epochs次数过大导致过拟合怎么办?
       为了防止过拟合,我们常用的有Early stopping、数据增强、正则化、Dropout等方法。点击这里查看参考文献。
1)Early stopping:提前停止epochs迭代,来防止过拟合,一般的当验证集精确度连续10次Epoch没有达到最佳时,便认为精度不会不再提高,于是停止迭代。一般n_epochs取10、20、30…;
2)数据增强:也就是扩展训练集,常用方法:采集更多数据、在原数据加上随机噪声、bootstrap重采样(随机森林)、利用数据分布估计产生该分布更多数据
3)正则化:在损失函数上加上正则式,使得在优化时考虑其他影响因素的代价,常见的有L1正则与L2正则,形式就跟lasso回归与岭回归相似。L1正则对稀疏数据更友好,L2的稳定性更好,点击这里查看L1与L2正则差异。
4)Dropout:与正则不同的是,正则通过在损失函数上进行控制,而Dropout通过修改神经网络本身结构进行控制,通过随机删除隐藏层的神经元个数,来控制过拟合。(参考《deep learning》)

参数2:batch
       我们在训练网络时不时直接将全部样本丢进学习器进行迭代,因为这样的收敛很慢,而且并不能降低标准差,还会每次迭代很长的时间。于是我们就是用一般常说的mini-batch采用小批量的数据集来一次次的进行迭代训练得到更好的收敛结果?

Q1:为什么mini-batch收敛结果会更好?
       我们这个地方需要知道神经网络的损失loss是一个非凸的,拥有多个局部最优点,而且很有可能是鞍点,鞍点和局部最优点的区别在于,就是鞍点是一阶导数为0二阶导至少一个方向小于0,而局部最优点是二阶导均小于0。这也就以为这鞍点还不是最棒的点,点击这里查看鞍点与局部最优点区别。
       那么如果收敛到了鞍点会产生一种已经收敛的假象,传统最优化算法无法自动避开局部最优点,那么mini-batch如何做到的呢?可以简单的理解为,对于一阶优化算法(SGD、Adagrad、Adam)小批量数据会有一个很大的方差,而这个大方差能够帮助我们跳过鞍点有机会寻找到更优的点。但是对于二阶的优化算法似乎需要大批量的数据,点击这里查看参考文献。
       其实与其担心如何跳出局部最优点,其实可以使用batch normalization的方法,对每次输入之前的数据进行处理,这个方法在实践中能够极高的提高搜索能力。(参考Batch Normalization.,2015. Ioffe, S. and Szegedy, C. )

Q2:如何选择batch的规模
在实际工程中一般size设置为几十到几百,一般对于GPU选择2的次方的batch可以更好的发挥性能。所以一般选择32、64、256。

参数3:momentum
       这里的momentum指的是SGD的动量方法的系数,动量学习法是和SGD一起使用的非常流行的技术,利用物理动量的概念来对梯度下降进行优化,这里简单的说一下动量学习法。点击这里可以查看动量学习法参看文献。

Q1:什么是动量学习法?
       通过对物理学中进行定义,我们用变量v表示速度,表明参数在参数空间移动的方向即速率,而损失函数的负梯度表示参数在参数空间移动的力,力有大小有方向,并且速度可以累积,我们可以把权值理解为速度,力能够改变加速度,加速度进而影响速度。根据牛顿定律,动量等于质量乘以速度,而在动量学习中,我们假设质量的单位为1,因此速度v就可以直接当动量,同时引入超参数 β \beta β(也就是这里的momentum参数),其取值范围为0-1,用于调节先前梯度(力)的衰减效果,关于具体的实现算法(在一个训练周期中)如下,
Step1.随机采样m条数据(mini-batch): ( x 1 , y 1 ) , ( x 2 , y 2 ) . . . , ( x m , y m ) {(x^1,y^1),(x^2,y^2)...,(x^m,y^m)} (x1,y1),(x2,y2)...,(xm,ym);
Step2.计算采样数据平均损失梯度: Δ w = 1 / m × ∑ j = 1 m ∂ L ( y j , f ( x j ; w ) ) ∂ w \Delta w=1/m\times \sum_{j=1}^{m}{\frac{\partial L(y^j,f(x^j;w))}{\partial w}} Δw=1/m×

  • 17
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
对于手写体数字识别MNIST问题,您可以使用PyTorch来实现。以下是一个简单的代码示例: 首先,导入所需的库: ``` import torch import torch.nn as nn import torchvision import torchvision.transforms as transforms ``` 接下来,定义超参数: ``` input_size = 784 hidden_size = 100 num_classes = 10 num_epochs = 5 batch_size = 100 learning_rate = 0.001 ``` 然后,加载并预处理数据集: ``` train_dataset = torchvision.datasets.MNIST(root='./data', train=True, transform=transforms.ToTensor(), download=True) test_dataset = torchvision.datasets.MNIST(root='./data', train=False, transform=transforms.ToTensor()) train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True) test_loader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False) ``` 定义神经网络模型: ``` class NeuralNet(nn.Module): def __init__(self, input_size, hidden_size, num_classes): super(NeuralNet, self).__init__() self.fc1 = nn.Linear(input_size, hidden_size) self.relu = nn.ReLU() self.fc2 = nn.Linear(hidden_size, num_classes) def forward(self, x): out = self.fc1(x) out = self.relu(out) out = self.fc2(out) return out model = NeuralNet(input_size, hidden_size, num_classes) ``` 定义损失函数和优化器: ``` criterion = nn.CrossEntropyLoss() optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate) ``` 训练模型: ``` total_step = len(train_loader) for epoch in range(num_epochs): for i, (images, labels) in enumerate(train_loader): images = images.reshape(-1, 28*28) # 前向传播 outputs = model(images) loss = criterion(outputs, labels) # 反向传播和优化 optimizer.zero_grad() loss.backward() optimizer.step() if (i+1) % 100 == 0: print ('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}' .format(epoch+1, num_epochs, i+1, total_step, loss.item())) ``` 在测试集上评估模型: ``` model.eval() with torch.no_grad(): correct = 0 total = 0 for images, labels in test_loader: images = images.reshape(-1, 28*28) outputs = model(images) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() print('准确率: {} %'.format(100 * correct / total)) ``` 这是一个简单的PyTorch实现手写体数字识别MNIST的示例。您可以根据需要进行进一步的调整和改进。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值