2016-07-06 4 views
13

У меня есть некоторые данные, представленные input_x. Это тензор неизвестного размера (должен быть введен партией), и каждый элемент имеет размер n. input_x подвергается tf.nn.embedding_lookout, так что embed теперь имеет размеры [?, n, m], где m - размер внедрения, а ? относится к неизвестному размеру партии.Tensorflow - матрица входной матрицы с данными пакета

Это описано здесь:

input_x = tf.placeholder(tf.int32, [None, n], name="input_x") 
embed = tf.nn.embedding_lookup(W, input_x) 

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

Сначала я попытался использовать tf.matmul, но он дает ошибку из-за несоответствия в фигурах. Затем я попытался следующие, расширяя размерность U и применяя batch_matmul (я также пытался функцию от tf.nn.math_ops., результат был тот же):

U = tf.Variable(...)  
U1 = tf.expand_dims(U,0) 
h=tf.batch_matmul(embed, U1) 

Это проходит первоначальную компиляцию, но тогда, когда фактические данные приложенное, я получаю следующее сообщение об ошибке:

In[0].dim(0) and In[1].dim(0) must be the same: [64,58,128] vs [1,128,128]

Я также знаю, почему это происходит - я копировал измерение U и теперь 1, но размер minibatch, 64, Безразлично» t подходит.

Как я могу правильно выполнить умножение матрицы на моем тензорном матричном вводе (для неизвестного размера партии)?

+0

Просто добавить одну вещь. Вам нужно будет добавить инициализатор для функции сканирования, размер вывода ваших двух матричных умножений, U * x –

+0

В настоящее время [tf.matmul] (http://stackoverflow.com/a/43829731/1090562) является правильным способ выполнения пакетного умножения. –

ответ

10

matmul operation работает только с матрицами (2D тензоры). Вот два основных подхода к этому: оба предполагают, что U является двумерным тензором.

  1. фрагмент embed в 2D тензоров и умножать каждый из них с U индивидуально. Это, вероятно, проще всего сделать с помощью tf.scan() так:

    h = tf.scan(lambda a, x: tf.matmul(x, U), embed) 
    
  2. С другой стороны, если эффективность имеет важное значение, может быть лучше, чтобы изменить embed быть 2D тензор поэтому умножение может быть сделано с помощью одного matmul как это:

    embed = tf.reshape(embed, [-1, m]) 
    h = tf.matmul(embed, U) 
    h = tf.reshape(h, [-1, n, c]) 
    

    где c это число столбцов в U. Последнее изменение будет гарантировать, что h представляет собой трехмерный тензор, где 0-й размер соответствует партии, как и исходные x_input и embed.

+0

Спасибо! Я забочусь об эффективности. Сколько я должен избегать варианта 1, или же тензорный поток (с графическим процессором и т. Д.) Делает это более или менее эффективно? О опции 2, я теряю часть структуры матрицы таким образом, не так ли? Я удивлен, что нет никакой поддержки для этой операции. Разве это не обычная операция? – yoki

+0

@yoki Если я не ошибся, результаты двух подходов должны быть полностью идентичными после второго изменения в варианте 2. В основном я включил вариант 1, потому что может быть проще понять, как и почему он работает. Я не думаю, что вы делаете очень часто за пределами повторяющихся сетей. (Это одно из основных применений 'scan'.) Я заметил, что существует операция [' batch_matmul'] (https://www.tensorflow.org/versions/master/api_docs/python/math_ops.html#batch_matmul) которые вы также можете использовать, но для этого вам нужно будет создать множество копий вашей матрицы 'U'. – Styrke

+1

@yoki На самом деле теперь, когда я думаю об этом, то, что вы пытаетесь сделать, на самом деле не имеет никакого значения. Поскольку матричное умножение является ассоциативным, вы получите тот же результат, умножив 'W' на' U', прежде чем вы начнете поиск вложений, а затем просмотрите вложения в этом продукте. Поэтому, если вы не делаете что-то экзотическое, о котором я не знаю, самым эффективным подходом было бы просто определить единую матрицу, которая представляет 'WU', вместо того, чтобы фактически определять оба, а затем умножать их вместе. – Styrke

4

Как ответил @Stryke, есть два пути для достижения этой цели: 1. Сканирование и 2. перепрофилирования

  1. tf.scan требует лямбда-функции и, как правило, используется для рекурсивных операций.Некоторые примеры для них приведены здесь: https://rdipietro.github.io/tensorflow-scan-examples/

  2. Я лично предпочитаю переформировать, поскольку он более интуитивно понятен. Если вы пытаетесь матрицей умножить каждую матрицу в трехмерном тензоре на матрицу, являющуюся 2D-тензором, например Cijl = Aijk * Bkl, вы можете сделать это с простой перестановкой.

    A' = tf.reshape(Aijk,[i*j,k]) 
    C' = tf.matmul(A',Bkl) 
    C = tf.reshape(C',[i,j,l]) 
    
37

Предыдущие ответы устарели. В настоящее время tf.matmul() поддержки тензоры с рангом> 2:

The inputs must be matrices (or tensors of rank > 2, representing batches of matrices), with matching inner dimensions, possibly after transposition.

Также tf.batch_matmul() был удален и tf.matmul() правильный способ сделать пакетное умножение. Основная идея может быть понята из следующего кода:

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)

+1

Каков правильный способ сделать это, если, как и в вопросе, вы хотите размножить одну матрицу со многими другими? Вам нужно реплицировать (черепицу) одну матрицу batch_sizetimes или есть лучший способ? – KarlSt

+1

@KarlSt Основываясь на моих экспериментах, это не работает, когда первые измерения N-2 не совпадают. Очевидно, что numpy-версия этой команды поддерживает широковещательную рассылку, но я думаю, что единственный способ сделать это в TF - это разбиение времени на единую матрицу batch_size.Я даже попробовал сыграть транспонированные трюки (так что это выглядит так: [batch_size, n, m], а вторая - [1, m, k]), не повезло. Я не уверен, что это можно назвать ошибкой, но ясно, что это должно быть реализовано в TF с его такой общей операции. – sirgogo

+0

Я нашел здесь лучший способ: https://groups.google.com/a/tensorflow.org/forum/#!topic/discuss/4tgsOSxwtkY Вы можете скомпоновать два измерения, не используемые при умножении, с использованием изменения, умножения две матрицы, а затем перезвоним, чтобы получить желаемую форму. Это эквивалентно выполнению пакетного умножения. – KarlSt

Смежные вопросы