34

重複コンテンツに近いものを見つけるために、ミンハッシングを実装したいと考えています。http://blog.cluster-text.com/tag/minhash/には素晴らしい記事がありますが、合理的な結果を得るためにドキュメント内の帯状疱疹に対して実行する必要があるハッシュ アルゴリズムの数が問題になります。

上記のブログ投稿では、200 のハッシュ アルゴリズムのようなものについて言及しています。http://blogs.msdn.com/b/spt/archive/2008/06/10/set-similarity-and-min-hash.aspxには、デフォルトとして 100 がリストされています。

明らかにハッシュの数が増えると精度が上がりますが、ハッシュ関数の数はどれくらいが妥当でしょうか?

ブログより引用

統計的にサンプリングされた値のエラーバーがスケールする方法のため、類似性推定のエラーバーを [7%] よりもはるかに小さくするのは困難です。エラーバーを半分にするには、4 倍のサンプル数が必要になります。

これは、ハッシュの数を 12 (200 / 4 / 4) のように減らすと、エラー率が 28% (7 * 2 * 2) になるということですか?

4

5 に答える 5

24

200 個のハッシュ値を生成する 1 つの方法は、適切なハッシュ アルゴリズムを使用して 1 つのハッシュ値を生成し、適切なハッシュ値と同じ長さを持つランダムに見えるビットの 199 セットで適切なハッシュ値を XOR することによって 199 個の値を安価に生成することです (つまり、適切なハッシュが 32 ビットの場合、199 個の 32 ビット疑似乱数整数のリストを作成し、各適切なハッシュを 199 個の乱数整数のそれぞれと XOR します)。

しないでください符号なし整数 (符号付き整数は問題ありません) を使用している場合は、単純にビットをローテーションしてハッシュ値を安価に生成します。これにより、同じシングルが何度も選択されることがよくあります。ビットを 1 ずつローテーションすることは、2 で除算して古い下位ビットを新しい上位ビット位置にコピーすることと同じです。適切なハッシュ値の約 50% は下位ビットに 1 があるため、下位ビットが上位ビットの位置にローテーションしたときに、最小ハッシュになることを期待せずに巨大なハッシュ値を持つことになります。適切なハッシュ値の残りの 50% は、1 ビットシフトすると元の値を 2 で割った値になります。2 で割っても、最小値は変わりません。そう、適切なハッシュ関数で最小のハッシュを与えたシングルがたまたま下位ビットに 0 を持っていた場合 (その可能性は 50%)、1 ビットシフトすると再び最小のハッシュ値が返されます。極端な例として、適切なハッシュ関数からの最小のハッシュ値を持つシングルのハッシュ値がたまたま 0 である場合、ビットをどれだけ回転させても常に最小のハッシュ値になります。この問題は符号付き整数では発生しません。これは、最小ハッシュ値が極端な負の値を持つため、最上位ビットが 1 で、その後にゼロが続く傾向があるためです (100...)。したがって、最下位ビットが 1 のハッシュ値のみが、1 ビットローテーションした後に新しい最下位ハッシュ値になる可能性があります。ハッシュ値が最小のシングルの最下位ビットが 1 の場合、1 ビット下にローテーションすると 1100... のようになります。

于 2013-10-31T16:14:47.563 に答える
18

かなり..しかし、28% は「誤差の推定値」になります。

つまり、報告された 78% の測定値は、わずか 50% の類似性から簡単に得られることを意味します。または、50% の類似性が 22% と簡単に報告される可能性があります。私には、ビジネスの期待に十分に正確に聞こえません。

数学的には、2 桁を報告している場合、2 番目が意味を持つはずです。

なぜハッシュ関数の数を 12 に減らしたいのですか? 「200 のハッシュ関数」が実際に意味することは、各シングル/文字列に対してまともな品質のハッシュコードを 1 回計算し、次に 200 の安価で高速な変換を適用して、特定の要素を強調したり、特定のビットを前面に出したりすることです。

ビット単位のローテーション(またはシャッフル) とXOR 演算を組み合わせることをお勧めします。各ハッシュ関数は、いくつかのビット数でローテーションを組み合わせてから、ランダムに生成された整数で XOR することができます。

これにより、ビットの周りに min() 関数の選択性が「広がり」、min() が最終的にどの値を選択するかが決まります。

ローテーションの理論的根拠は、「min(Int)」が 256 回のうち 255 回、上位 8 ビットのみを選択することです。すべての上位ビットが同じ場合にのみ、下位ビットが比較に影響を与えます。そのため、シングル内の 1 つまたは 2 つの文字だけが過度に強調されるのを避けるために、分散が役立ちます。

XOR の理論的根拠は、それ自体で、ビットごとのローテーション (ROTR) が 50% の時間 (左から 0 ビットがシフトインされた場合) 0 に向かって収束する可能性があり、それによって「別個の」ハッシュ関数が望ましくない結果を表示する可能性があるためです。一緒にゼロに向かって一致する傾向 - したがって、彼らが独立した帯状疱疹ではなく、同じ帯状疱疹を選択することになる過度の傾向.

MSB が負であるが、後続のすべてのビットが正である、符号付き整数の非常に興味深い「ビット単位の」癖があり、符号付き整数の場合、回転の収束傾向があまり目立たなくなりますunsignedの場合は明らかです。とにかく、これらの状況でも XOR を使用する必要があります。

Java には 32 ビットのハッシュコードが組み込まれています。また、Google Guava ライブラリを使用する場合は、64 ビットのハッシュコードを利用できます。

XORが必要であることを指摘してくれた@BillDimmの意見と粘り強さに感謝します。

于 2013-10-31T08:17:44.370 に答える
1

N個の適切なハッシュ値を取得する別の方法は、同じハッシュをN個の異なるソルト値でソルトすることです。

実際には、2 番目にソルトを適用すると、データをハッシュしてから、ハッシュの内部状態を「複製」し、最初のソルトを追加して最初の値を取得できるようです。このクローンをクリーンなクローン状態にリセットし、2 番目のソルトを追加して、2 番目の値を取得します。すべての N 個のアイテムについて、すすぎと繰り返しを行います。

N 値に対する XOR ほど安くはない可能性がありますが、特にハッシュされるデータがソルト値よりもはるかに大きい場合は、最小限の追加コストで、より良い品質の結果が得られる可能性があるようです。

于 2015-01-28T20:13:20.230 に答える