テンソル代数を用いた研究をしています.この度,テンソルのタッカー分解のpython実装が求められています.このタッカー分解の実装にあたって,テンソルのモードn積を実行する必要があります.テンソル代数では頻繁に登場する「テンソルと行列」の演算ですが,NumPyを調べたところテンソルのモード積については,自前で用意しないといけないようです.
モードn積の定義
モードn積は,テンソル X と 行列 M の間に成立する二項演算です.
テンソルと行列の次元を次のようにします.
X ∈ R^{l_1×l_2×…×l_N}
M ∈ R^{J×l_n}
ここで,Rは実数.l_1,l_2,…,l_N と J はゼロを含まない自然数です.nをN以下の自然数とするとき,テンソルXと行列Mの間のモードn積 X ⊗_n M は次のように定義されます.
( X ⊗_n M ) ∈ R^{l_1×l_2×…×l_(n-1)×J×l_(n+1)×…×l_N}
( X ⊗_n M ){i_1,…,i{n-1},j,i_{n+1},…,i_N} = Σ_{i_n}^{l_n} X_{i_1,…,i_{n-1},i_n,i_{n+1},…,i_N} m_{j,i_n}
これをてっとり早くpythonで実装するにはどうしたらよいでしょうか.どうも大量のfor文ループになるようで困惑しています.
参照
モードn積の定義やRでの実装は以下を参考にしています.
https://www.alexejgossmann.com/tensor_decomposition_tucker/
np.tensordot で対応できると良いのですが...
実装
たとえば,n=3 だあれば,こんな感じかと思います.
絶対にもっと良い実装方法があるとは思うのですが...
Python
1l1 = 3 2l2 = 3 3l3 = 3 4l4 = 3 5J = 2 6X = np.random.uniform(0,1,(l1,l2,l3,l4)) 7M = np.random.uniform(0,1,(J,l3)) 8 9def mode_3_prodcut(X,M,mode=3): 10 A = np.zeros((l1,l2,J,l4)) 11 for i1 in range(l1): 12 for i2 in range(l2): 13 for j in range(J): 14 for i4 in range(l4): 15 term = 0 16 for i3 in range(l3): 17 term += X[i1,i2,i3,i4] * M[j,i3] 18 19 A[i1,i2,j,i4] = term 20 21 return A
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/06/29 04:41 編集
2020/06/29 04:41