DAY23 神经网路优化技巧

昨天我们尝试动手刻了一个神经网路,准确度虽然看似很高了,但似乎还有进步的空间,今天我们就来介绍如何优化我们的神经网路。


一、怎麽样算是一个好的神经网路

在优化前我们要先搞清楚,要优化神经网路的哪个部分,那就必须知道什麽样的神经网路是好的,一般来说评估标准有以下三点:

  1. 准确度(Accuracy)
  2. 推论速度(Inference)
  3. 模型大小(Model size)

准确度自然不用多说,我们当然希望模型预测的答案越准越好,而推论速度是指模型预测出答案的时间,在一些实务上(自动驾驶),我们需要模型在短时间内就给出预测值,这时候推论速度就很重要,而模型大小则会影响神经网路在一些边缘装置上的应用,例如架设摄影机辨识路人有没有戴口罩,我们不可能搬一台电脑到路上,就要应用一些边缘装置,像是Jetson Nano。

具体该优化哪个指标,其实还是要看我们面对什麽样的问题,假如是自动驾驶要感应周围有没有障碍物,推论速度就是一个很重要的指标;假如是要找出潜在的信用卡盗刷交易,那麽准确度就是重要的指标,先了解该追求哪项指标,再去优化自己的神经网路模型,下面我们开始介绍有哪些优化方法。


二、资料集优化

对资料集的优化通常是最有效的办法,尤其是对於准确率的提升,能拥有一个好的资料集比其他模型超参数的优化来的重要许多,资料集优化主要有以下几项:

  1. 设法取得更多资料,提高训练样本数
  2. 资料正规化 (Data Normalization)
  3. 资料增强 (Data Augmentation)

这部分我们在前面的章节有详细的介绍过,大家可以回去看这篇。

(要附连结)


三、超参数优化

调参的部分也是在打比赛中一个很重要的优化过程,有人说神经网路内部的训练过程就像一个黑盒子,我们无法得知他的计算过程,因此只能透过调整参数的方式去尝试更好的组合,下面我们就来介绍一些超参数以及调整方式:

批次大小(Batch_size)

每个训练批次所提取的资料数,通常我们会设定比目标类别还要多一些,才能确保每次训练都会抽到不同标签的样本,但批次大小也不太能随意调整,需考虑自身设备的记忆体大小,若批次太大可能会跑不动。

轮次大小(epoch)

神经网路训练的次数,当你发现模型训练的准确度不断上升时,就可以调高训练的轮次,让模型继续收敛,反之模型如果一直没有进步,就要将降低训练的轮次

学习率(Learning rate)

学习率是控制梯度下降的参数,学习率过大会导致模型找不到局部最佳解;而学习率过小则会造成收敛速度过慢,且会被困在局部最佳解的点,无法找到全局最佳解,一般来说会设定0.01,但要随时根据不同情况做调整。

最好的方法是设置"动态学习率",在模型随着训练次数的增加去调整它的学习率,当梯度下降较快时,增加学习率,而当梯度趋於平缓时就降低学习率,下面的程序码范例可根据不同情况做调整。

#设置动态学习率
from tensorflow.keras.callbacks import ReduceLROnPlateau
LR_function=ReduceLROnPlateau(monitor='val_acc',
                             patience=5,
                             # 5 epochs 内acc没下降就要调整LR
                             verbose=1,
                             factor=0.5,
                             # LR降为0.5
                             min_lr=0.00001
                             # 最小 LR 到0.00001就不再下降
                             )

四、最佳化方法优化

最佳化方法有很多种,最常见的就是随机梯度下降(SGD),其他还有像是Adagrad、RMSProp、Adam...等多种方法,模型都可以尝试去套套看,Keras中也有支援,只需简单的程序码即可使用。

#SGD
tf.keras.optimizers.SGD(
    learning_rate=0.01, momentum=0.0, nesterov=False, name='SGD', **kwargs
)

#Adagrad
tf.keras.optimizers.Adagrad(
    learning_rate=0.001, initial_accumulator_value=0.1, epsilon=1e-07,
    name='Adagrad', **kwargs
)

#RMSProp
tf.keras.optimizers.RMSprop(
    learning_rate=0.001, rho=0.9, momentum=0.0, epsilon=1e-07, centered=False,
    name='RMSprop', **kwargs
)

