Python
 Computer >> コンピューター >  >> プログラミング >> Python

MatplotlibでMLPClassifierのloss_curve_から取得した損失値を適切にプロットする方法

scikit-learnのMLPClassifier(多層パーセプトロン分類器)は、学習の進行に伴う各イテレーションごとの損失値をloss_curve_属性に記録します。この損失曲線を可視化することで、学習率やモーメンタムなどのハイパーパラメータが収束に与える影響を直感的に把握できます。

ここでは、Matplotlibを使ってloss_curve_で取得した損失値を適切にプロットする手順を紹介します。

実装の手順

  • 図のサイズを設定し、サブプロット間および周囲の余白(パディング)を調整します。
  • ソルバーの設定をまとめた辞書のリスト(params)を作成します。
  • ラベルのリストと、プロット時のスタイル指定(色・線種)のリストを作成します。
  • nrows=2、ncols=2として、図とサブプロットのセットを作成します。
  • アイリスデータセット(分類用)を読み込みます。
  • digitsデータセットからX_digitsとy_digitsを取得します。
  • 複数のデータセットを格納したタプルのリスト(data_sets)を作成します。
  • zipで結合したaxes・data_sets・タイトル名のリストを反復処理します。
  • plot_on_dataset()関数内で、現在の軸にタイトルを設定します。
  • MLPClassifierのインスタンスを生成します。
  • 学習済みモデルを格納するリスト(mlps)を作成します。
  • mlpsを反復処理し、plot()メソッドでmlp.loss_curve_をプロットします。
  • 図を表示するにはshow()メソッドを使用します。

コード例

import warnings
import matplotlib.pyplot as plt
from sklearn.neural_network import MLPClassifier
from sklearn.preprocessing import MinMaxScaler
from sklearn import datasets
from sklearn.exceptions import ConvergenceWarning

plt.rcParams["figure.figsize"] = [7.50, 3.50]
plt.rcParams["figure.autolayout"] = True

params = [{'solver': 'sgd', 'learning_rate': 'constant', 'momentum': 0, 'learning_rate_init': 0.2},
    {'solver': 'sgd', 'learning_rate': 'constant', 'momentum': .9, 'nesterovs_momentum': False, 'learning_rate_init': 0.2},
    {'solver': 'sgd', 'learning_rate': 'constant', 'momentum': .9, 'nesterovs_momentum': True, 'learning_rate_init': 0.2},
    {'solver': 'sgd', 'learning_rate': 'invscaling', 'momentum': 0, 'learning_rate_init': 0.2},
    {'solver': 'sgd', 'learning_rate': 'invscaling', 'momentum': .9, 'nesterovs_momentum': True, 'learning_rate_init': 0.2},
    {'solver': 'sgd', 'learning_rate': 'invscaling', 'momentum': .9, 'nesterovs_momentum': False, 'learning_rate_init': 0.2},
    {'solver': 'adam', 'learning_rate_init': 0.01}]

labels = ["constant learning-rate", "constant with momentum", "constant with Nesterov's momentum", "inv-scaling learning-rate", "inv-scaling with momentum", "inv-scaling with Nesterov's momentum", "adam"]

plot_args = [{'c': 'red', 'linestyle': '-'},
    {'c': 'green', 'linestyle': '-'},
    {'c': 'blue', 'linestyle': '-'},
    {'c': 'red', 'linestyle': '--'},
    {'c': 'green', 'linestyle': '--'},
    {'c': 'blue', 'linestyle': '--'},
    {'c': 'black', 'linestyle': '-'}]

def plot_on_dataset(X, y, ax, name):
    ax.set_title(name)
    X = MinMaxScaler().fit_transform(X)
    mlps = []
    if name == "digits":
        max_iter = 15
    else:
        max_iter = 400
    for label, param in zip(labels, params):
        mlp = MLPClassifier(random_state=0, max_iter=max_iter, **param)
        with warnings.catch_warnings():
            warnings.filterwarnings("ignore", category=ConvergenceWarning, module="sklearn")
            mlp.fit(X, y)
        mlps.append(mlp)
    for mlp, label, args in zip(mlps, labels, plot_args):
        ax.plot(mlp.loss_curve_, label=label, **args)

fig, axes = plt.subplots(2, 2)
iris = datasets.load_iris()
X_digits, y_digits = datasets.load_digits(return_X_y=True)
data_sets = [(iris.data, iris.target), (X_digits, y_digits), datasets.make_circles(noise=0.2, factor=0.5, random_state=1), datasets.make_moons(noise=0.3, random_state=0)]

for ax, data, name in zip(axes.ravel(), data_sets,
['iris', 'digits', 'circles', 'moons']):
    plot_on_dataset(*data, ax=ax, name=name)

fig.legend(ax.get_lines(), labels, ncol=3, loc="upper center")

plt.show()

ポイント解説

  • MinMaxScalerによる前処理: 各データセットの特徴量を0〜1の範囲に正規化することで、ニューラルネットワークの学習を安定させています。
  • ConvergenceWarningの抑制: 学習が最大イテレーション数に達しても収束しない場合に出る警告を、warningsモジュールで非表示にしています。
  • max_iterの使い分け: digitsデータセットは計算コストが高いため15回、それ以外は400回に設定しています。
  • 比較対象のパラメータ: SGD(定学習率・逆スケーリング学習率)×モーメンタムの有無×Nesterov加速の有無、さらにAdamオプティマイザーの計7種類を色と線種で区別して描画しています。

出力結果

MatplotlibでMLPClassifierのloss_curve_から取得した損失値を適切にプロットする方法

MatplotlibでMLPClassifierのloss_curve_から取得した損失値を適切にプロットする方法

このように、iris・digits・circles・moonsの4つのデータセットそれぞれについて、オプティマイザーや学習率スケジュールの違いによる損失の減少挙動を一目で比較できます。一般的に、Adamは初期の損失低下が速く、モーメンタム付きSGDも滑らかな収束を示す傾向があります。

  1. Matplotlibのプロットからデータを抽出する方法|get_xdata・get_ydataの使い方

    Matplotlibで作成したプロットから元のデータを取り出したい場合、get_xdata() メソッドと get_ydata() メソッドを使うことで簡単に実現できます。これらのメソッドは、プロットされたLine2DオブジェクトからX軸・Y軸のデータポイントをそれぞれ取得します。実行手順図のサイズを設定し、サブプロット間および周囲の余白(パディング)を調整します。numpy を使って y のデータポイントを作成します。y のデータポイントを color=red(赤色)・linewidth=5(線幅5)でプロットします。データ抽出の開始を示すメッセージを出力します。get_xdata() と

  2. MatplotlibでNaN値を含むデータをプロット・操作する方法を解説

    MatplotlibでNaN値をプロット・操作する手順 Matplotlibでは、NaN(欠損値)を含むデータもそのまま可視化できます。基本的な流れは以下の3ステップです。 NumPyを使って、NaN値をいくつか含むデータ(配列)を作成します。 imshow()メソッドを使用し、カラーマップとステップ1で作成したデータを指定して、2次元の正規ラスタ上に画像として表示します。デフォルトでは、NaNの部分は自動的に空白(マスクされた領域)として描画されます。 作成した図を画面に表示するには、show()メソッドを呼び出します。 コード例 import numpy as np from matp