#python #tensorflow #keras #loss #tensorflow-probability
#python #tensorflow #keras #потеря #тензорный поток-вероятность
Вопрос:
При создании пользовательской потери для модели с использованием уровня вероятности промежуточного тензорного потока DistributionLambda
было легко без быстрого выполнения, поскольку слой можно было сохранить в переменной, а затем использовать внутри потери. При включении быстрого выполнения происходит сбой, поскольку сообщается, что сетевые переменные не были оценены на предмет потери. Если вместо DistributionLambda
слоя я использую входные параметры из предыдущего уровня в потере, создавая распределение на месте, то это завершается неудачей, потому что этот входной слой является символическим тензором. Любая помощь о том, как это сделать?
Это полный пример colab, и вот он пример кода:
import numpy as np
from tensorflow.keras import layers
from tensorflow.keras import models
from tensorflow import math
from tensorflow import version
from tensorflow_probability import distributions
from tensorflow_probability import layers as tfp_layers
print(version.GIT_VERSION)
print(version.VERSION)
x = np.array([[1.0], [2.0], [3.0], [4.0], [5.0]])
y = np.array([[6.0, 7.0], [7.0, 8.0], [8.0, 9.0], [9.0, 10.0], [10.0, 11.0]])
def normal_distribution(param):
"""Normal distribution parameterization from input."""
return distributions.Normal(param[:, 0], math.sqrt(math.exp(param[:, 1])))
class DistribNN(object):
"""Neural net with a distributional output."""
def __init__(self):
"""Constructor of DistribNN."""
self._distribution_layer = None
self._predist = None
self._the_model = None
def _loss(self):
"""Correct final loss for this model."""
def likelihood_loss(y_true, y_pred):
"""Adding negative log likelihood loss."""
# return -distributions.Normal(self._predist[:, 0],
# math.sqrt(math.exp(self._predist[:, 1]))).log_prob(
# y_true y_pred - y_pred 0.001)
# return -normal_distribution(self._predist).log_prob(
# y_true y_pred - y_pred 0.001)
return -self._distribution_layer.log_prob(y_true 0.001)
return likelihood_loss
def create_net(self):
"""Create neural net model.."""
input_layer = layers.Input((1,))
dense_layer = layers.Dense(10)(input_layer)
params_dense_layer = layers.Dense(4)(dense_layer)
self._predist = layers.Reshape((2, 2))(params_dense_layer)
self._distribution_layer = tfp_layers.DistributionLambda(
make_distribution_fn=normal_distribution)(self._predist)
last_layer = layers.Lambda(lambda param: param - 0.001)(self._distribution_layer)
self._the_model = models.Model(inputs=input_layer, outputs=last_layer)
self._the_model.compile(loss=self._loss(), optimizer='Adam')
def fit(self, x, y):
self._the_model.fit(x=x, y=y, epochs=2)
one_model = DistribNN()
one_model.create_net()
one_model.fit(x, y)
Выдает ошибку:
v2.3.0-0-gb36436b087
2.3.0
Epoch 1/2
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-3-6b2d34187a56> in <module>()
40 one_model = DistribNN()
41 one_model.create_net()
---> 42 one_model.fit(x, y)
11 frames
/usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/func_graph.py in wrapper(*args, **kwargs)
971 except Exception as e: # pylint:disable=broad-except
972 if hasattr(e, "ag_error_metadata"):
--> 973 raise e.ag_error_metadata.to_exception(e)
974 else:
975 raise
ValueError: in user code:
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:806 train_function *
return step_function(self, iterator)
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:796 step_function **
outputs = model.distribute_strategy.run(run_step, args=(data,))
/usr/local/lib/python3.6/dist-packages/tensorflow/python/distribute/distribute_lib.py:1211 run
return self._extended.call_for_each_replica(fn, args=args, kwargs=kwargs)
/usr/local/lib/python3.6/dist-packages/tensorflow/python/distribute/distribute_lib.py:2585 call_for_each_replica
return self._call_for_each_replica(fn, args, kwargs)
/usr/local/lib/python3.6/dist-packages/tensorflow/python/distribute/distribute_lib.py:2945 _call_for_each_replica
return fn(*args, **kwargs)
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:789 run_step **
outputs = model.train_step(data)
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:757 train_step
self.trainable_variables)
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:2737 _minimize
trainable_variables))
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/optimizer_v2/optimizer_v2.py:562 _aggregate_gradients
filtered_grads_and_vars = _filter_grads(grads_and_vars)
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/optimizer_v2/optimizer_v2.py:1271 _filter_grads
([v.name for _, v in grads_and_vars],))
ValueError: No gradients provided for any variable: ['dense/kernel:0', 'dense/bias:0', 'dense_1/kernel:0', 'dense_1/bias:0'].
Комментарии:
1. Единственное решение, которое я нашел, — это добавить промежуточные слои в качестве выходных данных модели и получить к ним доступ в функции потерь, хотя тогда я должен опубликовать выходные данные процесса, прежде чем передавать их в дальнейший код (это часть более крупного проекта). Я думаю, что это решение работает, но это определенно то, что я хотел.