У меня есть две сети 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