У меня есть обученная модель керас, для которой мне нужно вычислить как градиенты, так и гессианы выходных данных относительно входных данных.Входные данные X
являются массивом 5000x3, а выходные значения y
равны 5000x1.
Градиентное вычисление отлично работает как с использованием градиентов кераса, так и функций градиента тензорного потока, и я получаю массив 5000x3 с правильными значениямив нем, но гессиан с использованием tf.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
.
. Я бы понял, что если и градиент, и гессенский расчет не пройдены, тогда было бы ясно, что я сделал что-то глупое ... но градиенты работают нормально, покагессианы терпят неудачу, и документы, кажется, указывают, что они оба подчиняются одному и тому же синтаксическому вызову, что я и сделал здесь.Любая помощь в том, почему это происходит?
РЕДАКТИРОВАТЬ: Если я использую вычисленный градиент в качестве входных данных для другого вызова get_derivative_NN
, я получаю правильное значение для второй производной, так что это доказывает, что есть что-то странноепроисходит с функцией tf.hessians()
.