stMind

You'll never blog alone

単純パーセプトロンのアルゴリズム

Machine Learning: An Algorithmic Perspective (Chapman & Hall/Crc Machine Learning & Patrtern Recognition)

Machine Learning: An Algorithmic Perspective (Chapman & Hall/Crc Machine Learning & Patrtern Recognition)

単純パーセプトロンとそのアルゴリズムについて学習したことのまとめ。

単純パーセプトロンのアルゴリズム

  • 初期化
    • 重みw_{ij}(i番目のノードとj番目のノードの間の重み)をランダムな数値に初期化
  • 学習
    • for T:
      • for each 入力ベクトル:
        • j番目のニューロンの出力を計算 \begin{eqnarray} y_j = g(\sum_{i=0}^{m} w_{ij} x_i) = \left\{ \begin{array}{||} 1 & if w_{ij} x_i > 0 \\ 0 & if   w_{ij} x_i \leq 0 \\ \end{array} \right. \end{eqnarray}
          • gはactivation function、 y_jはj番目のニューロンの出力、x_iはi番目の入力
        • 重みの更新  w_{ij} \leftarrow w_{ij} + \eta (t_j - y_j) \cdot x_i
          • 出力がターゲットになるように重みを更新する
          • t_j - y_jはerror function、\etaは学習係数
  • 再現

実装

書籍のサポートページにあるプログラムで関連するところを切り出してprint文を追加。

from numpy import *

class pcn:
    """ 単純パーセプトロン """
    
    def __init__(self, inputs, targets):
        """ Constructor """
        # setup network size
        if ndim(inputs):
            self.nIn = shape(inputs)[1]
        else:
            self.nIn = 1

        if ndim(targets):
            self.nOut = shape(targets)[1]
        else:
            self.nOut = 1
        
        self.nData = shape(inputs)[0]
        
        # 重みをランダムな数値で初期化
        self.weights = random.rand(self.nIn+1, self.nOut)*0.1-0.05

    def pcntrain(self, inputs, targets, eta, nIterations):
        """学習フェーズ"""
        # バイアスノードを追加
        inputs = concatenate((inputs, -ones((self.nData, 1))), axis=1)
        # 学習
        change = range(self.nData)

        for n in range(nIterations):
            
            self.outputs = self.pcnfwd(inputs);
            self.weights += eta * dot(transpose(inputs), targets-self.outputs)

            # Randomise order of inputs
            random.shuffle(change)
            inputs = inputs[change,:]
            targets = targets[change,:]

            print "Iteration:" , n
            print self.weights

        print "Final outpus are:"
        print self.outputs

    def pcnfwd(self, inputs):
        """再現フェーズ"""
        
        outputs = dot(inputs, self.weights)

        # Threshold the outputs
        return where(outputs > 0, 1, 0)

テスト

書籍にあるように、入力ノード2、バイアスノード1、ニューロン1の例で試してみる。

In [1]: from numpy import *

In [2]: import pcn

In [3]: inputs = ([[0,0],[0,1],[1,0],[1,1]])

In [4]: targets = array([[0], [1], [1], [1]])

In [5]: p = pcn.pcn(inputs, targets)

In [6]: p.pcntrain(inputs, targets, 0.25, 30)
Iteration: 0
[[ 0.45296743]
 [ 0.28747833]
 [-0.48064425]]
Iteration: 1
[[ 0.45296743]
 [ 0.28747833]
 [-0.23064425]]
Iteration: 2
[[ 0.45296743]
 [ 0.28747833]
 [ 0.01935575]]
Iteration: 3
[[ 0.45296743]
 [ 0.28747833]
 [ 0.01935575]]
Iteration: 4
[[ 0.45296743]
 [ 0.28747833]
 [ 0.01935575]]
Iteration: 5
[[ 0.45296743]
 [ 0.28747833]
 [ 0.01935575]]
・・・
(中略)
・・・
Iteration: 28
[[ 0.45296743]
 [ 0.28747833]
 [ 0.01935575]]
Iteration: 29
[[ 0.45296743]
 [ 0.28747833]
 [ 0.01935575]]
Final outpus are:
[[0]
 [1]
 [1]
 [1]]

なんとなく雰囲気はつかめた(ような気がする)。