深度学习训练过程中BatchSize的设置
昨天配置好GPU加速敲开心,开始跑我的小模型。结果惊奇的发现CPU效率比GPU高5倍多,这是什么鬼?和群里各个大佬讨论了一下,最终发现是BatchSize的问题,在此顺便讨论一下在模型训练过程中BatchSize的设置。
- Show一下硬件和我简陋的小模型
- 不同Size下GPU和CPU的运算时间
- 到底需要设置多大的Size?
先简单说一下我理解的Batch Size吧。
比如你有1w个数据(或者图片)需要训练,也就是需要找1w个数据的规律(感觉深度学习就是让模型找规律)。这时候有几种策略:
- 全部数据都拿来用,一次性找所有的规律。
这个首先就是很难(很费时间)总结他们的规律,类似“众口难调”,全局学习速率也不好定。其次就是,往往内存很难容纳全局那么大的数据量。全部数据都拿来用也叫Batch Gradient Descent,批梯度下降,就是每次都用全部数据找规律。
- 每次就拿一个数据来找规律。
这个就会造成模型很难收敛,类似“公说公有理,婆说婆有理”。这样是不可取的=-=
- 因此就诞生了mini-batches
就是把数据总量分为n份,每次找一份的规律,一轮把每一份的规律找一遍。而Batch Size参数就是每一份有多少数据的意思,比如Batch Size=1000,那么1w的数据就被分成10份,这个意思。
很多大佬的博客写的超级好,我也是看完之后才能总结出上面这些,详细请看:
机器学习中常见问题_几种梯度下降法谈谈深度学习中的 Batch_Size
Show一下硬件和我简陋的小模型
首先说一下我的模型,我的测试模型很简单,就是6层全连接层,每层64个unit,激活函数用relu,最后加个BN层。训练集总量135844。
计算的硬件如下,CPU是i7-3770:
CPU
Intel(R) Core(TM) i7-3770 CPU @ 3.40GHz
基准速度: 3.40 GHz
插槽: 1
内核: 4
逻辑处理器: 8
虚拟化: 已启用
L1 缓存: 256 KB
L2 缓存: 1.0 MB
L3 缓存: 8.0 MB
利用率 5%
速度 3.15 GHz
正常运行时间 0:23:56:01
进程 188
线程 2579
句柄 83109
GPU是GTX 1060 6G版本:
GPU 0
NVIDIA GeForce GTX 1060 6GB
驱动程序版本: 22.21.13.8554
驱动程序日期: 09/01/2017
DirectX 版本: 12 (FL 12.1)
物理位置: PCI 总线 1、设备 0、功能 0
利用率 2%
专用 GPU 内存 0.2/6.0 GB
共享 GPU 内存 0.0/12.0 GB
GPU 内存 0.2/18.0 GB
不同Size下GPU和CPU的运算时间
Epoch定50次,改变不同的Batch Size。
这个是CPU运行情况:
这个是GPU运行情况:
其实,感叹一下,GPU加速还是对CNN效果更明显,我这个模型和数据量对GTX1060来说还是有点弱。
下面数字是程序开始和程序结束的时间,代码是:
from time import time
timeBeg=time()
#中间是程序
timeEnd=time()
print (timeEnd-timeBeg)
结果为:
Epoch | 100 | 500 | 1000 | 2000 | 3000 | 4000 | 5000 | 6000 | 7000 | 8000 | 9000 | 10000 | 135844 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
CPU | 128.1 | 75.1 | 60.5 | 54.3 | 50.8 | 51.0 | 54.0 | 53.3 | 54.5 | 53.1 | 53.1 | 52.6 | 69.0 |
GPU | 522.1 | 134.5 | 85.0 | 60.9 | 51.5 | 47.0 | 44.8 | 44.4 | 42.5 | 40.1 | 40.2 | 39.7 | 35.2 |
CPU/GPU | 0.2 | 0.6 | 0.7 | 0.9 | 1.0 | 1.1 | 1.2 | 1.2 | 1.3 | 1.3 | 1.3 | 1.3 | 2.0 |
GPU/CPU | 4.1 | 1.8 | 1.4 | 1.1 | 1.0 | 0.9 | 0.8 | 0.8 | 0.8 | 0.8 | 0.8 | 0.8 | 0.5 |
做个折线图:

可以看到,Size为100时,CPU的效率时GPU的4倍,而Size为总数据量时,GPU效率是CPU的2倍。
对于GTX 1060有1280个CUDA核心,i7-3770 是4核8线程。
所以非常非常粗略的证明了,Batch-Size大于显卡核心数可以发挥显卡的最大功能。
额,确实粗略,主要结论足够了,方案欠缺点见下:
- 对于每个Epoch应做几个重复,取均值和方差减少随机误差;
- GTX1060显卡和早它1年多的i7 3770相比,这两个不同的东西是否有可比性?
- 每个核心的计算量应该也做个梯度(比如增大模型层数等)
这样才比较完善,不过懒得做了=-=
上面的证明过程也可以用我之前举得大力士和小学生的栗子来说明:
8个大力士类似CPU,跑的快力气大;1280个小学生类似GPU,跑的慢力气小;
如果都让他们去送信,一次只给他们100封送,大力士跑得快效率占优,小学生也就100个忙活,其他都闲的没事做;而让他们一次去送1280封信,小学生虽然跑的慢,但是一轮全部送完,大力士跑的快但是得送N多次。就是这个到理。
对了,实际中设置Batch Size大小最好设置为2的次方数,比如256,512等,据说能快很多。
到底需要设置多大的Size?
问题来了,到底需要设置多大的Size?
这个,首先作为“工程学”的深度学习,肯定是哪个准确率高,Precision和Recall都好,ROC和PR都优秀,就用哪个呗。
不过通过经验和网上大佬评测:
以下引用:谈谈深度学习中的 Batch_Size
- 随着 Batch_Size 增大,处理相同数据量的速度越快。
- 随着 Batch_Size 增大,达到相同精度所需要的 epoch 数量越来越多。
- 由于上述两种因素的矛盾, Batch_Size 增大到某个时候,达到时间上的最优。
- 由于最终收敛精度会陷入不同的局部极值,因此 Batch_Size 增大到某些时候,达到最终收敛精度上的最优。
突然发现像我这种数据,量不大的,做深度学习,完全可以全部加载去找最优值啊~
