ハッシュベクトライザーとtfidfベクトライザーの違いは何ですか


11

テキストドキュメントのコーパスを各ドキュメントの単語ベクトルに変換しています。私が使用してこれを試してみたTfidfVectorizerHashingVectorizerを

a HashingVectorizerIDFaのようにスコアを考慮しないことを理解してTfidfVectorizerいます。ここここでHashingVectorizer説明さいるように、私がまだaを使用している理由は、巨大なデータセットを処理する際の柔軟性です。(私の元のデータセットには3000万のドキュメントがあります)

現在、私は45339のドキュメントのサンプルを使用しているので、aを使用することTfidfVectorizerもできます。同じ45339ドキュメントでこれら2つのベクトライザーを使用すると、取得する行列が異なります。

hashing = HashingVectorizer()
with LSM('corpus.db')) as corpus:
    hashing_matrix = hashing.fit_transform(corpus)
print(hashing_matrix.shape) 

ハッシュマトリックスの形状(45339、1048576)

tfidf = TfidfVectorizer()
with LSM('corpus.db')) as corpus:
    tfidf_matrix = tfidf.fit_transform(corpus)
print(tfidf_matrix.shape) 

tfidfマトリックス形状(45339、663307)

a HashingVectorizerとaの違いTfidfVectorizer、およびこれらの行列のサイズが異なる理由、特に語句/用語の数がよくわかります。


データセットを私と共有してもらえますか?(応答は削除されます)
nKarza 2017

回答:


7

主な違いは、コーパス全体に広く出現する用語にペナルティを課すことにより、各ドキュメントの用語頻度カウントにHashingVectorizerハッシュ関数を適用することTfidfVectorizerです。ここに素晴らしい要約があります:https : //spark.apache.org/docs/latest/mllib-feature-extraction.html

  • ハッシュ関数は、用語をフィーチャにマッピングする効率的な方法です。必ずしも用語の頻度のみに適用する必要はありませんが、HashingVectorizerここではそのように使用しています。45339のドキュメントと共に、特徴ベクトルはデフォルトの2 ^ 20なので、長さは1048576であると思いますn_features。これを減らして処理コストを下げることができますが、関数が異なる機能を同じ機能にマッピングする衝突のリスクが高くなります。http//preshing.com/20110504/hash-collision-probabilities/

  • 単語ベクトルの使用例に応じて、許容可能な精度/有効性の損失(衝突の増加による)でハッシュ特徴ベクトルの長さ(したがって複雑さ)を大幅に削減することが可能です。Scikit-learnには、たとえば、役立つハッシュパラメータがいくつかありますalternate_sign

  • ハッシュマトリックスがディクショナリよりも広い場合、ハッシュマトリックスの列エントリの多くが空になることを意味します。これは、特定のドキュメントに特定の用語が含まれていないだけでなく、全体にわたって空であるためです。マトリックス。そうでない場合は、同じ機能ハッシュに複数の用語が送信される可能性があります。これは、これまで説明してきた「衝突」です。HashingVectorizerこれを緩和するように機能する設定があり、alternate_signデフォルトでオンになっています。en.wikipedia.org/ wiki / Feature_hashing#Properties

  • 「用語頻度-逆ドキュメント頻度」は、各ドキュメントの用語頻度を取り、コーパス全体でより頻繁に出現する単語にペナルティを課すことにより、それらに重みを付けます。直感は、状況的に見つかる用語が特定のドキュメントのトピックを表す可能性が高いということです。これは、逆ドキュメント頻度を計算するためにコーパスに単語の完全な辞書を持っている必要があるという点でハッシュ関数とは異なります。あなたのtf.idfマトリックスの次元は、コーパスの663307ワードによる45339ドキュメントであると思います。Manning et alは、計算の詳細と例を提供しています:https : //nlp.stanford.edu/IR-book/html/htmledition/term-frequency-and-weighting-1.html

Leskovec et alによる 'Mining of Massive Datasets'は、機能ハッシングとtf.idfの両方について多くの詳細を持っています。著者は、pdfをここで利用できるようにしました:http ://www.mmds.org/


1
tfidf vectorizerがidf計算に単語の完全な辞書を必要とする場合、tfidf行列の項はハッシュ行列の項よりも多くあるべきではありませんか?
Minu

2
ハッシュマトリックスがディクショナリよりも広い場合、ハッシュマトリックスの列エントリの多くが空になることを意味します。これは、特定のドキュメントに特定の用語が含まれていないだけでなく、全体にわたって空であるためです。マトリックス。少しトピックから外れていますが、ベクトル化する前にドキュメント内の単語に何らかの処理を行っていますか?ストップワード、ステミングなど?
redhqs 2017

はい、処理しています。私はスペイシーを使用しています。
2017

1
確認:n_featuresが言及されていない場合、ハッシュマトリックスのデフォルトの長さは1048576ですか?コーパスに実際に663307語しかない場合、残りの385269の特徴は空になります。空の機能をすべて使わずに、このハッシングマトリックスをぴったりと作成するにはどうすればよいですか?
Minu

1
そうです-パラメータを変更することで機能の数をサイズ変更できn_features=1048576ます。時間があれば、640k、320kを試して、精度に大きな影響があるかどうかを確認してください。少なくともトレーニング時間を短縮する必要があります。@ネイサンの答えを見てくださいn_features=5
redhqs 2017

5

にはデフォルトのHashingVectorizerパラメータn_featuresがあり1048576ます。ハッシュするとき、実際には、それぞれに使用する一意のインデックスに用語をマッピングする辞書を計算しません。代わりに、各用語をハッシュし、衝突が多すぎるとは思わない十分な大きさのサイズを使用しますhash(term) mod table_size。を設定することにより、返される行列を任意のサイズにすることができますn_features。デフォルトが妥当であると思わない場合は、コーパスに適した球場になるように調整する必要があります(これを大きくすると、メモリを多く消費しますが、衝突が少なくなります)。

from sklearn.feature_extraction.text import HashingVectorizer
vectorizer = HashingVectorizer()
print(vectorizer.transform(['a very small document']).shape)
(1, 1048576)

small_vectorizer = HashingVectorizer(n_features=5)
print(small_vectorizer.transform(['a very small document']).shape)    
(1, 5)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.