search
LoginSignup
3

More than 3 years have passed since last update.

posted at

updated at

パーセプトロンのまとめ

はじめに

パーセプトロンを一から実装した時のまとめ

パーセプトロンの理論

まず、2 つのクラスを1(陽性)-1(陰性)に分けます。
そうすると活性化関数$φ$が定義できます。
この活性化関数は特定の入力$x$に対応する重みベクトル$w$の線形結合を引数とします。

Z = \sum_{i=1}^{n}w_ix_i
\quad
w = \begin{pmatrix}
w_1 \\
w_2 \\
\vdots \\
w_n
\end{pmatrix}
\quad
x = \begin{pmatrix}
x_1 \\
x_2 \\
\vdots \\
x_n
\end{pmatrix}

活性化関数には単位ステップ関数を使います

φ(z) = \left\{
\begin{array}{ll}
1 & (z \gt \theta) \\
-1 & (z \lt \theta)
\end{array}
\right.

$\theta$はしきい値です

パーセプトロンの学習規則

  1. 重み$w$を 0 または小さな乱数で初期化する

  2. トレーニングサンプル$x^{(i)}$毎に以下の手順を実行する

    1. 出力$\breve{y}$を計算する
    2. 重み$w$を更新する

重みベクトル$w$の各重み$w_i$は同時に更新され以下の式で表されます。

w_i := w_i + \Delta w_i

$\Delta w_i$の計算は以下のようにされます。

\Delta w_i = \eta(y_i - \breve{y_i})x_i^{(i)}

$\eta$は学習率で$0<\eta<1$です。
$y_i$はトレーニングクラスラベルで$\breve{y_i}$は予測クラスラベルです。

実装

以下の環境で実装しました。
実装した後に、実際にアヤメのデータセットを使って訓練していきます。

  • python 3.6

  • JupyterLab 0.35.4

使用したモジュールはnumpyです。
データセットを入手して処理するためのpandasと可視化するためにmatplotlibを使います。

コード

class Perceptron(object):
    """
    パーセプトロン分類機

    eta:学習率
    n_iter:トレーニング回数
    ーーーー
    属性
    w_ :一次元配列
        適合後の重み
    errors_ :リスト
        各エポックでの誤分類数
    """
    def __init__(self,eta = 0.01,n_iter = 10):
        self.eta = eta
        self.n_iter = n_iter

    def fit(self,X,y):
        """
        トレーニングデータに適応させる
        パラメータ
        ----------
        X:トレーニングデータ(配列のようなデータ構造)、shape = {n_samples,n_features}
        y:配列のようなデータ構造,shape={n_samples}、目的変数

        戻り値
        self:object
        """
        self.w_ = np.zeros(1 + X.shape[1])
        self.errors_ = []

        for _ in range(self.n_iter):   #トレーニングデータの回数分反復
            errors = 0
            for xi,target in zip(X,y):  #Xとyのデータを同時に取り出す
                #重みWn(n=>1)の更新   △w = 学習率*(答え-予測結果)*X
                update = self.eta * (target - self.predict(xi))
                self.w_[1:] += update * xi
                #重みW0の更新
                self.w_[0] += update
                #重みの更新が0出ない場合に誤分類としてカウント
                errors += int(update !=0.0)
            #誤差を格納
            self.errors_.append(errors)
        return self
    #挿入力を計算
    def net_input(self,X):
        return np.dot(X,self.w_[1:]) + self.w_[0]
    #1ステップ後のクラスラベルを返す
    def predict(self,X):
        return np.where(self.net_input(X) >= 0.0,1,-1)

モデルの訓練

最初にデータの入手をします。

#Irisデータセットの入手
import pandas as pd

df = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data',header=None)

次にデータのプロットをしました。

#グラフの描画
import matplotlib.pyplot as plt
#1-100番目まで目的変数の抽出
y = df.iloc[0:100,4].values
#Iris-setosa を-1 iris-verginica を1に変換
y = np.where(y == 'Iris-setosa',-1,1)
#1-100行目の1,3列めの抽出
X = df.iloc[0:100,[1,3]].values
#グラフのプロット
plt.scatter(X[:50,0],X[:50,1],color = 'red',marker = 'o',label = 'setosa')
plt.scatter(X[50:100,0],X[50:100,1],color = 'blue',marker = '*',label='versicolor')
#軸ラベルの設定
plt.xlabel('speal length [cm]')
plt.ylabel('petal length [cm]')
#凡例の表示
plt.legend(loc = 'upper left')

plt.show()

これのような画像が出力されるはずです。

dataGraph.png

次に、実際に実装したモデルのトレーニングをします。トレーニングした後に間違えたデータの個数をエポック毎にプロットしました。

ppn = Perceptron(eta = 0.1,n_iter = 10)
#モデルの適合
ppn.fit(X,y)
plt.plot(range(1,len(ppn.errors_)+1),ppn.errors_,marker='*')
#軸ラベルの設定
plt.xlabel("epochs")
plt.ylabel("Number of missclassifications")
plt.show()

2回で収束したことがわかりました。

loss.png

次に、パーセプトロンが学習した境界線をプロットする関数を実装して、実際に表示しました。

from matplotlib.colors import ListedColormap

def plot_decision_regions(X,y,classifier,resolution = 0.02):
    #マーカーとカラーマップの用意
    markers = ('s','x','o','^','v')
    colors = ('red','blue','lightgreen','gray','cyan')
    cmap = ListedColormap(colors[:len(np.unique(y))])
    #決定領域のプロット
    x1_min,x1_max = X[:,0].min() - 1,X[:,0].max() + 1
    x2_min,x2_max = X[:,1].min() - 1,X[:,1].max() + 1
    #グリッドポイントの作成
    xx1,xx2 = np.meshgrid(np.arange(x1_min,x1_max,resolution),
                         np.arange(x2_min,x2_max,resolution))
    #特徴量を一次元配列に変換して予測を実行する
    Z = classifier.predict(np.array([xx1.ravel(),xx2.ravel()]).T)
    #予測結果をグリッドポイントのデータサイズに変換
    Z = Z.reshape(xx1.shape)
    #グリッドポイントの等高線のプロット
    plt.contourf(xx1,xx2,Z,alpha = 0.4,cmap = cmap)
    #軸の範囲の設定
    plt.xlim(xx1.min(),xx1.max())
    plt.ylim(xx2.min(),xx2.max())
    #クラスごとにサンプルをプロット
    #matplotlibが1.5.0以下ならc = cmapをc=colors[idx]に変更
    for idx,cl in enumerate(np.unique(y)):
        plt.scatter(x=X[y==cl,0],y=X[y == cl,1],alpha=0.8,c = cmap(idx),marker=markers[idx],label=cl)


plot_decision_regions(X,y,classifier=ppn)
plt.xlabel('spal length[cm]')
plt.ylabel('etal length[cm]')
#凡例の設定
plt.legend(loc = 'upper left')
plt.show()

以下の画像のようになりました。

result.png

参考にしたもの

[第 2 版]Python 機械学習プログラミング 達人データサイエンティストによる理論と実践

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
3