Трансляция динамического измерения в Tensorflow

Я использую Tensorflow из Python. У меня есть два тензора, которые я хочу объединить (это может быть и другая операция, я не думаю, что точная операция имеет значение для этого вопроса). Форма этих тензоров определяется как (N1 != N2 — положительные целые числа):

a: (None, N1)
b: (1   , N2)

Поскольку я буду конкатенировать по последней оси, кажется, что эту операцию можно выполнить. Но тензорный поток отказывает. Код

from tensorflow import keras
from tensorflow.keras import layers

N1 = 2
N2 = 3
D1 = None

a = keras.Input(shape=(D1, N1))
b = keras.Input(shape=(1, N2))

c = layers.Concatenate(axis=-1)([a, b])

терпит неудачу с

ValueError: A `Concatenate` layer requires inputs with matching shapes except for the concat axis. Got inputs shapes: [(None, None, 2), (None, 1, 3)]

Ближе всего к выполнению этой работы я подошел к использованию RepeatVector, как показано ниже, но, к сожалению, это работает только со статическими размерами, а не с динамическими:

N1 = 2
N2 = 3
D1 = 7

a = keras.Input(shape=(D1, N1))
b = keras.Input(shape=(N2))
b_repeated = layers.RepeatVector(D1)(b)

c = layers.Concatenate()([a, b_repeated])

Будем очень признательны за любые предложения о том, как объединить - т.е. сделать правильную трансляцию или повторение - с такими None размерами!


person josteinb    schedule 15.10.2019    source источник
comment
Вы не можете напрямую конкатенировать тензоры с фигурами (None, N1) и (1, N2) вдоль второй оси, как говорится в сообщении, каждое другое измерение (здесь только первое) должно иметь одинаковый размер. Вы хотите повторить второй тензор столько раз, сколько первое измерение первого тензора и затем соединить?   -  person jdehesa    schedule 15.10.2019
comment
Повторение тензора, а затем объединение было бы прекрасно! Есть ли способ сделать это?   -  person josteinb    schedule 15.10.2019


Ответы (1)


Вот способ сделать это с помощью лямбда-слоя:

import keras
from keras import layers
import keras.backend as K

N1 = 2
N2 = 3
D1 = None

a = keras.Input(shape=(D1, N1))
b = keras.Input(shape=(N2,))
c = layers.Lambda(lambda ab: K.concatenate([ab[0], K.repeat(ab[1], K.shape(ab[0])[1])],
                                           axis=-1))([a, b])
print(c)
# Tensor("lambda_1/concat:0", shape=(?, ?, 5), dtype=float32)
person jdehesa    schedule 15.10.2019
comment
Это сработало, спасибо. Поскольку я также имел дело с некоторыми тензорами более высокого ранга, я обнаружил, что keras.backend.repeat_elements также очень полезен, поскольку он может работать с тензорами не ранга 2. - person josteinb; 16.10.2019