I.距離メトリック
まず、データセット内の特徴(列)の数は、kNNで使用する距離メトリックを選択する際の要因ではありません。正確にこの質問に向けられたかなりの数の公開された研究があり、比較のための通常の根拠は次のとおりです。
データがサンプリングされた分布についての予備知識がない場合、少なくとも1つの(十分に文書化された徹底的な)調査で、ユークリッド距離が最良の選択であると結論付けられます。
メガスケールのWeb推奨エンジンおよび現在の学術研究で使用されているYEuclideanメトリック。ユークリッド距離は直感的な意味を持ち、計算スケールがあります。つまり、ユークリッド距離は、2つの点が2次元であろうと、22次元空間であろうと、同じ方法で計算されます。
私にとっては数回しか失敗しませんでした。基礎となる(デカルト)座標系が不適切な選択であったため、これらの各ケースでユークリッド距離が失敗しました。たとえば、パスの長さ(距離)が加算されなくなったため、通常はこれを認識します。たとえば、距離空間がチェスボードの場合、マンハッタンの距離はユークリッドよりも優れています。同様に、距離空間が地球で距離がトランスの場合も同様です。 -大陸便、極座標系に適した距離メトリックは良い考えです(たとえば、ロンドンからウィーンまでは2.5時間、ウィーンからサンクトペテルブルクまではさらに3時間、ほぼ同じ方向ですが、ロンドンからセント。ピーターズバーグは5.5時間ではなく、3時間強です。)
ただし、データが非デカルト座標系に属している場合を除いて、距離メトリックの選択は通常重要ではありません。(CS学生からのこのブログ投稿を参照して、kNN分類器への影響を調べることによっていくつかの距離メトリックを比較します-chi squareは最良の結果をもたらしますが、違いは大きくありません;より包括的な研究は学術論文のComparative Study of最近傍の距離関数-マハラノビス(本質的に、次元共分散を説明するために正規化されたユークリッド)は、この研究で最高でした。
重要な条件の1つ:距離メトリックの計算を意味のあるものにするには、再スケーリングする必要がありますデータ-これを行わずに正確な予測を生成するためにkNNモデルを構築することはめったにありません。たとえば、運動能力を予測するためにkNNモデルを構築していて、期待変数が身長(cm)、体重(kg)、体脂肪(%)、および安静時脈拍(1分あたりの心拍数)である場合、一般的なデータポイントは次のようになります。次のようになります:[180.4、66.1、11.3、71]。明らかに、距離の計算は身長によって支配されますが、体脂肪率による寄与はほとんど無視できます。言い換えると、代わりにデータが異なる方法で報告され、体重がキログラムではなくグラムであった場合、元の値86.1は86,100になり、結果に大きな影響を与えます。これはまさにあなたが行うことです。したくない。
X_new = (X_old - mu) / sigma
II。データ構造
kd-tree構造のパフォーマンスが心配な場合、A Voronoi Tessellationは概念的に単純なコンテナーですが、kd-Treeよりもパフォーマンスとスケーリングが大幅に向上します。

これは、kNNトレーニングデータを永続化するための最も一般的な方法ではありませんが、この目的でのVTの適用、およびその結果としてのパフォーマンス上の利点は、十分に文書化されています(たとえば、このMicrosoft Researchレポートを参照)。これの実際的な重要性は、「主流」言語を使用している場合(たとえば、TIOBEインデックス)、VTを実行するためのライブラリを見つける必要があるということです。PythonとRには、言語ごとに複数のオプションがあることを知っています(たとえば、CRANで利用可能なRのボロノイパッケージ)
kNNにVTを使用すると、次のように機能します。
データからランダムにwポイントを選択します。これらはボロノイ中心です。ボロノイセルは、各中心に最も近いすべての隣接点をカプセル化します。ボロノイ中心のそれぞれに異なる色を割り当てて、特定の中心に割り当てられた各点がその色でペイントされるようにすると想像してみてください。十分な密度がある限り、これを行うと、各ボロノイ中心の境界が(2つの色を分離する境界として)うまく表示されます。
ボロノイセンターの選択方法は?私は2つの直交するガイドラインを使用します。wポイントをランダムに選択した後、トレーニングデータのVTを計算します。次に、各ボロノイ中心に割り当てられたデータポイントの数を確認します。これらの値はほぼ同じである必要があります(データ空間全体でポイント密度が均一である場合)。2次元では、これにより同じサイズのタイルを持つVTが発生します。これが最初のルールであり、これが2番目のルールです。反復ごとにwを選択します。変数パラメーターとしてwを使用してkNNアルゴリズムを実行し、パフォーマンス(VTにクエリを実行して予測を返すために必要な時間)を測定します。
したがって、100万のデータポイントがあると想像してください.....ポイントが通常の2Dデータ構造またはkdツリーで永続化されている場合、それぞれに対して平均で数百万の距離計算を実行します。応答変数を予測する新しいデータポイント。もちろん、これらの計算は単一のデータセットに対して実行されます。V / Tを使用すると、2つの異なるデータ母集団に対して、2つのステップで最近傍探索が実行されます。最初はボロノイ中心に対して、次に最も近い中心が見つかると、セル内のポイントはに対応します。その中心を検索して、実際の最近傍を見つけます(連続した距離計算によって)これらの2つのルックアップを組み合わせると、単一のブルートフォースルックアップよりもはるかに高速になります。これは簡単にわかります。100万個のデータポイントの場合、データスペースをテッセレートするために250個のボロノイセンターを選択するとします。平均して、各ボロノイセルには4,000個のデータポイントがあります。したがって、平均500,000の距離計算(ブルートフォース)を実行する代わりに、実行する距離ははるかに少なく、平均で125+2,000になります。
III。結果の計算(予測された応答変数)
kNNトレーニングデータのセットから予測値を計算するには、2つのステップがあります。1つ目は、n、つまりこの計算に使用する最近傍の数を特定することです。2つ目は、予測値への寄与をどのように重み付けするかです。
最初のコンポーネントでは、最適化問題を解くことでnの最適値を決定できます(最小二乗最適化と非常によく似ています)。それが理論です。実際には、ほとんどの人はn=3を使用します。いずれにせよ、n = 1、n = 2、n = 3などの一連のテストインスタンス(予測値を計算するため)に対してkNNアルゴリズムを実行し、nの関数としてエラーをプロットするのは簡単です。nのもっともらしい値を開始したいだけの場合は、ここでもn=3を使用します。
2番目のコンポーネントは、各ネイバーの寄与をどのように重み付けするかです(n> 1と仮定)。
最も単純な重み付け手法は、各ネイバーに重み付け係数を掛けるだけです。これは、1 /(dist * K)、またはそのネイバーからテストインスタンスまでの距離の逆数に、経験的に導き出された定数Kを掛けたものです。この手法は、最も近い隣人を過大評価することが多いため(同時に、より遠い隣人を過小評価するため)、この手法のファンではありません。これの重要性は、与えられた予測がほぼ完全に単一のネイバーに依存する可能性があることです。これにより、アルゴリズムのノイズに対する感度が向上します。
この制限を実質的に回避する、より優れた重み関数は、Pythonでは次のように見えるガウス関数です。
def weight_gauss(dist, sig=2.0) :
return math.e**(-dist**2/(2*sig**2))
kNNコードを使用して予測値を計算するには、応答変数を予測するデータポイント(「テストインスタンス」)に最も近いn個の近傍を特定し、次に、n個の近傍ごとに1回、weight_gauss関数を呼び出します。この関数は、各近傍の重みを返します。これは、加重平均計算でその近傍の係数として使用されます。