Keras中有几个与梯度计算过程有关的占位符:
- 输入值
x
- 目标
y
- 样本权重:即使您未在其中提供
model.fit()
,Keras仍会为样本权重生成一个占位符,并np.ones((y.shape[0],), dtype=K.floatx())
在训练期间将其馈入图表。 - 学习阶段:仅当有任何图层(例如
Dropout
)使用时,此占位符才会连接到梯度张量。
所以,在你提供的例子,为了计算梯度,你需要饲料
x,
y并
sample_weights进入图形。这就是错误的根本原因。
内部
Model._make_train_function()有以下几行代码,显示了
K.function()在这种情况下如何构造必要的输入:
inputs = self._feed_inputs + self._feed_targets + self._feed_sample_weightsif self.uses_learning_phase and not isinstance(K.learning_phase(), int): inputs += [K.learning_phase()]with K.name_scope('training'): ... self.train_function = K.function(inputs, [self.total_loss] + self.metrics_tensors, updates=updates, name='train_function', **self._function_kwargs)通过模仿此功能,您应该能够获得norm值:
def get_gradient_norm_func(model): grads = K.gradients(model.total_loss, model.trainable_weights) summed_squares = [K.sum(K.square(g)) for g in grads] norm = K.sqrt(sum(summed_squares)) inputs = model.model._feed_inputs + model.model._feed_targets + model.model._feed_sample_weights func = K.function(inputs, [norm]) return funcdef main(): x = np.random.random((128,)).reshape((-1, 1)) y = 2 * x model = Sequential(layers=[Dense(2, input_shape=(1,)), Dense(1)]) model.compile(loss='mse', optimizer='rmsprop') get_gradient = get_gradient_norm_func(model) history = model.fit(x, y, epochs=1) print(get_gradient([x, y, np.ones(len(y))]))
执行输出:
Epoch 1/1128/128 [==============================] - 0s - loss: 2.0073 [4.4091368]
请注意,由于您使用
Sequential而不是
Model,
model.model._feed_*因此需要而不是
model._feed_*。



