5

Sklearn の TfidfVectorizer オブジェクトを使用して取得した疎行列があります。

vect = TfidfVectorizer(sublinear_tf=True, max_df=0.5, analyzer='word', vocabulary=my_vocab, stop_words='english')
tfidf = vect.fit_transform([my_docs])

疎行列は次のとおりです(一般性のために数字を取り出しています):

<sparse matrix of type '<type 'numpy.float64'>'
with stored elements in Compressed Sparse Row format>]

各行の数値を取得して、探している用語がドキュメントにどの程度含まれているかを確認しようとしています。どの単語が含まれているかはあまり気にしません。含まれている単語の数を知りたいだけです。だから、それぞれのノルムまたはrow*row.Tを取得したい. ただし、これを取得するために numpy を使用するのは非常に困難です。

私の最初のアプローチは、単に行うことでした:

tfidf[i] * numpy.transpose(tfidf[i])

ただし、numpy は明らかに 1 次元未満の配列を転置しないため、ベクトルが 2 乗されます。だから私はやってみました:

tfidf[i] * numpy.transpose(numpy.atleast_2d(tfidf[0]))

しかし、 numpy.transpose(numpy.atleast_2d(tfidf[0])) はまだ行を転置しません。

私は行のノルムを取得しようとしました(とにかくそのアプローチの方がおそらく優れています)。私の最初のアプローチは、numpy.linalg を使用することでした。

numpy.linalg.norm(tfidf[0])

しかし、それは私に「寸法の不一致」エラーを与えました。そこで、手動でノルムを計算しようとしました。変数を疎行列の numpy 配列バージョンに等しく設定し、最初の行の len を出力することから始めました。

my_array = numpy.array(tfidf)
print my_array
print len(my_array[0])

my_array は正しく出力されますが、len にアクセスしようとすると、次のように表示されます。

IndexError: 0-d arrays can't be indexed

fit_transform によって返される疎行列の各行の数値を取得したいだけです。規範を取得するのが最善でしょう。ここで何か助けていただければ幸いです。

4

3 に答える 3

10

いくつかの単純な偽データ:

a = np.arange(9.).reshape(3,3)
s = sparse.csr_matrix(a)

スパースから各行のノルムを取得するには、次を使用できます。

np.sqrt(s.multiply(s).sum(1))

そして繰り込まれたsものは

s.multiply(1/np.sqrt(s.multiply(s).sum(1)))

または、再正規化する前にスパースに保つには:

s.multiply(sparse.csr_matrix(1/np.sqrt(s.multiply(s).sum(1))))

そこから通常の行列または配列を取得するには、次を使用します。

m = s.todense()
a = s.toarray()

高密度バージョンに十分なメモリがある場合は、次の方法で各行のノルムを取得できます。

n = np.sqrt(np.einsum('ij,ij->i',a,a))

また

n = np.apply_along_axis(np.linalg.norm, 1, a)

正規化するには、次のことができます

an = a / n[:, None]

または、元の配列をその場で正規化するには:

a /= n[:, None]

基本的には、垂直配列になるよう[:, None]に転置します。n

于 2013-11-23T23:11:29.290 に答える
6

scipy.sparseは優れたパッケージであり、リリースごとに改善され続けていますが、多くのことはまだ半分しか調理されておらず、アルゴリズムのいくつかを自分で実装すると、パフォーマンスが大幅に向上します。たとえば、scipy 関数を使用した @askewchan の実装の 7 倍の改善:

In [18]: a = sps.rand(1000, 1000, format='csr')

In [19]: a
Out[19]: 
<1000x1000 sparse matrix of type '<type 'numpy.float64'>'
    with 10000 stored elements in Compressed Sparse Row format>

In [20]: %timeit a.multiply(a).sum(1)
1000 loops, best of 3: 288 us per loop

In [21]: %timeit np.add.reduceat(a.data * a.data, a.indptr[:-1])
10000 loops, best of 3: 36.8 us per loop

In [24]: np.allclose(a.multiply(a).sum(1).ravel(),
    ...:             np.add.reduceat(a.data * a.data, a.indptr[:-1]))
Out[24]: True

同様に、次のようにして配列をその場で正規化できます。

norm_rows = np.sqrt(np.add.reduceat(a.data * a.data, a.indptr[:-1]))
nnz_per_row = np.diff(a.indptr)
a.data /= np.repeat(norm_rows, nnz_per_row)

スパース行列を頻繁に使用する場合は、ウィキペディアの圧縮されたスパース形式に関するページを読んでください。デフォルトよりも優れた方法が見つかることがよくあります。

于 2013-11-23T23:42:29.540 に答える