Как работает TensorFlow batch matmul?

Tensorflow имеет функцию под названием batch_matmul который умножает тензоры высших измерений. Но мне трудно понять, как это работает, возможно, отчасти потому, что мне трудно это представить.

enter image description here

то, что я хочу сделать, это умножить матрицу на каждый срез 3D-тензора, но я не совсем понимаю, что такое форма тензора А. Является ли z самым внутренним измерением? Что из нижеследующего верно?

enter image description here

Я бы предпочел, чтобы первый был правильным - это наиболее интуитивно для меня и легко увидеть .функция eval() выход. Но я подозреваю, что второе верно.

Tensorflow говорит, что batch_matmul выполняет:

out[..., :, :] = matrix(x[..., :, :]) * matrix(y[..., :, :])

что это значит? Что это означает в контексте моего примера? С чем умножается, с чем? И почему я не получаю 3D-тензор, как я ожидал?

6 ответов


вы можете представить себе это как выполнение matmul над каждым примером обучения в партии.

например, если у вас есть два тензора со следующими размерами:

a.shape = [100, 2, 5]
b.shape = [100, 5, 2]

и вы делаете партию tf.matmul(a, b), ваш выход будет иметь форму [100, 2, 2].

100-это ваш размер пакета, два других измерения-это размеры ваших данных.


в первую очередь tf.batch_matmul() был удалены и больше не доступен. Теперь вы предполагаете использовать tf.matmul():

входы должны быть матрицами (или тензорами ранга > 2, представляющими партии матриц), с соответствующими внутренними размерами, возможно, после перенос.

предположим, у вас есть следующий код:

import tensorflow as tf
batch_size, n, m, k = 10, 3, 5, 2
A = tf.Variable(tf.random_normal(shape=(batch_size, n, m)))
B = tf.Variable(tf.random_normal(shape=(batch_size, m, k)))
tf.matmul(A, B)

теперь вы получите тензор формы (batch_size, n, k). Вот что продолжайте. Предположим, у вас есть batch_size матриц nxm и batch_size матриц mxk. Теперь для каждой пары из них вы вычисляете nxm X mxk что дает вам nxk матрица. У вас будет batch_size из них.

обратите внимание, что что-то вроде этого также действительно:

A = tf.Variable(tf.random_normal(shape=(a, b, n, m)))
B = tf.Variable(tf.random_normal(shape=(a, b, m, k)))
tf.matmul(A, B)

и форма (a, b, n, k)


теперь вы можете сделать это с помощью tf.einsum, начиная с Tensorflow 0.11.0rc0.

например,

M1 = tf.Variable(tf.random_normal([2,3,4]))
M2 = tf.Variable(tf.random_normal([5,4]))  
N = tf.einsum('ijk,lk->ijl',M1,M2)       

он умножает матрицу M2 на каждый кадр (3 кадра) в каждой партии (2 партии) в M1.

выход:

[array([[[ 0.80474716, -1.38590837, -0.3379252 , -1.24965811],
        [ 2.57852983,  0.05492432,  0.23039417, -0.74263287],
        [-2.42627382,  1.70774114,  1.19503212,  0.43006262]],

       [[-1.04652011, -0.32753903, -1.26430523,  0.8810069 ],
        [-0.48935518,  0.12831448, -1.30816901, -0.01271309],
        [ 2.33260512, -1.22395933, -0.92082584,  0.48991606]]], dtype=float32),
array([[ 1.71076882, 0.79229093, -0.58058828, -0.23246667],
       [ 0.20446332,  1.30742455, -0.07969904,  0.9247328 ],
       [-0.32047141,  0.66072595, -1.12330854,  0.80426538],
       [-0.02781649, -0.29672042,  2.17819595, -0.73862702],
       [-0.99663496,  1.3840003 , -1.39621222,  0.77119476]], dtype=float32), 
array([[[ 0.76539308, 2.77609682, -1.79906654,  0.57580602, -3.21205115],
        [ 4.49365759, -0.10607499, -1.64613271,  0.96234947, -3.38823152],
        [-3.59156275,  2.03910899,  0.90939498,  1.84612727,  3.44476724]],

       [[-1.52062428,  0.27325237,  2.24773455, -3.27834225,  3.03435063],
        [ 0.02695178,  0.16020992,  1.70085776, -2.8645196 ,  2.48197317],
        [ 3.44154787, -0.59687197, -0.12784094, -2.06931567, -2.35522676]]], dtype=float32)]

Я проверил, арифметика правильная.


tf.tensordot должен решить эту проблему. Он поддерживает пакетные операции, например, если вы хотите заключить контракт 2D-тензора с 3D-тензором, причем последний имеет размер партии.

Если a-форма [n, m] b-форма [?,m, l], то

y = tf.тензордот (B, a, axes=[1, 1]) произведет тензор формы [?, n, l]

https://www.tensorflow.org/api_docs/python/tf/tensordot


Это просто как расщепление на первом измерении соответственно, умножить и объединить их обратно. Если вы хотите сделать 3D 2D, вы можете изменить его, умножить и изменить обратно. I. e. [100, 2, 5] -> [200, 5] -> [200, 2] -> [100, 2, 2]


ответ на этот конкретный ответ использует tf.функция сканирования.

Если a = [5,3,2] #размер партии 5, с мат 3X2 в каждой партии
и b = [2,3] # постоянная матрица, умножаемая на каждый образец

тогда пусть def fn(a, x): возвращение tf.matmul (x,b)

инициализатор = tf.Переменная(ТФ.random_number (3,3))

h = tf.scan (fn,выходы,инициализатор)

этот h будет хранить все выходы.