web-dev-qa-db-ja.com

高次元データの最近傍?

question 数日前に、与えられたベクトルの最近傍を見つける方法を尋ねました。私のベクトルは21次元になりました。先に進む前に、機械学習や数学の領域からではないので、基本的な質問をし始めています。

  • ユークリッド距離は、そもそも最近傍を見つけるための良い指標ですか?そうでない場合、私のオプションは何ですか?
  • さらに、k近傍を決定するための適切なしきい値をどのように決定しますか?この値を把握するために実行できる分析はありますか?
  • 以前、私はkd-Treesを使用するように提案されましたが、Wikipediaページでは、高次元ではkd-Treeはブルートフォース検索とほぼ同等であると明確に述べています。その場合、100万ポイントのデータセットで最も近い隣人を効率的に見つけるための最良の方法は何ですか?

誰かが上記の質問のいくつか(またはすべて)を明確にしていただけますか?

152
Legend

現在、音楽情報の検索のために、分類、最近傍検索などの問題を研究しています。

近似最近傍ANN)アルゴリズムに興味があるかもしれません。アイデアは、アルゴリズムが十分にnear neighbors(おそらく最も近い隣人ではない)を返すことを許可することです。そうすることで、複雑さが軽減されます。 kd-tree;について言及しましたそれは一例です。しかし、あなたが言ったように、kd-treeは高次元ではうまく機能しません。実際、all現在のインデックス付け手法(空間分割に基づく)は、十分に高い次元の線形検索に低下します[1] [2] [3]。

ANN最近提案されたアルゴリズムの中で、おそらく最も人気があるのはLocality-Sensitive Hashing(-LSH)で、これはポイントのセットをマッピングしますビンのセット、つまりハッシュテーブル[1] [3]への高次元空間で。しかし、従来のハッシュとは異なり、locality-sensitiveハッシュプレースnearbyは同じビン。

LSHにはいくつかの大きな利点があります。まず、簡単です。データベース内のすべてのポイントのハッシュを計算し、それらからハッシュテーブルを作成します。クエリを実行するには、クエリポイントのハッシュを計算し、ハッシュテーブルから同じビン内のすべてのポイントを取得します。

第二に、そのパフォーマンスをサポートする厳密な理論があります。クエリ時間は、データベースのサイズでsublinearであることがわかります。つまり、線形検索よりも高速です。どれだけ速くなるかは、許容できる近似値に依存します。

最後に、LSH0 < p <= 2のLpノルムと互換性があります。したがって、最初の質問に答えるには、ユークリッド距離メトリックでLSHを使用するか、マンハッタン(L1)距離メトリックで使用できます。ハミング距離とコサイン類似度のバリアントもあります。

2008年にIEEE Signal Processing MagazineのMalcolm SlaneyとMichael Caseyによってまともな概要が書かれました[4]。

LSHは一見どこでも適用されています。試してみてください。


[1] Datar、Indyk、Immorlica、Mirrokni、「p-安定分布に基づく局所性依存ハッシュ方式」、2004年。

[2] Weber、Schek、Blott、「高次元空間での類似性検索手法の定量分析とパフォーマンス研究」、1998年。

[3] Gionis、Indyk、Motwani、「ハッシングによる高次元の類似性検索」1999。

[4] Slaney、Casey、「最近傍を見つけるための局所性に敏感なハッシュ」、2008年。

171
Steve Tjoa

I。距離メトリック

まず、データセット内のフィーチャ(列)の数は、kNNで使用する距離メトリックを選択する要因ではありません。まさにこの質問に向けられた公開された研究がかなりあり、比較のための通常のベースは次のとおりです。

  • データの基礎となる統計分布。

  • データを構成する機能間の関係(独立しているかどうか、つまり共分散行列はどのように見えるか);そして

  • データの取得元の座標空間。

データのサンプリング元の分布についての予備知識がない場合、少なくとも1つ(十分に文書化され、徹底的に) study は、ユークリッド距離が最良の選択であると結論付けます。

