SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Pythonによるデータ解析入門

定番のPython機械学習ライブラリ「scikit-learn」ではじめての学習モデル作成から改善まで

scikit-learnによる、はじめてのPython機械学習(2)

学習モデルの改善と過学習

 では次に、線形モデルではなく非線形モデルを使ってみましょう。非線形モデルとして多次元の多項式を使います。np.vanderメソッドと組み合わせることで線形回帰を利用することができます。ここでは2次・3次・10次の多次元多項式での学習を試みてみましょう。

[コラム] numpyのvanderメソッド

 多次元の多項式を表現するための行列式はnumpyのvanderメソッドで利用できます。この行列式はヴァンデルモンドの行列式と呼ばれます。ヴァンデルモンドの行列式は多次元の多項式を表現する以外にもさまざまな特徴があります。より詳しくヴァンデルモンドの行列式を理解したい方はWikipediaの下記記事を参照してください。

 ヴァンデルモンドの行列式 - Wikipedia

lr2 = lm.LinearRegression()
fig, ax = plt.subplots(1, 1, figsize=(7, 4))
ax.plot(x_target, y_target, '--k')

for deg, style in zip([2, 3,10], ['.', '.', '-']):
    lr2.fit(np.vander(x, deg + 1), y)
    y_lr2 = lr2.predict(np.vander(x_target, deg + 1))
    ax.plot(x_target, y_lr2, style,label=f'degree {deg}')
    ax.legend(loc=2)
    ax.set_xlim(0, 1.5)
    ax.set_ylim(0, 90)
    # モデルの係数
    print(f'次元 {deg}の場合の係数:\n\t',' '.join(f'{c:.1f}' for c in lr2.coef_))
ax.plot(x, y, 'o', ms=10)
ax.set_title("Linear regression")

 結果は下記になります。

    次元 2の場合の係数:
    	 18.2 0.5 0.0
    次元 3の場合の係数:
    	 82.3 -145.1 103.1 0.0
    次元 10の場合の係数:
    	 -20240521.6 102820634.8 -201942763.6 159316105.0 49193764.3 -220981770.4 215878812.8 -113353443.3 34758868.6 -5873519.6 0.0

    Text(0.5,1,'Linear regression')
非線形モデル
非線形モデル

 ここでは2次、3次、10次の多項式をモデルとしてそれぞれ学習してみました。10次の場合におかしな結果になっています。3次の場合はうまく学習しているように見えますがxが0.4未満の範囲を見てみると大きく外れています。このような現象は「過学習」と呼ばれます。学習が訓練データに”適応しすぎた”ことによるものです。そのため訓練データ以外のデータ(xが1以上や0.4未満の範囲)に対してうまく予測ができない状態になってしまいました。

リッジ回帰による改善

 これを改善するため、リッジ回帰を使うことにします。リッジ回帰は線形回帰の応用の学習モデルです。正則化最小二乗学習とも呼ばれます。先ほどの過学習では多項式の係数が大きくなりすぎる現象が起こりました。リッジ回帰は多項式の係数が大きくなりすぎないように自ら調整し適した学習を行います。

 scikit-learnはリッジ回帰のモデルをRidgeCVメソッドで利用できます。先ほどのコードlm.LinearRegression()をlm.RidgeCV()に置き換えます。この箇所以外は同じです。

ridge = lm.RidgeCV()

fig, ax = plt.subplots(1, 1, figsize=(7, 4))
ax.plot(x_target, y_target, '--k')

for deg, style in zip([2, 3,10], ['.', '.', '-']):
    ridge.fit(np.vander(x, deg + 1), y)
    y_ridge = ridge.predict(np.vander(x_target, deg + 1))
    ax.plot(x_target, y_ridge, style, label='degree ' + str(deg))
    ax.legend(loc=2)
    ax.set_xlim(0, 1.5)
    ax.set_ylim(0, 90)
    print(f'次元 {deg}の場合の係数:\n\t', ' '.join(f'{c:.1f}' for c in ridge.coef_))

ax.plot(x, y, 'o', ms=10)
ax.set_title("Ridge regression")

 結果は下記になります。

    次元 2の場合の係数:
    	 11.1 7.8 0.0
    次元 3の場合の係数:
    	 6.9 6.5 5.0 0.0
    次元 10の場合の係数:
    	 0.3 0.3 0.4 0.6 1.0 1.6 2.4 3.5 4.4 4.3 0.0

    Text(0.5,1,'Ridge regression')
リッジ回帰
リッジ回帰

 今度の図では10次の式は3次や2次の式より正確に正解モデルを予測しているようです。また3次の式の過学習も改善されました。これはリッジ回帰が複雑なモデルでも過学習を回避するように働いたためです。多項式の係数が過学習が起きた際とくらべて小さくなってることを確認してください。

まとめ

 今回はPythonによる機械学習に挑戦しました。機械学習は複雑な処理もありますがライブラリの力をかりて手軽に可能であることを確認していきました。今回解説した手法以外にもさまざまなアルゴリズムが利用可能ですので手元の環境で確認してみてください。

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
Pythonによるデータ解析入門連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 西 潤史郎(ニシ ジュンシロウ)

WINGSプロジェクト について>有限会社 WINGSプロジェクト が運営する、テクニカル執筆コミュニティ(代表 山田...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/11252 2018/12/12 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー