Объединение тензоров произвольной формы

#python #tensorflow

#python #тензорный поток

Вопрос:

Я хотел бы объединить два тензора переменной длины.

Поскольку они не совпадают по форме, я не могу использовать tf.concat или tf.stack.

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

Например,

 a = [ [1,2], [3,4] ]
flat_b = [5, 6]

combine(a, flat_b) would be [ [ [1,5,6], [2,5,6] ],
                              [ [3,5,6], [4,5,6] ] ]
 

Есть ли такой метод?

Ответ №1:

Использование tf.map_fn с tf.concat , пример кода:

 import tensorflow as tf

a = tf.constant([ [1,2], [3,4] ])
flat_b = [5, 6]
flat_a = tf.reshape(a, (tf.reduce_prod(a.shape).numpy(), ))[:, tf.newaxis]
print(flat_a)
c = tf.map_fn(fn=lambda t: tf.concat([t, flat_b], axis=0), elems=flat_a)
c = tf.reshape(c, (-1, a.shape[1], c.shape[1]))
print(c)
 

Выводит:

 tf.Tensor(
[[1]
 [2]
 [3]
 [4]], shape=(4, 1), dtype=int32)
tf.Tensor(
[[[1 5 6]
  [2 5 6]]

 [[3 5 6]
  [4 5 6]]], shape=(2, 2, 3), dtype=int32)
 

Комментарии:

1. я получаю InvalidArgumentError: ввод размеров должен быть 1-D, а не [] [Op: Reshape], возможно, это зависит от версии tf или чего-то еще

2. @ Какую версию TF вы используете? Я тестирую с использованием TF версии V2.3

3. tensorflow 2.0.0

4. @MaxYarmolinsky откуда у вас ошибка?

5. flat_a = tf.reshape(a, tf.reduce_prod(a.shape))[:, tf.newaxis] …. InvalidArgumentError: ввод размеров должен быть 1-D, а не [] [Op:Reshape]

Ответ №2:

Вот несколько более простая версия предыдущего ответа. Вместо того, чтобы изменять форму несколько раз, я предпочитаю использовать tf.expand_dims и tf.stack . Последнее добавляет измерение, так что на один вызов меньше tf.reshape , что может сбить с толку.

 import tensorflow as tf

a = tf.constant([[1,2], [3,4]])
b = [5, 6]

flat_a = tf.reshape(a, [-1]) 

c = tf.map_fn(lambda x: tf.concat([[x], b], axis=0), flat_a)
c = tf.stack(tf.split(c, num_or_size_splits=len(a)), axis=0)
 
 <tf.Tensor: shape=(2, 2, 3), dtype=int32, numpy=
array([[[1, 5, 6],
        [2, 5, 6]],
       [[3, 5, 6],
        [4, 5, 6]]])>
 

Ответ №3:

Вы могли бы пройти по элементам. В форме списка вы должны сделать что-то вроде out[i][j] = [a[i][j]] flat_b, начиная с того, что out имеет ту же форму, что и a . Это приведет к желаемой форме. Я не уверен, существует ли такая поэлементная конкатенация в библиотеке tensorflow.