YEuclideanメトリックは、大規模なWeb推奨エンジンおよび現在の学術研究で使用されています。ユークリッドによって計算された距離には直感的な意味があり、計算スケール-つまり、ユークリッド距離は、2点が2次元または22次元空間にあるかどうかにかかわらず、同じ方法で計算されます。

私にとっては数回しか失敗しませんでした。それぞれの場合、基礎となる(デカルト)座標系が適切な選択ではなかったため、ユークリッド距離は失敗しました。また、たとえば、パスの長さ(距離)はもはや加算されないため、通常これを認識します。たとえば、メトリック空間がチェス盤の場合、マンハッタン距離はユークリッドよりも優れています。同様に、メトリック空間が地球で、距離がトランスの場合-コンチネンタル航空の場合、極座標系に適した距離メトリックは良い考えです(たとえば、ロンドンからウィーンは2.5時間、ウィーンからサンクトペテルブルクはさらに3時間、ほぼ同じ方向ですが、ロンドンからStピーターズバーグは5.5時間ではなく、3時間強です。)

ただし、データが非デカルト座標系に属している場合を除き、通常、距離メトリックの選択は重要ではありません。 (これを参照してください ブログ投稿 CS学生から、kNN分類器への影響を調べることによっていくつかの距離メトリックを比較します--chi squareは最良の結果を与えますが、差は大きくありません;より包括的な研究は学術論文 最も近い隣人の距離関数の比較研究 -マハラノビス(本質的に次元共分散を考慮して正規化されたユークリッド)は、この研究で最高でした。

重要な但し書き:距離メトリックの計算を有効にするには、re-scaleデータ- -まれに、これを行わずにkNNモデルを構築して正確な予測を生成することが可能です。たとえば、運動パフォーマンスを予測するkNNモデルを構築していて、期待変数が身長(cm)、体重(kg)、体脂肪(%)、および安静時の脈拍(1分あたりの拍数)である場合、典型的なデータポイントは次のようになります:[180.4、66.1、11.3、71]。明らかに、距離の計算は高さによって支配されますが、bodyfat%による寄与はほとんど無視できます。別の言い方をすれば、代わりにデータが異なる方法で報告され、体重がキログラムではなくグラムであった場合、元の値86.1は86,100になり、結果に大きな影響を与えます。したくないおそらく、最も一般的なスケーリング手法は、平均値を減算し、標準偏差で除算することです(平均値とsdは、各列、またはそのデータセットの機能について個別に計算されます。Xは、データ行内の個々のエントリ/セルを示します)。

X_new = (X_old - mu) / sigma


II。データ構造

Kdツリー構造のパフォーマンスが懸念される場合、AVoronoi Tessellationは概念的にシンプルなコンテナーですが、kdよりもパフォーマンスとスケールが大幅に向上します-木。

dat

これはkNNトレーニングデータを保持するための最も一般的な方法ではありませんが、この目的のためのVTの適用とその結果としてのパフォーマンスの利点は十分に文書化されています(例:this Microsoft Research report を参照)。これの実際的な意味は、「 TIOBE Index で」「メインストリーム」言語を使用している場合、VTを実行するライブラリを見つける必要があるということです。 PythonとRには、各言語に複数のオプションがあります(たとえば、Rのvoronoiパッケージは _ cran _)で利用可能です

KNNにVTを使用すると、次のように機能します。

データからwポイントをランダムに選択します。これらはボロノイ中心です。ボロノイセルは、各中心に最も近いすべての隣接ポイントをカプセル化します。ボロノイ中心のそれぞれに異なる色を割り当て、特定の中心に割り当てられた各ポイントがその色でペイントされると想像してください。十分な密度がある限り、これを行うと、各ボロノイ中心の境界がうまく表示されます(2色を分離する境界として)。

ボロノイセンターの選択方法2つの直交ガイドラインを使用します。 wポイントをランダムに選択した後、トレーニングデータのVTを計算します。次に、各ボロノイ中心に割り当てられたデータポイントの数を確認します。これらの値はほぼ同じである必要があります(データ空間全体で均一なポイント密度が与えられています)。 2次元では、これにより同じサイズのタイルでVTが発生します。これが最初のルールで、2番目のルールがあります。反復でwを選択します-変数パラメーターとしてwを使用してkNNアルゴリズムを実行し、パフォーマンス(VTを照会して予測を返すのに必要な時間)を測定します。

100万のデータポイントがあると想像してください。...通常の2Dデータ構造またはkdツリーにポイントが保持されている場合、に対して平均で数百万の距離計算を実行します。各応答変数を予測する新しいデータポイント。もちろん、これらの計算は単一のデータセットで実行されます。 V/Tの場合、最近隣検索は2つの異なるデータの集団に対して2つのステップで次々に実行されます-最初にボロノイ中心に対して、次に最も近い中心が見つかると、に対応するセル内のポイントその中心が検索され、実際の最近傍が検索されます(連続した距離計算により)。これら2つのルックアップは、単一のブルートフォースルックアップよりもはるかに高速です。簡単にわかります。1Mのデータポイントに対して、データ空間をテッセレーションするために250のボロノイ中心を選択するとします。平均して、各ボロノイセルには4,000個のデータポイントがあります。そのため、平均500,000の距離計算(ブルートフォース)を実行する代わりに、平均125 + 2,000で、はるかに少ないパフォーマンスを実行します。

III。結果の計算(予測される応答変数)

KNNトレーニングデータのセットから予測値を計算するには、2つのステップがあります。 1つ目は、n、またはこの計算に使用する最近傍の数を識別することです。 2つ目は、予測値に対する貢献度の重み付け方法です。

W/r/t最初のコンポーネントでは、最適化問題を解くことによりnの最適値を決定できます(最小二乗最適化に非常に似ています)。それが理論です。実際には、ほとんどの人はn = 3を使用します。いずれにしても、n = 1、n = 2、n = 3などのテストインスタンスのセットに対してkNNアルゴリズムを実行し(予測値を計算する)、nの関数としてエラーをプロットするのは簡単です。 nの妥当な値を開始するだけの場合は、n = 3を使用します。

2番目の要素は、各近傍の寄与に重み付けする方法です(n> 1と仮定)。

最も単純な重み付け手法は、各近傍に単に1 /(dist * K)である重み付け係数を乗算するか、その近傍からテストインスタンスまでの距離の逆数に経験的に導出された定数Kを乗算することです。多くの場合、最も近い隣人を過剰に重み付けします(同時に、より遠くの隣人を重み付けしすぎます)ため、この手法のファンではありません。これの重要性は、与えられた予測が単一の近傍にほぼ完全に依存する可能性があることです。これにより、ノイズに対するアルゴリズムの感度が向上します。

この制限を実質的に回避するより良い重み関数は、ガウス関数です。次のようになります。

def weight_gauss(dist, sig=2.0) :
    return math.e**(-dist**2/(2*sig**2))

KNNコードを使用して予測値を計算するには、応答変数を予測するデータポイント(「テストインスタンス」)に最も近いn個の近傍を識別し、n個の近傍のそれぞれに対して1回ずつweight_gauss関数を呼び出します。この関数は、各近傍の距離でテストポイントを返します。この関数は、各近傍の重みを返します。重みは、加重平均計算でその近傍の係数として使用されます。

77
doug

あなたが直面しているのは、 次元の呪い として知られています。 PCAのようなアルゴリズムを実行したり、 ICA 21次元すべてが本当に必要であることを確認し、ほぼ同じ結果品質で21未満を使用できる線形変換を見つける可能性があります。

更新:RangayyanのBiomedical Signal Processingという本でそれらに遭遇しました(正しく覚えているといいのですが)。 ICAは些細な手法ではありませんが、フィンランドの研究者によって開発されたもので、Matlabのコードは一般にダウンロードして入手できると思います。 PCAはより広く使用されている手法であり、そのRまたは他のソフトウェア実装を見つけることができるはずです。 PCAは、線形方程式を繰り返し解くことにより実行されます。方法を思い出すにはあまりにも前にやったことがあります。 =)

