#编译神经网络,指定优化器、损失函数,以及评估指标
ann.compile(optimizer = 'adam', # 优化器
loss = 'binary_crossentropy', # 损失函数
metrics = ['acc']) # 评估指标
其中adam就是一个优化器。优化器的引入和神经网络的特点有十分密切的关系。
在之前的学习中我们已经了解过了线性回归和逻辑回归,他们两个在进行梯度优化的时候利用的是凸函数的性质。但是在神经网络中,由于局部最低点、鞍点(形状类似马鞍)的存在,损失函数变得非常复杂,先前的方法已经不再适用。下面我们将介绍几种基本方法。
在实际应用中,人们发现局部最低点的出现是可以接受的。如果每次训练网络都进行权重的初始化,随机赋值,那么只要训练次数足够多,我们总能找到一个相对优秀的局部最低点。
对应python源码,参数随机初始化的任务在Keras中已经打包完成,如下图所示。
ann.add(Dense(64,
kernel_initializer = 'random_uniform', # 默认权重随机初始化
bias_initializer = 'zeros')) # 默认偏置值为0
除了上述的参数初始化方法,人们还开发了一系列优化器,下面我们将列举几个介绍他们的特点。
批量梯度下降(Batch Gradient Descent,BGD)将数据拆分成一组组的小批量,进而通过向量化的计算方式进行处理。这大大提高的运算速度。
以下面代码为例,批量大小为128,也就是同时训练128个样本。
history = model.fit(X_train, y_train, # 指定训练集
epochs=30, # 指定轮次
batch_size=128, # 指定批量大小
validation_data=(X_test, y_test)) # 指定验证集
当然批量大小设定需要考虑计算机性能。若批量太大,会超出CPU和GPU的负荷,效率反而下降。
BGD提高了效率,但其实并没有局部最低点的问题。因此人们又提出了另一个优化方案:随机梯度下降(Stochastic Gradient Descent,SGD)。此处的随机与参数的随机初始化不同,而是每次只随机选择一个样本更新模型参数。因此,这种方法学习速度更快,所需轮次也更多。
显然随机梯度下降中,参数的更新梯度方向远不如批量梯度下降精准,每次也不一定向着最低点进行。但是考虑一下我们设计的出发点:解决局部最低点问题。这也是说,随机波动正是我们需要的,这将增大我们“跳出”局部最低点的概率,最终收敛于一个更好的点,甚至是最低点。
SGD是早起神经网络中的常用优化器。在编译网络时,可以指定SGD优化器。
ann.compile(loss = keras.losses.categorical_crossentropy,
optimizer = keras.optimizer.SGD()) # 指定SGD优化器
当然这种随机梯度下降的方法也不是完全可靠的方法。我们不能保证每次参数的更新都朝着正确的方向。