Python, scikit-learn

【scikit-learn】ニューラルネットワークによる回帰分析【MLPRegressor】


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

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

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

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

回帰分析とは

対象のデータから特定の数値を予測するための統計的手法のことです。

例としては、株価の予測(金利や為替などの情報から株価を予測)などが挙げられます。

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

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

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

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

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

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

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

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

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

プログラム作成の手順

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

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

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

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

scikit-learnには、学習やテストで使用する実験用のデータセットが用意されているため、今回はその中の一つのボストンの住宅価格データ(load_boston)を使用します。

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

ボストン市内の地域ごとの犯罪率や税率などの情報(13項目)を入力データとしてその地域の住宅価格を予測します。

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

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

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

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

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

実装例

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

from sklearn.datasets import load_boston
from sklearn.neural_network import MLPRegressor

import random

if __name__ == '__main__':

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

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

    # 学習データの件数を指定する
    train_size = 300
    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 = MLPRegressor(hidden_layer_sizes=(100,), max_iter=200)
    mlp.fit(train_x, train_y)

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

    # 予測結果から決定係数を算出する
    print('R^2 = {0}'.format(mlp.score(test_x, test_y)))

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

[0] correct:19.600, predict:23.873 (-4.273)
[1] correct:21.000, predict:23.160 (-2.160)
[2] correct:19.300, predict:20.032 (-0.732)
...省略...
[203] correct:22.000, predict:28.461 (-6.461)
[204] correct:10.200, predict:13.339 (-3.139)
[205] correct:16.200, predict:19.643 (-3.443)
R^2 = 0.558631848559529

出力結果の最後の行は「決定係数」の値です。

決定係数とは、回帰分析において正解の値と予測値の誤差を算出した指標であり、その値が1.0に近いほど良い予測性能であると評価されます。

一般的に決定係数が0.6以上あれば予測モデルとして一定の性能を持つとされているため、上記のプログラムで構築したモデルは若干予測の性能に不安があると判断できます。

もう少しパラメータ設定などを工夫する必要がありそうです。