機械学習 はじめよう

第20回 ロジスティック回帰の実装

この記事を読むのに必要な時間:およそ 3 分

パラメータの初期値と学習の終了条件

後はパラメータwの初期化と学習の終了条件だけです。この2つは実は少々関連があります。

パーセプトロンの解法アルゴリズムは,0で初期化したパラメータで始めるとすべてのデータ点を完全に正しく分離する解にたどり着くことが示されています。

この時の学習ループの終了条件は明確で,⁠すべてのデータ点での予測が正解と一致するまで」となります。⁠線形分離可能な問題に限る」という強い条件が付いているだけあって,非常に強い性質を持っているわけですね。

一方の確率的勾配降下法で求まるのは,パラメータwの初期値に依存した局所解になります。そこでランダムな初期値で始めるのが一般的ですが,パラメータが大きくなりすぎるのを嫌って,あえて0から始めることもあります。

w = np.random.randn(3)  # パラメータをランダムに初期化

そうして求めた局所解は,一般に全データ点で正解を予測できるものにはなりませんので,学習ループの終了条件もパーセプトロンのままというわけにはいきません。

そこで確率的勾配降下法では尤度などの指標値があまり変化しなくなったら終了したり,あるいはあらかじめ学習の回数を適当に決めておきます。

今回はシンプルに学習回数を50周と決めておきましょう。

これらをすべて反映したコードは次のようになります。

import numpy as np
import matplotlib.pyplot as plt

# データ点の個数
N = 100

# データ点のために乱数列を固定
np.random.seed(0)

# ランダムな N×2 行列を生成 = 2次元空間上のランダムな点 N 個
X = np.random.randn(N, 2)

def f(x, y):
    return 5 * x + 3 * y - 1  #  真の分離平面 5x + 3y = 1

T = np.array([ 1 if f(x, y) > 0 else 0 for x, y in X])

# 特徴関数
def phi(x, y):
    return np.array([x, y, 1])

# シグモイド関数
def sigmoid(z):
    return 1.0 / (1 + np.exp(-z))

np.random.seed() # 乱数を初期化
w = np.random.randn(3)  # パラメータをランダムに初期化

# 学習率の初期値
eta = 0.1

for i in xrange(50):
    list = range(N)
    np.random.shuffle(list)

    for n in list:
        x_n, y_n = X[n, :]
        t_n = T[n]

        # 予測確率
        feature = phi(x_n, y_n)
        predict = sigmoid(np.inner(w, feature))
        w -= eta * (predict - t_n) * feature

    # イテレーションごとに学習率を小さくする
    eta *= 0.9

# 図を描くための準備
seq = np.arange(-3, 3, 0.01)
xlist, ylist = np.meshgrid(seq, seq)
zlist = [sigmoid(np.inner(w, phi(x, y))) for x, y in zip(xlist, ylist)]

# 散布図と予測分布を描画
plt.imshow(zlist, extent=[-3,3,-3,3], origin='lower', cmap=plt.cm.PiYG_r)
plt.plot(X[T==1,0], X[T==1,1], 'o', color='red')
plt.plot(X[T==0,0], X[T==0,1], 'o', color='blue')
plt.show()

画像

さて,長々と20回続けてきた本連載ですが,次回で最終回となります。

最終回は連載の流れの中では触れられなかった落ち穂拾いをしつつ,これまでのまとめをしようと思います。

著者プロフィール

中谷秀洋(なかたにしゅうよう)

サイボウズ・ラボ(株)にてWebアプリ連携や自然言語処理を中心に研究開発を行いながら,英単語タイピングゲーム iVocaをサービス提供している。

URLhttp://d.hatena.ne.jp/n_shuyo/
Twitterhttp://twitter.com/shuyo