K-NN training


Preparing Data with Numpy

  • 図3に示すように、fish lengthおよびfish weight配列を作成する.
  • 2-1. (既存)zip関数を使用して長さと重量をリストにマージ
    fish_data = [[l, w] for l, w in zip(fish_length, fish_weight)]
    2-2. (Numpyを使用)column_stack関数を使用して渡されたリストを一列に並べ、順番に並べて接続します.
    fish_data = np.column_stack((fish_length, fish_weight))
  • 上位35個は1、下位14個は0
  • Split set with scikit-learn


    Lecutore 3では、直接に配列されたインデックスを混合してトレーニングセットとテストセットを作成します.
    今回はもっと簡単にscikit-learningを使ってトレーニングセットとテストセットを作ります.train_test_split()関数を使用して、伝達されたリストまたは配列を訓練セットおよびテストセットに比例して分割する.
    また、分ける前に、自分でかき混ぜます:)
    from sklearn.model_selection import train_test_split
    
    train_input, test_input, train_target, test_target = train_test_split(
        fish_data, fish_target, random_state=42
    )
    
    print(test_target)
    # [1. 0. 0. 0. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
    fish data、fish targetの2つの配列で、それぞれtrainとtestに使用されます.
    合計4つの配列を返します.

    13個のテストキットのうち、10個は鯛(1)、3個は白魚(0)であった.
    よく混ざっていますが、氷魚の割合がちょっと足りません.
    元々鯛と氷魚の個数は35個と14個だったので、2匹の割合は2.5:1でした.
    しかし,この試験キットの鯛と氷魚の割合は3.3:1であり,サンプリングバイアスが現れた.
    train test split()関数では、レベルパーセントstratify 매개변수에 타깃 데이터를 전달하면に従ってデータをグループ化します.
    この点は、トレーニングデータが小さい場合や、特定のカテゴリのサンプル数が少ない場合に特に有用である.
    train_input, test_input, train_target, test_target = train_test_split(
        fish_data, fish_target, stratify=fish_target, random_state=42
        )

    K-Nearest Neighbor Classifier


    K-Nearest Neighborアルゴリズムはscikit-learningライブラリで使用できます.
  • KNeighborsClassifierモデル
  • fitは、データ値に基づいてトレーニングを行う方法である.
  • scoreは、正解のパーセンテージを返す関数で、0から1の間の値を返します.
    1を返すと、すべてのデータが正しいことを示します.
  • from sklearn.neighbors import KNeighborsClassifier
    
    kn = KNeighborsClassifier() # 1. 모델 생성
    
    kn.fit(train_input, train_target) # 2. 모델 학습
    kn.score(test_input, test_target) # 3. 모델 평가
    しかし、長さが25、重さが150メートル以上のデータを入れて確認すると、以下のエラーが氷魚(0)と予測されていることがわかります.
    散点図を描いてデータを確認します.(scatter -> xlabel, ylabel -> show )
    print(kn.predict([[25, 150]]))
    # [0.]

    この試料は明らかに右上隅に延びる他の多メートルデータに近いが,左下隅の氷魚データにも近い.
    K−NNは周囲のサンプルにおいて複数のカテゴリを予測として用いた.
    このサンプルの周辺サンプルを調べてみましょう.KNeighborsClassifierクラスのkneighbors()methodは、隣接する距離と隣接する例のインデックスを返します.
    KNeighborsClassifierクラスの隣接数nのデフォルト値は5であるため、5つの隣接を返します.
    distances, indexes = kn.kneighbors([[25, 150]])
    
    plt.scatter(train_input[:,0], train_input[:,1])
    plt.scatter(25, 150, marker='^')
    plt.scatter(train_input[indexes,0], train_input[indexes,1], marker='D')   # marker 매개변수로 모양을 지정
    plt.xlabel('length')
    plt.ylabel('weight')
    plt.show()

    三角形に近い試料の5つの試料を緑色菱形とした.
    print(train_input[indexes])
    # [[[ 25.4 242. ]
    #  [ 15.   19.9]
    #  [ 14.3  19.7]
    #  [ 13.   12.2]
    #  [ 12.2  12.2]]]
    
    print(train_target[indexes])
    # [[1. 0. 0. 0. 0.]]
    トレーニングコースのデータを直接確認すると、4つ近くの魚が氷魚であることも確認できます.
    今回は距離配列を印刷します.
    print(distances)
    # [[ 92.00086956 130.48375378 130.73859415 138.32150953 138.39320793]]

    さらに、散点図を見ると、三角形サンプルに最も近い最初のサンプルまでの距離は92であり、他の最も近いサンプルは130、138である.
    グラフに表示される距離パーセント異常が表示されます.これは、x軸が10~40の範囲が狭く、y軸が0~1000の範囲が広いためである.
    従って、y軸から少し離れていても、距離は大きな値として計算され、多メートルサンプルが隣接するものとして選択されない.
    これは、x軸範囲が狭く(10~40)、y軸範囲が広い(0~1000).したがって,y軸から少しずれても距離は大きな値として計算されるため,右上隅の多メートルサンプルは隣接として選択されない.
    これを明確に見るために,x軸の範囲を0〜1000に調整した.xlim()x軸の範囲を関数で0から1000に調整し、散点を再度確認します.
    plt.scatter(train_input[:,0], train_input[:,1])
    plt.scatter(25, 150, marker='^')
    plt.scatter(train_input[indexes,0], train_input[indexes,1], marker='D')
    plt.xlim((0, 1000))
    plt.xlabel('length')
    plt.ylabel('weight')
    plt.show()

    x軸とy軸の範囲を揃えると、すべてのデータが垂直に並んでいることがわかります.
    これらのデータであれば,魚の長さ(x軸)は最近の隣人を探すのにあまり影響を及ぼさず,魚の重量(y軸)のみを考慮する.
    この2つの特性(長さと重量)の値の範囲は非常に異なり、すなわち2つの特性のスケールが異なる.

    Data Processing


    表現データの基準が異なると,アルゴリズムは正確に予測できない.
    これらのアルゴリズムはサンプル間距離の影響が大きいため,正しく使用するには一定の基準で特徴値をフィットさせなければならない.
    このような仕事を데이터 전처리(data preprocessing)と呼ぶ.
    最も広く用いられている前処理方法の1つは표준점수(standard score)である.
    標準スコアは、各特性値の平均距離の標準偏差の数倍を表します.
    これにより、実際の特性値の大きさにかかわらず、同じ条件で比較することができる.
    平均を減算し、標準偏差で除算すればよい.
    この場合、各特性の値の大きさが異なるため、平均偏差と標準偏差は各特性に基づいて計算される.
    このため、axis=0として指定します.これにより、各カラムの統計値を行に沿って計算できます.
    mean = np.mean(train_input, axis=0) # 각 특성 별로 계산
    std = np.std(train_input, axis=0)
    
    # 평균을 빼고 표준편차를 나누기
    train_scaled = (train_input - mean) / std

    Train a model with preprocessed data

    new = ([25, 150] - mean) / std
    
    plt.scatter(train_scaled[:,0], train_scaled[:,1])
    plt.scatter(new[0], new[1], marker='^')
    plt.xlabel('length')
    plt.ylabel('weight')
    plt.show()

    標準偏差に変換する前の散点とほぼ同じです.
    違いは、x軸とy軸の範囲が−1.5~1.5であることである.
    現在,訓練データの2つの特性が類似の範囲を占めている.
    今からK-NNモデルでトレーニングしていきましょう
    kn.fit(train_scaled, train_target)
    test_scaled = (test_input - mean) / std
    kn.score(test_scaled, test_target) # 1.0
    print(kn.predict([new])) # [1.]
    今回の予測では、ドミノの骨牌を使った正確な予測を見ることができます.
    散点図を再描画して確認し、

    今回は三角形のサンプルと最近の5人の隣人が鯛であることがわかります.

    Overfitting & Underfitting

    kn = KNeighborsClassifier()
    kn.fit(train_input, train_target)
    
    for n in range(5, 50):
        # 최근접 이웃 개수 설정 (5부터 50까지)
        kn.n_neighbors = n
        
        # 점수 계산
        score = kn.score(test_input, test_target)
        
        # 100% 정확도에 미치지 못하는 이웃 개수 출력
        if score < 1:
            print(n, score)
            break
            
    # 20 0.9230769230769231
    一例だけ挙げたが,このようにscoreは常に1ではなく不正確な予測値を与える.
    mgroopライブラリを使用するにはpipを使用してインストールする必要があります.
    !pip install mglearn
    import mglearn
    
    fig, axis = plt.subplots(1, 3, figsize=(10, 3))
    
    for n_neighbors, ax in zip([2, 5, 30], axis):    
        # 모델 훈련
        clf = KNeighborsClassifier(n_neighbors=n_neighbors).fit(train_scaled, train_target)
        # 산점도 제작
        mglearn.plots.plot_2d_separator(clf, train_scaled, fill=True, eps=0.5, ax=ax, alpha=.4)
        mglearn.discrete_scatter(train_scaled[:, 0], train_scaled[:, 1], train_target, ax=ax)
        ax.set_title("{} neighbor(s)".format(n_neighbors))
        ax.set_xlabel("feature0")
        ax.set_ylabel("feature1")
        
    axis[0].legend(loc=3)
    plt.show()

    kが小さい頃は反応が敏感すぎて、平均値と大きく異なるデータがたくさんありました(Noise).△現在のデータ数は少なく、よく見えません.
    -> Underfittingk=30では反応が鈍く、グループ境界に対する弁別力がない.
    -> Overfitting