Конкатенация входного тензора с кратным отрицательным тензором 1 - PullRequest
1 голос
/ 29 сентября 2019

Похожие сообщения: Во-первых, эти 2 сообщения похожи, если не совпадают. Я пытался реализовать это напрасно. Так что я что-то упускаю, вероятно, из-за моей неопытности в Керасе. аналог 1 , аналог 2

Проблема: У меня есть генератор данных для подачи данных в различные модели для оценки производительности модели и обученияKeras.

model.fit_generator(generator=img_gen.next_train(), ....

Одним из входных данных, генерируемых этим генератором, является тензорные «метки» формы = [batch_size, num_letters]. Этот тензор является первым входом для

K.ctc_batch_cost(labels, .... 

, аналогичным image_ocr.py строка 369.

Приведенный выше «пример keras» создает RNN / GRU, где каждый выходшаг RNN является одним входом в ctc, где в RNN есть шаги num_letters, а метки имеют форму (?, num_letters). Это работало нормально для первых 6 моделей, которые я до сих пор тестировал.

Я тестирую новую модель, в которой каждый шаг вывода RNN / GRU представляет собой входы "1 - n" в КТК и оставляет его для обучения. оптимизировать вывод каждого шага. Так что моему КТК в качестве первого ввода необходим тензор формы = (?, Num_letters * n), но генератор данных выдает форму = (?, num_letters).

Примечание: RNN в моей модели фактически выдает какцелая форма = (?, n, num_letters). Я знаю, как преобразовать это в (?, N * num_letters).

Решение 1 - это хак, измените генератор так, чтобы он был уникальным для тестируемой модели. Этот генератор будет генерировать тензоры формы = (?, Num_letters * n). Мне это не нравится, потому что генератор также оценивается и хотел бы, чтобы он был постоянным для каждой оцениваемой модели.

Решение 2 - это хак, создайте генератор, который инкапсулируетисходный генератор и увеличивает полученный результат.

Решение 3: пусть модель принимает входные данные shape = (?, num_letters) и объединяет необходимые отступы, чтобы форма была (?, num_letters* n) что хочет ctc.

Вот что я попробовал:

num_letters = 3
n = 5

keras_tensor_input = keras.layers.Input( shape=[num_letters], dtype='float32' )
print("keras_tensor_input = ", keras_tensor_input)
# keras_tensor_input =  Tensor("input_1:0", shape=(?, 3), dtype=float32)
# note ? is batch size

keras_tensor_neg_1 = keras.backend.constant( -1, dtype='float32', shape=[num_letters] )
print("keras_tensor_neg_1 = ", keras_tensor_neg_1)
# keras_tensor_neg_1 =  Tensor("Const_1:0", shape=(3,), dtype=float32)
# note no batch size

keras_tensor_neg_1_tiled = keras.backend.tile(keras_tensor_neg_1, (n-1))
print("keras_tensor_neg_1_tiled = ", keras_tensor_neg_1_tiled)
# keras_tensor_neg_1_tiled =  Tensor("Tile_2:0", shape=(12,), dtype=float32)
# note no batch size, but now the correct fill length

# FAILED attempt to put in a batch size

layer_const_neg_1 = keras.layers.Lambda(lambda x: keras_tensor_neg_1_tiled ,output_shape=[(n-1)*num_letters] )
keras_tensor_neg_1_prime = layer_const_neg_1(keras_tensor_neg_1)
print("keras_tensor_neg_1_prime = ", keras_tensor_neg_1_prime)
# keras_tensor_neg_1_prime =  Tensor("Tile_2:0", shape=(12,), dtype=float32)

# CRASH AT NEXT STEP BECAUSE NO ? in keras_tensor_neg_1_prime

# concatenate the input from the generator and the padding
keras_tensor_concat = keras.layers.Concatenate()( inputs = [keras_tensor_input, keras_tensor_neg_1_prime] )
print("keras_tensor_concat = ", keras_tensor_concat)

my_model = keras.models.Model( inputs=[keras_tensor_input], output=keras_tensor_concat)

# dummy optimizer, loss, and metric just to allow compile to pass
my_model.compile(optimizer='rmsprop',loss='categorical_crossentropy', metrics=['accuracy'])

# a batch of size 1, for a tensor of shape =[3]
d1 = numpy.array([[1, 2, 3]])

out = my_model.predict( [ d1 ] )
print(out)

Примечания:

  1. мог бы сделать константу shape = [num_letters * (n-1)] и отбросить плитку, но осталась та же проблема с отсутствующим размером пакета.
  2. , если я помещу batch_size в качестве первого измерения, то он все равно завершится ошибкойжалоба на (?, 3) не может быть объединена с (1, 12)

Заранее спасибо.

1 Ответ

0 голосов
/ 30 сентября 2019

Я нашел решение для модели, которая принимает

# a batch of size 1, for a tensor of shape =[3]
d1 = numpy.array([[1, 2, 3]])

и выдает в качестве вывода

out = my_model.predict( [ d1 ] )
print(out)
# [[ 1.  2.  3. -1. -1. -1. -1. -1. -1. -1. -1. -1. -1. -1. -1.]]

Большой урок состоит в том, что keras.layers хочетв качестве ввода вывод других keras.layers . Таким образом, функциональность из keras.backend , например tile , должна быть заключена в keras.layers.Lambda перед подачей их в качестве ввода в keras.layer .

Спасибо

Вот решение:

# instantiate a Keras tensor ... as per document https://keras.io/layers/core/
keras_tensor_input = keras.layers.Input( shape=[num_letters], dtype='float32' )
print("keras_tensor_input = ", keras_tensor_input)
# keras_tensor_input =  Tensor("input_1:0", shape=(?, 3), dtype=float32)

# /12413381/ispolzovanie-vychitaniya-sloya-v-keras
keras_tensor_neg_1 = keras.layers.Lambda(lambda x: -keras.backend.ones_like(x) )(keras_tensor_input)
print("keras_tensor_neg_1 = ", keras_tensor_neg_1)
# keras_tensor_neg_1 =  Tensor("lambda_1/Neg:0", shape=(?, 3), dtype=float32)
# note batch size, just like keras_tensor_input

# https://stackoverflow.com/questions/53250533/how-to-use-tile-function-in-keras
keras_tensor_neg_1_tiled = keras.layers.Lambda(lambda x: keras.backend.tile(x, (1, n-1)))(keras_tensor_neg_1)
print("keras_tensor_neg_1_tiled = ", keras_tensor_neg_1_tiled)
# keras_tensor_neg_1_tiled =  Tensor("Tile_2:0", shape=(12,), dtype=float32)
# note batch size, just like keras_tensor_input

# concatenate the input from the generator and the padding
keras_tensor_concat = keras.layers.Concatenate()( inputs = [keras_tensor_input, keras_tensor_neg_1_tiled] )
print("keras_tensor_concat = ", keras_tensor_concat)
# keras_tensor_concat =  Tensor("concatenate_1/concat:0", shape=(?, 15), dtype=float32)

my_model = keras.models.Model( inputs=keras_tensor_input, output=keras_tensor_concat)

# dummy optimizer, loss, and metric so I can compile and test the model
my_model.compile(optimizer='rmsprop',loss='categorical_crossentropy', metrics=['accuracy'])

# a batch of size 1, for a tensor of shape =[3]
d1 = numpy.array([[1, 2, 3]])

out = my_model.predict( [ d1 ] )
print(out)
# [[ 1.  2.  3. -1. -1. -1. -1. -1. -1. -1. -1. -1. -1. -1. -1.]]
...