畅游人工智能之海--Keras教程之优化器(一)

畅游人工智能之海--Keras教程之优化器(一)

前言

从这篇文章开始,分析神经网络的优化器以及其在keras框架中的实现。在前面讲过,神经网络的编写分成:准备数据、搭建网络结构、配置算法参数这几步,其中配置算法参数是关键的一步,而optimizer的配置是其中的重中之重。 神经网络的本质目的就是寻找合适的参数,使得损失函数的值尽可能小,该过程为称为最优化。解决这个问题的算法称为优化器。

理论模型

梯度下降法更新参数是常用的手段,举一个很简单的例子作为说明。

  • 现有三组训练数据\((x,\hat{y})\)如下:
1
2
3
(0,1)
(1,2)
(2,3)
  • 构建神经网络为 \(y = ax + b\)

  • 计算损失函数 \(loss(L) = \frac{1}{2}\sum(y - \hat{y})^2 = \frac{1}{2}\sum(ax + b - \hat{y})^2 = \frac{1}{2}(b - 1)^2 + \frac{1}{2}(a + b - 2)^2 + \frac{1}{2}(2a+b-3)^2\)

  • 计算偏导数(梯度)

    • \(\frac{\partial{L} }{\partial{a} } = \sum x(ax + b - \hat{y})\)
    • \(\frac{\partial{L} }{\partial{b} } = \sum (ax + b - \hat{y})\)
  • 更新参数

    • \(a \gets a - \alpha * \frac{\partial{L} }{\partial{a} }\)
    • \(b \gets b - \alpha * \frac{\partial{L} }{\partial{b} }\)

\(a,b\)初始化为2,运行结果如下所示:

1
2
3
4
5
6
7
1.2 1.4
0.98 1.22
0.924 1.16
0.914 1.1348
0.9166 1.1202
0.9222 1.1091
0.9284 1.0997

source code:

1
2
3
4
5
6
7
8
9
10
11
12
13
global a,b,alpha
a = 2;b = 2;alpha = 0.1;train = [[0,1],[1,2],[2,3]]
def update():
global a,b,alpha
delta_a = 0;delta_b = 0
for tmp in train:
x = tmp[0];y = tmp[1]
delta_a += x * (a * x + b - y);delta_b += (a * x + b - y)
a = a - alpha * delta_a;b = b - alpha * delta_b
return
while (a - 1) > 0.1 or (b - 1) > 0.1:
update()
print(round(a,4),round(b,4))

keras接口

基本optimizer

在调用compile函数时,在函数的参数中给定优化器,可以通过实例化的方法,也可以通过字符串声明。

1
2
3
# 实例化
opt = keras.optimizers.Adam(learning_rate=0.01)
model.compile(loss='categorical_crossentropy', optimizer=opt)
1
2
# 字符串声明
model.compile(loss='categorical_crossentropy', optimizer='adam')

自定义层

在新版本的keras中可以调用apply_gradients()函数,通过将gradients,model作为传入参数更新参数,官网给出的代码如下所示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
optimizer = tf.keras.optimizers.Adam()

# Iterate over the batches of a dataset.
for x, y in dataset:
# Open a GradientTape.
with tf.GradientTape() as tape:
# Forward pass.
logits = model(x)
# Loss value for this batch.
loss_value = loss_fn(y, logits)

# Get gradients of loss wrt the weights.
gradients = tape.gradient(loss_value, model.trainable_weights)

# Update the weights of the model.
optimizer.apply_gradients(zip(gradients, model.trainable_weights))

Learning rate decay / scheduling

通过这个接口,可以设定学习率随着时间变化,不过回调函数也可以做到这一点,后面会分析。

结尾

keras提供了8种具体的优化器,下面的几篇关于keras文章会对其进行讲解。