Python手書きSklearnのkNNパッケージアルゴリズム.

12357 ワード

昨日、あるバーでワインを当てた話で、機械学習で最も簡単なアルゴリズムであるkNN(K近隣アルゴリズム)を紹介し、Pythonでこのアルゴリズムを一歩一歩実現しました.また対比のために,Sklearn中のkNNアルゴリズムパケットを呼び出し,5行のコードのみを用いた.2つの方法は殊途同帰で、2つの分類問題を正しく解決した.すなわち、新しく倒れたワインは赤霞珠に属している.
文書転送ゲート:
Python手書きマシン学習最も簡単なkNNアルゴリズム(クリック可能)
Sklearnライブラリアルゴリズムを呼び出すと、簡単な数行のコードで問題を解決することができて、気持ちがいいですが、実は私たちはブラックボックスの中にいて、Sklearnの背後で何をしたのか分かりません.初心者として、アルゴリズムの原理をはっきりさせないで直接バッグを調整して、学んだのも表面の工夫だけで、卵の役に立ちません.
そこで今日は、SklearnがどのようにkNNアルゴリズムをカプセル化し、自分でPythonを実現しているのかを理解してみましょう.このように,後でSklearnアルゴリズムパッケージを呼び出すと,より明確な認識が得られる.
まず、昨日のSklearnのkNNアルゴリズムの5行のコードを振り返ってみましょう.
from sklearn.neighbors import KNeighborsClassifier 
kNN_classifier = KNeighborsClassifier(n_neighbors=3)
kNN_classifier.fit(X_train,y_train )
x_test = x_test.reshape(1,-1)
kNN_classifier.predict(x_test)[0]

コードは説明されていますが、今日は1枚の図で理解を深め続けます.
Sklearn呼び出しのすべての機械学習アルゴリズムは,訓練データを選択したアルゴリズムに与えてfitフィッティングを行い,モデルがあれば予測するデータをモデルに与え,予測predictを行い,最終的に結果を出力し,分類と回帰アルゴリズムがそうであるといえる.
注意すべき点は、*kNNは特殊なアルゴリズムであり、トレーニング(fit)でモデルを構築する必要がなく、テストデータを直接トレーニングセットに持って結果を予測することができることです.**これもkNNアルゴリズムが最も簡単な機械学習アルゴリズムである理由の一つである.
しかし、上のSklearnではなぜここでfitがこのステップにフィットしているのか、実際には使わなくてもいいのですが、Sklearnのインタフェースは整然と統一されているので、多くのアルゴリズムと一致するようにトレーニングセットをモデルとしています.
その後、より多くのアルゴリズムを学ぶにつれて、各アルゴリズムにはいくつかの特徴があることがわかり、まとめて比較することができます.
昨日の手書きコードを関数にまとめると、訓練過程がないことがわかります.
import numpy as np
from math import sqrt
from collections import Counter

def kNNClassify(K, X_train, y_train, X_predict):
    distances = [sqrt(np.sum((x - X_predict)**2)) for x in X_train]
    sort = np.argsort(distances)
    topK = [y_train[i] for i in sort[:K]]
    votes = Counter(topK)
    y_predict = votes.most_common(1)[0][0]
    return y_predict

次に、上の図の考え方に従って、Sklearnにカプセル化されたkNNアルゴリズムを、その5行のコードがどのように動作しているかを下から一歩一歩書き出します.
import numpy as np
from math import sqrt
from collections import Counter

class kNNClassifier:
    def __init__(self,k):
        self.k =k
        self._X_train = None
        self._y_train = None

    def fit(self,X_train,y_train):
        self._X_train = X_train
        self._y_train = y_train
        return self

まず、以前の関数をkNNClassifierというClassクラスに書き換える必要があります.Sklearnのアルゴリズムはオブジェクト向けなので、クラスの使用が便利です.
もしあなたがクラスに慣れていないなら、私の以前の文章を参考にしてください.
Python類Classの理解(クリック可能)__init__関数では3つの初期変数が定義され、kは私たちが伝達したk個の近隣点を選択することを示す.self._X_trainself._y_trainの前に下線があります.それらを内部の私有変数と見なし,内部でのみ演算し,外部では変更できないという意味である.
次にfit関数を定義します.この関数はkNNモデルをフィットさせるために使用されますが、kNNモデルはフィットする必要はありません.そのため、私たちはそのままデータセットをコピーし、最後に2つのデータセット自体を返します.
ここで入力した変数を制約します.一つはX_です.trainとy_trainの行数は同じで、1つは私たちが選んだk近隣点が不正数ではなく、例えば負数以上のサンプル点の数でなければ、後続の計算が間違っています.何を制約するか、assert断言文を使用します.
def fit(self,X_train,y_train):
        assert X_train.shape[0] == y_train.shape[0],"   assert                 k ,              ,       "
        assert self.k <= X_train.shape[0]
        self._X_train = X_train
        self._y_train = y_train
        return self

