「[[.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