web-dev-qa-db-ja.com

python)の逆ソートとargsort

Python(まだnoob!)で、tfidfスコアの内積順に並べられたドキュメントのインデックスとスコアを返す関数を作成しようとしています。手順は次のとおりです。

  • Doc idxと他のすべてのドキュメント間の内積のベクトルを計算します
  • 降順で並べ替える
  • 「スコア」とインデックスを2番目から最後まで返します(つまり、それ自体ではありません)

私が現在持っているコードは次のとおりです。

_import h5py
import numpy as np

def get_related(tfidf, idx) :
    ''' return the top documents '''

    # calculate inner product   
    v = np.inner(tfidf, tfidf[idx].transpose())

    # sort
    vs = np.sort(v.toarray(), axis=0)[::-1]
    scores = vs[1:,]

    # sort indices
    vi = np.argsort(v.toarray(), axis=0)[::-1]
    idxs = vi[1:,] 

    return (scores, idxs)
_

ここで、tfidfは_sparse matrix of type '<type 'numpy.float64'>'_です。

ソートが2回実行され(sort() then argsort())、結果を逆にする必要があるため、これは非効率的です。

  • これをより効率的に行うことができますか?
  • これは、toarray()を使用してスパース行列を変換せずに実行できますか?
14
tdc

toarrayをスキップする必要はないと思います。 v配列の長さはn_docsのみであり、実際の状況ではn_docs×n_termstf-idf行列のサイズよりも小さくなります。また、2つのドキュメントで共有される用語は、ゼロ以外の類似性を与えるため、非常に密度が高くなります。スパース行列表現は、格納している行列がveryスパースである場合にのみ効果があります(Matlabで80%を超える数値を確認し、Scipyも同様であると想定していますが、正確なものはありません図)。

二重ソートを行うことでスキップできます

v = v.toarray()
vi = np.argsort(v, axis=0)[::-1]
vs = v[vi]

ところで、スパース行列でのnp.innerの使用は、最新バージョンのNumPyでは機能しません。 2つのスパース行列の内積を取る安全な方法は次のとおりです。

v = (tfidf * tfidf[idx, :]).transpose()
9
Fred Foo