vertical una tamaño logaritmica linea grafico grafica fijar etiquetas escala ejes como cambiar ajustar python tensorflow neural-network gradient-descent

python - una - fijar ejes matplotlib



Tensorflow: ¿Cómo escribir op con gradiente en python? (2)

Me gustaría escribir una operación TensorFlow en Python, pero me gustaría que fuera diferenciable (para poder calcular un gradiente).

Esta pregunta pregunta cómo escribir una operación en python, y la respuesta sugiere usar py_func (que no tiene gradiente): Tensorflow: Escribir una operación en Python

La documentación de TF describe cómo agregar una operación comenzando solo desde el código C ++: https://www.tensorflow.org/versions/r0.10/how_tos/adding_an_op/index.html

En mi caso, estoy creando prototipos, así que no me importa si se ejecuta en la GPU, y no me importa que sea utilizable desde otra cosa que no sea la API TF Python.


Aquí hay un ejemplo de agregar gradiente a un py_func específico here

Aquí está la discussion problema


Sí, como se menciona en la respuesta de @ Yaroslav, es posible y la clave son los enlaces a los que hace referencia: here y here . Quiero dar más detalles sobre esta respuesta dando un ejemplo concreto.

Operación de módulo: Implementemos la operación de módulo de elemento en flujo de tensor (ya existe pero su gradiente no está definido, pero por ejemplo lo implementaremos desde cero).

Función Numpy: el primer paso es definir la operación que queremos para las matrices numpy. La operación del módulo en cuanto a elementos ya está implementada en numpy, por lo que es fácil:

import numpy as np def np_mod(x,y): return (x % y).astype(np.float32)

La razón del .astype(np.float32) se debe a que, por defecto, el tensorflow toma los tipos float32 y si le da float64 (el predeterminado numpy) se quejará.

Función de gradiente: a continuación, debemos definir la función de gradiente para nuestra operación para cada entrada de la operación como función de tensor de flujo. La función debe tomar una forma muy específica. Debe tomar la representación de flujo de tensor de la operación de operación y el gradiente del gradiente de salida y decir cómo propagar los gradientes. En nuestro caso, los gradientes de la operación mod son fáciles, la derivada es 1 con respecto al primer argumento y con respecto al segundo (casi en todas partes, e infinito en un número finito de puntos, pero ignoremos eso, vea https://math.stackexchange.com/questions/1849280/derivative-of-remainder-function-wrt-denominator para detalles). Entonces tenemos

def modgrad(op, grad): x = op.inputs[0] # the first argument (normally you need those to calculate the gradient, like the gradient of x^2 is 2x. ) y = op.inputs[1] # the second argument return grad * 1, grad * tf.neg(tf.floordiv(x, y)) #the propagated gradient with respect to the first and second argument respectively

La función grad necesita devolver una n-tupla donde n es el número de argumentos de la operación. Tenga en cuenta que necesitamos devolver las funciones de tensorflow de la entrada.

Realización de una función TF con gradientes: como se explica en las fuentes mencionadas anteriormente, existe un truco para definir gradientes de una función utilizando tf.RegisterGradient [doc] y tf.Graph.gradient_override_map [doc] .

Al copiar el código de here podemos modificar la función tf.py_func para que defina el gradiente al mismo tiempo:

import tensorflow as tf def py_func(func, inp, Tout, stateful=True, name=None, grad=None): # Need to generate a unique name to avoid duplicates: rnd_name = ''PyFuncGrad'' + str(np.random.randint(0, 1E+8)) tf.RegisterGradient(rnd_name)(grad) # see _MySquareGrad for grad example g = tf.get_default_graph() with g.gradient_override_map({"PyFunc": rnd_name}): return tf.py_func(func, inp, Tout, stateful=stateful, name=name)

La opción con stateful es decirle al tensorflow si la función siempre da la misma salida para la misma entrada (stateful = False) en cuyo caso el tensorflow puede simplemente el gráfico de tensorflow, este es nuestro caso y probablemente será el caso en la mayoría de las situaciones.

Combinándolo todo: ahora que tenemos todas las piezas, podemos combinarlas todas juntas:

from tensorflow.python.framework import ops def tf_mod(x,y, name=None): with ops.op_scope([x,y], name, "mod") as name: z = py_func(np_mod, [x,y], [tf.float32], name=name, grad=modgrad) # <-- here''s the call to the gradient return z[0]

tf.py_func actúa en listas de tensores (y devuelve una lista de tensores), es por eso que tenemos [x,y] (y devuelve z[0] ). Y ahora hemos terminado. Y podemos probarlo.

Prueba:

with tf.Session() as sess: x = tf.constant([0.3,0.7,1.2,1.7]) y = tf.constant([0.2,0.5,1.0,2.9]) z = tf_mod(x,y) gr = tf.gradients(z, [x,y]) tf.initialize_all_variables().run() print(x.eval(), y.eval(),z.eval(), gr[0].eval(), gr[1].eval())

[0.30000001 0.69999999 1.20000005 1.70000005] [0.2 0.5 1. 2.9000001] [0.10000001 0.19999999 0.20000005 1.70000005] [1. 1. 1. 1.] [-1. -1. -1. 0.]

¡Éxito!