#Adam
tf.keras.optimizers.Adam(
    learning_rate=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-07, amsgrad=False,
    name='Adam', **kwargs
)

五、模型优化

除了参数的调整,我们也可以对整个网路模型进行一些优化方法。

Dropout

这是Google提出的一种正规化技术,用来防止过度拟合的问题,其作法是在神经网路的某些层中,随机丢弃部分的神经元,如此可避免在训练的过程中有过多的神经元产生复杂的相互适应,让剩下的神经元在更新资讯後更强健,作法如下:

input_shape = (128, 128, 3)
# 建立简单的线性执行的模型
model = Sequential()
# 建立卷积层
model.add(Conv2D(32, kernel_size=(3, 3),
                 activation='relu',
                 input_shape=input_shape,
                 padding="same"))
# 建立卷积层
model.add(Conv2D(64, (3, 3), activation='relu',padding="same"))
# 建立池化层,池化大小2x2,取最大值
model.add(MaxPooling2D(pool_size=(2, 2)))
# Dropout层随机断开输入神经元,用於防止过度拟合,断开比例:0.25
model.add(Dropout(0.25))
# Flatten层把多维的输入一维化,常用在从卷积层到全连接层的过渡。
model.add(Flatten())
# 全连接层: 128个output
model.add(Dense(128, activation='relu'))
# Dropout层随机断开输入神经元,用於防止过度拟合,断开比例:0.5
model.add(Dropout(0.5))
# 使用 softmax activation function,将结果分类
model.add(Dense(num_classes, activation='softmax'))

剪枝(Pruning)

这个技巧主要是为了使模型变小,其原理为去除神经网路中冗余的参数,使得模型大小缩减、运算速度提高,有点类似Dropout,但Pruning是对已训练完成或套用其他权重的模型使用。这个做法稍微有些复杂,但Tensorflow有好心的提供范例,小编在此附上连结大家可以去参考。

Keras中Pruning的范例


六、其他优化方式

降低精度

目前大多数的神经网路模型在训练即推论时都是使用FP32的精度(32位元浮点数),而我们可以透过咿些转换的方法将精度调降为FP16或是int8,如此一来其运算速度可以倍数成长,但精度调整就像一把双面刃,调整时会造成资讯的流失,准确度也会随之降低,因此要决定出一个好的平衡点,再去使用这个方法,TensorRT有提供转换教学,网址如下:

TensorRT教学

使用TFLite

TFLite是Tensorflow提供的一种架构,其价值在於将神经网路部属到一些微型装置,透过转换、压缩等功能可以降低模型的大小、提升模型的推论速度。
https://ithelp.ithome.com.tw/upload/images/20210914/20140427j70JkZ3agP.jpg
篇幅的关系我这边就不详细介绍了,一样附上网址:

TFLite教学


七、结论

今天介绍了一些优化神经网路的方法,最後想要提醒大家的是,尽管优化方法有很多,但不代表我们用了很多方法加到模型里,我们的模型就会变得多厉害,也不是一次把所有方法加上去就好,调参时要有耐心的慢慢尝试每种方法,找到一个最适合模型的组合。

明天我们将介绍另一种常见的优化方法-使用预训练模型,敬请期待吧!


<<:  DAY22 类神经网路之架设与训练

>>:  Day 09:今天又想不出标题了!tmux plugin 和 mouse mode

[Day 3] 一同面对焦虑吧!

焦虑感的来袭 不得不说,在有工作的情形下,一方面要努力完成现有的工作,另一方面还得焦虑自己是否能够真...

[ASP.Net MVC] 如何套用 Bootstrap 网页设计样版 SB Admin 2 开发网站管理介面 (附范例)

想要快速开发一个 Bootstrap 网页设计样版的网站,可以利用网路上已经设计好的网页样版下载套用...

每个人都该学的30个Python技巧|技巧 10:回圈二部曲—for回圈(字幕、衬乐、练习)

昨天的range函式有搞清楚了吗?如果没有一定要再回去复习,不然今天的for回圈你会一直混乱呦 (⊙...

Trouble with Distributed Systems (1)

从 2020 Day 21 - Replication 开始到现在,我们大多都是在谈系统出错了怎麽办...