ブール行列計算のための最速の方法

フランヴェーザー:

私はとブール行列持って1.5E6行と20E3次の例のように列を:

M = [[ True,  True, False,  True, ...],
     [False,  True,  True,  True, ...],
     [False, False, False, False, ...],
     [False,  True, False, False, ...],
     ...
     [ True,  True, False, False, ...]
     ]

また、私は別のマトリックスを持っているN1.5E6行、1列):

 N = [[ True],
      [False],
      [ True],
      [ True],
      ...
      [ True]
      ]

私は何をする必要があるか、マトリックスから各列のペアを通過することですMによって結合(1&1、1&2、1&3、1&N、2&1、2&2など)ANDオペレータ、および結果とマトリックスの間がありますどのように多くの重複カウントN

私はPython / numpyのコードは次のようになります。

for i in range(M.shape[1]):
  for j in range(M.shape[1]):
    result = M[:,i] & M[:,j] # Combine the columns with AND operator
    count = np.sum(result & N.ravel()) # Counts the True occurrences
    ... # Save the count for the i and j pair

問題は、通過している20E3 x 20E3forループ2との組み合わせは、(計算コストが高く周りにかかる 5-10日を計算するために)。私が試したより良いオプションは、全体の行列Mに各列を比較しています。

for i in range(M.shape[1]):
  result = M[:,i]*M.shape[1] & M # np.tile or np.repeat is used to horizontally repeat the column
  counts = np.sum(result & N*M.shape[1], axis=0)
  ... # Save the counts

これは、10%前後にオーバーヘッドと、計算時間を短縮し、それはだ、まだ取って 1日かそこら計算します。

私の質問は次のようになります
(基本的にはこれらの計算を行うために最速の方法ものです(多分非Pythonは?)ANDSUM)?

私は、低レベルの言語についての考え方、GPU処理、量子コンピューティングなどだった..しかし、方向に関するいかなるアドバイスは歓迎ですので、私はこれらのいずれかについて多くを知りません!

追加の思考: 内積を用いた高速な方法がある場合は、現在の組み合わせのトリプレットを計算する(Davikarが提案されたように)考えて:

def compute(M, N):
    out = np.zeros((M.shape[1], M.shape[1], M.shape[1]), np.int32)
    for i in range(M.shape[1]):
        for j in range(M.shape[1]):
            for k in range(M.shape[1]):
                result = M[:, i] & M[:, j] & M[:, k]
                out[i, j, k] = np.sum(result & N.ravel())
    return out
Divkr:

単純に使うnp.einsumすべてのカウントを取得するために-

np.einsum('ij,ik,i->jk',M,M.astype(int),N.ravel())

遊ぶこと自由に感じなさいoptimizeとフラグnp.einsumまた、異なるdtypes変換で遊ぶこと自由に感じ。

レバレッジGPUのために、我々は使用することができますtensorflowもサポートしているパッケージをeinsum

とより高速な代替手段np.dot

(M&N).T.dot(M.astype(int))
(M&N).T.dot(M.astype(np.float32))

タイミング -

In [110]: np.random.seed(0)
     ...: M = np.random.rand(500,300)>0.5
     ...: N = np.random.rand(500,1)>0.5

In [111]: %timeit np.einsum('ij,ik,i->jk',M,M.astype(int),N.ravel())
     ...: %timeit (M&N).T.dot(M.astype(int))
     ...: %timeit (M&N).T.dot(M.astype(np.float32))
227 ms ± 191 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)
66.8 ms ± 198 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
3.26 ms ± 753 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

そして、ブール配列の両方のためのfloat32変換してビットさらにそれを取ります -

In [122]: %%timeit
     ...: p1 = (M&N).astype(np.float32)
     ...: p2 = M.astype(np.float32)
     ...: out = p1.T.dot(p2)
2.7 ms ± 34.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=8786&siteId=1