如何在不重塑的情况下在张量流中将向量和矩阵相乘?
How can I multiply a vector and a matrix in tensorflow without reshaping?
这个:
import numpy as np
a = np.array([1, 2, 1])
w = np.array([[.5, .6], [.7, .8], [.7, .8]])
print(np.dot(a, w))
# [ 2.6 3. ] # plain nice old matrix multiplication n x (n, m) -> m
import tensorflow as tf
a = tf.constant(a, dtype=tf.float64)
w = tf.constant(w)
with tf.Session() as sess:
print(tf.matmul(a, w).eval())
结果:
C:\_\Python35\python.exe C:/Users/MrD/.PyCharm2017.1/config/scratches/scratch_31.py
[ 2.6 3. ]
# bunch of errors in windows...
Traceback (most recent call last):
File "C:\_\Python35\lib\site-packages\tensorflow\python\framework\common_shapes.py", line 671, in _call_cpp_shape_fn_impl
input_tensors_as_shapes, status)
File "C:\_\Python35\lib\contextlib.py", line 66, in __exit__
next(self.gen)
File "C:\_\Python35\lib\site-packages\tensorflow\python\framework\errors_impl.py", line 466, in raise_exception_on_not_ok_status
pywrap_tensorflow.TF_GetCode(status))
tensorflow.python.framework.errors_impl.InvalidArgumentError: Shape must be rank 2 but is rank 1 for 'MatMul' (op: 'MatMul') with input shapes: [3], [3,2].
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:/Users/MrD/.PyCharm2017.1/config/scratches/scratch_31.py", line 14, in <module>
print(tf.matmul(a, w).eval())
File "C:\_\Python35\lib\site-packages\tensorflow\python\ops\math_ops.py", line 1765, in matmul
a, b, transpose_a=transpose_a, transpose_b=transpose_b, name=name)
File "C:\_\Python35\lib\site-packages\tensorflow\python\ops\gen_math_ops.py", line 1454, in _mat_mul
transpose_b=transpose_b, name=name)
File "C:\_\Python35\lib\site-packages\tensorflow\python\framework\op_def_library.py", line 763, in apply_op
op_def=op_def)
File "C:\_\Python35\lib\site-packages\tensorflow\python\framework\ops.py", line 2329, in create_op
set_shapes_for_outputs(ret)
File "C:\_\Python35\lib\site-packages\tensorflow\python\framework\ops.py", line 1717, in set_shapes_for_outputs
shapes = shape_func(op)
File "C:\_\Python35\lib\site-packages\tensorflow\python\framework\ops.py", line 1667, in call_with_requiring
return call_cpp_shape_fn(op, require_shape_fn=True)
File "C:\_\Python35\lib\site-packages\tensorflow\python\framework\common_shapes.py", line 610, in call_cpp_shape_fn
debug_python_shape_fn, require_shape_fn)
File "C:\_\Python35\lib\site-packages\tensorflow\python\framework\common_shapes.py", line 676, in _call_cpp_shape_fn_impl
raise ValueError(err.message)
ValueError: Shape must be rank 2 but is rank 1 for 'MatMul' (op: 'MatMul') with input shapes: [3], [3,2].
Process finished with exit code 1
(不确定为什么在其处理中会引发相同的异常)
中建议的解决方案是将向量重塑为矩阵,但这会导致不必要的复杂代码 - 是否仍然没有其他方法可以将向量与矩阵相乘?
顺便使用带有默认参数的 expand_dims
(如上文 link 中所建议的)会引发 ValueError
- docs 中未提及并且违背了 docs 的目的有默认参数。
Matmul 被编码为二阶或更高阶的张量。不知道为什么要诚实,因为 numpy 有它,它也允许矩阵向量乘法。
import numpy as np
a = np.array([1, 2, 1])
w = np.array([[.5, .6], [.7, .8], [.7, .8]])
print(np.dot(a, w))
# [ 2.6 3. ] # plain nice old matix multiplication n x (n, m) -> m
print(np.sum(np.expand_dims(a, -1) * w , axis=0))
# equivalent result [2.6, 3]
import tensorflow as tf
a = tf.constant(a, dtype=tf.float64)
w = tf.constant(w)
with tf.Session() as sess:
# they all produce the same result as numpy above
print(tf.matmul(tf.expand_dims(a,0), w).eval())
print((tf.reduce_sum(tf.multiply(tf.expand_dims(a,-1), w), axis=0)).eval())
print((tf.reduce_sum(tf.multiply(a, tf.transpose(w)), axis=1)).eval())
# Note tf.multiply is equivalent to "*"
print((tf.reduce_sum(tf.expand_dims(a,-1) * w, axis=0)).eval())
print((tf.reduce_sum(a * tf.transpose(w), axis=1)).eval())
tf.einsum
使您能够以简洁直观的形式准确地完成您需要的工作:
with tf.Session() as sess:
print(tf.einsum('n,nm->m', a, w).eval())
# [ 2.6 3. ]
您甚至可以明确地写下您的评论 n x (n, m) -> m
。在我看来,它更具可读性和直观性。
我最喜欢的用例是当您想将一批矩阵与权重向量相乘时:
n_in = 10
n_step = 6
input = tf.placeholder(dtype=tf.float32, shape=(None, n_step, n_in))
weights = tf.Variable(tf.truncated_normal((n_in, 1), stddev=1.0/np.sqrt(n_in)))
Y_predict = tf.einsum('ijk,kl->ijl', input, weights)
print(Y_predict.get_shape())
# (?, 6, 1)
因此,您可以轻松地将所有批次的权重相乘,而无需转换或重复。您不能像其他答案那样通过扩展尺寸来做到这一点。因此,您可以避免 tf.matmul
对批次和其他外部尺寸具有匹配尺寸的要求:
The inputs must, following any transpositions, be tensors of rank >= 2 where the inner 2 dimensions specify valid matrix multiplication arguments, and any further outer dimensions match.
您可以使用tf.tensordot
and set axes=1
. For the simple operation of a vector times a matrix, this is a bit cleaner than
tf.tensordot(a, w, 1)
这个:
import numpy as np
a = np.array([1, 2, 1])
w = np.array([[.5, .6], [.7, .8], [.7, .8]])
print(np.dot(a, w))
# [ 2.6 3. ] # plain nice old matrix multiplication n x (n, m) -> m
import tensorflow as tf
a = tf.constant(a, dtype=tf.float64)
w = tf.constant(w)
with tf.Session() as sess:
print(tf.matmul(a, w).eval())
结果:
C:\_\Python35\python.exe C:/Users/MrD/.PyCharm2017.1/config/scratches/scratch_31.py
[ 2.6 3. ]
# bunch of errors in windows...
Traceback (most recent call last):
File "C:\_\Python35\lib\site-packages\tensorflow\python\framework\common_shapes.py", line 671, in _call_cpp_shape_fn_impl
input_tensors_as_shapes, status)
File "C:\_\Python35\lib\contextlib.py", line 66, in __exit__
next(self.gen)
File "C:\_\Python35\lib\site-packages\tensorflow\python\framework\errors_impl.py", line 466, in raise_exception_on_not_ok_status
pywrap_tensorflow.TF_GetCode(status))
tensorflow.python.framework.errors_impl.InvalidArgumentError: Shape must be rank 2 but is rank 1 for 'MatMul' (op: 'MatMul') with input shapes: [3], [3,2].
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:/Users/MrD/.PyCharm2017.1/config/scratches/scratch_31.py", line 14, in <module>
print(tf.matmul(a, w).eval())
File "C:\_\Python35\lib\site-packages\tensorflow\python\ops\math_ops.py", line 1765, in matmul
a, b, transpose_a=transpose_a, transpose_b=transpose_b, name=name)
File "C:\_\Python35\lib\site-packages\tensorflow\python\ops\gen_math_ops.py", line 1454, in _mat_mul
transpose_b=transpose_b, name=name)
File "C:\_\Python35\lib\site-packages\tensorflow\python\framework\op_def_library.py", line 763, in apply_op
op_def=op_def)
File "C:\_\Python35\lib\site-packages\tensorflow\python\framework\ops.py", line 2329, in create_op
set_shapes_for_outputs(ret)
File "C:\_\Python35\lib\site-packages\tensorflow\python\framework\ops.py", line 1717, in set_shapes_for_outputs
shapes = shape_func(op)
File "C:\_\Python35\lib\site-packages\tensorflow\python\framework\ops.py", line 1667, in call_with_requiring
return call_cpp_shape_fn(op, require_shape_fn=True)
File "C:\_\Python35\lib\site-packages\tensorflow\python\framework\common_shapes.py", line 610, in call_cpp_shape_fn
debug_python_shape_fn, require_shape_fn)
File "C:\_\Python35\lib\site-packages\tensorflow\python\framework\common_shapes.py", line 676, in _call_cpp_shape_fn_impl
raise ValueError(err.message)
ValueError: Shape must be rank 2 but is rank 1 for 'MatMul' (op: 'MatMul') with input shapes: [3], [3,2].
Process finished with exit code 1
(不确定为什么在其处理中会引发相同的异常)
顺便使用带有默认参数的 expand_dims
(如上文 link 中所建议的)会引发 ValueError
- docs 中未提及并且违背了 docs 的目的有默认参数。
Matmul 被编码为二阶或更高阶的张量。不知道为什么要诚实,因为 numpy 有它,它也允许矩阵向量乘法。
import numpy as np
a = np.array([1, 2, 1])
w = np.array([[.5, .6], [.7, .8], [.7, .8]])
print(np.dot(a, w))
# [ 2.6 3. ] # plain nice old matix multiplication n x (n, m) -> m
print(np.sum(np.expand_dims(a, -1) * w , axis=0))
# equivalent result [2.6, 3]
import tensorflow as tf
a = tf.constant(a, dtype=tf.float64)
w = tf.constant(w)
with tf.Session() as sess:
# they all produce the same result as numpy above
print(tf.matmul(tf.expand_dims(a,0), w).eval())
print((tf.reduce_sum(tf.multiply(tf.expand_dims(a,-1), w), axis=0)).eval())
print((tf.reduce_sum(tf.multiply(a, tf.transpose(w)), axis=1)).eval())
# Note tf.multiply is equivalent to "*"
print((tf.reduce_sum(tf.expand_dims(a,-1) * w, axis=0)).eval())
print((tf.reduce_sum(a * tf.transpose(w), axis=1)).eval())
tf.einsum
使您能够以简洁直观的形式准确地完成您需要的工作:
with tf.Session() as sess:
print(tf.einsum('n,nm->m', a, w).eval())
# [ 2.6 3. ]
您甚至可以明确地写下您的评论 n x (n, m) -> m
。在我看来,它更具可读性和直观性。
我最喜欢的用例是当您想将一批矩阵与权重向量相乘时:
n_in = 10
n_step = 6
input = tf.placeholder(dtype=tf.float32, shape=(None, n_step, n_in))
weights = tf.Variable(tf.truncated_normal((n_in, 1), stddev=1.0/np.sqrt(n_in)))
Y_predict = tf.einsum('ijk,kl->ijl', input, weights)
print(Y_predict.get_shape())
# (?, 6, 1)
因此,您可以轻松地将所有批次的权重相乘,而无需转换或重复。您不能像其他答案那样通过扩展尺寸来做到这一点。因此,您可以避免 tf.matmul
对批次和其他外部尺寸具有匹配尺寸的要求:
The inputs must, following any transpositions, be tensors of rank >= 2 where the inner 2 dimensions specify valid matrix multiplication arguments, and any further outer dimensions match.
您可以使用tf.tensordot
and set axes=1
. For the simple operation of a vector times a matrix, this is a bit cleaner than
tf.tensordot(a, w, 1)