Python, scikit-learn

【scikit-learn】ニューラルネットワークによるクラス分類【MLPClassifier】


今回は機械学習ライブラリのscikit-learnを利用し、ニューラルネットワークのアルゴリズムに基づいてクラス分類を行う方法について書きます。

本記事における用語の説明

まずはいくつか用語の説明をします。

既に知っているという方は読み飛ばして下さい。

クラス分類とは

対象となるデータがいくつかのグループの内どれに属するのかを予測することです。

例としては、スパムメールの分類(受信メールがスパムか否かを予測)などが挙げられます。

ニューラルネットワークとは

AI関連技術である機械学習の代表的な手法の一つです。基本単位のニューロンがいくつも連結することでネットワークを構築し、これを利用して様々な予測を行います。

ニューラルネットワークの内部は一番最初にデータが入力される入力層、計算結果を出力する出力層、入力層と出力層の間の隠れ層のどれかに分類されます。

各層では入力された値を基に計算を行い、その計算結果を次の層のニューロンへ入力するという流れを入力層から出力層まで繰り返します。

各ニューロンにはどの入力を重要視するかを決定する重みがそれぞれ設定されており、重みの値を調整することで望ましい出力を得ることが可能です。

なお、ニューラルネットワークのメリット、デメリットはそれぞれ以下のようになります。

  • メリット:
    層やニューロンの数を増やすことで容易にモデルを拡張できる(層やニューロンの数が多いほど、高い性能が得られやすい)
  • デメリット:
    構造が複雑でブラックボックス化しやすく、何故その結果が得られるのかがわかりにくい

実際にプログラムを作成してみる

それでは実際にニューラルネットワークのアルゴリズムに基づいてクラス分類を行うプログラムを作成してみます。

プログラム作成の手順

ここでは、以下の手順で処理を実装します。

  1. 実験用のデータセットを用意する
  2. データセットの一部を利用して学習(モデルの構築)を行う
  3. 構築したモデルを用いて残りのデータセットに対する予測を行う

今回に限らず、機械学習のモデルを構築する際には上記手順で実行することが多いです。

使用する実験用データセット

scikit-learnには、学習やテストで使用する実験用のデータセットが用意されているため、今回はその中の一つのアヤメの計測データ(load_iris)を使用します。

使用するデータセットの概要は以下の通りです。

花弁や萼片の長さなどの情報(4項目)を入力データとしてアヤメの種類を予測します。

モデル構築に使用するクラス

scikit-learnには、ニューラルネットワークのアルゴリズムに基づいてクラス分類の処理を行うMLPClassifierクラスが存在するため、今回はこれを利用します。

MLPClassifierの主なパラメータは以下の通りです。(一部省略)

  • hidden_layer_sizes:タプル型
    隠れ層のニューロンの数を指定する
  • max_iter:int型
    最大で何回学習を行うかを指定する
  • activation:{‘identity’, ‘logistic’, ‘tanh’, ‘relu’}
    活性化関数の種類を指定する
  • solver:{‘lbfgs’, ‘sgd’, ‘adam’}
    重み最適化の手法を指定する
  • random_state:int型
    乱数のシードを指定する

MLPClassifierはsklearn.neural_networkからインポートします。

実装例

上記の手順に従ってプログラムを作成します。使用する言語はPythonです。

from sklearn.datasets import load_iris
from sklearn.neural_network import MLPClassifier

import random

if __name__ == '__main__':

    # データセットを読み込む
    iris = load_iris()
    x = iris.data
    y = iris.target

    # 読み込んだデータセットをシャッフルする
    p = list(zip(x, y))
    random.shuffle(p)
    x, y = zip(*p)

    # 学習データの件数を指定する
    train_size = 100
    test_size = len(x) - train_size

    # データセットを学習データとテストデータに分割する
    train_x = x[:train_size]
    train_y = y[:train_size]
    test_x = x[train_size:]
    test_y = y[train_size:]

    # ニューラルネットワークの学習を行う
    mlp = MLPClassifier(hidden_layer_sizes=(100,), max_iter=200)
    mlp.fit(train_x, train_y)

    # 学習させたモデルを使ってテストデータに対する予測を出力する
    count = 0
    pred = mlp.predict(test_x)
    for i in range(test_size):
        print('[{0}] correct:{1}, predict:{2}'.format(i, test_y[i], pred[i]))
        if pred[i] == test_y[i]:
            count += 1

    # 予測結果から正答率を算出する
    score = float(count) / test_size
    print('{0} / {1} = {2}'.format(count, test_size, score))

このプログラムを実行すると以下の出力結果が得られます。

[0] correct:2, predict:2
[1] correct:2, predict:2
[2] correct:0, predict:0
...省略...
[47] correct:0, predict:0
[48] correct:0, predict:0
[49] correct:1, predict:1
49 / 50 = 0.98

予測の結果を見ると、正答率が0.98と非常に高い分類精度が得られていることがわかります。