Tensorflow tf.hessian仅返回零

时间:2019-02-26 14:12:12

标签: python tensorflow keras hessian

我有一个训练有素的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()函数发生了一些奇怪的事情。

1 个答案:

答案 0 :(得分:0)

“将计算出的梯度用作另一个get_derivative调用的输入”是什么意思?您是指get_derivatives_NN吗?