我有一个训练有素的keras模型,我需要计算出相对于输入的输出的梯度和粗麻布。
输入X
是5000x3的numpy数组,输出y
是5000x1。
使用keras的梯度和tensorflow的梯度函数,梯度计算都可以正常工作,并且我得到了一个具有正确值的数组5000x3,但是使用tf.hessian()的hessian仅返回零。 情况并非如此,因为我的模型正在逼近一个高度非线性的函数,因此人们很希望二阶导数为非零。
代码如下(为简化可重用性,我简化了一些参数):
def get_derivatives_NN(X, y):
# Define Keras model
model = keras.Sequential()
model.add(keras.layers.Dense(500, activation=tf.nn.relu, input_shape=(X.shape[1],)))
model.add(keras.layers.Dense(300, activation=tf.nn.relu))
model.add(keras.layers.Dense(100, activation=tf.nn.relu))
model.add(keras.layers.Dense(y.shape[1]))
# Compile and fit model
optimz = keras.optimizers.Adam(optimizer_parameters)
model.compile(optimizer=optimz, loss='mse', metrics=['mae'])
model.fit(X, y, epochs = 200, validation_split=0)
# Evaluate gradients in Keras
grads = keras.backend.gradients(model.output, model.input)[0] # tensor
get_gradients = keras.backend.function([model.input], [grads])
evaluated_gradients = get_gradients([X]) # this is the evaluated gradient in Keras
# Evaluate gradienst in tf
session = keras.backend.get_session()
session.run(tf.global_variables_initializer())
evaluated_gradients_TF = session.run(tf.gradients(model.output, model.input), feed_dict={model.input: X})
# Evaluate hessian in tf
evaluated_hessian = session.run(tf.hessians(model.output, model.input), feed_dict={model.input: X})
return evaluated_gradients, evaluated_gradients_TF, evaluated_hessian
输出为(截断我的复制粘贴):
GRADIENT KERAS:
[array([[-0.00286908, 0.06114262, 0.0178928 ],
[-0.00717778, 0.05055936, 0.0415092 ],
[-0.00725342, 0.0075229 , 0.06268862],
..., dtype=float32)]
GRADIENT TF:
[array([[-0.00286908, 0.06114262, 0.0178928 ],
[-0.00717778, 0.05055936, 0.0415092 ],
[-0.00725342, 0.0075229 , 0.06268862],
..., dtype=float32)]
HESSIAN TF:
[array([[[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
...,
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]], ....... etcetera
这有两个问题:
1)粗麻布的大小对我来说真的没有意义。我期望最多有(5000,3,3)个数组,或者最多(5000,9)个数组,而我却得到(5000,3,5000,3);
2)这些值都是零,我已经检查过np.count_nonzero(evaluated_hessian)
并返回了0
。
我会理解,如果渐变和hessian计算都失败了,那么很显然我做了些愚蠢的事情……但是在hessians失败时渐变仍然可以正常工作,并且文档似乎表明它们都遵循相同的语法电话,这是我在这里所做的。 为什么会发生这种情况有帮助吗?
编辑:
如果我将计算出的梯度用作另一个get_derivative_NN
调用的输入,则可以得到二阶导数的正确值,因此这证明tf.hessians()
函数发生了一些奇怪的事情。
答案 0 :(得分:0)
“将计算出的梯度用作另一个get_derivative
调用的输入”是什么意思?您是指get_derivatives_NN
吗?