15

それぞれが 784 ピクセルで構成される 42000 枚の画像のセットに、TF-IDF と呼ばれる重み付けシステムを実装していました。これは基本的に 42000 × 784 のマトリックスです。

私が試みた最初の方法は、明示的なループを利用したもので、2 時間以上かかりました。

def tfidf(color,img_pix,img_total):
    if img_pix==0:
        return 0
    else:
        return color * np.log(img_total/img_pix)

...

result = np.array([])
for img_vec in data_matrix:
    double_vec = zip(img_vec,img_pix_vec)
    result_row = np.array([tfidf(x[0],x[1],img_total) for x in double_vec])
    try:
        result = np.vstack((result,result_row))
    # first row will throw a ValueError since vstack accepts rows of same len
    except ValueError:
        result = result_row

私が試みた 2 番目の方法では、numpy マトリックスを使用し、5 分もかかりませんでした。data_matrix と img_pix_mat はどちらも 42000 x 784 の行列ですが、img_total はスカラーであることに注意してください。

result = data_matrix * np.log(np.divide(img_total,img_pix_mat))

私は誰かが速度の計り知れない違いを説明できることを望んでいました.

「NumPy 配列: 効率的な数値計算のための構造」( http://arxiv.org/pdf/1102.1523.pdf ) というタイトルの次の論文の著者は、500 倍の速度向上を観察したと 4 ページの上部に述べています。ベクトル化された計算によるものです。私が見ている速度の増加の多くは、これによるものだと推測しています。しかし、さらに一歩進んで、numpy のベクトル化された計算が標準の Python ループよりもはるかに高速である理由を尋ねたいと思います。

また、おそらく、最初の方法が遅い他の理由を知っているかもしれません。try/except 構造のオーバーヘッドは高いですか? それとも、ループごとに新しい np.array を作成するのに時間がかかるのでしょうか?

ありがとう。

4

2 に答える 2

8

あなたが見ている違いは、SSE のベクトル化のような凝ったものによるものではありません。主な理由は 2 つあります。1 つ目は、NumPy は C で記述されており、C の実装では、Python の実装が実行する大量のランタイム メソッドのディスパッチや例外チェックなどを実行する必要がないことです。

2 番目の理由は、Python コードであっても、ループベースの実装が非効率的であることです。をループで使用vstackしており、 を呼び出すたびに、vstack渡したすべての配列を完全にコピーする必要があります。len(data_matrix)これにより、漸近的な複雑さに追加の要素が追加されます。

于 2013-07-05T07:18:33.697 に答える