アイデアは、信号を独立した固有ベクトル(実際には離散固有関数)とその固有値(この場合は21)に分割することです。各固有値は、各固有関数が各測定に与える寄与の量を示します。固有値が小さい場合、対応する固有関数をまったく使用せずに信号を非常に厳密に表すことができます。これが次元を取り除く方法です。

16
Phonon

上位の回答は良いですが、古いので、2016年の回答を加算したいと思います。


前述のように、高次元の空間では、次元の呪いが隅に潜んでおり、人気のあるk-dツリーなどの従来のアプローチは、ブルートフォースアプローチと同じくらい遅くなります。その結果、近似最近傍検索(ANNS)に関心を向けます。これにより、精度が向上し、プロセスが高速化されます。正確なNNの適切な近似が得られ、良好な適応性が得られます。


価値があるかもしれないホットなトピック:

  1. LSHの現代的なアプローチ、 Razenshteyn など。
  2. RKD forestFLANN で説明されているように、ランダム化されたkdツリー(RKD)のフォレストまたは、最近のアプローチでは、 kd-GeRaF の一部でした。
  3. LOPQこれは、 here で説明されているように、Locally Optimized Product Quantizationの略です。新しいBabenko + Lemptitskyの approach に非常に似ています。

関連する回答も確認できます。

  1. 2組の高次元ポイント:他のセットで最も近い隣を見つけます
  2. 異なるデータ構造での最近傍クエリのランタイムの比較
  3. PCL kd-treeの実装が非常に遅い
