「[[.NET 開発基盤部会 Wiki>http://dotnetdevelopmentinfrastructure.osscons.jp]]」は、「[[Open棟梁Project>https://github.com/OpenTouryoProject/]]」,「[[OSSコンソーシアム .NET開発基盤部会>https://www.osscons.jp/dotNetDevelopmentInfrastructure/]]」によって運営されています。

-[[戻る>深層学習(deep learning)]]
--パーセプトロン
--[[ニューラルネットワーク]]

*目次 [#c61e2c38]
#contents

*概要 [#cf4fe02a]
ここでは正確には、人口ニューロン、単純パーセプトロンについて説明する。

-[[ニューラルネットワーク]]の起源となるアルゴリズム

-米国の心理学者フランク・ローゼンブラットが1958年に提案。

-パーセプトロンは
--複数の信号を入力として受取り、一つの信号を出力する。
--ここでの信号は「流す/流さない(0/1)」の二値の値

-パーセプトロンは
--AND, NAND, ORなどの論理回路を表現できる。
--「重み」のパラメタ(w1, w2, θ(-b))の決定は人手によって行われる。

--しかし、XORは、
---単層パーセプトロンでは表現できない。~
単層パーセプトロンは、線形領域しか表現できないため。
---従って、多層パーセプトロン(MLP)を用いる。~
多層パーセプトロン(MLP)は、&color(red){非線形領域を表現できる};ため。

--NANDの組み合わせから、原理的にはコンピュータを作ることができる。

-パーセプトロンの収束定理
--線形分離可能な問題は、データからの自動学習が可能。
--線形分離不可能な問題は、データからの自動学習が不可能。
--有限回の学習によって線形分離可能な問題が解ける。

-パーセプトロンの学習規則、[[重回帰分析などで使用した二乗誤差関数での勾配降下法>統計解析#n02d9d64]]と異なる。

*動作原理 [#y5a3da9c]

 (x1) --------- w1 --------> (y)
                              ↑
 (x2) --------- w2 -----------┘
  入力信号  固有の重み     出力信号

-xは「入力信号」、yは「出力信号」を表す。
-wは「重み」 (= 信号の流れ易さ/難さ)を表す。
-入力信号、出力信号の()の部分を、「ニューロン」 or 「ノード」と呼ぶ。
-出力は、信号の総和 (x1 w1 + x2 w2) が閾値θより大きな値の場合に出力される。
--この閾値θを超えた場合を「ニューロンが発火する」と表現することがある。
--wもθも発火のし易さを制御するため「重み」と呼ぶことがある。

-パーセプトロンの動作原理はこれだけ。

**式 [#m429f127]
-パーセプトロンを式に表すと以下のようになる。
     ┌
     │0 ( x1 w1 + x2 w2 <= θ )
 y = <
     │1 ( x1 w1 + x2 w2 > θ )
     └

-この式は、以下のように変形できる。
     ┌
     │0 ( -θ + x1 w1 + x2 w2 <= 0 )
 y = <
     │1 ( -θ + x1 w1 + x2 w2 > 0 )
     └
     ┌
     │0 ( b + x1 w1 + x2 w2 <= 0 )
 y = <
     │1 ( b + x1 w1 + x2 w2 > 0 )
     └

>-θ= bはバイアスと呼ばれ、w, θ同様に、「重み」と呼ぶことがある。

**バイアス [#id3f4198]
-以下の図は動作原理にバイアスを加えたもの。~
以下の総和が0を超えた場合、1を出力する。
 ((1))--------- b  -----------┐
                              ↓ 
 (x1) --------- w1 --------> (y)
                              ↑
 (x2) --------- w2 -----------┘
 入力信号  固有の重み     出力信号

-式を書き換える。
 a = b + x1 w1 + x2 w2

**[[活性化関数>ニューラルネットワーク#m155734b]] [#id3f4198]
-活性化関数 (Activation Function)~
活性化関数 = 入力信号の総和を出力信号に変換する変数である。~
特に閾値によって出力が変わる活性化関数を[[Step関数>ニューラルネットワーク#af597062]]と呼ぶ。
            ┌
            │0 ( a <= 0 )
 y = h(a) = <
            │1 ( a > 0 )
            └

-動作原理に反映する。
 ((1))--------- b  -----------┐
                              ↓  h()
 (x1) --------- w1 --------> ((a) ---> (y))
                              ↑
 (x2) --------- w2 -----------┘
 入力信号   固有の重み     出力信号

*論理回路をパーセプトロンで表現 [#s226d370]
機械学習では下のパラメタ(w1, w2, θ(-b))を決める作業をコンピュータに行わせる。

**ANDゲート [#m33fa3b4]
下記のANDゲートを満たすパーセプトロン(w1, w2, θ(-b))を作る。

|x1|x2|y|h
|0|0|0|
|1|0|0|
|0|1|0|
|1|1|1|

***例 [#q8f5df40]
-(w1, w2, θ) = (0.5, 0.5, 0.7)
-(w1, w2, θ) = (0.5, 0.5, 0.8)
-(w1, w2, θ) = (1.0, 1.0, 1.0)

***プロット [#k263cc9e]
  │
  0  ①
  │
  │
 ─0──0─────
  │

**NANDゲート [#q8a4ae9d]
下記のNANDゲートを満たすパーセプトロン(w1, w2, θ(-b))を作る。

|x1|x2|y|h
|0|0|1|
|1|0|1|
|0|1|1|
|1|1|0|

***例 [#m787b3fd]
(ANDゲートのパラメタの符号を反転すればOK)
-(w1, w2, θ) = (-0.5, -0.5, -0.7)
-(w1, w2, θ) = (-0.5, -0.5, -0.8)
-(w1, w2, θ) = (-1.0, -1.0, -1.0)

***プロット [#za3225cc]
  │
  ①  0
  │
  │
 ─①──①─────
  │

**ORゲート [#a944decc]
下記のORゲートを満たすパーセプトロン(w1, w2, θ(-b))を作る。

|x1|x2|y|h
|0|0|0|
|1|0|1|
|0|1|1|
|1|1|1|

***例 [#a655846c]
-(w1, w2, θ) = (0.5, 0.5, 0.3)
-(w1, w2, θ) = (0.5, 0.5, 0.4)
-(w1, w2, θ) = (1.0, 1.0, 0.9)

***プロット [#saeff028]
  │
  ①  ①
  │
  │
 ─0──①─────
  │

**XORゲート [#db2c73d6]
下記のXORゲートを満たす1層のパーセプトロンを作ることはできない。

|x1|x2|y|h
|0|0|0|
|1|0|1|
|0|1|1|
|1|1|0|

***プロット [#afbc1bb0]
理由は、以下の縦軸x1、横軸x2のプロットは、~
非線形領域のため、閾値の直線を引けないため。

  │
  ①  0
  │
  │
 ─0──①─────
  │

***多層のパーセプトロン [#pb62b4f1]
しかし、前述の[[AND>#m33fa3b4]]、[[NADN>#q8a4ae9d]]、[[OR>#a944decc]]のゲートを~
組みわせた多層のパーセプトロンであればXORゲートを作ることができる。

例えば、
-s1 = NAND ゲート(x1, x2)
-s2 = OR   ゲート(x1, x2)
-y  = AND  ゲート(s1, s2)

を使用すると、

|>|第0層|>|第1層|第2層|h
|x1|x2|s1|s2|y|h
|0|0|1|0|0|
|1|0|1|1|1|
|0|1|1|1|1|
|1|1|0|1|0|

と多層(2層)パーセプトロンとしてXORゲートを作ることができる。

 (x1) ──NAND──→ (s1)─AND┐
   └── OR ───↑┐       ↓
                  ││       (y)
   ┌───NAND──┘↓       ↑
 (x2) ── OR ──→ (s2)─AND┘

*論理回路をパーセプトロンで実装 [#o35ff3c2]
**簡単な実装 [#c42e540b]
ここから、VSCodeでPythonファイルに書いた。

***[[ANDゲート>#m33fa3b4]] [#bea4b0ae]
 """This is a test program."""
 def and_method(x_1, x_2):
     """This is a test program."""
     w_1, w_2, theta = 0.5, 0.5, 0.7
     tmp = x_1 * w_1 + x_2 * w_2
     if tmp <= theta:
         return 0
     else:
         return 1
 
 print(and_method(0, 0))
 print(and_method(1, 0))
 print(and_method(0, 1))
 print(and_method(1, 1))

***[[NANDゲート>#m33fa3b4]] [#a70fcf93]
w, θを以下のようにする。

 w_1, w_2, theta = -0.5, -0.5, -0.7

***[[ORゲート>#a944decc]] [#a1783d43]
w, θを以下のようにする。

 w_1, w_2, theta = 0.5, 0.5, 0.3

**バイアスを用いた実装 [#ycebb3f0]
[[上記>#c42e540b]]を[[バイアス>#m429f127]]とベクトルを用いて書き直す。

***[[ANDゲート>#m33fa3b4]] [#a8ee117c]
 """This is a test program."""
 
 import numpy as np
 
 def and_method(x_1, x_2):
     """This is a test program."""
     x = np.array([x_1, x_2])
     w = np.array([0.5, 0.5])
     b = -0.7
     tmp = b + np.sum(x*w)
     if tmp <= 0:
         return 0
     else:
         return 1
 
 print(and_method(0, 0))
 print(and_method(1, 0))
 print(and_method(0, 1))
 print(and_method(1, 1))

***[[NANDゲート>#m33fa3b4]] [#j0870d1d]
w, bを以下のようにする。
 w = np.array([-0.5, -0.5])
 b = 0.7

***[[ORゲート>#a944decc]] [#i1594435]
w, bを以下のようにする。
 w = np.array([0.5, 0.5])
 b = -0.3

***[[XORゲート>#db2c73d6]] [#tcad477b]
多層パーセプトロン(MLP)として以下のように実装できる。

 """This is a test program."""
 
 import numpy as np
 
 def and_method(x_1, x_2):
     """This is a test program."""
     x = np.array([x_1, x_2])
     w = np.array([0.5, 0.5])
     b = -0.7
     tmp = b + np.sum(x*w)
     if tmp <= 0:
         return 0
     else:
         return 1
 
 def nand_method(x_1, x_2):
     """This is a test program."""
     x = np.array([x_1, x_2])
     w = np.array([-0.5, -0.5])
     b = 0.7
     tmp = b + np.sum(x*w)
     if tmp <= 0:
         return 0
     else:
         return 1
 
 def or_method(x_1, x_2):
     """This is a test program."""
     x = np.array([x_1, x_2])
     w = np.array([0.5, 0.5])
     b = -0.3
     tmp = b + np.sum(x*w)
     if tmp <= 0:
         return 0
     else:
         return 1
 
 def xor_method(x_1, x_2):
     """This is a test program."""
     s_1 = nand_method(x_1, x_2)
     s_2 = or_method(x_1, x_2)
     return and_method(s_1, s_2)
 
 print(xor_method(0, 0))
 print(xor_method(1, 0))
 print(xor_method(0, 1))
 print(xor_method(1, 1))

*参考 [#gc9eeb7e]
-パーセプトロン - Wikipedia~
https://ja.wikipedia.org/wiki/%E3%83%91%E3%83%BC%E3%82%BB%E3%83%97%E3%83%88%E3%83%AD%E3%83%B3

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS