#python #tensorflow #keras
Вопрос:
Я пытаюсь создать слой взвешенной суммы, который выполняет взвешенную сумму из нескольких параллельных слоев, аналогичную той, что опубликована здесь, за исключением того, что я хочу иметь возможность определять количество входных слоев (т. Е. Количество весов n, где n определяется как создание экземпляра), и я хочу использовать нормализованные веса. Однако я получаю эту ошибку:
Traceback (most recent call last):
File "multi_fidelity_training_full_link.py", line 341, in <module>
main()
File "multi_fidelity_training_full_link.py", line 283, in main
linked_model.fit(x,y,batch_size = batch_size, epochs = mult_of*(1 i), verbose = 2, initial_epoch = mult_of*i)
File "/usr/WS2/mvander/py3venv/py3venv/lib/python3.7/site-packages/tensorflow/python/keras/engine/training.py", line 1183, in fit
tmp_logs = self.train_function(iterator)
File "/usr/WS2/mvander/py3venv/py3venv/lib/python3.7/site-packages/tensorflow/python/eager/def_function.py", line 889, in __call__
result = self._call(*args, **kwds)
File "/usr/WS2/mvander/py3venv/py3venv/lib/python3.7/site-packages/tensorflow/python/eager/def_function.py", line 950, in _call
return self._stateless_fn(*args, **kwds)
File "/usr/WS2/mvander/py3venv/py3venv/lib/python3.7/site-packages/tensorflow/python/eager/function.py", line 3024, in __call__
filtered_flat_args, captured_inputs=graph_function.captured_inputs) # pylint: disable=protected-access
File "/usr/WS2/mvander/py3venv/py3venv/lib/python3.7/site-packages/tensorflow/python/eager/function.py", line 1961, in _call_flat
ctx, args, cancellation_manager=cancellation_manager))
File "/usr/WS2/mvander/py3venv/py3venv/lib/python3.7/site-packages/tensorflow/python/eager/function.py", line 596, in call
ctx=ctx)
File "/usr/WS2/mvander/py3venv/py3venv/lib/python3.7/site-packages/tensorflow/python/eager/execute.py", line 75, in quick_execute
raise e
File "/usr/WS2/mvander/py3venv/py3venv/lib/python3.7/site-packages/tensorflow/python/eager/execute.py", line 60, in quick_execute
inputs, attrs, 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: linked_model/high_fidelity_model/weighted_sum/truediv:0
Мой код таков:
class WeightedSum(krs.layers.Layer):
def __init__( self, n_models = 2, **kwargs):
super( WeightedSum, self ).__init__( **kwargs)
self.n_models = n_models
w_init = tf.random_uniform_initializer()
self.sum_weights = tf.Variable(initial_value = w_init(shape=(1,self.n_models)),trainable=True)
self.sum_weights = tf.divide(self.sum_weights,tf.math.reduce_sum(self.sum_weights))
def call(self,inputs):
self.sum_weights = tf.divide(self.sum_weights,tf.math.reduce_sum(self.sum_weights))
output = tf.multiply(tf.cast(self.sum_weights[0,0],inputs[0].dtype),inputs[0])
for i in range(1,len(inputs)):
output = tf.multiply(inputs[i],tf.cast(self.sum_weights[0,i],inputs[0].dtype))
return output
Как мне заставить это работать?
Примечание: У меня есть другая версия этого кода, которая выглядит совсем по-другому, которая строится и обучается, но выдает ошибку unicode при попытке сохранения. Ошибка почти наверняка исходит от моего слоя WeightedSum.
Ответ №1:
Решение проблемы требует реализации ограничения и использования add_weight
функции. Ограничение требуется, потому что по какой-то причине tf.divide
его нельзя использовать так, как показано в вопросе.
class NormalizeSumWeights(krs.constraints.Constraint):
def __init__(self,**kwargs):
super(NormalizeSumWeights,self).__init__(**kwargs)
def call(self,w):
return tf.math.divide(w,tf.math.reduce_sum(w))
с изменением класса WeightedSum на этот.
class WeightedSum(krs.layers.Layer):
def __init__( self, n_models = 2, **kwargs):
super( WeightedSum, self ).__init__( **kwargs)
self.n_models = n_models
def build(self,input_shape):
self.sum_weights = self.add_weight(name="sum_weights",shape=(1,self.n_models),
initializer = krs.initializers.RandomUniform(0,1.0),
constraint = NormalizeSumWeights(),
trainable = True)
def call(self,inputs):
output = tf.multiply(tf.cast(self.sum_weights[0,0],inputs[0].dtype),inputs[0])
for i in range(1,len(inputs)):
output = tf.multiply(inputs[i],tf.cast(self.sum_weights[0,i],inputs[0].dtype))
return output
def get_config(self):
data = { "n_models": self.n_models}
return data