2012-04-22 3 views
4

対角にdを最初に付けて作成した対角行列適用関数を実装したいと思います。次に、xで行列 - ベクトル乗算の束を実行します。もちろん、必要なのは要素ごとのベクトルの乗算だけなので、実際の行列を作成したくありません。1次元目の配列(形状(k、1)または(k、))を乗算し、結果が最初の形状になるようにする

ここで、一部のユーザーは、dの形の(k,)と、一部の形の(k,1)を提供する予定です。また、xは、形状(k,)および(k,1)を有することができる。入力(x)と同じ形をしているという点で、numpy行列の場合は*のように振る舞います。

したがって質問:のPython/numpyの、得られた配列は、の形状を有するように、2つnp.arrays x及び(任意の組み合わせ)の形状(k,)又は(k,1)yを要素単位-乗算する非あやふや方法がありますx

私は、[:,None]で少し実験

x = np.empty((4,1)) 
y = np.empty(4) 
(x * y).shape   # (4,4) -- nope 
(y * y).shape   # (4,) -- yes 
(x * y[:,None]).shape # (4, 1) -- yes 
(y * y[:,None]).shape # (4,4) -- nope 

と私は確かにif len(x.shape)==...:に私のコードをラップすることができますが、それは非常にニシキヘビ感じることはありません。

提案?

>>> result.shape 
(4,) 

xの形状を維持するために:

>>> result=x.flatten()*y.flatten() 

は、1次元配列を返す必要があります:あなたはxyはその後、numpyのの.flatten()アレイ法を使用して、両方の本質的1D配列であると仮定できる場合

+0

OK、これはクリスタルクリアです、ありがとう!私の[編集](http://stackoverflow.com/a/10268164/577088)を参照してください。 – senderle

答えて

5

私はあなたの質問を理解したので、私の提案はの形になります。です。 reshapeを呼び出すとビューが返されるため、大きなコピーコストなどが発生することはありません。単純に、配列を再形成乗算し、再び再構築:より簡潔

>>> def shape_preserving_mult(x, y): 
...  return (x.reshape((-1,)) * y.reshape((-1))).reshape(x.shape) 
... 

かを、あなたとrroowwllaannddが指摘したように:

>>> def shape_preserving_mult(x, y): 
...  return x * y.reshape(x.shape) 
... 
>>> shape_preserving_mult(x, y) 
array([[ 0], 
     [ 1], 
     [ 4], 
     [ 9], 
     [16]]) 
>>> shape_preserving_mult(x, y.T) 
array([[ 0], 
     [ 1], 
     [ 4], 
     [ 9], 
     [16]]) 
>>> shape_preserving_mult(x.T, y) 
array([[ 0, 1, 4, 9, 16]]) 
>>> shape_preserving_mult(x.T, y.T) 
array([[ 0, 1, 4, 9, 16]]) 

私の以前の提案の物質は以下のまま。

形の数字の配列(1, 4)に形状の配列(4,)を掛け合わせると、あなたが望むものに近いものが得られます。

>>> x = numpy.arange(5).reshape((5, 1)) 
>>> y = numpy.arange(5) 
>>> x.shape 
(5, 1) 
>>> x.T.shape 
(1, 5) 
>>> y * x.T 
array([[ 0, 1, 4, 9, 16]]) 

これはaの形状を有していないが、それはa.Tの形状を持っています。あなたはいつでも結果にTを再度呼び出すことができます。これは形状の配列(5,)にも作用します。なぜなら、1次元配列の転置操作は変更を起こさないからです。

>>> def transposed_mult(x, y): 
...  return (x.T * y).T 
... 
>>> transposed_mult(x, y) 
array([[ 0], 
     [ 1], 
     [ 4], 
     [ 9], 
     [16]]) 

しかし、あなたは形状 (1, 5)の配列を渡す場合は、もちろん、これは逆の問題が発生します:だから、おそらくあなたはこれを行うことができます

>>> transposed_mult(x.T, y) 
array([[ 0, 0, 0, 0, 0], 
     [ 0, 1, 2, 3, 4], 
     [ 0, 2, 4, 6, 8], 
     [ 0, 3, 6, 9, 12], 
     [ 0, 4, 8, 12, 16]]) 

のでtransposed_multがあなたの元にを求め、正確なことを行いますあなたはさらに柔軟性が必要な場合、期待どおりに動作しません。そして確かに、あなたはさらなる柔軟性が必要と思われます。

+1

整形は良いアイデアのようです。 'return x * y.reshape(x.shape)'と同じような何かがうまくいくようです。 –

3

以下を行うことができます:

>>> result = x*y.reshape(x.shape) 
>>> result.shape 
(4,1) 
+0

常に '(4、)'という形になります。しかし、私が望むのは、最初の要素の形を保つ乗法です。 –

関連する問題