如何在Keras中获取层的权重?

48

我正在使用Windows 10,Python 3.5和tensorflow 1.1.0。我有以下脚本:

import tensorflow as tf
import tensorflow.contrib.keras.api.keras.backend as K
from tensorflow.contrib.keras.api.keras.layers import Dense

tf.reset_default_graph()
init = tf.global_variables_initializer()
sess =  tf.Session()
K.set_session(sess) # Keras will use this sesssion to initialize all variables

input_x = tf.placeholder(tf.float32, [None, 10], name='input_x')    
dense1 = Dense(10, activation='relu')(input_x)

sess.run(init)

dense1.get_weights()

我遇到了错误:AttributeError: 'Tensor' object has no attribute 'weights'

我做错了什么?如何获取dense1的权重?我看过这个这个问题的SO帖子,但仍然无法使其正常工作。

4个回答

98

如果您想获取所有层的权重和偏置,您可以简单地使用:

for layer in model.layers: print(layer.get_config(), layer.get_weights())

这会打印出所有相关的信息。

如果您想要将权重直接返回为numpy数组,您可以使用:

first_layer_weights = model.layers[0].get_weights()[0]
first_layer_biases  = model.layers[0].get_weights()[1]
second_layer_weights = model.layers[1].get_weights()[0]
second_layer_biases  = model.layers[1].get_weights()[1]

等等。


41

如果你写:

dense1 = Dense(10, activation='relu')(input_x)

那么 dense1 并不是一层,而是一层的输出。这一层是 Dense(10, activation='relu')

所以看起来你的意思应该是:

dense1 = Dense(10, activation='relu')
y = dense1(input_x)

这里是完整的代码片段:

import tensorflow as tf
from tensorflow.contrib.keras import layers

input_x = tf.placeholder(tf.float32, [None, 10], name='input_x')    
dense1 = layers.Dense(10, activation='relu')
y = dense1(input_x)

weights = dense1.get_weights()

如果我想要多层,应该采用什么适当的方式?即,有比 y=dense2(dense1(input_x)) 更好的方式吗? - Toke Faurby
感谢您的说明,让我更清晰了解了。 - Rajesh Mappu

24

如果您想查看层的权重和偏置如何随时间变化,可以添加回调函数,在每个训练时期记录它们的值。

例如,使用这样的模型:

import numpy as np
model = Sequential([Dense(16, input_shape=(train_inp_s.shape[1:])), Dense(12), Dense(6), Dense(1)])

在拟合过程中添加回调函数的 **kwarg:

gw = GetWeights()
model.fit(X, y, validation_split=0.15, epochs=10, batch_size=100, callbacks=[gw])

回调函数的定义位置在

class GetWeights(Callback):
    # Keras callback which collects values of weights and biases at each epoch
    def __init__(self):
        super(GetWeights, self).__init__()
        self.weight_dict = {}

    def on_epoch_end(self, epoch, logs=None):
        # this function runs at the end of each epoch

        # loop over each layer and get weights and biases
        for layer_i in range(len(self.model.layers)):
            w = self.model.layers[layer_i].get_weights()[0]
            b = self.model.layers[layer_i].get_weights()[1]
            print('Layer %s has weights of shape %s and biases of shape %s' %(
                layer_i, np.shape(w), np.shape(b)))

            # save all weights and biases inside a dictionary
            if epoch == 0:
                # create array to hold weights and biases
                self.weight_dict['w_'+str(layer_i+1)] = w
                self.weight_dict['b_'+str(layer_i+1)] = b
            else:
                # append new weights to previously-created weights array
                self.weight_dict['w_'+str(layer_i+1)] = np.dstack(
                    (self.weight_dict['w_'+str(layer_i+1)], w))
                # append new weights to previously-created weights array
                self.weight_dict['b_'+str(layer_i+1)] = np.dstack(
                    (self.weight_dict['b_'+str(layer_i+1)], b))
此回调函数将根据层编号为所有层的权重和偏差构建一个字典,因此您可以看到在模型训练过程中它们随着时间如何变化。您会注意到每个权重和偏差数组的形状取决于模型层的形状。每个模型层保存一个权重数组和一个偏差数组。第三个轴(深度)显示它们随时间的演变。
这里我们使用了10个epochs和一个有16、12、6和1个神经元层的模型:
for key in gw.weight_dict:
    print(str(key) + ' shape: %s' %str(np.shape(gw.weight_dict[key])))

w_1 shape: (5, 16, 10)
b_1 shape: (1, 16, 10)
w_2 shape: (16, 12, 10)
b_2 shape: (1, 12, 10)
w_3 shape: (12, 6, 10)
b_3 shape: (1, 6, 10)
w_4 shape: (6, 1, 10)
b_4 shape: (1, 1, 10)

你能否在批处理后保存所得到的矩阵吗?或者在完成一定数量的批次后保存? - Marco Armenta
其中 Callback = tf.keras.callbacks.Callback ;-) - mm_

10

如果层的索引号让人困惑,您也可以使用层名称。

权重:

model.get_layer(<<layer_name>>).get_weights()[0]

偏见

model.get_layer(<<layer_name>>).get_weights()[1]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接