Bagaimana cara melakukan batch product dalam Tensorflow?

10

Saya memiliki dua tensor a:[batch_size, dim] b:[batch_size, dim]. Saya ingin melakukan produk dalam untuk setiap pasangan dalam batch, menghasilkan c:[batch_size, 1], di mana c[i,0]=a[i,:].T*b[i,:]. Bagaimana?

HenrySky
sumber

Jawaban:

9

Tidak ada .dot_productmetode asli . Namun, produk titik antara dua vektor hanyalah elemen-bijaksana dikalikan, jadi contoh berikut berfungsi:

import tensorflow as tf

# Arbitrarity, we'll use placeholders and allow batch size to vary,
# but fix vector dimensions.
# You can change this as you see fit
a = tf.placeholder(tf.float32, shape=(None, 3))
b = tf.placeholder(tf.float32, shape=(None, 3))

c = tf.reduce_sum( tf.multiply( a, b ), 1, keep_dims=True )

with tf.Session() as session:
    print( c.eval(
        feed_dict={ a: [[1,2,3],[4,5,6]], b: [[2,3,4],[5,6,7]] }
    ) )

Outputnya adalah:

[[ 20.]
 [ 92.]]
Neil Slater
sumber
Ini memecahkan masalah saya, terima kasih!
HenrySky
1
tf.mul sekarang tf.multiply. github.com/tensorflow/tensorflow/issues/7032
Rahul Jha
1
Tampaknya tidak ada yang lebih disukai pengembang TF daripada mengubah API ...
Emre
@sajedzarrinpour Terima kasih. Saya harap itu muncul beberapa waktu antara 2016 dan sekarang? Akan menyesuaikan jawaban saya dengan tepat
Neil Slater
6

Pilihan lain yang patut dicoba adalah [tf.einsum][1]- ini pada dasarnya versi sederhana dari Notasi Einstein .

Mengikuti bersama dengan contoh Neil dan Dumkar:

import tensorflow as tf

a = tf.placeholder(tf.float32, shape=(None, 3))
b = tf.placeholder(tf.float32, shape=(None, 3))

c = tf.einsum('ij,ij->i', a, b)

with tf.Session() as session:
    print( c.eval(
        feed_dict={ a: [[1,2,3],[4,5,6]], b: [[2,3,4],[5,6,7]] }
    ) )

Argumen pertama einsumadalah persamaan yang mewakili sumbu yang akan dikalikan dan dijumlahkan. Aturan dasar untuk persamaan adalah:

  1. Input-tensor dijelaskan oleh string dimensi-label yang dipisahkan koma
  2. Label yang berulang menunjukkan bahwa dimensi yang sesuai akan dikalikan
  3. Output-tensor dijelaskan oleh string label dimensi lain yang mewakili input (atau produk) yang sesuai
  4. Label yang hilang dari string keluaran dijumlahkan

Dalam kasus kami, ij,ij->iberarti bahwa input kami akan menjadi 2 matriks dengan bentuk yang sama (i,j), dan output kami akan menjadi vektor bentuk (i,).

Setelah Anda menguasainya, Anda akan menemukan bahwa einsummenyamaratakan sejumlah besar operasi lain:

X = [[1, 2]]
Y = [[3, 4], [5, 6]]

einsum('ab->ba', X) == [[1],[2]]   # transpose
einsum('ab->a',  X) ==  [3]        # sum over last dimension
einsum('ab->',   X) ==   3         # sum over both dimensions

einsum('ab,bc->ac',  X, Y) == [[13,16]]          # matrix multiply
einsum('ab,bc->abc', X, Y) == [[[3,4],[10,12]]]  # multiply and broadcast

Sayangnya, einsummengambil hit kinerja yang lumayan besar jika dibandingkan dengan + mengalikan manual. Di mana kinerja sangat penting, saya pasti akan merekomendasikan tetap dengan solusi Neil.

menang
sumber
3

Mengambil diagonal tf.tensordot juga melakukan apa yang Anda inginkan, jika Anda menetapkan sumbu ke misalnya

[[1], [1]]

Saya telah mengadaptasi contoh Neil Slater:

import tensorflow as tf

# Arbitrarity, we'll use placeholders and allow batch size to vary,
# but fix vector dimensions.
# You can change this as you see fit
a = tf.placeholder(tf.float32, shape=(None, 3))
b = tf.placeholder(tf.float32, shape=(None, 3))

c = tf.diag_part(tf.tensordot( a, b, axes=[[1],[1]]))

with tf.Session() as session:
    print( c.eval(
        feed_dict={ a: [[1,2,3],[4,5,6]], b: [[2,3,4],[5,6,7]] }
    ) )

yang sekarang juga memberi:

[ 20.  92.]

Ini mungkin suboptimal untuk matriks besar (lihat diskusi di sini )

Dumkar
sumber
1
Pawai kemajuan :-), saya tidak yakin versi API mana ini ditambahkan? Saya sarankan perluas jawaban Anda dengan contoh singkat (mungkin berdasarkan pada milik saya, tetapi harus lebih sederhana, karena tidak perlu reduce_sum)
Neil Slater
Saya menambahkan contoh! Sebenarnya itu juga memberikan dot-produk off-diagonal jika Anda tidak menggunakan tf.diag_part, jadi jawaban Anda mungkin akan lebih cepat. Tidak begitu yakin di mana versi API tf.tensordot diperkenalkan, tetapi mungkin sudah lama sejak itu juga tersedia di numpy.
dumkar
Tidakkah ini membutuhkan lebih banyak memori daripada elemen-bijak melipatgandakan dan menjumlahkan?
kbrose