深度学习中数据集很小是一种什么样的体验

您所在的位置:网站首页 numpy添加一行 深度学习中数据集很小是一种什么样的体验

深度学习中数据集很小是一种什么样的体验

#深度学习中数据集很小是一种什么样的体验| 来源: 网络整理| 查看: 265

点击小眼睛开启蜘蛛网特效 深度学习中数据集很小是一种什么样的体验 Oldpan 2018年6月5日 1条评论 13,603次阅读 12人点赞 《深度学习中数据集很小是一种什么样的体验》前言

今天提一个比较轻松的话题,简单探讨数据集大小对深度学习训练的影响。 不知道大家有没有看过这篇文章:Don’t use deep learning your data isn’t that big 《深度学习中数据集很小是一种什么样的体验》

是的,有人对深度学习的局限性提供了一个证据:那就是当你数据比较少的时候,深度学习的作用相比较于其他传统的方法并没有什么优势,相反效果还不如传统的方法。

提出这个说法的作者利用两种方法进行了测试,测试的数据集是MNIST,测试计算机是否能正确识别0和1,采用的方法分别是:

5层的深度神经网络,活函数是双曲正切函数; 另一种方法使用的是李加索变量选择方法,这种方法思想就是挑选10个边际p值最小的像素来进行(用这些值做回归就可以了);

然后得出一个结论: 《深度学习中数据集很小是一种什么样的体验》

那就是使用李加索方法的表现要优于神经网络。What?

正文

那么回到正题,上面的说法到底对不对,我们在数据比较小的时候能否正确地进行深度学习的训练从而达到比较满意的效果?

我们都知道,神经网络相当于一个无限深的万能函数,我们输入变量x然后得到结果y,中间经历了很多复杂的计算过程。理论上,通过传统算法可以解决的问题通过深度学习都可以解决,但是如果神经网络足够深的时候,虽然这个网络的功能很强大,但是如果数据不够,很容易达到过拟合的现象,从而达不到我们要求的效果。

那么数据集过小是否可以通过深度学习来做,我们来测试一下。

一维信号

我们测试数据很简单,不是我们平常使用的三通道RGB图(3 x 256 x 256),而是普通的一通道一维信号(1 x 168)。

《深度学习中数据集很小是一种什么样的体验》

上方是我们的一维信号,532nm和1064mn分别对应两种不同的信号,我们只需要对一种信号处理器可。信号的格式是.mat文件,也就是matlab文件。

上面的文件中,train数据集是161 x 168,第一行是x轴的坐标我们不用理会只需要y轴的数据,每40个数据组是一类也就是 2-41、42-81、82-121、122-161,一共四类。而test数据集是81×168,第一行同样是x坐标我们不管,每20个数据组是一类(和train数据组顺序上类别是一样的)。也就是说我们一共有四类信号要进行分类。

label分别为:0、1、2、3.

我们的训练数据量只有160组,而测试数据量也只有80组。

数据读取

我们采用的深度学习库是Pytorch,利用的python上的scipy库,scipy是一个线性函数处理库,当然我们只是使用它对mat文件的读取功能。

创建一个文件读取.py,引入以下头文件。

import torch import torch.utils.data as data import scipy.io import os import os.path as osp

然后我们编写文件读取类.py:

