ハッシュの考え方は、データの最小の変更でさえ、劇的に異なる結果を得るということです。
私が求めているのはその逆です。ほぼ同じデータの近接ハッシュ値を生成するアルゴリズム。違いがどこにあるかに関係なく、違いの程度を測定するだけであり、結果のハッシュ値は、2番目のデータセットが元のデータセットに似ているかどうかに応じて、元のハッシュ値に近づきます。
私は特定のデータ型をターゲットにしていません。生のバイト配列で問題ありません。
ハッシュの考え方は、データの最小の変更でさえ、劇的に異なる結果を得るということです。
いいえそうではありません。
ハッシュの考え方は、より大きく、潜在的に無限の入力空間を、より小さく、有限で、通常は固定の出力空間にマッピングすることです。例えば。 SHA-3は、無限に多くのオクテット文字列を2にマッピングします512 ビットストリング。
あなたが話しているのは、ハッシュ関数の(非常に小さい)特殊なケースである暗号的に安全なメッセージダイジェストのプロパティの1つです。
たとえば、オンラインビデオプラットフォームで著作権違反を検出するために使用されるハッシュ関数(指紋)は、このプロパティがある場合は役に立ちません。
反対の特性を持つ最もよく知られているハッシュ関数の1つ、つまり、類似の入力が類似の出力を生成するものは、soundexです。これは、類似に聞こえる単語に対して類似のハッシュ値を生成するアルゴリズムです。
私が求めているのはその逆です。ほぼ同じデータの近接ハッシュ値を生成するアルゴリズム。違いがどこにあるかに関係なく、違いの程度を測定するだけで、結果のハッシュ値は、2番目のデータセットが元のデータセットに似ているかどうかに応じて、元のハッシュ値に近づきます。
これは、ハッシュ関数よりも類似度の測定値に似ています。特に、記述には、小さな固定サイズの有限出力スペースを意味するものはありません。
あなたが話しているのは Cluster Analysis です。
クラスター分析またはクラスター化は、同じグループ(クラスターと呼ばれます)内のオブジェクトが他のグループ(クラスター)内のオブジェクトよりも(何らかの意味で)互いに類似するようにオブジェクトのセットをグループ化するタスクです。
k-means clustering など、これには多くのアプローチがあります。
それは知覚ハッシュと呼ばれています
https://en.wikipedia.org/wiki/Perceptual_hashing
pHash-オープンソースの知覚ハッシュライブラリ http://www.phash.org/
Blockhash.io-知覚的ハッシュのオープンスタンダード http://blockhash.io/
インサイト-知覚ハッシュチュートリアル http://bertolami.com/index.php?engine=blog&content=posts&detail=perceptual-hashing
これはおそらくあなたが望んでいることではありませんが、面白いので、私はそれを育てようと思いました。実際には、約10年前に作成された 類似性メトリック と呼ばれるものが存在します( 圧縮によるクラスタリング も参照)。 x
とy
が与えられたx
とy
が与えられたy
を与えられたx
を生成する最短のプログラムの長さを計算したい(いくつかのファッジファクターを法として)。これを適切に正規化すると、相対的な類似性の良い概念が得られます。ただし、この概念は計算できないコルモゴロフの複雑さの観点から定義されているため、実際には使用可能なアルゴリズムを生成しません。代わりに近似する必要があります。これにより、正規化された圧縮距離は次のようになります。
_NCD(x,y) = (C(x++y) - min(C(x),C(y))/max(C(x),C(y))
_
ここで、_x++y
_は、x
とy
の連結を表し、ビットシーケンスと見なされます。そして、重要なことに、C(x)
は、一部の(適切に動作する)圧縮アルゴリズムx
のC
の圧縮表現のビット長を表します。基本的に、gzip
などの圧縮アルゴリズムを使用する場合、各入力とその連結を単純に圧縮し、上記の式を使用して0と1の間の有理数を取得し、それらがどの程度「類似」しているかを示します。 (次に、その有理数を、指定されたビット数の最も近い固定小数点数に丸めて、固定サイズの出力を取得できます。)これは、すべてのビットが重要であることを前提としています。入力を「正規化」して(たとえば、無関係な空白やローパスフィルタリングを削除して)偽の差異を回避することは、理にかなっています。概念的には、これは圧縮アルゴリズムに組み込むことができます。これは、この類似性の概念が圧縮アルゴリズムによって異なることを指摘していますが、多くの場合、汎用の圧縮アルゴリズムで十分です。これを行うためのいくつかのツールは here ですが、自分でロールするのは簡単です。
実際のコンプレッサーはあなたの目的のために類似点を見つけるのに「良すぎる」と思います。つまり、類似したくないものの間の類似性が見つかります。これは、適切なコンプレッサーの選択によって技術的に解決できる可能性がありますが、他のメトリックを使用することは、これを行うよりも意味がある場合があります。
他の人が言ったように、類似性メトリックはおそらく必要なものです。あなたはバイト配列を持っていると言います。配列は長さが等しくなくてもかまいませんが、長さが常に同じであってもそれほど大きな違いはありません。コサイン類似度のような単純なメトリックから始めます。順序は重要ではなく、配列に値が現れる回数だけが重要だと言います。
それでは、バイトを-128から127と仮定します。2つの配列を256次元のユークリッド空間内のベクトルに変換します。ここで、新しいvector [i]の値は、元の配列に-128 + iが出現する回数のカウントです。簡単にするために、疎なベクトル表現を想定します。
これで、両方の配列が同じ次元空間内にあります。これで、新しい表現でコサイン類似性を計算できます。コサイン類似度は自然にバインドされるため[-1,1]、類似度1の2つの配列は等しく、類似度-1の2つの配列は完全に異なることがわかります。
これを行うと、たとえば次の3つの配列[1,2,3] [2,3,1]と[3,1,2]のいずれか2つの類似性が1になります。