2016-07-06 37 views
13

Tôi có một số dữ liệu được đại diện bởi input_x. Nó là một tensor có kích thước không xác định (nên được nhập vào theo lô) và mỗi mục có kích thước n. input_x trải qua tf.nn.embedding_lookout, sao cho embed hiện có kích thước [?, n, m] trong đó m là kích thước nhúng và ? là kích thước lô không xác định.Tensorflow - matmul của ma trận đầu vào với dữ liệu lô

này được mô tả ở đây:

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

bây giờ tôi đang cố gắng để nhân lên mỗi mẫu trong dữ liệu đầu vào của tôi (mà bây giờ là một ma trận nhúng) bởi một biến ma trận, U, và tôi dường như không thể để biết cách làm điều đó.

Lần đầu tiên tôi thử sử dụng tf.matmul nhưng lỗi này do lỗi không phù hợp về hình dạng. sau đó tôi thử như sau, bằng cách mở rộng kích thước của U và áp dụng batch_matmul (Tôi cũng đã cố gắng hàm từ tf.nn.math_ops., kết quả là như nhau):

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

này vượt qua biên soạn ban đầu, nhưng sau đó khi dữ liệu thực tế là ứng dụng, tôi nhận được lỗi sau:

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

tôi cũng biết tại sao điều này xảy ra - tôi lặp lại kích thước của U và bây giờ là 1, nhưng kích thước minibatch, 64, doesn' t phù hợp.

Làm cách nào tôi có thể thực hiện phép nhân ma trận trên đầu vào ma trận tensor của mình một cách chính xác (đối với kích thước lô chưa biết)?

+0

Chỉ cần thêm một điều. Bạn sẽ phải thêm initializer để quét chức năng, với kích thước của đầu ra của hai phép nhân ma trận của bạn, U * x –

+0

