Tensorflow: Error de división por cero durante la concatenación de elementos únicos del tensor.
Actualmente estoy trabajando en un agente actor-crítico “four wins” en Python. Mientras intentaba propagar hacia atrás a través de distribuciones de probabilidad de acción previamente recolectadas, me encontré con el siguiente error: “ZeroDivisionError: división de entero o módulo por cero”.
Fue capaz de reproducir el error con el siguiente código en Tensorflow versión 2.7.0 en mi CPU (Ubuntu 20.04.3 LTS):
import tensorflow as tf
with tf.GradientTape() as tape:
t = tf.Variable([1.])
concat = tf.concat(values=[t[0], t[0]], axis=0)
concat_sum = tf.reduce_sum(concat)
grads = tape.gradient(concat_sum, t)
Sé que el problema puede parecer trivial en este ejemplo de código. Sin embargo, todavía es incomprensible para mí por qué hay un error aquí. ¿No debería ser lo mismo concatenar los primeros elementos del tensor y sumarlos finalmente que hacer la suma directamente, como en el siguiente código?
with tf.GradientTape() as tape:
t = tf.Variable([1.])
result = t + t
grads = tape.gradient(result, t)
¿Por qué uno genera gradientes válidos mientras que el otro no?
davy.ai
La razón del error en el ejemplo de código se debe al hecho de que la operación de
concat
crea un tensor de longitud 2 donde ambos elementos son iguales, es decir, [1., 1.]. Al llamar atf.reduce_sum
, esto sumará los dos elementos para dar 2. Como estamos tratando de calcular el gradiente deconcat_sum
con respecto at
, esto resultará en una división por cero, de ahí elZeroDivisionError
.En el segundo ejemplo de código, simplemente agregamos
t
a sí mismo, lo que resulta en un valor escalar de 2. Como estamos tratando de calcular el gradiente deresultado
con respecto at
, esta es una operación válida y obtenemos un gradiente válido.Para solucionar el problema en el primer ejemplo, simplemente se puede cambiar el eje de concatenación a
axis=1
, de modo que obtengamos un tensor de forma [1, 2], y luego llamar atf.reduce_sum
conaxis=1
para sumar en la segunda dimensión. Esto se vería de la siguiente manera:Esto ahora debería dar un gradiente válido sin errores.