抽出したngramの約200のドキュメントのデータベースがあります。クエリドキュメントに最も類似しているドキュメントをデータベースで検索したい。つまり、クエリドキュメントと最も多くのngramを共有するデータベース内のドキュメントを見つけたいのです。現在、1つずつ調べて1つずつ比較できますが、これはO(N)時間を要し、Nが非常に大きい場合はコストがかかります。効率的な類似性検索を行うための効率的なデータ構造または方法があるかどうか疑問に思っていました。ありがとう
抽出したngramの約200のドキュメントのデータベースがあります。クエリドキュメントに最も類似しているドキュメントをデータベースで検索したい。つまり、クエリドキュメントと最も多くのngramを共有するデータベース内のドキュメントを見つけたいのです。現在、1つずつ調べて1つずつ比較できますが、これはO(N)時間を要し、Nが非常に大きい場合はコストがかかります。効率的な類似性検索を行うための効率的なデータ構造または方法があるかどうか疑問に思っていました。ありがとう
回答:
テーブル
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
あなたの説明から-
データベースごとに、ドキュメントを表す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」でより高いスコアになります。使用するために)小さいです。
ドキュメント内の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」に取得します。