# 将原始数据转化为训练需要的数据格式 def to_tensor(data): data = torch.from_numpy(data).type(torch.float32) data = data.unsqueeze(0) return data # 读取数据类 class LineData(data.Dataset): def __init__(self, root, name=532, train=True, transform=to_tensor): self.root = os.path.expanduser(root) self.name = name self.train = train self.transform = transform self.classes = [0, 1, 2, 3] if not osp.exists('datasets'): raise FileExistsError('Missing Datasets') if self.train: self.train_datas = [] self.train_labels = [] dataset_dir = osp.join(self.root, 'train_{}nm.mat'.format(self.name)) train_data = scipy.io.loadmat(dataset_dir)['lineIntensity'] data_length = len(train_data) - 1 # 161 - 1 = 160 if self.transform: for i in range(data_length): # 0 - 159 self.train_datas.append(transform(train_data[i+1])) # i+1 => 1 - 160 self.train_labels.append(self.classes[int(i / 40)]) else: raise ValueError('We need tranform function!') if not self.train: self.test_datas = [] self.test_labels = [] dataset_dir = osp.join(self.root, 'test_{}nm.mat'.format(self.name)) test_data = scipy.io.loadmat(dataset_dir)['lineIntensity'] data_length = len(test_data) - 1 # 81 - 1 = 80 if self.transform: for i in range(data_length): # 0 - 79 self.test_datas.append(transform(test_data[i+1])) # i+1 => 1 - 80 self.test_labels.append(self.classes[int(i / 20)]) else: raise ValueError('We need tranform function!') def __getitem__(self, index): """ Args: index (int): Index Returns: tuple: (image, target) where target is index of the target class. """ if self.train: data, target = self.train_datas[index], self.train_labels[index] else: data, target = self.test_datas[index], self.test_labels[index] return data, target def __len__(self): if self.train: return len(self.train_datas) else: return len(self.test_datas) 编写神经网络

写好文件读取代码后,我们来设计一下神经网络,因为数据量很少,所以我们的神经网络的层数也应该下降。否则很容易出现过拟合的现象。

我们首先设计5层的神经网络,两个卷积层,一个池化层,两个线性层,激活函数使用Relu:

每个数据的长度为168 模型:两个个卷积层、两个线性层 class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1 = nn.Conv1d(1, 10, 3) # (168 - 3)/1 + 1 = 166 (* 10) self.pool = nn.MaxPool1d(2, 2) # (166 - 2)/2 + 1= 83 (* 10) self.conv2 = nn.Conv1d(10, 20, 3) # (83 - 3)/1 + 1 = 81 (* 20) self.fc1 = nn.Linear(81*20, 100) self.fc2 = nn.Linear(100, 4) def forward(self, x): x = self.pool(F.relu(self.conv1(x))) x = F.relu(self.conv2(x)) x = x.view(-1, 81*20) x = F.relu(self.fc1(x)) x = self.fc2(x) return x 训练以及测试

设计好神经网络后,我们来进行训练吧!

首先编写训练块的代码,我们使用的优化策略是SGD随机下降法(带有动能),默认的学习率设置为0.001,验证方式采用经典的分类常用的验证法CrossEntropyLoss。

我们首先进行训练然后进行验证准确率,准确率就是每次测试这四种信号正确次数和总次数的比。

# 主程序页面 import torch import torch.nn as nn import torch.utils.data import torch.optim as optim from model import Net from data_utils import LineData root = 'datasets' # 数据所在目录,相对目录地址 train_name = '532' # 或者 '1064' # device = torch.device('cuda:0') # 读取文件类 trainset = LineData(root, name=train_name) trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=True) testset = LineData(root, name=train_name, train=False) testloader = torch.utils.data.DataLoader(testset, batch_size=4, shuffle=True) net = Net() # net = net.to(device) criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9) # 下面的epoch改成 2 可以达到100%的准确率 epoch_sum = 1 # 训练 for epoch in range(epoch_sum): loss_sum = 0.0 for i, data in enumerate(trainloader, 0): inputs, labels = data optimizer.zero_grad() outputs = net(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() loss_sum += loss.item() if i % 10 == 9: print('[epoch:{} num:{}] loss:{}'.format(epoch, i, loss_sum / 20)) loss_sum = 0.0 print('Finished Training') # 验证 correct = 0 total = 0 with torch.no_grad(): for data in testloader: inputs, labels = data outputs = net(inputs) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() print('Accuracy of the network on the 80 test images: %d %%' % ( 100 * correct / total)) pass

好了,开始训练,由于数据量很少,所以在CPU上训练即可。

