Как получить кросс-контрактную матрицу из двух 2-мерных тензоров в тензорном потоке? - PullRequest
0 голосов
/ 10 мая 2018
import tensorflow as tf 
with tf.Session() as sess:
    with tf.variable_scope('masssdsms'):
        a = tf.get_variable('a', [1000,24,128], dtype=tf.float32, initializer=tf.random_normal_initializer(stddev=0.1) )
        b = tf.get_variable('b', [1000,15,128], dtype=tf.float32, initializer=tf.random_normal_initializer(stddev=0.1) )

Я хочу получить новый тензор с именем c от a и b. 1000 - размер партии, а форма c должна быть (1000,20, 10, 1). Для каждого экземпляра из a и b: ai и bi они оба являются двумерными тензорами. Новый экземпляр ci является результатом ai и bi и имеет 20 * 10 = 200 элементов, каждый элемент которого является точечным произведением ai и bi с 128-мерным измерением соответственно. Таким образом, в сумме получается 200 точечных произведений. CI больше похож на двухмерное изображение.

enter image description here

Как я могу инициализировать эту операцию?

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

Вот что я делаю, но я не уверен, что это эффективный способ сделать это:

with tf.Session() as sess:
    with tf.variable_scope('masssdsms'):
        a = tf.get_variable('a', [1000,24,128], dtype=tf.float32, initializer=tf.random_normal_initializer(stddev=0.1) )
        b = tf.get_variable('b', [1000,15,128], dtype=tf.float32, initializer=tf.random_normal_initializer(stddev=0.1) )
        i = 999 # for i in range(1000):
        ai = tf.slice(a,[i,0,0],[1,-1,-1]) # (1,24,128)
        bi = tf.slice(b,[i,0,0],[1,-1,-1]) # (1,15,128)
        ci = contact_func(ai,bi) # (1,24,15)

Ответы [ 2 ]

0 голосов
/ 10 мая 2018

Этого можно добиться с умным применением вещания. Попробуйте это:

a = tf.ones([1000, 20, 128])
b = tf.ones([1000, 10, 128])

a = tf.expand_dims(a, axis=1)               # [1000, 1, 20, 128]
b = tf.expand_dims(b, axis=2)               # [1000, 10, 1, 128]

products = a * b                            # [1000, 10, 20, 128]
reduced = tf.reduce_sum(products, axis=-1)  # [1000, 10, 20]

products содержит все попарные умножения всех элементов в a и b. И reduced агрегирует сумму по последней оси.

0 голосов
/ 10 мая 2018

Выполнение matmul матрицы a с транспонированием измерения-1 в b должно дать желаемый результат:

c = tf.matmul(a, tf.transpose(b, [0, 2, 1])) # [1000, 20, 10]

# to get (1000, 20, 10, 1) you do 
tf.expand_dims(c, 3)

EDIT: Для операции contact_func может потребоваться выполнить вещание вручную, используя оператор tile. Вот код для gaussian distance:

 # use tile to repeat the rows 
 d = tf.reshape(tf.tile(a, [1, 1, b.shape[1]]), (-1,a.shape[1]*b.shape[1],a.shape[2]))
     #[1000, 360, 128], 
 # repeat the columns 
 e = tf.tile(b, [1, a.shape[1], 1])
     #[1000, 360, 128]

 # exp(-d_i_j), where d_i_j is the eucludian distance of i, j
 c = tf.reshape(tf.exp(tf.reduce_sum(d-e, 2)), (-1, a.shape[1], b.shape[1]))  
 #[1000, 24, 15]
...