Нет трансляции для tf.matmul в TensorFlow

У меня есть проблема, с которой я боролся. Это связано с tf.matmul() и его отсутствием в эфире.

Мне известно о похожей проблеме на https://github.com/tensorflow/tensorflow/issues/216, но tf.batch_matmul() не похоже на решение для моего случая.

Мне нужно закодировать входные данные в виде 4D-тензора: X = tf.placeholder(tf.float32, shape=(None, None, None, 100)) Первое измерение — это размер пакета, второе — количество записей в пакете. Вы можете представить каждую запись как композицию ряда объектов (третье измерение). Наконец, каждый объект описывается вектором из 100 значений с плавающей запятой.

Обратите внимание, что я использовал None для второго и третьего измерений, потому что фактические размеры могут меняться в каждой партии. Однако для простоты сформируем тензор с реальными числами: X = tf.placeholder(tf.float32, shape=(5, 10, 4, 100))

Это шаги моего вычисления:

  1. вычислить функцию каждого вектора из 100 значений с плавающей запятой (например, линейную функцию) W = tf.Variable(tf.truncated_normal([100, 50], stddev=0.1)) Y = tf.matmul(X, W) проблема: нет трансляции для tf.matmul() и нет успеха с использованием tf.batch_matmul() ожидаемой формы Y: (5, 10, 4, 50)

  2. применение среднего пула для каждой записи пакета (по объектам каждой записи): Y_avg = tf.reduce_mean(Y, 2) ожидаемая форма Y_avg: (5, 10, 50)

Я ожидал, что tf.matmul() будет поддерживать вещание. Затем я нашел tf.batch_matmul(), но все же похоже, что это не относится к моему случаю (например, W должен иметь как минимум 3 измерения, непонятно почему).

Кстати, выше я использовал простую линейную функцию (веса которой хранятся в W). Но в моей модели вместо этого у меня есть глубокая сеть. Итак, более общая проблема, с которой я сталкиваюсь, заключается в автоматическом вычислении функции для каждого среза тензора. Вот почему я ожидал, что tf.matmul() будет иметь широковещательное поведение (если это так, возможно, tf.batch_matmul() даже не понадобится).

С нетерпением ждем возможности учиться у вас! Алессио


person Alessio B    schedule 27.06.2016    source источник


Ответы (2)


Вы можете добиться этого, изменив форму X на форму [n, d], где d — это размерность одного единственного «экземпляра» вычисления (100 в вашем примере), а n — это количество этих экземпляров в вашем многомерном объекте (5*10*4=200 в вашем примере) . После изменения формы вы можете использовать tf.matmul, а затем вернуть желаемую форму. Тот факт, что первые три измерения могут различаться, немного усложняет задачу, но вы можете использовать tf.shape для определения фактических форм во время выполнения. Наконец, вы можете выполнить второй шаг ваших вычислений, который должен быть простым tf.reduce_mean по соответствующему измерению. В целом это будет выглядеть так:

X = tf.placeholder(tf.float32, shape=(None, None, None, 100))
W = tf.Variable(tf.truncated_normal([100, 50], stddev=0.1))
X_ = tf.reshape(X, [-1, 100])
Y_ = tf.matmul(X_, W)
X_shape = tf.gather(tf.shape(X), [0,1,2]) # Extract the first three dimensions
target_shape = tf.concat(0, [X_shape, [50]])
Y = tf.reshape(Y_, target_shape)
Y_avg = tf.reduce_mean(Y, 2)
person lballes    schedule 27.06.2016
comment
Спасибо за Ваш ответ. К сожалению, у вашего решения есть две проблемы: 1. оно усредняет по всем векторам, что неверно 2. изменение формы допустимо только в случае тензора фиксированной формы, тогда как у меня есть партии, в которых различаются первые 3 параметра (фиксированные в каждой партии, разные в разных партиях) - person Alessio B; 29.06.2016
comment
Почему он усредняется по всем векторам? X[i, j, k, :] представляет собой единый вектор, верно? Изменяя форму так, как я предложил, мы складываем эти векторы в большую матрицу (каждая строка содержит один из векторов). Если мы теперь выполним умножение матриц, каждая строка будет умножена на матрицу отдельно. Теперь мы можем делать с каждой строкой то, что нужно (например, взять среднее значение, как в вашем примере), а затем изменить форму до той формы, которую мы хотим иметь. Я не вижу, где мы берем среднее значение по векторам, но я могу что-то упустить. - person lballes; 29.06.2016
comment
Что касается второй проблемы, пока размерность векторов (100 в вашем примере) фиксирована, tf.reshape(X, [-1, 100]) должно работать нормально? Используя -1 , теперь нет необходимости в других измерениях априори. - person lballes; 29.06.2016
comment
Правда, не усредняет по всем векторам, но то, что вы реализовали, мне не нужно. Ваш код получает скаляр для каждого вектора, тогда как мне нужен средний вектор для каждого среза тензора. Фактически, в своем вопросе я указал, что ожидаемая форма Y_avg должна быть (5, 10, 50): третье измерение исчезает, потому что мы получаем средний вектор из 50 элементов. Что касается второй проблемы, правда, я могу использовать -1 для изменения формы, но тогда я не могу вернуться к исходной форме тензора. Приносим извинения, если мой вопрос не ясен на 100%, и еще раз большое спасибо за вашу помощь! - person Alessio B; 29.06.2016
comment
PS: Y_avg_ в вашем коде имеет форму (200), поэтому вы даже не можете изменить форму с помощью Y_avg = tf.reshape(Y_avg_, [5, 10, 50]), потому что 200 != 5 * 10 * 50 - person Alessio B; 29.06.2016
comment
О да, я вижу. Я совершенно неправильно понял вторую часть вашего расчета. Тем не менее, я думаю, что то, что вы хотите сделать, может быть достигнуто с помощью tf.reshape. Я отредактирую ответ! - person lballes; 29.06.2016
comment
Прохладный! Вот и все! Наконец-то я научился передавать целевую форму в виде тензора. Спасибо большое Лукас :) - person Alessio B; 30.06.2016
comment
Ааа! Спасибо, парни! Долго боролся с этой проблемой :):):):):) - person stianlp; 20.02.2017

Как следует из переименованного названия проблемы GitHub, на которую вы ссылаетесь, вы должны использовать tf.tensordot(). Это позволяет сжимать пары осей между двумя тензорами в соответствии с Numpy tensordot(). Для вашего случая:

X = tf.placeholder(tf.float32, shape=(5, 10, 4, 100))
W = tf.Variable(tf.truncated_normal([100, 50], stddev=0.1))
Y = tf.tensordot(X, W, [[3], [0]])  # gives shape=[5, 10, 4, 50]
person buzjwa    schedule 17.10.2018