¿Cómo puedo definir solo el degradado para un Subgraph de Tensorflow?

Primero: solo llevo unos días con Tensorflow, así que por favor tengan paciencia conmigo.

Comencé con el código tutorial cifar10 y ahora estoy usando una combinación de convoluciones y descomposiciones de valores propios que rompen la diferenciación simbólica. Es decir, el gráfico se construye, luego al llamar a train() el script se detiene con “No gradient defined for operation […] (op type: SelfAdjointEig)”. No es sorpresa allí.

Las entradas al subgráfico en cuestión siguen siendo solo los mapas de características de entrada y los filtros que se usan, y tengo las fórmulas para los gradientes disponibles y deben ser fáciles de implementar dadas las entradas al subgráfico y el gradiente con respecto a su salida.

De lo que puedo ver en los documentos, puedo registrar un método de degradado para Ops personalizados con RegisterGradient o anularlos con el gradient_override_map experimental. Ambos deberían darme acceso a exactamente las cosas que necesito. Por ejemplo, al buscar en Github encuentro muchos ejemplos que acceden a las entradas de la op.input[0] como op.input[0] o op.input[0] .

El problema que tengo es que quiero esencialmente “atajar” un subgrafo completo, no una sola operación, así que no tengo una sola opción para decorar. Como esto está sucediendo en una de las capas convolucionales del ejemplo cifar, traté de usar el objeto de scope para esa capa. Conceptualmente, lo que entra y sale de ese gráfico del scope es exactamente lo que quiero, así que si pudiera de alguna manera anular los gradientes de todo el scope que “ya” lo haría.

Vi tf.Graph.create_op que (creo) podría usar para registrar un nuevo tipo de operación y luego pude anular el cálculo del gradiente de ese tipo de operación con los métodos mencionados anteriormente. Pero no veo una forma de definir el pase hacia adelante de esa operación sin escribirla en C ++ …

Tal vez me estoy acercando a esto de la manera incorrecta por completo? Dado que todas mis operaciones hacia delante o hacia atrás se pueden implementar con la interfaz de python, obviamente quiero evitar implementar cualquier cosa en C ++.

Aquí hay un truco de Sergey Ioffe:

Supongamos que quiere un grupo de operaciones que se comporten como f (x) en el modo de avance, pero como g (x) en el modo de retroceso. Usted lo implementa como

 t = g(x) y = t + tf.stop_gradient(f(x) - t) 

Entonces, en tu caso, tu g (x) podría ser una operación de identidad, con un degradado personalizado usando gradient_override_map

¿Qué tal multiplicar y dividir, en lugar de sumr y restar t?

 t = g(x) y = tf.stop_gradient(f(x) / t) * t