Оценка максимального логарифмического правдоподобия нормального распределения с помощью Tensorflow 2.0 - PullRequest
0 голосов
/ 05 августа 2020

Я решил начать изучать TensorFlow 2.0 и в качестве упражнения я хотел реализовать сценарий, который решает задачу оценки максимального логарифмического правдоподобия для нормального распределения. Моя общая проблема в том, что мой скрипт неправильно вычисляет градиенты. Я предполагаю, что моя функция отрицательного правдоподобия определена неправильно или я неправильно использую методы TensorFlow.

Я использовал следующую ссылку для реализации математики. Кто-нибудь знает, почему получаются следующие результаты:

Loss = 1363,5, mean = 1787,0, sigma = 1,0, grads0 = -9,4, grads1 = 110,8

и

Потери = 25160,5, среднее значение = 4116480,5, сигма = -33726359552,0, грады0 = 0,0, грады1 = -0,0

Нормальное распределение, из которого я отбираю данные, имеет среднее значение 1787 и дисперсию 1,0. Вот мой текущий код:

import math as m
import tensorflow as tf
import tensorflow_probability as tfp
tfd = tfp.distributions

SAMPLE_SIZE = 1000
SIGMA = 1.
MEAN = 1787.

INIT_SIGMA = -33726359552.0
INIT_MEAN = 4116480.5


normal_distribution_truth = tfd.Normal(loc=MEAN, scale=SIGMA)
data = normal_distribution_truth.sample(SAMPLE_SIZE)


optimizer = tf.optimizers.SGD(0.5)
mean = tf.Variable(INIT_MEAN, name='mean', dtype=tf.float32)
sigma = tf.Variable(INIT_SIGMA, name='sigma', dtype=tf.float32)


def negative_likelihood(mean, sigma):
    pi_term = ((SAMPLE_SIZE / 2) * tf.math.log(2 * m.pi))
    sigma_term = ((SAMPLE_SIZE / 2) * tf.math.log(tf.math.square(sigma)))

    mean_term = ((1/(2*tf.math.square(sigma)))*tf.reduce_sum(tf.math.square((data-mean))))
    return pi_term+sigma_term+mean_term


opt = tf.keras.optimizers.SGD(learning_rate=0.5)

for i in range(100):
    with tf.GradientTape() as tape:
        y = negative_likelihood(mean, sigma)
    grads = tape.gradient(y, [mean, sigma])
    processed_grads = [g for g in grads]
    print('Loss = {:.1f}, mean = {:.1f}, sigma = {:.1f},  grads0 = {:.1f}, grads1 = {:.1f} '.format(y.numpy(),
                                                                                                    mean.numpy(),
                                                                                                    sigma.numpy(),
                                                                                                    grads[0].numpy(),
                                                                                                    grads[1].numpy()))

    grads_and_vars = zip(processed_grads, [mean, sigma])
    opt.apply_gradients(grads_and_vars)
...