Python “layer.get_weights()”返回什么?

Python “layer.get_weights()”返回什么?,python,keras,Python,Keras,我正在使用Keras做一些实验,我只是监测了一个简单mlp模型的重量更新: # model contains one input layer in the format of dense, # one hidden layer and one output layer. model=mlp() weight_origin=model.layers[0].get_weights()[0] model.compile(loss='categorical_crossentropy', optimi

我正在使用Keras做一些实验,我只是监测了一个简单mlp模型的重量更新:

# model contains one input layer in the format of dense, 
# one hidden layer and one output layer.
model=mlp() 
weight_origin=model.layers[0].get_weights()[0]
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(.....) # with adam optimizer
weight_updated=model.layers[0].get_weights()[0]
print weight_origin-weight_updated
对于第一个密集层,我得到了一个零矩阵。我以为训练不会改变体重。但是,其他层中的权重会发生更改。所以我很困惑,为什么第一层是不变的? 我检查了源代码,但仍然没有得到答案,然后我尝试监视:

model.layers[0].get_weights()[1] # get_weight() returns a list of weights
这一次,重量确实发生了变化。所以我想知道哪种体重才是训练中起作用的“真实”体重?为什么权重列表中有两个元素


定义
mlp()


对于
层的问题。获取权重()

我对这个问题进行了一些测试,并检查了源代码。我发现,
密集的
层是
的一个子类,它的权重是python
列表的一种
有两个元素,层的权重存储在
层。get_weights()[0]
偏差
存储在
层。get_weights()[1]

需要注意的是,
bias
可以在定义层时禁用:
model.add(稠密(503,init='normal',activation='relu',
bias=False
)。在这种情况下,列表
层.get_weights()
只有一个元素。如果在定义后将
bias
属性设置为
False
,则
bias
仍将有一个元素,并且在拟合模型后将更新该元素

关于不更新的问题

我建立了一个只有一个致密层的顺序模型:

def mlp_2():
模型=顺序()
模型添加(密集(10,输入尺寸=784,激活=softmax,偏差=False))
退货型号

然后我使用上面相同的方法来编译和拟合它。这就是我得到的:


它似乎仍然没有更新重量,但是,我们可以告诉重量是明确改变。因为准确度在提高。我认为唯一的解释是第一个
densite
层(您定义的
input\u dim
)的更新太小,Keras无法打印出来。我没有检查更精确的重量值,如果有人能确认它,那就太好了。

这里是一个工作示例

import numpy as np
from  keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten

X_train=np.random.rand(1,10)
Y_train=2*X_train
input_dim = X_train.shape[1]
model=Sequential()
model.add(Dense(20, input_dim=10))
model.add(Dense(10, activation='softmax'))
weight_origin_0=model.layers[0].get_weights()[0]
weight_origin_1=model.layers[1].get_weights()[0]
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(X_train, Y_train, batch_size=1, nb_epoch=10, verbose=1)
print(weight_origin_0-model.layers[0].get_weights()[0])  #the first layer
print(weight_origin_1-model.layers[1].get_weights()[0])  #the second layer

有一种方法可以准确地看到所有权重和偏差的值是如何随时间变化的。您可以使用Keras回调方法,该方法可用于记录每个训练阶段的权重值。以这样的模型为例

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个时期和一个由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)

你能给我们提供mlp()函数吗?这真的很奇怪behaviour@MarcinMożejko我已经更新了。我对
层中的第二个权重感到困惑。权重
列表。你编译了你的模型吗?@MarcinMożejko是的,很抱歉我的错误careless@LudwigZhou在比较这两个矩阵之前,你要训练多长时间?我认为如果你得到一个批处理规范或退出层,这将是不正确的,它也有可训练的权重伟大的解释!!
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)