次に、予測されるサンプルポイントに移動し、各サンプルポイントとの距離を計算し、Sklearnのpreditに対応します.これはアルゴリズムの核心部分です.このステップのコードは私たちが前に書いた関数で、直接持ってきて使うことができて、何行かの断言を加えて入力の変数が合理的であることを保証します.
def predict(self,X_predict):
        assert self._X_train is not None,"  predict        fit   self._X_train      "
        assert self._y_train is not None
        assert X_predict.shape[1] == self._X_train.shape[1],"                "

        distances = [sqrt(np.sum((x_train - X_predict)**2)) for x_train in self._X_train]
        sort = np.argsort(distances)
        topK = [self._y_train[i] for i in sort[:self.k]]
        votes = Counter(topK)
        y_predict = votes.most_common(1)[0][0]
        return y_predict

ここで簡単なSklearn kNNパッケージアルゴリズムを完成し、kNN_sklearn.pyファイルに保存し、jupyter notebookでテストを実行します.
基礎データを取得するには、次の手順に従います.
#    
X_raw = [[13.23,  5.64],
       [13.2 ,  4.38],
       [13.16,  4.68],
       [13.37,  4.8 ],
       [13.24,  4.32],
       [12.07,  2.76],
       [12.43,  3.94],
       [11.79,  3.  ],
       [12.37,  2.12],
       [12.04,  2.6 ]]
X_train = np.array(X_raw)

#    
y_raw = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1]
y_train = np.array(y_raw)

#     
x_test= np.array([12.08,  3.3])
X_predict = x_test.reshape(1,-1) 

注意:予測変数が1つしかない場合は、reshape(1,-1)を2次元配列にしないとエラーが発生します.
jupyter notebookでプログラムを実行するには、魔法コマンド%runを使用します.
%run kNN_Euler.py

これでkNN_をそのまま運転できましたEuler.pyプログラムは、その後、プログラム内のkNNClassifierクラスを呼び出し、kパラメータを3とし、インスタンスkNN_と命名することができる.classify .
kNN_classify = kNNClassifier(3)

次にサンプルセットX_をtrain,y_trainはインスタンスfitに渡される:
kNN_classify.fit(X_train,y_train)

fitが完了したら予測対象サンプルX_に転送するpredictで予測すると分類結果が得られます.
y_predict = kNN_classify.predict(X_predict)
y_predict

[out]:1

答えは1と昨日の2つの方法の結果は同じです.
難しくないですか.
さらに、1回の予測が1つのポイントではなく、次の2つのポイントがどのクラスに属するかを予測するなど、複数のポイントを予測します.
予測の分類結果を同時に与えることができますか?答えはもちろんいいです.以下のパッケージアルゴリズムを少し修正すればいいです.predict関数を以下のように修正します.
def predict(self,X_predict):
        y_predict = [self._predict(x) for x in X_predict]  #               list      
        return np.array(y_predict)

def _predict(self,x):  # _predict    
        assert self._X_train is not None
        assert self._y_train is not None

        distances = [sqrt(np.sum((x_train - x)**2)) for x_train in self._X_train]
        sort = np.argsort(distances)
        topK = [self._y_train[i] for i in sort[:self.k]]
        votes = Counter(topK)
        y_predict = votes.most_common(1)[0][0]
        return y_predict

ここでは2つの関数を定義し、predictはリスト生成式で複数の予測分類値を格納し、予測値はどこから来たのか、_predict関数を用いて計算され、_predictの前の下線は同様にパッケージされたプライベート関数であり、内部でのみ使用され、外部では呼び出せないことを示している.
アルゴリズムを書くには、複数の予測サンプルを入力するだけでいいです.ここでは2つを渡します.
X_predict = np.array([[12.08,  3.3 ],
		[12.8,4.1]])

予測結果を出力:
y_predict = kNN_classify.predict(X_predict)
y_predict

[out]:array([1, 0])

見て、2つの値を返して、1番目のサンプルの分類結果は1である赤霞珠で、2番目のサンプルの結果は0である黒ピノである.実際の結果と一致して完璧です.
ここまでは、Sklearnアルゴリズムパッケージ方式でkNNアルゴリズムを書きましたが、SklearnのkNNアルゴリズムはこれよりも複雑です.kNNアルゴリズムには、**kNNアルゴリズムを処理する欠点の一つである計算に時間がかかるため、考慮すべきことがたくさんあります.**簡単に言えば,kNNアルゴリズムの実行時間はサンプルセットの有と特徴値の数の次元に高度に依存し,次元が高いとアルゴリズムの実行時間が極めて速く増加し,具体的な原因と改善方法は後で述べる.
今もう一つ重要な問題があります.私たちはすべての訓練セットでkNNアルゴリズムを実現しましたが、その予測の効果と正確率はどうなのか、次の文章では、kNNアルゴリズムの効果の良し悪しをどのように測定するか分かりません.
本文のjupyter notebookコード、私の公众号:“高级の农民工”の楽屋で“kNN 2”を返事することができて、顽张ります!
転載先:https://juejin.im/post/5cf793e76fb9a07ea6486265