2017-12-05 13 views
1

私は、次のしている:numpy - 複数の3x3および100x100x3配列の行列?

import numpy as np 

XYZ_to_sRGB_mat_D50 = np.asarray([ 
    [3.1338561, -1.6168667, -0.4906146], 
    [-0.9787684, 1.9161415, 0.0334540], 
    [0.0719453, -0.2289914, 1.4052427], 
]) 

XYZ_1 = np.asarray([0.25, 0.4, 0.1]) 
XYZ_2 = np.random.rand(100,100,3) 

np.matmul(XYZ_to_sRGB_mat_D50, XYZ_1) # valid operation 
np.matmul(XYZ_to_sRGB_mat_D50, XYZ_2) # makes no sense mathematically 

私は私がXYZ_2の場合とXYZ_2上で同じ操作を実行するにはどうすればよいですか?私は何とか配列を最初から作り直していますか?

答えて

2

は、それはあなたがXYZ_2(axis=2)の最後の1でsum-reduceXYZ_to_sRGB_mat_D50(axis=1)の最後の軸をしようとしているようです。

np.tensordot(XYZ_2, XYZ_to_sRGB_mat_D50, axes=((2),(1))) 

Related post to understand tensordot - だから、あなたはそうのようなnp.tensordotを使用することができます。完全のために


、我々は確かにそうように、XYZ_2の最後の二つの軸をswappping後、あまりにもnp.matmulを使用することができます -

np.matmul(XYZ_to_sRGB_mat_D50, XYZ_2.swapaxes(1,2)).swapaxes(1,2) 

これはtensordot 1ほど効率的ではありません。


ランタイムテスト - それはテンソルでsum-reductionsに来るとき

In [158]: XYZ_to_sRGB_mat_D50 = np.asarray([ 
    ...:  [3.1338561, -1.6168667, -0.4906146], 
    ...:  [-0.9787684, 1.9161415, 0.0334540], 
    ...:  [0.0719453, -0.2289914, 1.4052427], 
    ...: ]) 
    ...: 
    ...: XYZ_1 = np.asarray([0.25, 0.4, 0.1]) 
    ...: XYZ_2 = np.random.rand(100,100,3) 

# @Julien's soln 
In [159]: %timeit XYZ_2.dot(XYZ_to_sRGB_mat_D50.T) 
1000 loops, best of 3: 450 µs per loop 

In [160]: %timeit np.tensordot(XYZ_2, XYZ_to_sRGB_mat_D50, axes=((2),(1))) 
10000 loops, best of 3: 73.1 µs per loop 

一般tensordotがはるかに効率的である、話します。 sum-reductionの軸はちょうど1であるので、テクスチャを2Dに再整形することで、np.dotを使用して結果を得て、3Dに戻すことができます。

+0

ありがとう - この回答は素晴らしいです。興味深いことに、テンソルドは、ここで転調して普通のドットを打ち、スピードワイズです。 –

+0

@BrandonDubeテンソルの場合、 'dot'はあるレベル(おそらくCレベル)でループしていますが、' tensordot'はそれを避けています。 – Divakar

+0

うわー!それを知らなかった!なぜ形状を変えるのが10倍速くなるのかについての洞察はありますか?それは意味をなさないと思われます... – Julien

1

おそらく、単にこれが欲しい:

XYZ_2.dot(XYZ_to_sRGB_mat_D50.T) 

np.matmul(XYZ_to_sRGB_mat_D50, XYZ_1)XYZ_1.dot(XYZ_to_sRGB_mat_D50.T)に相当し、あなたは、単に100×100×3行列に操作を放送することができます。

関連する問題