Потери Кераса с участием многомерного нормального закона с полной ковариационной матрицей - PullRequest
0 голосов
/ 22 апреля 2020

У меня есть две сети MLP (написанные с помощью Keras), одна выводит вектор средних значений, а другой - вектор значений дисперсии, которые в конечном итоге должны сформировать ковариационную матрицу. Обе обучаются одна за другой, партия за партию (тренировка последней партии -> создать новую партию -> повторить). Таким образом, у меня есть две одинаковые потери, одна из которых y_pred является предсказанным вектором средних значений (а значения дисперсии являются дополнительным параметром потери), и наоборот. Не удивительно, что потеря, которую мне нужно использовать, использует многомерное нормальное распределение с полной ковариационной матрицей.

Вот пользовательские потери Keras для сети, выводящей сигма-вектор:

def sigma_loss(self, adv, mu):
  def loss(y_true, y_pred):
    dmu       = y_true - mu
    tmu       = tf.transpose(dmu)
    cov       = tf.reshape(y_pred,
                          [-1, self.act_dim, self.act_dim])
    cov       = tf.square(cov)
    det       = tf.linalg.det(cov)
    log_det   = kb.log(det)
    icov      = tf.linalg.inv(cov)

    loss_sg = tf.multiply(icov, dmu)
    loss_sg = tf.multiply(tmu, loss_sg)
    loss_sg = loss_sg + log_det

    the_loss = -0.5*kb.mean(loss_sg)

    return the_loss
return loss

I довольно долго боролся с этим, не понимая его механики. Я понял, что все должно быть с помощью keras backend, поэтому может произойти автоматическое дифференцирование c. Но:

  • Нужно ли всегда вызывать keras.backend, или tf. функции в порядке, как я делал выше?
  • Как мне обработать размер партии? Точнее, все в порядке здесь для операции tf.reshape для сигмы?

В данный момент я не могу правильно выполнить тестирование, так как у меня появляется следующая ошибка:

Traceback (most recent call last):
  File "start.py", line 18, in <module>
    n_avg, clip_adv, mirror_adv)
  File "/Users/viquerat/cemef/machine_learning/ppo/training.py", line 69, in launch_training
    agent.train_network()
  File "/Users/viquerat/cemef/machine_learning/ppo/ppo_cma.py", line 254, in train_network
    verbose = 0)
  File "/usr/local/lib/python3.7/site-packages/tensorflow/python/keras/engine/training.py", line 880, in fit
    validation_steps=validation_steps)
  File "/usr/local/lib/python3.7/site-packages/tensorflow/python/keras/engine/training_arrays.py", line 329, in model_iteration
    batch_outs = f(ins_batch)
  File "/usr/local/lib/python3.7/site-packages/tensorflow/python/keras/backend.py", line 3076, in __call__
    run_metadata=self.run_metadata)
  File "/usr/local/lib/python3.7/site-packages/tensorflow/python/client/session.py", line 1439, in __call__
    run_metadata_ptr)
  File "/usr/local/lib/python3.7/site-packages/tensorflow/python/framework/errors_impl.py", line 528, in __exit__
    c_api.TF_GetCode(self.status.status))
tensorflow.python.framework.errors_impl.InvalidArgumentError: Input is not invertible.
     [[{{node training/Adam/gradients/loss_1/dense_3_loss/det_grad/MatrixInverse}}]]

что, скорее всего, связано с тем, как я изменяю свою ковариационную матрицу.

Для полноты, вот потеря для сети, выводящей значения mu:

def mean_loss(self, adv, sigma):
  def loss(y_true, y_pred):

    dmu       = y_true - y_pred
    tmu       = tf.transpose(dmu)
    cov       = tf.reshape(sigma,
                      [-1, self.act_dim, self.act_dim])
    det       = tf.linalg.det(cov)
    log_det   = kb.log(det)
    icov      = tf.linalg.inv(cov)

    loss_mu = tf.multiply(icov, dmu)
    loss_mu = tf.multiply(tmu, loss_mu)
    loss_mu = loss_mu + log_det

    the_loss = -0.5*kb.mean(loss_mu)

    return the_loss
  return loss

Любая подсказка или идея будет оценена.

Редактировать

Я пытался использовать tfp.distributions.MultivariateNormalFullCovariance безуспешно. Простая загрузка пакета вынуждает меня обновить тензор потока с 1.13.1 до 2.1, и при этом больше ничего не работает:

Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/tensorflow_core/python/eager/execute.py", line 61, in quick_execute
    num_outputs)
TypeError: An op outside of the function building code is being passed
a "Graph" tensor. It is possible to have Graph tensors
leak out of the function building context by including a
tf.init_scope in your function building code.
For example, the following function will fail:
  @tf.function
  def has_init_scope():
    my_constant = tf.constant(1.)
    with tf.init_scope():
      added = my_constant * 2
The graph tensor has name: input_6:0
...