Pythonで機械学習の初歩の初歩 - 基礎概念とクラス分類 -

はじめに

Python3とscikit-learnで機械学習のプログラミングを勉強中です.
今までに勉強したことのまとめとして,初歩的な内容ですが,クラス分類と回帰のモデルについて,そのコーディング方法についてまとめたいと思います.

大局的な理解を目標としたいので,本記事では細かい定義や数式に関しては省略しています.

実行環境

バージョン

コーディングは,Jupyter Notebook上で行っています.

Python 3.6.2
NumPy 1.13.3
matplotlib 2.0.2
IPython 6.1.0
scikit-learn 0.19.0

インポート設定

この辺をそろえておけば十分かと思います.

import sys
import numpy as np
import pandas as pd
import scipy as sp
import matplotlib
import matplotlib.pyplot as plt
%matplotlib inline
import sklearn

基本的な流れと重要概念

モデルの構築

機械学習を行うにあたっては,まず利用するモデルにデータを入力し,学習させる必要があります.
モデルをデータに沿って学習させることで,未知のデータに対しても正確な予測を返すことが期待できます.
f:id:Szarny:20171016225408p:plain:w500

モデルの評価

ところで,モデルにデータを学習させたからと言って「必ずしも未知のデータに対応できるモデルになっている」と言い切ることはできません.
つまり,適切に学習が行われたのかを評価する仕組みが必要になります.

このような場合,所持しているデータセット訓練用データテストデータに分割する手法が有用です.
すなわち,モデルを訓練用データを用いて学習させた後,訓練用データとテストデータそれぞれを用いて期待するような結果を返すかを確かめるのです.(交差検証といいます)
f:id:Szarny:20171016230105p:plain:w650

モデルの評価結果それぞれにおいて,考えられる状態を以下に示します.
f:id:Szarny:20171016231519p:plain

汎化とは

汎化とは,学習済みのモデルが,未知のデータに対して正確な予測を返すことができている状態のことをいいます.
テストデータに対して高い適合度を示しているということは,このモデルは未知のデータに対しても正確な予測をすることが可能だということが言えるでしょう.

過剰適合とは

過剰適合とは,訓練用データに対して,過度に複雑なモデルを構築してしまう状態のことを言います.
言い換えれば,モデルが訓練用データ専用になってしまっている状態です.
そのため,訓練用データに対しては高い適合度を示しますが,テストデータや未知のデータに対しては低い適合度を示します.
過学習とも言います

適合不足とは

適合不足とは,訓練用データに対して,過度に単純なモデルを構築してしまう状態のことを言います.
そのため,訓練用データに対しても,テストデータに対しても低い適合度を示してしまいます.
この状態になった場合は,そもそもデータ量や特徴量が足りないのではないかモデルのパラメータ設定が不適切ではないのか,ということをチェックする必要があります.

クラス分類

クラス分類の概要

クラス分類には,大きく分けて2クラス分類多クラス分類があります.

「あるデータはAクラスとBクラスどちらに属するのか」といった分類方法は2クラス分類にあたります.
一方で,「あるデータはA,B,C,...クラスのどれに属するのか」といった分類方法は多クラス分類にあたります.

これから,以下のモデルを用いて,クラス分類を実際に試してみます.

k-近傍法

k-近傍法とは,あるデータのベクトルとの距離が最も小さいk個のベクトルを基にクラスを分類するモデルです.

f:id:Szarny:20171016222939p:plain
k近傍法 - Wikipediaより

上の例は,緑のデータが赤と青のどちらに分類するかをk-近傍法で決定する様子を示しています.

k=3の時,緑のデータに近い3つのデータを見ると,赤の方が多いことが分かります.
この時,緑のデータは赤の方に属すると判断されます.
k=5の時も同じように進めると,先ほどとは異なり,緑のデータは青の方に属すると判断されます.

k-近傍法のリファレンス

モデルは,sklearn.neighbors.KNeighborsClassifierを用います.
よく用いられる代表的なメソッドは,以下の通りです.

# データXと解答yのペアを分割する
X_train, X_test, y_train, y_test = train_test_split(X, y)

# 近傍の数をnとして,モデルを生成
KNeighborsClassifier(n_neighbors=n)

# データXと解答yのペアをモデルに学習させる
KNeighborsClassifier(...).fit(X, y)

# データXと解答yのペアを与え,モデルの適合度を調査する
KNeighborsClassifier(...).score(X, y)

# データXに対する解答yを予測させる
KNeighborsClassifier(...).predict(X)

k-近傍法の実例

データセットとして,お馴染みのアイリスデータセットを用います.
詳細は,こちらを参照してください.
The Iris Dataset — scikit-learn 0.19.1 documentation


パラメータである近傍の数を変化させていったときに,適合度がどう変化するのかを調査します.

# データセットとモジュールのインポート
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split 
from sklearn.neighbors import KNeighborsClassifier

# アイリスデータセットの特徴量と答えを抽出
iris_data = load_iris()
feature_data = iris_data.data
target_data = iris_data.target

# 訓練用データとテストデータに分割
X_train, X_test, y_train, y_test = train_test_split(feature_data, target_data, random_state=9999)

# 近傍の数を変化させながら,適合度を調査する
n_neighbors = range(1, 101)
train_score = []
test_score = []

for n_neighbor in n_neighbors:
    # 分類器の訓練
    clf = KNeighborsClassifier(n_neighbors=n_neighbor).fit(X_train, y_train)
    
    train_score.append(clf.score(X_train, y_train))
    test_score.append(clf.score(X_test, y_test))
    
plt.figure(facecolor="w")
plt.plot(n_neighbors, train_score, "-", label="train score")
plt.plot(n_neighbors, test_score, "-", label="test score")
plt.hlines(1, 0, len(n_neighbors), color="k")
plt.title("Score of KNeighborsClassifier")
plt.ylabel("Score")
plt.xlabel("n_neighbors")
plt.xlim(0, len(n_neighbors))
plt.legend(loc="lower left")
plt.grid()

f:id:Szarny:20171016234736p:plain:w600

結果を見ると,近傍の数が3から15くらいの間では,比較的優秀な適合度を示しているのに対し,それ以外では劣った適合度を示しています.

近傍の数が少ないときに,訓練用データに対しては適合度が高い一方,テストデータに対しては適合度が落ちています.
これは,過剰学習が発生したためだと考えられます.
つまり,少ない近傍しか考慮していないために,汎用的なモデルの構築に失敗している状態です.

逆に,近傍の数が多いときには,両方のデータに対して適合度が急落しています.
これは,適合不足が発生したためだと考えられます.
つまり,あまりにも多くの近傍を考慮した結果,ずさんなモデルが構築されてしまった状態です.

以上より,このデータセットに対しては,モデルのパラメータとして,近傍の数を3から15くらいに設定するのが最適であるとわかりました.

もちろん,データセットの分割方法によって変化する可能性もあります.(random_stateパラメータで変更可能です)

おわりに

機械学習の基礎概念について,k-近傍法によるクラス分類を用いてまとめました.
次回は,回帰モデルについてまとめようと思います.