Что я пытаюсь сделать
В настоящее время я делаю очень простой LSTM от последовательности к последовательности, используя Keras с небольшим поворотом, более ранние предсказания в последовательности должны засчитываться против потери меньше, чем позже из них. Я пытаюсь сделать это путем подсчета порядкового номера и умножения на квадрат root этого числа. (Я хочу сделать это, потому что это значение представляет относительный коэффициент неопределенности в процессе Пуассона, основанный на количестве собранных выборок. Моя сеть собирает данные и пытается оценить инвариантное значение на основе собранных данных.)
Как я пытаюсь это сделать
Я реализовал как пользовательскую функцию потерь, так и пользовательский слой.
Функция потерь:
def loss_function(y_true, y_pred):
# extract_output essentially concatenates the first three regression outputs of y
# into a list representing an [x, y, z] vector, and returns it along with the rest as a tuple
r, e, n = extract_output(y_true)
r_h, e_h, n_h = extract_output(y_pred)
# Hyperperameters
dir_loss_weight = 10
dist_loss_weight = 1
energy_loss_weight = 3
norm_r = sqrt(dot(r, r))
norm_r_h = sqrt(dot(r_h, r_h))
dir_loss = mean_squared_error(r/norm_r, r_h/norm_r_h)
dist_loss = mean_squared_error(norm_r, norm_r_h)
energy_loss = mean_squared_error(e, e_h)
return sqrt(n) * (dir_loss_weight * dir_loss + dist_lost_weight * dist_loss + energy_loss_weight * energy_loss)
Пользовательский слой:
class CounterLayer(Layer):
def __init__(self, **kwargs):
super(CounterLayer, self).__init__(**kwargs)
def build(self, input_shape):
self.sequence_number = 0
pass
def call(self, x):
self.sequence_number += 1
return [self.sequence_number]
def compute_output_shape(self, input_shape):
return (1,)
Затем я добавил вход в качестве конкатенации к обычному выводу:
seq_num = CounterLayer()(inputs)
outputs = concatenate([out, seq_num])
Что не так
Моя ошибка:
Traceback (most recent call last):
File "lstm.py", line 119, in <module>
main()
File "lstm.py", line 115, in main
model = create_model()
File "lstm.py", line 74, in create_model
seq_num = CounterLayer()(inputs)
File "/usr/lib/python3.7/site-packages/keras/engine/base_layer.py", line 497, in __call__
arguments=user_kwargs)
File "/usr/lib/python3.7/site-packages/keras/engine/base_layer.py", line 565, in _add_inbound_node
output_tensors[i]._keras_shape = output_shapes[i]
AttributeError: 'int' object has no attribute '_keras_shape'
Я предполагаю, что у меня неправильная форма. Но я не знаю как. Кто-нибудь знает, неправильно ли я поступаю? Что я должен сделать, чтобы это произошло?
Дальнейшие приключения
Согласно комментарию @Mohammad Jafar Mashhadi, мое возвращение call
должно было быть заключено в keras.backend.variable
; однако, согласно его связанному ответу, мой подход не будет работать, потому что call
не вызывается несколько раз, как я изначально предполагал, что это было.
Как я могу получить счетчик для RNN?
Для ясности, если RNN с заданным входом xi выдает yi, я пытаюсь получить i как часть моего вывода.
x1 -> RNN -> (y1, 1)
h1 |
v
x2 -> RNN -> (y2, 2)
h2 |
v
x3 -> RNN -> (y3, 3)
h3 |
v
x4 -> RNN -> (y4, 4)