如何取出 tf.layers.dense 定义的全连接层的weight和bias参数值

原文链接:https://www.codelast.com/%e5%8e%9f%e5%88%9b-%e5%a6%82%e4%bd%95%e5%8f%96%e5%87%ba-tf-layers-dense-%e5%ae%9a%e4%b9%89%e7%9a%84%e5%85%a8%e8%bf%9e%e6%8e%a5%e5%b1%82%e7%9a%84weight%e5%92%8cbias%e5%8f%82%e6%95%b0%e5%80%bc/

TensorFlow版本:1.14.0
Python版本:3.6.8

在TensorFlow中,tf.layers.dense 定义了一个全连接层,其实现的是(来自官方文档):

This layer implements the operation: outputs = activation(inputs * kernel + bias) Where activation is the activation function passed as the activation argument (if not None), kernel is a weights matrix created by the layer, and bias is a bias vector created by the layer (only if use_bias is True).

意思就是它实现了 y = activation(x * kernel + bias) 的操作,其中,activation是激活函数。在这里,kernel 就是指我们通常所说的 weight,它被TF称为 kernel 而不是 weight。因此,如果你想从这个模型里取出weight参数的话,就要注意它的名字了,否则会读不到这个参数。

下面我们就来看具体的例子。
下面这段代码的逻辑非常简单,它干了下面这些事情:

  • 创建了一个非常简单的2层全连接网络
  • 训练网络
  • 训练完成后把它保存成checkpoint格式的模型文件
  • 从保存的checkpoint读取模型里第一层的 weight 和 bias 参数值,打印出来
import tensorflow as tf
import numpy as np
LAYER_1_NAME = 'layer1'  # 第一层的名字
LAYER_2_NAME = 'layer2'  # 第二层的名字

# 创建一个非常简单的神经网络,它有两层
x = tf.placeholder(shape=[None, 2], dtype=tf.float32)
layer1 = tf.layers.dense(x, 5, activation=tf.nn.sigmoid, name=LAYER_1_NAME)
layer2 = tf.layers.dense(layer1, 2, activation=tf.nn.sigmoid, name=LAYER_2_NAME)
loss = tf.reduce_mean((layer2 - x) ** 2)
optimizer = tf.train.AdamOptimizer(0.01).minimize(loss)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
x_values = np.random.normal(0, 1, (5000, 2))  # 生成用于输入的随机数
    for step in range(1000):
_, loss_value = sess.run([optimizer, loss], feed_dict={x: x_values})
if step % 100 == 0:
print("step: %d, loss: %f" % (step, loss_value))
# 把模型保存成checkpoint
    saver = tf.compat.v1.train.Saver()
save_path = saver.save(sess, './checkpoint/model.ckpt')
print("model saved in path: %s" % save_path, flush=True)
# 读取刚保存的checkpoint
    reader = tf.train.NewCheckpointReader(save_path)
weights = reader.get_tensor(LAYER_1_NAME + '/kernel')  # weight的名字,是由对应层的名字,加上默认的"kernel"组成的
    bias = reader.get_tensor(LAYER_1_NAME + '/bias')  # bias的名字
    print(weights)
print(bias)
# 如果想打印模型中的所有参数名和参数值的话,把下面几行取消注释
    # var_to_shape_map = reader.get_variable_to_shape_map()
    # for key in var_to_shape_map:
    #     print("tensor name: ", key)
    #     print(reader.get_tensor(key))

上面程序的输出:

step: 0, loss: 1.166642
step: 100, loss: 0.764896
step: 200, loss: 0.659553
step: 300, loss: 0.622590
step: 400, loss: 0.604577
step: 500, loss: 0.595308
step: 600, loss: 0.590193
step: 700, loss: 0.587147
step: 800, loss: 0.585213
step: 900, loss: 0.583916
model saved in path: ./checkpoint/model.ckpt
[[-3.0937738   3.6378026   0.91563785 -1.2663897  -0.09645918]
 [ 0.727915    0.22842272 -2.656725   -2.0831287  -3.4844823 ]]
[ 0.906906   -1.6009021   0.46897942  0.75946033  1.4348172 ]

注意,在取某一层的 weight 参数值的时候,我们用了以下方法:

weights = reader.get_tensor(LAYER_1_NAME + '/kernel')

这里,weight 的名字,是类似于 “layer1/kernel” 这样的字符串,其中,"layer1"就是在用 tf.layers.dense() 创建网络的一个layer的时候,设置的 “name=xxx” 里的名字。前面已经说过了,TF 里把 weight 叫做 kernel,所以这里的 weight 名是 “layer1/kernel” 而不是 “layer1/weight”!

你可能感兴趣的:(Tensorflow)