`layer.get_weights()` return 是什么意思?
What does `layer.get_weights()` return?
我正在使用 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
这一次,权重确实发生了变化。所以我想知道在训练期间起作用的 "true" 重量是多少?为什么权重列表中有两个元素?
mlp()
的定义:
def mlp():
model=Sequential()
model.add(Dense(500, input_dim=784))
model.add(Dense(503,init='normal',activation='relu'))
model.add(Dense(503,init='normal',activation='relu'))
model.add(Dense(10, activation='softmax'))
return model
对于layer.get_weights()
的问题:
我运行 对这个问题进行了一些测试并检查了源代码。我发现 Dense
层是 Layer
的子类,它的权重是 python list
的一种类型,层的两个元素权重存储在 layer.get_weights()[0]
并且 bias
存储在 layer.get_weights()[1]
。
需要注意的是,bias
可以在定义图层时禁用:model.add(Dense(503,init='normal',activation='relu',
bias=False
))
.在这种情况下,列表 layer.get_weights()
只有一个元素。如果你在定义后将 bias
属性设置为 False
,那么仍然会有一个 bias
的元素,它会在你拟合模型后更新。
关于不更新的问题:
我设置了一个只有一个密集层的顺序模型:
def mlp_2():
model=Sequential()
model.add(Dense(10, input_dim=784, activation='softmax', bias =False))
return model
然后我用上面同样的方法编译适配。这是我得到的:
好像还是没有更新权重,但是可以看出权重肯定是变了。因为准确度越来越高。我认为唯一的解释是第一个 dense
层(您定义 input_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)
我正在使用 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
这一次,权重确实发生了变化。所以我想知道在训练期间起作用的 "true" 重量是多少?为什么权重列表中有两个元素?
mlp()
的定义:
def mlp():
model=Sequential()
model.add(Dense(500, input_dim=784))
model.add(Dense(503,init='normal',activation='relu'))
model.add(Dense(503,init='normal',activation='relu'))
model.add(Dense(10, activation='softmax'))
return model
对于layer.get_weights()
的问题:
我运行 对这个问题进行了一些测试并检查了源代码。我发现 Dense
层是 Layer
的子类,它的权重是 python list
的一种类型,层的两个元素权重存储在 layer.get_weights()[0]
并且 bias
存储在 layer.get_weights()[1]
。
需要注意的是,bias
可以在定义图层时禁用:model.add(Dense(503,init='normal',activation='relu',
bias=False
))
.在这种情况下,列表 layer.get_weights()
只有一个元素。如果你在定义后将 bias
属性设置为 False
,那么仍然会有一个 bias
的元素,它会在你拟合模型后更新。
关于不更新的问题:
我设置了一个只有一个密集层的顺序模型:
def mlp_2():
model=Sequential()
model.add(Dense(10, input_dim=784, activation='softmax', bias =False))
return model
然后我用上面同样的方法编译适配。这是我得到的:
好像还是没有更新权重,但是可以看出权重肯定是变了。因为准确度越来越高。我认为唯一的解释是第一个 dense
层(您定义 input_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)