質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

2197閲覧

python で テンソル代数.モードn積の実装について.

physics303

総合スコア89

NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/06/26 16:05

編集2020/06/26 16:27

テンソル代数を用いた研究をしています.この度,テンソルのタッカー分解の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

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

モードn積については知らなかったのですが、定義に従うと以下のコードになると思います。

python

1def mode_n_product(x, m, mode): 2 x = np.asarray(x) 3 m = np.asarray(m) 4 if mode <= 0 or mode % 1 != 0: 5 raise ValueError('`mode` must be a positive interger') 6 if x.ndim < mode: 7 raise ValueError('Invalid shape of X for mode = {}: {}'.format(mode, x.shape)) 8 if m.ndim != 2: 9 raise ValueError('Invalid shape of M: {}'.format(m.shape)) 10 return np.swapaxes(np.swapaxes(x, mode - 1, -1).dot(m.T), mode - 1, -1)

補足:

  • np.swapaxes(x, m, n) :
    テンソルxm個目の添字とn個目の添字を交換する関数です。
    ただし添字の番号は0始まりで、-1は末尾の添字を表します。
    したがって、np.swapaxes(x, mode - 1, -1)で i_n と i_N が交換されて
    X'{i_1, i_2, …, i{n-1}, i_N, i_{n+1} …, i_{N-1}, i_n}
    := X_{i_1, i_2, …, i_{n-1}, i_n, i_{n+1} …, i_{N-1}, i_N}
    が得られます。

  • m.T:
    Mの転置です。M'{i_n, j} := M{j, i_n} が得られます。

  • c = a.dot(b):
    b が行列であれば以下の関係が成り立ちます。
    C_{…, i, j} = Σ_k A_{…, i, k} B_{k, j}
    したがって np.swapaxes(x, mode - 1, -1).dot(m.T) と書くと
    A'{i_1, …, i{n-1}, i_N, i_{n+1}, …, i_{N-1}, j}
    := Σ_{i_n}^{l_n} X'{i_1, i_2, …, i{n-1}, i_N, i_{n+1} …, i_{N-1}, i_n} M'{i_n, j}
    = Σ
    {i_n}^{l_n} X_{i_1, i_2, …, i_{n-1}, i_n, i_{n+1} …, i_{N-1}, i_N} M_{j, i_n}
    が得られます。

  • 最後に、再び np.swapaxes(x, mode - 1, -1) を適用することで
    ( X ⊗_n M ){i_1, …, i{n-1}, j, i_{n+1}, …, i_N}
    = A'{i_1, …, i{n-1}, i_N, i_{n+1}, …, i_{N-1}, j}
    を得ます。

投稿2020/06/26 19:51

編集2020/06/26 19:55
kzm4269

総合スコア184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

physics303

2020/06/29 04:41 編集

いつもありがとうございます! 動作確認しましたがこれで良さそうです!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問