一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情。
使用 Keras 构建神经网络初体验
在本节中,我们将学习如何使用 Keras
创建神经网络模型,我们使用与从零开始学习神经网络前向传播 - 掘金 (juejin.cn)中相同的简单数据集,将模型定义如下:
- 输入连接到具有三个节点的隐藏层
- 隐藏层连接到输出,输出层有一个节点
- 定义数据集,导入相关库:
import keras
import numpy as np
x = np.array([[1], [2], [3], [7]])
y = np.array([[3], [6], [9], [21]])
- 实例化一个可以顺序计算的神经网络模型,可以在其中堆叠添加多个网络层,计算过程按网络层的堆叠顺序进行。
Sequential
方法能够构建顺序计算模型:
model = keras.models.Sequential()
- 向模型添加一个
Dense
层(全连接层)。Dense
层用于模型中各个层之间的全连接(上一层的每个节点与本层的每个节点间都有连接),Dense
层的工作方式与我们在从零开始学习神经网络前向传播 - 掘金 (juejin.cn)中相同使用的隐藏层完全相同。在以下代码中,我们将输入层连接到隐藏层:
model.add(Dense(3, activation='relu', input_shape=(1,)))
在使用前面的代码初始化的 Dense
层中,需要确保为模型提供输入形状(由于这是第一个全连接层,因此需要指定模型期望的接受的数据形状)。隐藏层中有三个节点,并且在隐藏层中使用的激活函数是ReLU函数。
- 将隐藏层连接到输出层:
model.add(keras.layers.Dense(1, activation='linear'))
在此 Dense
层中,我们无需指定输入形状,因为模型可以从上一层推断出输入形状。输出层具有一个节点,并使用线性激活函数。
可以将模型概要信息 (model summary
) 可视化输出:
model.summary()
可以看到模型概要信息如下所示:
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense (Dense) (None, 3) 6
_________________________________________________________________
dense_1 (Dense) (None, 1) 4
=================================================================
Total params: 10
Trainable params: 10
Non-trainable params: 0
_________________________________________________________________
从模型概要信息可以看到,从输入层到隐藏层的连接中总共有六个参数(三个权重和三个偏置项),另外,使用三个权重和一个偏置项将隐藏层连接到输出层。
- 编译模型。首先,需要定义损失函数和优化器,以及优化器相对应的学习率:
from keras.optimizers import SGD
sgd = SGD(lr=0.01)
上述代码指定优化器是随机梯度下降,学习率为 0.01。将预定义的优化器及其相应的学习率、损失函数作为参数传递给 compile
方法编译模型:
model.compile(optimizer=sgd,loss='mean_squared_error')
- 拟合模型。更新权重,以优化模型:
model.fit(x, y, epochs=1, batch_size = 4, verbose=1)
fit
方法需要接收一个输入 x
和相应的实际值 y
,epochs
代表训练数据集的次数,batch_size
代表每次更新权重的迭代中训练的数据量大小,verbose
指定训练过程中的输出信息,可以包含有关训练和测试数据集上损失值以及模型训练的进度等信息。
- 提取权重值。权重值的相关信息是通过调用模型的
weights
属性获得的:
model.weights
获得的权重相关信息如下:
[<tf.Variable 'dense/kernel:0' shape=(1, 3) dtype=float32, numpy=array([[1.1533519 , 1.2411805 , 0.39152434]], dtype=float32)>,
<tf.Variable 'dense/bias:0' shape=(3,) dtype=float32, numpy=array([ 0.03425962, -0.05432956, -0.1607531 ], dtype=float32)>,
<tf.Variable 'dense_1/kernel:0' shape=(3, 1) dtype=float32, numpy=array([[1.2210085 ], [1.2086679 ],[0.21541257]], dtype=float32)>,
<tf.Variable 'dense_1/bias:0' shape=(1,) dtype=float32, numpy=array([0.09131978], dtype=float32)>]
从前面的输出中,可以看到首先打印的权重属于 dense_1
层中的三个权重和三个偏置项,然后是 dense_2
层的三个权重和一个偏置项。其中包括权重的尺寸、数据类型以及参数的具体值等。我们也可以仅提取这些权重的值:
print(model.get_weights())
权重以数组列表的形式显示,其中每个数组对应于 model.weights
输出中的相应项:
[array([[1.1533519 , 1.2411805 , 0.39152434]], dtype=float32), array([ 0.03425962, -0.05432956, -0.1607531 ], dtype=float32), array([[1.2210085 ],
[1.2086679 ],
[0.21541257]], dtype=float32), array([0.09131978], dtype=float32)]
- 使用
predict
方法来预测一组新输入的输出:
x1 = [[5], [6]]
output = model.predict(x1)
print(output)
x1
是保存新测试集值的变量,我们需要为其预测输出值。与 fit
方法类似,predict
方法接受数组作为其输入。代码的输出如下:
[[14.996691]
[17.989458]]
当训练多个 epoch
时,网络的输出将与预期的输出 (15, 18) 十分接近。