在深度学习任务中,虽然可以通过堆叠参数、设计更复杂的结构来提高模型的表征能力,但这也会导致模型的计算量增加,训练时间延长。所以,模型的预测有多好并不是唯一的考虑因素,训练时间长会导致成本的上升。
一、影响网络训练速度的因素
1.使用的处理器(GPU和CPU)
CPU(中央处理器)是一台计算机的运算核心和控制核心。CPU、内部存储器和输入/输出设备是电子计算机三大核心部件。其功能主要是解释计算机指令以及处理计算机软件中的数据。
GPU(图形处理器)是一个专门的图形核心处理器。GPU是显示卡的“大脑”,决定了该显卡的档次和大部分性能,同时也是2D显示卡和3D显示卡的区别依据。
CPU需要很强的通用性来处理各种不同的数据类型,同时又要逻辑判断又会引入大量的分支跳转和中断的处理。这些都使得CPU的内部结构异常复杂。而GPU面对的则是类型高度统一的、相互无依赖的大规模数据和不需要被打断的纯净的计算环境。GPU通常来说会比CPU快。
2.batchsize大小
如果batchsize很大,例如达到百万数量级,训练速度往往会很慢,因为每次迭代都要对所有样本进行进行求和运算和矩阵运算。
但是如果batchsize过小,会使得耗时长,训练效率低。
batchsize太大或者太小都不好。所以,我们需要设置一个合适的batchsize值,在训练速度和内存容量之间寻找到最佳的平衡点。
更多详情请看以下链接:
batchsize太小的缺点&随着batchsize逐渐增大的优缺点&如何平衡batchsize的大小
3.模型的大小和权重参数
参数和模型的大小方面是影响网络模型训练速度的关键因素。
网络将其学习的参数或权重存储在主内存中。通常,模型的权重越少,运行速度就越快。
4.内存访问成本(训练过程中的中间结果)
权重的参数只是影响神经网络训练速度的一部分,所占内存的大多数时候对于训练速度更重要。因为在当前的计算机体系结构中,来自主内存的内存访问比计算权重慢得多大约100倍或更多!
比如,对于每一层网络,设备需要:
①从主存储器读取输入矢量或特征图
②计算点积 - 这也涉及从主内存中读取层的权重
③将结果作为新矢量或特征图写回主存储器。
这涉及大量的内存访问。由于内存非常慢,因此该层执行的内存读/写量也会对其速度产生重大影响。
5.网络的结构也会影响神经网络的速度
图a为DenseNet网络结构图,该网络在参数和模型大小方面小于ResNet但在运行效率方面却不如ResNet,主要由于DenseNet网络把上一层的特征图与下一层的特征图在维度上进行累加,这样虽然提高了网络提取特征的能力但会导致内存访问成本随网络深度呈二次增长,进而导致计算开销和更多能耗。
但是残差连接也需要一定的计算量,只是相比于DenseNet网络结构计算量更小。
图b为VoVNet网络结构,它可以一次聚合中间特征,这种聚合方法在保持连接强度的同时,极大地提高了媒体访问控制和图形处理器的计算效率。
二、加速神经网络训练的方法
1. 合理的超参数设计
BatchSize
batchsize太大或者太小都不好。所以,我们需要设置一个合适的batchsize值,在训练速度和内存容量之间寻找到最佳的平衡点。
更多详情请看以下链接:
batchsize太小的缺点&随着batchsize逐渐增大的优缺点&如何平衡batchsize的大小
epoch和学习率策略
为了减少保存模型所占用内存的时间,我们可以选择每100次迭代(或者其他)保存一次模型。更小的学习率通常只需要更少的epoch。因此,可以通过修改学习率和训练epoch的策略来达到相同精度的前提下降低训练时间。
2. 权值共享
每轮迭代的推理速度和模型的参数量、计算量息息相关,而通过设置参数权值共享,可以降低总的参数量和计算量,另外如tensorflow,pytorch等深度学习框架都有针对权值共享的推理优化,所以会有相对明显的加速效果。
3. 升级相关软件包
如将cuda、tensorflow、pytorch进行升级,一般来说越新越好。旧版cuda可能只是针对一些显卡做了适配,但是新版cuda会针对一些新的算子、显卡做针对性优化,如常见的Tesla V系列显卡,采用cuda11的推理速度就明显快于cuda8、9。tensorflow、pytorch等框架也是同理。并且这些软件包都是向下兼容的,因此不用过于担心代码移植问题。
4. 多卡训练、数据并行
在采用NVIDIA GPU进行训练的时候,可以通过$ watch -n 0.1 nvidia-smi命令时刻观察GPU显存和利用率情况,只有当GPU 利用率处于高位的时候GPU才是在高效的工作,否则大部分时间都是在闲置,而这一般是由于数据读取过慢导致的。可以通过自己实现多线程读数据或者采用tensorflow、pytorch等框架提供的并行读数据的方法让GPU保持较高利用率,从而减少GPU等待时间,降低整体训练耗时。
5. 混合精度训练
通常参数都是采用float32进行计算的,而将参数保存为float16格式理论上能加快一倍的训练速度并且节省一倍的模型大小,同时精度损失不会太多,这就是混合精度训练方法。具体细节可以参照常见的深度学习框架提供的混合精度训练包。
6.减少不必要的网络连接和RELU层
不必要的shortcut、DesNet连接和ReLU层都会增加计算量。
我们可以根据实际训练需要删减ReLU层(例如:同样RELU没有必要每一个卷积后连接)。