es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Agregando pérdidas en Keras

Estoy tratando de encontrar una manera de acumular pérdidas en Keras. Esto funciona (para la pérdida de modelo de mezcla gaussiana = verosimilitud negativa logarítmica), pero no es tan elegante:

def neg_log_likelihood(y, phis, mu, sigmasq):
    a = phis[:, 0]*gaussian_pdf(y, mu[:, 0*t:(0+1)*t], sigmasq[:, 0])
    for i in range(1, k):
        a += phis[:, i]*gaussian_pdf(y, mu[:, i*t:(i+1)*t], sigmasq[:, i])
    loss = tf.math.reduce_mean(-tf.math.log(a))
    return loss

Prefiero crear una nueva variable para las pérdidas y acumular todo allí. Por ejemplo, lo intenté de esta manera:

def neg_log_likelihood(y, phis, mu, sigmasq):
    losses = tf.Variable(np.zeros(n, dtype=np.float32))
    for i in range(k):
        losses.assign_add(phis[:, i]*gaussian_pdf(y, mu[:, i*t:(i+1)*t], sigmasq[:, i]))
    loss = tf.math.reduce_mean(-tf.math.log(losses))
    return loss

Pero esto no produce gradientes por alguna razón. Es decir, cuando llamo:

gradients_init = tape.gradient(loss, model.trainable_weights)

Obtengo None.

¿Hay alguna manera de superar esto?

EDIT: Aquí está gaussian_pdf, aunque este no es el problema, ya que el primer ejemplo también lo usa.

def gaussian_pdf(x, mu, sigmasq):
    return (1/tf.math.sqrt(2*math.pi*sigmasq)) * tf.exp((-1/(2*sigmasq)) * tf.norm((x-mu),ord=2,axis=1)**2)   
Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Un problema potencial con la segunda implementación es que la variable “losses” se crea como una constante en lugar de una variable entrenable. Por lo tanto, cuando se calculan los gradientes, no se pueden propagar a través de esta variable.

    Para solucionar esto, podemos crear una variable entrenable para acumular las pérdidas:

    def neg_log_likelihood(y, phis, mu, sigmasq):
        losses = tf.Variable(np.zeros(n, dtype=np.float32), trainable=True)
        for i in range(k):
            losses.assign_add(phis[:, i]*gaussian_pdf(y, mu[:, i*t:(i+1)*t], sigmasq[:, i]))
        loss = tf.math.reduce_mean(-tf.math.log(losses))
        return loss
    

    Tenga en cuenta que agregamos “trainable=True” a la llamada de tf.Variable, lo que hace que la variable sea parte de los pesos entrenables del modelo.

    Con este cambio, deberíamos poder calcular los gradientes con respecto a los pesos entrenables del modelo:

    with tf.GradientTape() as tape:
        loss = neg_log_likelihood(y, phis, mu, sigmasq)
    
    gradients_init = tape.gradient(loss, model.trainable_weights)
    

    Por supuesto, esto asume que y, phis, mu y sigmasq son tensores que están correctamente definidos en el código.

Comments are closed.