第一次训练,epoch为1,lr为0.001:

[epoch:0 num:9] loss:1.693671927541118e+16 [epoch:0 num:19] loss:53694975.30745087 [epoch:0 num:29] loss:6.2672371854667905e+28 [epoch:0 num:39] loss:51403236.52956776 Finished Training Accuracy of the network on the 80 test images: 25 %

结果看起来很不好嘛…准确率25%,看起来是猜的,损失波动很剧烈,应该是我们学习率调的太高了,接下来调整一下学习率。

第二次训练,epoch为1,lr为0.0001:

[epoch:0 num:9] loss:133432.54784755706 [epoch:0 num:19] loss:67940.00796541572 [epoch:0 num:29] loss:109.18773172795773 [epoch:0 num:39] loss:1.1358043849468231 Finished Training Accuracy of the network on the 80 test images: 25 %

loss下降很平缓,但是epoch看起来不够导致loss下降没有彻底,准确率依然很低,让我们来调整一下epoch。

第三次训练,epoch为5,lr为0.0001:

[epoch:0 num:9] loss:3024598166.2773805 [epoch:0 num:19] loss:3117157163.829549 [epoch:0 num:29] loss:258.4028107881546 [epoch:0 num:39] loss:0.6990358293056488 [epoch:1 num:9] loss:0.6830220401287079 [epoch:1 num:19] loss:66.56461009383202 [epoch:1 num:29] loss:0.7117315053939819 [epoch:1 num:39] loss:0.6977931916713714 [epoch:2 num:9] loss:0.6974189281463623 [epoch:2 num:19] loss:0.6898959457874299 [epoch:2 num:29] loss:0.7101178288459777 [epoch:2 num:39] loss:0.6914324820041656 [epoch:3 num:9] loss:0.686737447977066 [epoch:3 num:19] loss:0.6972651600837707 [epoch:3 num:29] loss:0.7028001189231873 [epoch:3 num:39] loss:0.6998239696025849 [epoch:4 num:9] loss:0.6997098863124848 [epoch:4 num:19] loss:0.6969940900802613 [epoch:4 num:29] loss:0.696108078956604 [epoch:4 num:39] loss:0.6910847663879395 Finished Training Accuracy of the network on the 80 test images: 25 %

loss下降到一定级别没有再下降,而准确率依然很迷,有可能还是因为学习率过高而导致loss一直卡在一个范围无法彻底下降,我们再试着尝试下降一下学习率。

第四次训练,epoch为2,lr为0.00001:

[epoch:0 num:9] loss:200.58453428081702 [epoch:0 num:19] loss:5.724525341391564 [epoch:0 num:29] loss:0.2976263818090047 [epoch:0 num:39] loss:0.05558242934057489 [epoch:1 num:9] loss:0.0004892532759185996 [epoch:1 num:19] loss:0.00012833428763769916 [epoch:1 num:29] loss:9.479262493137242e-05 [epoch:1 num:39] loss:3.948449189010717e-05 Finished Training Accuracy of the network on the 80 test images: 100 %

完美,看来我们摸索出了合适的学习率(0.00001),经过10次测试,准确率分别为:100%、100%、100%、100%、100%、100%、100%、100%、100%、98%。

如果我将epoch从2换成1,则是100%、77%、100%、100%、100%、86%、100%、100%、100%、100%。

epoch从1换成3则是:100%、100%、100%、100%、100%、100%、100%、100%、100%、100%。

我们如果修改一下神经网络层为3层全连接层,lr为0.00001效果会很差,即使训练10个以上的epochy也不会达到100%的准确率,但是如果将lr下降到0.000001,准确率则就会达到100%了:

class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.fc1 = nn.Linear(168, 1000) self.fc2 = nn.Linear(1000, 100) self.fc3 = nn.Linear(100,4) def forward(self, x): x = x.view(-1, 168) x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) x = self.fc3(x) return x 结论

