ドキュメントのクラスタリングを扱うコードがたくさんあります。1 つのステップでは、特定のコーパス内の他のすべてのドキュメントに対するすべてのドキュメントの類似度 (「類似」の重要でない定義) を計算し、後で使用するために類似度を保存します。類似性はバケット化されており、分析の目的では特定の類似性が何であるかは気にしません。それがどのバケットにあるかだけです。たとえば、ドキュメント 15378 と 3278 が 52% 類似している場合、順序付けられたペア (3278, 15378) は次のようになります。 [0.5,0.6) バケットに格納されます。ドキュメントは、最初の分析後にコーパスに追加または削除されることがあるため、対応するペアが必要に応じてバケットに追加または削除されます。
これらの ID ペアのリストを格納するための戦略を検討しています。SQL データベース (このプロジェクトの他のほとんどのデータが存在する場所) は、私たちの目的には遅すぎ、ディスク容量が大きすぎることがわかりました。そのため、現時点では、各バケットを圧縮された整数のリストとしてディスクに保存します (元々は zlib 圧縮されていましたが、現在は速度のために代わりに lz4 を使用しています)。これについて私が好きなこと:
- 読み取りと書き込みはどちらも非常に高速です
- 事後的なコーパスへの追加は、かなり簡単に追加できます (lz4 にはフレーミング メカニズムが組み込まれていないため、zlib よりも lz4 の方が少し手間がかかりますが、実行可能です)。
- 書き込み時と読み取り時の両方で、データをストリーミングできるため、一度にすべてをメモリに保持する必要はありません。これは、コーパスのサイズを考えると非常に困難です。
ひどいもの:
- 削除は非常に面倒で、基本的にはすべてのバケットをストリーミングし、削除されたドキュメントの ID を含むペアを省略した新しいバケットを書き出す必要があります。
- より特殊な目的のデータ構造および/または圧縮戦略を使用して、速度とコンパクトさの両方の点でまだうまくいくと思います
では、どのようなデータ構造を見ればよいのでしょうか? 正しい答えはある種のエキゾチックで簡潔なデータ構造だと思いますが、これは私がよく知っている空間ではありません。また、重要な場合: すべてのドキュメント ID は unsigned 32-bit int であり、このデータを処理する現在のコードは Python 拡張機能として C で記述されているため、可能であればこれが一般的なテクノロジ ファミリであり、これに固執する可能性があります。