Làm thế nào để làm hàng loạt sản phẩm bên trong trong Tensorflow?


10

Câu trả lời:


9

Không có .dot_productphương pháp bản địa . Tuy nhiên, một sản phẩm chấm giữa hai vectơ chỉ là phép nhân tổng hợp phần tử, vì vậy ví dụ sau hoạt động:

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]] }
    ) )

Đầu ra là:

[[ 20.]
 [ 92.]]

Nó đã giải quyết vấn đề của tôi, thx!
HenrySky

1
tf.mul bây giờ là tf.multiply. github.com/tensorflow/tensorflow/issues/7032
Rahul Jha

1
Dường như không có gì các nhà phát triển TF yêu thích hơn việc thay đổi API ...
Emre

6

Một lựa chọn khác đáng để kiểm tra là [tf.einsum][1]- về cơ bản nó là một phiên bản đơn giản của Ký hiệu Einstein .

Theo sau cùng với ví dụ của Neil và 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]] }
    ) )

Đối số đầu tiên einsumlà một phương trình đại diện cho các trục được nhân và tính tổng. Các quy tắc cơ bản cho một phương trình là:

  1. Các tenxơ đầu vào được mô tả bằng một chuỗi các kích thước được phân tách bằng dấu phẩy
  2. Nhãn lặp lại cho biết rằng kích thước tương ứng sẽ được nhân lên
  3. Các tenxơ đầu ra được mô tả bởi một chuỗi các nhãn kích thước khác đại diện cho các đầu vào (hoặc sản phẩm) tương ứng
  4. Các nhãn bị thiếu trong chuỗi đầu ra được tóm tắt

Trong trường hợp của chúng tôi, ij,ij->icó nghĩa là đầu vào của chúng tôi sẽ là 2 ma trận có hình dạng bằng nhau (i,j)và đầu ra của chúng tôi sẽ là một vectơ hình dạng (i,).

Khi bạn hiểu rõ về nó, bạn sẽ thấy rằng einsumtổng quát hóa một số lượng lớn các hoạt động khác:

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

Thật không may, einsummất một hiệu suất khá lớn khi so sánh với nhân + giảm thủ công. Nếu hiệu suất là quan trọng, tôi chắc chắn khuyên bạn nên gắn bó với giải pháp của Neil.


3

Lấy đường chéo của tf.tensordot cũng làm những gì bạn muốn, nếu bạn đặt trục thành vd

[[1], [1]]

Tôi đã điều chỉnh ví dụ của 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]] }
    ) )

mà bây giờ cũng cho:

[ 20.  92.]

Điều này có thể là tối ưu cho các ma trận lớn mặc dù (xem thảo luận ở đây )


1
Diễu hành của sự tiến bộ :-), tôi không chắc phiên bản API này đã được thêm vào? Tôi đề nghị mở rộng câu trả lời của bạn bằng một ví dụ ngắn (có lẽ dựa trên câu hỏi của tôi, nhưng nó sẽ đơn giản hơn, vì nó sẽ không cần reduce_sum)
Neil Slater

Tôi đã thêm ví dụ! Trên thực tế, nó cũng cung cấp các sản phẩm chấm chéo nếu bạn không sử dụng tf.diag_part, vì vậy câu trả lời của bạn có thể sẽ nhanh hơn. Không thực sự chắc chắn về phiên bản API mà tf.tensordot đã giới thiệu, nhưng có thể đã lâu rồi vì nó cũng có sẵn trong numpy.
dumkar

Điều này sẽ không chiếm nhiều bộ nhớ hơn so với nhân và tổng của phần tử?
kbrose
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.