2

A_{ij}特定の vectorb_iと別のmatrix から新しい matrix を作成する高速な方法を探していC_{ij}ます。新しいマトリックスのコンポーネントは、次の形式にする必要があります。

A_{ij} = b_i * C_{ij}.

ここまでは を使ってdot(diag(b), C)いますが、内積は当然ゼロとの掛け算が多く、かなり非効率です。より良い方法はありますか?

4

5 に答える 5

2

*適切なブロードキャストで要素ごとの積である を使用します。

>>> b = array([1,2,3])
>>> C = arange(9).reshape(3,3)
>>> dot(diag(b), C)
array([[ 0,  1,  2],
       [ 6,  8, 10],
       [18, 21, 24]])
>>> atleast_2d(b).T * C
array([[ 0,  1,  2],
       [ 6,  8, 10],
       [18, 21, 24]])

atleast_2d(b).T(またはb.reshape(-1,1)) ベクトルbを列ベクトルに再形成します。

于 2012-12-03T13:19:20.620 に答える
1

einsumも使用できます。

>>> b = np.array([1,2,3])
>>> C = np.arange(9).reshape(3,3)
>>> np.einsum('i,ij->ij', b, C)
array([[ 0,  1,  2],
       [ 6,  8, 10],
       [18, 21, 24]])

私のマシンでは、この方法は両方よりも高速です

np.dot(np.diag(b), C)

np.atleast_2d(b).T * C

100,000 ループの場合、einsum は 1.16 秒、dot は 1.61 秒、atleast_2d は 2.03 秒かかります。

Einstein summation notationに精通している場合、einsum は非常に便利な関数です。インデックス表記を使用すると、多くの単純な線形代数演算を定式化する方が簡単であり、追加された実行速度はケーキのアイシングです。

于 2013-03-08T03:30:45.030 に答える
0

行列を配列に変換し、(ブロードキャスト)配列乗算を実行して、元に戻します。

np.matrix(b * np.asarray(C))
于 2012-12-03T13:15:06.393 に答える
0

行う

b[:,np.newaxis] * C

また

b[:,None] * C
于 2012-12-03T22:35:12.893 に答える
0

すでに与えられた答えを組み合わせて、新しい(しかし非効率的な方法)を試してみると、次のタイミングになります。

  • einsum: 0.54 秒 (Thycydides)
  • ブロードキャスト: 0.44 秒 (larsmans)
  • ドット対角: 15.6 秒 (henrikr、TS)
  • まばらな dia マトリックス: 16.8 秒 (自分の試行、惨めに失敗しました:-p)

einsum とブロードキャストをそれぞれ 10 回繰り返すと (より正確なタイミング)、次のことがわかります。

  • アインサム: 5.2 秒
  • ブロードキャスト: 4.5 秒

そのためのテストコードは次のとおりです。

import timeit
from scipy.sparse.dia import dia_matrix
import numpy as np

def get_bc():
    N = 10000
    M = 10000
    b = np.random.random(size=N)
    c = np.random.random(size=[N, M])
    return b, c

def multiply_dot_diag():
    global b, c
    return np.dot(np.diag(b), c)

def multiply_broadcast():
    global b, c
    return np.atleast_2d(b).T * c

def mulitply_sparse():
    global b, c
    N = b.size
    return dia_matrix((b, 0), shape=[N, N]).todense().dot(c)

def multiply_einsum():
    global b, c
    return np.einsum('i,ij->ij', b, c)

if __name__ == '__main__':
    global b, c
    b, c = get_bc()
    print (b, c)

    print (timeit.timeit(multiply_einsum, number=1))
    print (timeit.timeit(multiply_broadcast, number=1))
    print (timeit.timeit(multiply_dot_diag, number=1))
    print (timeit.timeit(mulitply_sparse, number=1))

    np.testing.assert_array_equal(multiply_dot_diag(), multiply_broadcast())
    np.testing.assert_array_equal(multiply_dot_diag(), mulitply_sparse())
    np.testing.assert_array_equal(multiply_dot_diag(), multiply_einsum())
于 2015-02-20T06:27:24.303 に答える