一、背景
略
二、初始化网络层参数
1. 思路
其实没有什么思路,因为keras中内置了初始化参数的接口
使用:
layers.Dense(...,kernel_initializer,bias_initializer,...)
中的kernel_initializer和bias_initializer初始化Dense神经网络层中的参数,其中kernel_initializer初始化参数w,bias_initializer初始化参数b,变量类型为tensorflow.python.keras.initializers.*
,例如tf.keras.initializers.ones()
或者tf.keras.initializers.constant([2.0])
。
2.代码示例
下面给出一个拟合方程y=x+2的只含有一层全连接层的神经网络进行示范说明。
对于该网络,训练数据为一个实数x和对应的y, 其中y=x+2。
代码如下:
import tensorflow as tf
import numpy as np
from tensorflow.keras import layers
import pandas as pd
# 使用网络方式实现一个网络拟合一次函数 y = a*x+b,其中 a = 1, b= 2
# 构建网络
def buildModel():
# 只有一层全连接层,存在两个参数w和b,并使用kernel_initializer初始化w参数为1.0
# 使用bias_initializer参数为2.0
model = tf.keras.Sequential([
layers.Dense(1, kernel_initializer=tf.keras.initializers.ones(),
bias_initializer=tf.keras.initializers.constant([2.0]))
])
# 定义优化器
optimizer = tf.keras.optimizers.RMSprop(0.001)
# 编译优化器
model.compile(loss='mse',
optimizer=optimizer,
metrics=['mae', 'mse'])
return model
# 生成训练,测试数据
def generateData():
train_dataset = []
test_dataset = []
for i in range(0, 5):
train_dataset.append([i, i + 2])
for i in range(6, 10):
test_dataset.append([i, i + 2])
return np.array(train_dataset, dtype=np.float), np.array(test_dataset,dtype=np.float)
train_dataset, test_dataset = generateData()
# 构建Dataframe格式的dataset
train_dataset = pd.DataFrame(train_dataset)
test_dataset = pd.DataFrame(test_dataset)
# 用第2列(下标为1即y值)的数据作为label
train_labels = train_dataset.pop(1)
test_labels = test_dataset.pop(1)
# 训练1000个epoch
Epochs = 1000
model = buildModel()
# 开始训练
history = model.fit(train_dataset, train_labels, epochs=Epochs, validation_split=0.0, verbose=0)
# 训练结果
hist = pd.DataFrame(history.history)
print(hist)
运行结果如下所示:
loss mae mse
0 0.0 0.0 0.0
1 0.0 0.0 0.0
2 0.0 0.0 0.0
3 0.0 0.0 0.0
4 0.0 0.0 0.0
.. ... ... ...
995 0.0 0.0 0.0
996 0.0 0.0 0.0
997 0.0 0.0 0.0
998 0.0 0.0 0.0
999 0.0 0.0 0.0
[1000 rows x 3 columns]
可以看到,由于我们设置了网络的初始参数w=1.0,b=2.0,即网络初始的参数就满足真实的结果y=1.0*x+2.0,因此训练时第一次的误差就是0.0,即可达到最优解,此时可以直接结束训练,但是此处为了继续观察驯良过程并未手动结束。
当我们修改网络的初始参数时,例如我们将相应的代码改为:
model = tf.keras.Sequential([
layers.Dense(1, kernel_initializer=tf.keras.initializers.ones(),
bias_initializer=tf.keras.initializers.constant([3.0]))
])
使用w=1.0,b=3.0初始网络参数。重新训练后的结果如下:
loss mae mse
0 1.000000 1.000000 1.000000
1 0.981136 0.990513 0.981136
2 0.967663 0.983669 0.967663
3 0.956508 0.977957 0.956508
4 0.946696 0.972899 0.946696
.. ... ... ...
995 0.000418 0.016978 0.000418
996 0.000399 0.016265 0.000399
997 0.000381 0.016228 0.000381
998 0.000363 0.015520 0.000363
999 0.000346 0.015484 0.000346
[1000 rows x 3 columns]
在epoch=0时,由于初始参数b=3.0,而真实的的偏移参数b应该为2.0,因此``loss=1.0 mae=1.0 mse=1.0```。经过1000次训练后误差可以减小到0.000346。
三、总结
上面两个实验结果对比可以表明,在使用keras构建神经网络时可以使用参数kernel_initializer和bias_initializer初始化网络的w和b参数。手动初始化网络参数对于减小训练次数,提高网络训练精度具有重要意义。
四、参考
[1]. Layer weight initializers
[2]. keras系列(一):参数设置