2017-04-07 7 views
3

この:中ベクトルとテンソルの行列を再構成することなくどのように乗算できますか?

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 

行列にベクトルを再形成されたソリューションはTensorflow exception with matmulで提案

(同じ例外は、その取り扱いの内側に上げている理由がわかりません)これは不必要に複雑なコードにつながります。ベクトルを行列に乗算する他の方法はまだありませんか?ちなみにデフォルト引数で(上記のリンクで提案されているよう)expand_dimsを使用して

ValueError提起 - docsに記載されていないだとデフォルトの引数を使用する意味がなくなります。

+1

受け入れ答えの作品をそれが実際にAPIのバグです - 報告:https://github.com/tensorflow/tensorflow/issues/9055 –

+0

問題を起こしてくれてありがとう、この行動は私にも迷惑をかけました。これとはるかに良いソリューションのための多くのユースケースは私の答えを参照してください。 – dsalaj

答えて

3

Matmulはランク2以上のテンソルでコード化されていました。それが行列ベクトルの乗算を可能にするように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()) 
+1

ああ、ありがとう - それでは、行列の乗算ではありません;)それらは2つの同等ですか?和を減らすことについて少し説明できますか?申し訳ありませんが、今日はtfとあまりにも多くの戦い、私はめまいです –

+0

"*"乗算操作は、通常のnumpy放送sematicsをサポートしています(それはいくつかの素晴らしい索引のものが不足している可能性があります)。上の例では、wの各ベクトルに渡ってベクトルを乗算します。 reduce_sumは、その次元に沿って合計することによって次元を崩壊させます。だから私たちは* w - > reduce_sum(製品) - > ansから行く。 ([n * nxm])→[nxm]→[m]である。軸は、この場合、どの軸を加算するかを決定し、次元mの最終結果を得るために0を求めます。 – Steven

+0

いいえ申し訳ありません - > 'print(tf.reduce_sum(a * w、axis = 0).eval())'はValueErrorになります:寸法は同じでなければなりませんが、 'mul' : 'Mul')入力の形:[3]、[3,2] .'のコード –

4

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.

+0

ありがとうございましたeinsum –

関連する問題