9
gsamaras

質問に1つずつ答えるには:

  • いいえ、ユークリッド距離は高次元空間では悪い指標です。基本的に高次元では、最も近い隣人と最も遠い隣人の間にほとんど違いはありません。
  • 多くの論文/研究が高次元データにありますが、ほとんどのものは多くの数学的な洗練を必要とします。
  • KDツリーは高次元のデータには不適切です...絶対に避けてください

正しい方向で始めるための素敵な論文があります。 「 最も近い近隣にいる場合 ?」バイエル他による。

20K以上の寸法のテキストデータを使用しています。テキスト関連のアドバイスが必要な場合は、お手伝いできる場合があります。

8
BiGYaN

コサイン類似度は、高次元ベクトルを比較する一般的な方法です。距離ではなく類似性であるため、最小化ではなく最大化することに注意してください。ドメイン固有の方法を使用してデータを比較することもできます。たとえば、データがDNAシーケンスである場合、突然変異などの確率を考慮したシーケンス類似性を使用できます。

使用する最近傍の数は、データのタイプ、ノイズの量などによって異なります。一般的なルールはありません。特定のデータと問題に最適なものを見つけるには、範囲内のすべての値を試してください。 。人々は、データが多いほど、必要な隣人が少ないことを直感的に理解しています。すべての可能なデータがある仮想的な状況では、分類するために単一の最近傍のみを探す必要があります。

K最近傍法は計算コストが高いことが知られています。これは、人々がサポートベクターマシンのような他のアルゴリズムに頼る主な理由の1つです。

5
Colin

実際、kdツリーは高次元データではあまりうまく機能しません。枝刈りの手順はあまり役に立たないため、最も近いエッジ(1次元の偏差)は、ほとんどの場合、既知の最近傍への全次元の偏差よりも小さくなります。

しかしさらに、kdツリーは、私が知っているすべての人にとってLpノルムでのみうまく機能します。また、距離ベースのアルゴリズムを次元数の増加とともに低下させる距離集中効果があります。

詳細については、次元の呪い、およびそのさまざまなバリエーション(複数の側面があります!)