通过上面的测试,看起来200数量以内的数据集,只要设计层合理,学习率合适,那么准确率也是可以达到比较好的效果。

其实所说的过拟合常常是因为我们设计的神经网络层数过深,但是数据没有那么多,神经网络就会充分“榨干”那些训练数据,过度吸收那些训练集的信息,导致在测试的时候没有那么准确,说以如果数据集过少,可以通过减少层数的方法来减轻错误。

但是如果数据包含的信息很丰富,但是数据量很少,这时候光调整层数就不够了,我们需要一些数据增强的技术扩充数据集,从而“喂饱”神经网络,不至于让神经网络出现异常。当然,数据集扩充是针对含信息量很丰富的信息来实现的,如果信息都像我们之前使用的一维信号一样,一般就没有必要扩充了。

  点赞 分享

打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮

python 基础 数据集 机器学习 深度学习 深度学习库 本篇文章采用 署名-非商业性使用-禁止演绎 4.0 国际 进行许可 转载请务必注明来源: https://oldpan.me/archives/deeplearning-dateset-small

   关注Oldpan博客微信公众号,你最需要的及时推送给你。

 猜你喜欢 深度学习部署神器-triton inference server第一篇 老潘的宝藏资料分享(不断更新~) Mac mini M1使用体验(编程、游戏、深度学习) 实现TensorRT自定义插件(plugin)自由! 利用Caffe推理CenterNet(下篇) 利用Caffe推理CenterNet(上篇) Pingback: 深度学习面试知识点汇总 - Oldpan的个人博客 发表评论 取消回复 Dontation

如果你与我志同道合于此,很愿意与你交流

如果你喜欢我的内容,欢迎关注和支持~

-------这是人工分割线------- 联系我请关注公众号哦关注 oldpan博客 不错过老潘的最新文章。公众号回复"666"获取老潘的宝藏资料(C++、CUDA、Python、深度学习、算法),希望与你交朋友~

公众号 weixin_social 微信捐赠 weixin_pay 标签聚合深度学习 机器学习 算法 pytorch 环境搭建 python 深度学习库 基础 互联网 运维 服务器 cuda 日志 博客 教程 Web TensorRT 程序 故障问题 推荐 ubuntu pycharm JavaScript TensorFlow 资讯 代码 C/C++ 数据集 资源 电脑 热门文章 本站专栏 社区文章 实践torch.fx第一篇——基于Pytorch的模型优化量化神器 实践torch.fx第一篇——基于Pytorch的模型优化量化神器 TORCH.FX第二篇——PTQ量化实操 TORCH.FX第二篇——PTQ量化实操 老潘的笔记本环境配置 老潘的笔记本环境配置 算法工程师老潘的一些经验 算法工程师老潘的一些经验 老潘的思考 老潘的思考 深度学习部署神器-triton inference server第一篇 深度学习部署神器-triton inference server第一篇 深度学习那些事-云+社区 腾讯云 深度学习那些事-知乎专栏 深度学习那些事-掘金专栏 CSDN-Oldpan博客 深度学习(DeepLearning)专栏 Pytorch深度学习框架专栏 每日一词

“逆转裁判”有趣单词 点击进入

最新评论 深 Oldpan: “使用的是WordPress,教程可以网上…” 12月 25, 11:30 深 Litteryi: “你的博客可是很好看的,哪里能搭建的呀!能…” 12月 14, 20:25 深 Litteryi: “:razz: :razz: :razz:…” 12月 14, 20:22 深 xiaoxia: “理解万岁” 12月 10, 00:57 深 youyou: “大佬,写一篇基于FX的QAT量化不?” 12月 5, 17:10 深 QQ游客: “博客卖吗” 11月 14, 00:48

 友链  资源  RSS          洛奇

Copyright 2023 Oldpan的个人博客. All Rights Reserved.     Thanks the theme by Kratos 陕ICP备17018520号-1



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3