Hiện tại [tf.matmul] (http://stackoverflow.com/a/43829731/1090562) là quyền cách để làm phép nhân hàng loạt. –

Trả lời

10

matmul operation chỉ hoạt động trên các ma trận (bản nén 2D). Dưới đây là hai cách tiếp cận chính để làm điều này, cả hai giả định rằng U là một tensor 2D.

  1. Slice embed vào tensors 2D và nhân mỗi người trong số họ với U riêng. Đây có lẽ là dễ nhất để làm bằng tf.scan() như thế này:

    h = tf.scan(lambda a, x: tf.matmul(x, U), embed) 
    
  2. Mặt khác nếu hiệu quả là rất quan trọng nó có thể là tốt hơn để định hình lại embed là một tensor 2D nên nhân có thể được thực hiện với một đơn matmul như này:

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

    nơi số cột trong U. Lần thay đổi hình ảnh cuối cùng sẽ đảm bảo rằng h là một hình chữ nhật 3D, trong đó thứ nguyên thứ 0 tương ứng với lô giống như số gốc x_inputembed.

+0

Cảm ơn bạn! Tôi quan tâm đến hiệu quả. Bao nhiêu tôi nên tránh tùy chọn 1, hoặc không tensorflow (với GPU vv) làm điều đó hiệu quả nhiều hơn hoặc ít hơn? Về tùy chọn 2, tôi mất một số cấu trúc ma trận theo cách này, phải không? Tôi ngạc nhiên không có hỗ trợ cho hoạt động này. Nó không phải là một hoạt động phổ biến? – yoki

+0

@yoki Trừ khi tôi thực hiện một số sai lầm, kết quả từ hai cách tiếp cận phải hoàn toàn giống nhau sau khi định hình lại thứ hai trong tùy chọn 2. Tôi chủ yếu bao gồm tùy chọn 1 vì có thể dễ hiểu hơn và tại sao nó hoạt động. Tôi không nghĩ rằng những gì bạn đang làm là rất phổ biến bên ngoài các mạng tái phát. (Đó là một trong những ứng dụng chính của 'quét'.) Tôi nhận thấy có một [' batch_matmul'] (https://www.tensorflow.org/versions/master/api_docs/python/math_ops.html#batch_matmul) hoạt động mà bạn cũng có thể sử dụng, nhưng bạn sẽ cần tạo nhiều bản sao của ma trận 'U' để sử dụng. – Styrke

+1

@yoki Thực ra bây giờ tôi đang nghĩ về nó, điều bạn đang cố gắng làm có lẽ không thực sự tạo nên sự khác biệt. Vì phép nhân là ma trận kết hợp, bạn sẽ nhận được kết quả giống hệt nhau bằng cách nhân 'W' với' U' trước khi bạn thực hiện tra cứu nhúng và sau đó tìm kiếm nhúng trong sản phẩm đó. Vì vậy, trừ khi bạn đang làm điều gì đó kỳ lạ mà tôi không biết, cách tiếp cận hiệu quả nhất sẽ chỉ đơn giản là xác định một ma trận đơn đại diện cho 'WU' thay vì thực sự xác định cả hai và sau đó nhân chúng với nhau. – Styrke

4

Như đã trả lời bởi @Stryke, có hai cách để đạt được điều này: 1. Quét và 2. Tái

  1. tf.scan đòi hỏi hàm lambda và thường được sử dụng cho các hoạt động đệ quy.Một số ví dụ cho tương tự ở đây: https://rdipietro.github.io/tensorflow-scan-examples/

  2. Cá nhân tôi thích định hình lại vì nó trực quan hơn. Nếu bạn đang cố gắng ma trận nhân mỗi ma trận trong bộ tạo hình 3D bằng ma trận là băng tải 2D, như Cijl = Aijk * Bkl, bạn có thể làm điều đó với một hình dạng đơn giản.

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

câu trả lời trước là lỗi thời. Hiện nay tf.matmul() hỗ trợ tensors với rank> 2:

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

Cũng tf.batch_matmul() đã được gỡ bỏ và tf.matmul() là đúng cách để làm nhân hàng loạt. Ý tưởng chính có thể được hiểu từ mã sau:

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) 

Bây giờ bạn sẽ nhận được một hình dạng có độ bền là (batch_size, n, k). Đây là những gì đang diễn ra ở đây. Giả sử bạn có batch_size ma trận nxmbatch_size ma trận mxk. Bây giờ cho mỗi cặp bạn tính nxm X mxk, cung cấp cho bạn ma trận nxk. Bạn sẽ có batch_size trong số họ.

Chú ý rằng một cái gì đó như thế này cũng là hợp lệ:

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) 

và sẽ cung cấp cho bạn một hình dạng (a, b, n, k)

+1

Cách chính xác để làm điều này là gì, nếu như trong câu hỏi, bạn muốn nhân một ma trận với nhiều ma trận khác? Bạn có phải nhân rộng (gạch) các ma trận đơn batch_sizetimes hoặc là có một cách tốt hơn? – KarlSt

+1

@KarlSt Dựa trên các thử nghiệm của tôi, điều này không hoạt động khi thứ nguyên N-2 đầu tiên không khớp. Rõ ràng, phiên bản gọn gàng của lệnh này hỗ trợ phát thanh truyền hình, nhưng tôi nghĩ cách duy nhất để làm điều đó trong TF là để gạch một lần batch_size ma trận duy nhất.Tôi thậm chí đã thử chơi thủ thuật chuyển vị (vì vậy có vẻ như ma trận là [batch_size, n, m] và ma trận thứ hai là [1, m, k]), không may mắn. Tôi không chắc chắn nó có thể được gọi là một lỗi, nhưng rõ ràng, điều này nên được thực hiện trong TF kể từ khi một hoạt động phổ biến của nó. – sirgogo

+0

Tôi đã tìm thấy một cách tốt hơn ở đây: https://groups.google.com/a/tensorflow.org/forum/#!topic/discuss/4tgsOSxwtkY Bạn có thể liên kết hai chiều không được sử dụng trong phép nhân sử dụng định hình lại, nhân hai ma trận, và sau đó gọi reshape một lần nữa để có được hình dạng mong muốn. Điều này tương đương với việc nhân lô. – KarlSt

Các vấn đề liên quan