ngramを指定して類似のドキュメントを検索する最良の方法


7

抽出したngramの約200のドキュメントのデータベースがあります。クエリドキュメントに最も類似しているドキュメントをデータベースで検索したい。つまり、クエリドキュメントと最も多くのngramを共有するデータベース内のドキュメントを見つけたいのです。現在、1つずつ調べて1つずつ比較できますが、これはO(N)時間を要し、Nが非常に大きい場合はコストがかかります。効率的な類似性検索を行うための効率的なデータ構造または方法があるかどうか疑問に思っていました。ありがとう


ngramを計算しない場合、どのようにして最も多くのngramを見つけるのですか?1つずつ比較しますか?これは非常に単純な単一のクエリです。
パパラッツォ

ドキュメントのngramは、クエリと同様にすべて計算されます。問題は、データベース内のどのドキュメントがクエリに最も類似しているかを確認したいことです。または、ngramに基づいて、クエリに最も類似した上位10のドキュメントを取得します。
okebz 2015年

記載されている質問は、ngramが抽出されたことです。彼らは計算されていると今言っています。私へのクエリドキュメントはドキュメントです。答えは質問と同じくらい良いです。どのデータベース?構文はさまざまです。
パパラッツォ

抽出したという意味です。どちらの方法でも、ngramは各ドキュメントから取得されるので、ngram自体を操作しています。データベース内の各ドキュメントを表すngramのデータベースがあります。検索したいクエリドキュメントがあり、クエリに最も類似していると思われるトップ10ドキュメントを例に挙げてみましょう。データベース
ごとに

そして、あなたは私の答えを持っています。明記されていないテーブル設計のデータベースは、実際にそれを絞り込みません。
パパラッツォ

回答:


3

文書でハッシュベクトライザーを使用できます。結果はベクトルのリストになります。次に、同じ方法でngramをベクトル化し、この新しいベクトルの古いベクトルへの投影を計算します。これはインデックスでのデータベース結合と同等ですが、オーバーヘッドが少なくなる場合があります。


1

通常使用されるデータ構造は、逆索引(データベースなど)です。

すべてのngramを一致させることは良いヒューリスティックですが、それを改善したい場合があることに注意してください。

各用語の確率とステミングを考慮することは、あなたが利益を得るかもしれない方向です。


1

テーブル

ngram
docID

PK(主キー)ngram、docID

データベースによっては多少変更される可能性がありますが、これはTSQLの場合です
xは一致するドキュメントです

select top(1) with ties *    
from 
(  select tm.docID, count(*) as count 
     from table td
     join table tm
       on tm.docID <> td.docID 
      and tm.ngram = td.ngram 
      and td.docID = x
    group by tm.docID 
) tt 
order by count desc

結合はインデックス(PK)に基づいているため、これは非常に高速です。これを数百万のドキュメントに対して数秒で実行します(より高度な条件を使用)。

これはより大きなドキュメントを支持しますが、それはあなたが求めたものです。

質問は変化しているようです

declare table @query (varchar ngram);
insert into @query values ('ng1'), ('ng2'), ('ng3');
select top(10) with ties *    
from 
(  select tm.docID, count(*) as count 
     from table td
     join @query
       on tm.ngram = @query.ngram
    group by tm.docID 
) tt 
order by count desc

1

あなたの説明から-

データベースごとに、ドキュメントを表すngramモデルの膨大なリストがあるとしましょう

もう少し構造化されたものを実行して、データをリレーショナルデータベースに配置するのがよいでしょう。これにより、より詳細な分析をより簡単かつ迅速に行うことができます。

「ngram」と言うと「1gram」を意味すると思います。必要に応じて、分析を拡張して2グラム、3グラムなどを含めることができます。

私はこのようなテーブル構造を持っているでしょう-

1Grams
ID

ドキュメント
ID
DocTitle
DocAuthor
など

Docs1Grams
1GramID
DocID
1GramCount

したがって、Docs1Gramsテーブルのレコードでは、1GramIDが1グラムの「the」を指し、DocIDがドキュメント「War and Peace」を指している場合、1GramCountは1グラムの「the」が戦争と平和に出現した回数を保持します。

「戦争と平和」のDocIDが1で「ロードオブザリング」のDocIdが2の場合、これら2つのドキュメントの1グラムの類似性スコアを計算するには、次のクエリを実行します-

Select count(*) from Docs1Grams D1, Docs1Grams D2   
where D1.DocID = 1 and   
D2.DocID = 2 and   
D1.1GramID = D2.1GramID and   
D1.1GramCount > 0 and   
D2.1GramCount > 0   

クエリを一般化して拡張することにより、これを簡単に変更して、選択したドキュメントを他のすべてのドキュメントと比較して、そのような最高のスコア/カウントを自動的に選択することができます。

D1.1GramCount > 0 and D2.1GramCount > 0クエリの一部を変更/拡張することで、たとえば2Grams、3Gramsなどを追加したり、単純一致を変更してngramあたりの一致率に応じてスコアを付けたりすることで、比較をより洗練されたものにすることができます。

したがって、対象のドキュメントの1グラムの0.0009%が「the」であり、ドキュメント1が0.001%であり、ドキュメント2が0.0015%である場合、差のモジュラス(または選択した他の測定値)により、ドキュメント1は「the」でより高いスコアになります。使用するために)小さいです。


1

ドキュメント内のnグラムの存在を確認する場合は、クエリドキュメントもnグラムに変換する必要があります。これを行うには、TFIDFベクトライザーを使用できます。

from nltk.tokenize import word_tokenize               
from sklearn.feature_extraction.text import TfidfVectorizer
vect = TfidfVectorizer(tokenizer=word_tokenize,ngram_range=(1,2), binary=True, max_features=10000)
TFIDF=vect.fit_transform(df_lvl0['processed_cv_data'])

上記のコードを説明するには:
word_tokenize:この関数はテキストを文字列トークンに変換しますが、それに応じてデータを消去する必要があります。
ngram_range:必要なngramの数を設定します。この場合、1ワードと2ワードの両方が必要です。
max_features:合計数を制限します。機能の。いくつかのドキュメントをnoとしてトークン化する場合は、これを使用することをお勧めします。機能の数が非常に多い(10 ^ 6のオーダー)。

モデルを適合させた後、機能は「vect」に保存されます。以下を使用してそれらを表示できます。

keywords=set(vect.get_feature_names())

クエリドキュメントのグラムがセットに格納されたので、ループに比べてはるかに高速なセット操作を実行できます。各セットの長さが10 ^ 5のオーダーであっても、秒単位で結果が得られます。Pythonでセットを試すことを強くお勧めします。

matching_keys = keywords.intersection(all_grams)   //all_grams is the set of your collected grams

最後に、一致するすべてのキーワードを「matching_keys」に取得します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.