読者です 読者をやめる 読者になる 読者になる

#daiizメモ

フレンチフライ トリュフ塩仕立て

技術ネタはてブ数が多いごはん情報

スポンサーリンク

パーセプトロン

前回の続きで『ゼロから作る Deep Learning』の勉強を進めた.今回は2章のパーセプトロンについて書く.

ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装

ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装

パーセプトロンの各ニューロンはいくつかの信号を受け取り,その和がある閾値 \thetaを超えたときに1を出力する(発火する).それぞれの入力信号には重み w_1, w_2が掛けられている.重みが大きいほど,その入力は重要であると判断される.

f:id:daiiz:20161030141636p:plain
図. 単層(中間の隠れ層がない)パーセプトロン

$$ y = \begin{cases} 0 & w_1 x_1 + w_2 x_2 \le \theta \\ 1 & w_1 x_1 + w_2 x_2 > \theta \\ \end{cases} $$

閾値\(\theta\)について,\(-\theta\)を\(b\)と置いたものはバイアスと呼ばれる.バイアスを用いた形で先程の定義式を書き換えると以下のようになる.

$$ y = \begin{cases} 0 & b + w_1 x_1 + w_2 x_2 \le 0\\ 1 & b + w_1 x_1 + w_2 x_2 > 0 \\ \end{cases} $$

例えばバイアスが -0.4 と設定されている場合は,入力信号の和が 0.4 を超えればその時点で発火することになる.つまりこの場合は,バイアスが無かったときに比べてニューロンは小さな値でも発火できるようになる.

本では,ここまでおさえたら,簡単な論理回路をパーセプトロンで実装していく.論理回路には AND, NAND, OR, XOR などがある.入力を\(x_1, x_2\),出力を\(y\)としたとき,各回路の真偽値表は次のようになる.

 x_1  x_2 AND NAND OR XOR
0 0 0 1 0 0
1 0 0 1 1 1
0 1 0 1 1 1
1 1 1 0 1 0

単層パーセプトロンの重みやバイアスを(人間が)うまく設定することで,AND, NAND, OR回路は実現できる.本では,値の設定の仕方やコードの書き方がとてもわかりやすく書かれている.

大学の講義でも聞いた記憶があるが,XOR回路は単層パーセプトロンでは表現できない.これについてはパーセプトロンの定義式の条件不等式を見ればわかるが,これらの式は直線で平面を分割することを言っている.つまり,入力として考えられる (0, 0), (1, 0), (0, 1), (1, 1) に関する出力が同じ値になる者同士が,直線を挟んで別領域に配置することが可能である場合のみ,単層パーセプトロンで表現可能ということになる.自分で図を書いて直線を動かしてみるとよく分かる.本に倣い,Pyplotを使って自分でXORの入力点を直線分割を試みたものが次の図である.

f:id:daiiz:20161030140038p:plain

出力が 1 となるべき点 (1, 0), (0, 1) は赤色,出力が 0 となるべき点 (0, 0), (1, 1) は青色で示した.黄色い領域は直線によって分けられて,0が出力される領域である.傾きや切片を色々と調整しても,赤と青の点を線形分離することは不可能だと分かってくる*1

そこで,パーセプトロンの層を増やすことを考える.論理回路の講義の初めの方に聞くような話だけど,XOR回路はAND, NAND, ORの組み合わせで書くことができる.結果だけ書くとXOR回路は,次のように書き換えられる.

def XOR (x1, x2):
  """
  x1, x2: 入力層での入力
  h1, h2: 隠れ層の出力
  y     : 出力層での出力
  という,2層パーセプトロン
  """
  h1 = OR(x1, x2)
  h2 = NAND(x1, x2)
  y = AND(h1, h2)
  return y

XOR回路の真偽値表の通りの出力が返されることが確認できる.本ではここで終わっているが,この実装の場合,どのような平面分離が行われているのかPyplotで描画してみた.今度は黄色い領域は,出力が 1 となる領域を表している.

f:id:daiiz:20161030140100p:plain

描画のためのプログラムは以下の通り.

def fig_xor ():
  x = np.arange(-2., 2., 0.1)

  for i in x:
    for j in x:
      s = XOR(i, j)
      if s == 1:
        plt.plot(i, j, 'o', color='yellow')
      else:
        plt.plot(i, j, 'o', color='gray', alpha=0.4)

  # XORで出力y=1になるべき入力点集合(赤色)
  xs = [1, 0]
  ys = [0, 1]
  plt.plot(xs, ys, 'o', color='red')

  # XORで出力y=0になるべき入力点集合(青色)
  xs = [0, 1]
  ys = [0, 1]
  plt.plot(xs, ys, 'o', color='blue')

  plt.show()

層を増やしたパーセプトロンを用いることで,単層では不可能であった線形分離(赤点と青点の分離)が可能になった.

*1:境界線が曲線ならばいけるが