Я пытаюсь реализовать специальную архитектуру DNN, которая будет использоваться для машинного обучения на основе физики. Как вы, возможно, знаете, в этой архитектуре уравнения в частных производных интегрированы в функцию потерь. Интересная архитектура изображена ниже:
Как вы можете заметить, эта специальная архитектура позволяет нам оценивать дифференциальные операции, такие как K.gradients(model.outputs, model.inputs[0])
, который является частной производной Txy относительно x , и иметь его как часть функции потерь.
Теперь я хотел бы иметь следующую архитектуру:
Как вы можете заметить, эта сеть имеет (x,y)
в качестве входа, Txy
в качестве выхода, за которым следуют операции градиента на Txy
и затем (Uxy, V_xy)
в качестве конечных выходов. Однако эта архитектура приводит к следующей ошибке:
raise ValueError('An operation has `None` for gradient. ')
Когда я проверяю градиенты потерь по отношению к весам, я обнаруживаю, что они равны None
прямо на слоях, которые я определяю (Grad_Txy_x, Grad_Txy,y)
.
Кто-нибудь знает, каков источник этой ошибки? Как я могу иметь промежуточные слои, которые являются производными некоторого другого слоя по отношению к входным данным?
Отредактировано:
Вы можете попробовать следующий код:
import numpy as np
import keras as k
import tensorflow as tf
def custom_gradient(y, x):
return tf.gradients(y, x, unconnected_gradients='zero')
x = k.layers.Input(shape=(1,), name='x')
y = k.layers.Input(shape=(1,), name='y')
lay = k.layers.Dense(50, name='lay1')(k.layers.concatenate([x,y]))
lay = k.layers.Activation('tanh', name='tanh')(lay)
lay = k.layers.Dense(50, name='lay2')(lay)
Txy = k.layers.Dense(1, name='Txy')(lay)
dT_dx = k.layers.Lambda(lambda F: custom_gradient(F, x)[0], name='dTxy_dx')
dT_dx = dT_dx(Txy)
dT_dy = k.layers.Lambda(lambda F: custom_gradient(F, y)[0], name='dTxy_dy')
dT_dy = dT_dy(Txy)
lay = k.layers.Dense(50, name='lay3')(k.layers.concatenate([dT_dx, dT_dy]))
Uxy = k.layers.Dense(1, name='Uxy')(lay)
Vxy = k.layers.Dense(1, name='Vxy')(lay)
model = k.models.Model([x,y], [Uxy, Vxy])
model.compile(optimizer='adam', loss='mse')
k.utils.plot_model(model, show_shapes=False, to_file='output.png')
for lay in model.layers:
print(k.backend.gradients(model.total_loss, lay.output))
model.fit([np.ones((10,1)), np.ones((10,1))],
[np.ones((10,1)), np.ones((10,1))])
Оценки градиента показывают, что лямбда-слой возвращает неправильные градиенты:
[<tf.Tensor 'gradients/concatenate_1/concat_grad/Slice:0' shape=(?, 1) dtype=float32>]
[<tf.Tensor 'gradients_1/concatenate_1/concat_grad/Slice_1:0' shape=(?, 1) dtype=float32>]
[<tf.Tensor 'gradients_2/lay1/MatMul_grad/MatMul:0' shape=(?, 2) dtype=float32>]
[<tf.Tensor 'gradients_3/tanh/Tanh_grad/TanhGrad:0' shape=(?, 50) dtype=float32>]
[<tf.Tensor 'gradients_4/AddN_1:0' shape=(?, 50) dtype=float32>]
[None]
[None]
[<tf.Tensor 'gradients_7/concatenate_2/concat_grad/Slice:0' shape=(?, 1) dtype=float32>]
[<tf.Tensor 'gradients_8/concatenate_2/concat_grad/Slice_1:0' shape=(?, 1) dtype=float32>]
[<tf.Tensor 'gradients_9/lay3/MatMul_grad/MatMul:0' shape=(?, 2) dtype=float32>]
[<tf.Tensor 'gradients_10/AddN:0' shape=(?, 50) dtype=float32>]
[<tf.Tensor 'gradients_11/loss/Uxy_loss/sub_grad/Reshape:0' shape=(?, 1) dtype=float32>]
[<tf.Tensor 'gradients_12/loss/Vxy_loss/sub_grad/Reshape:0' shape=(?, 1) dtype=float32>]