私はユークリッドの最近傍を盲目的に近似するだけで多くの用途があるとは確信していません。 LSHまたはランダム投影を使用します。そもそもはるかに微調整された距離関数を使用する必要があるかもしれません!

4
Erich Schubert

KDツリーは、すべてのポイントの5%を見た後、早期に終了した場合、21次元で正常に機能します。 FLANN は、128次元のSIFTベクトルに一致させるために、これ(およびその他の高速化)を行います。 (残念ながら、FLANNはユークリッドメトリックのみを実行し、高速かつ堅牢な scipy.spatial.cKDTree はLpメトリックのみを実行します。これらはyourdata。)もちろん、ここでは速度と精度のトレードオフがあります。

(Ndata、Nquery、データ分布を説明できれば、同様のデータを試すのに役立つかもしれません。)

4月26日、実行可能性の非常に大まかな概念を示すために、私の古いmac ppcのカットオフでcKDTreeの実行時間を追加しました。

kdstats.py p=2 dim=21 N=1000000 nask=1000 nnear=2 cutoff=1000 eps=0 leafsize=10 clustype=uniformp
14 sec to build KDtree of 1000000 points
kdtree: 1000 queries looked at av 0.1 % of the 1000000 points, 0.31 % of 188315 boxes; better 0.0042 0.014 0.1 %
3.5 sec to query 1000 points
distances to 2 nearest: av 0.131  max 0.253

kdstats.py p=2 dim=21 N=1000000 nask=1000 nnear=2 cutoff=5000 eps=0 leafsize=10 clustype=uniformp
14 sec to build KDtree of 1000000 points
kdtree: 1000 queries looked at av 0.48 % of the 1000000 points, 1.1 % of 188315 boxes; better 0.0071 0.026 0.5 %
15 sec to query 1000 points
distances to 2 nearest: av 0.131  max 0.245
3
denis

ブール機能の tf-idf のコサインは、ほとんどの問題に対してうまく機能すると思います。これは、Luceneなどの多くの検索エンジンで使用されている、その実績のあるヒューリスティックによるものです。私の経験では、ユークリッド距離は、テキストのようなデータに対して悪い結果を示しています。異なる重みとk-examplesの選択は、トレーニングデータとブルートフォースパラメーターの選択で実行できます。

3
yura

私は同じ問題を経験し、次のように言うことができます。

  1. ユークリッド距離は優れた距離メトリックですが、計算的には Manhattan distance よりも高価であり、結果がやや劣る場合があるため、後者を選択します。

  2. Kの値は経験的に見つけることができます。さまざまな値を試して、結果の ROC曲線 またはその他の精度/リコール測定値を確認して、許容値を見つけることができます。

  3. ユークリッド距離とマンハッタン距離はどちらも 三角形の不等式 を尊重するため、メトリックツリーで使用できます。実際、KDツリーは、データの次元が10を超えるとパフォーマンスが著しく低下します(この問題は自分で経験しました)。 VP-trees がより良いオプションであることがわかりました。

3

多くの場合、最も近い隣人を知りたい理由に依存します。データセットのモードを見つけることが本当に必要な場合は、平均シフトアルゴリズム http://en.wikipedia.org/wiki/Mean-shift を調べることができます。

3
phunctor

高次元データでの正確なknn検索には、おそらく距離が最適です。近似ボロノイテッセレーションとして表示できます。

3
Tim

Zオーダーカーブを試すことができます。 3次元では簡単です。

2
Gigamegs

ユークリッド距離は、そもそも最近傍を見つけるための良い指標ですか?そうでない場合、私のオプションは何ですか?

ソフト部分空間クラスタリングは、最近ではかなり一般的なアプローチであり、最も重要な次元を見つけるために特徴の重みが計算されることをお勧めします。たとえば、ユークリッド距離を使用する場合、これらの重みを使用できます。一般的な問題については次元の呪いをご覧ください。

混合数値およびカテゴリデータセットの部分空間クラスタリングのためのk-meansタイプクラスタリングアルゴリズム