数学的基礎から学ぶ Deep Learning

MPS - Yokohama
This is a hidden area for drag and drop.
数学的基礎から学ぶ Deep Learning
Morning Project Samurai
Table of Contents
1. はじめに
1.1. 質問等
2. Python のインストール
2.1. Windows 編
2.2. Mac 編
2.3. Linux 編
3. Deep Learning
3.1. Deep Learning とは
3.2. 多層ニューラルネットワーク
3.3. Deep Learning の応⽤
3.4. 教師あり学習と教師なし学習
4. ニューラルネットワーク
4.1. ニューラルネットワークとは
4.2. TensorFlow で⼿書き⽂字認識
5. 単⼀ニューロンの表現⽅法
5.1. ニューロンオブジェクト
6. 活性化関数
6.1. 活性化関数の役割
7. 学習するニューロンを作る
7.1. 様々な活性化関数
7.2. 単⼀のニューロンを動かす
7.3. ステップ関数での記述
7.3.1. ひとつの内積だけで計算する
7.3.2. NumPy での⾏列の表記
7.3.3. NumPy での⾏列の連接
7.3.4. 問題
7.4. 単⼀のニューロンを動かす (ステップ関数編)
7.4.1. ニューロンに学習させる
7.4.1.1. 学習って何?
7.4.1.2. 試⾏錯誤に必要なもの
7.4.1.3. ビット反転問題
7.4.1.3.1. ビット反転問題のゴール
7.4.1.3.2. ビット反転問題のアルゴリズム
7.4.1.3.3. ビット反転問題の評価関数
(C) 2016, Morning Project Samurai
Page 1
MPS - Yokohama
7.4.1.3.4. どうやってプログラムするか
7.4.1.3.5. 演習
7.5. 単⼀のニューロンを動かす (シグモイド関数編)
7.5.1. シグモイド関数とは
7.5.2. シグモイド関数でのビット反転問題
7.6. 評価関数 (⼆乗誤差)
7.6.1. 最急降下法で最⼩値を求める
7.6.2. 最急降下法
7.6.3. SE の微分
7.6.3.1. 2 変数関数の微分
7.6.3.2. SE に適⽤する
8. バックプロパゲーション
8.1. バックプロパゲーションと学習
8.2. フォワードプロパゲーションの復習
8.2.1. 1 層⽬のニューロンを考える
8.2.2. 2 層⽬のニューロンを考える
8.3. バックプロパゲーション
8.4. 3 層 NN を作る
8.5. 2 層⽬の状態 z^{(2)} が変化した時のエラー E の変化量
8.6. 重み w^{(2)} が変化した際の状態 z^{(2)} の変化量
8.7. ⾏列への変換
8.8. バイアス w^{(2)}_{k, b} \cdot b について考える
9. 勉強会記録
1. はじめに
このテキストは Morning Project Samurai1 - Yokohama にて開催している「数学的基礎から学ぶ
Deep Learning」を⻫藤が分かるように書き下したメモです。 間違えている部分も多々あると思いま
すが、お気づきの際には @hi_saito2 までご連絡いただけると助かります。
1.1. 質問等
全体的な質問等は Twitter ではハッシュタグ #mpsamurai3 または Facebook の Morning Project
Samurai (MPS)4 にてお願いします。
また、Facebook Group の Morning Project Samurai4 も合わせてご利⽤ください。
Page 2
(C) 2016, Morning Project Samurai
MPS - Yokohama
2. Python のインストール
あくまで原稿作成時のインストール⽅法であることに注意してください。
2.1. Windows 編
以下に 32 bit 版 Windows7 への Python のインストール⽅法を記述します。
1. Welcome to Python.org5 に ア ク セ ス し ま す 。 Download か ら Python 3.5.2 ( p
y
t
h
o
n
3.5.2.exe) をダウンロードします。
2. ダウンロードした Python 3.5.2 を管理者としてインストールします。
PATH を含めるにチェックを⼊れておきます。
3. numpy ( numpy-1.11.1+mklcp
35cp
35
m-w
in
32.
wh
l) と scipy ( s
ci
py
-0.
18
.0cp
3
5
c
p
3
5
m
win32.whl) を Python Extension Packages for Windows - Christoph Gohlke6 から取得して
インストールします。(ここでは C:
\p
ub にダウンロードしたものとして進めます。後述の
インストール⽅法を参照してください)
ただし、これは 32 bit Windows ⽤であり、適宜⾃分の PC に合わせたものをダウン
ロードする必要があります。
4. matplotlib は pip でインストールします。(後述のインストール⽅法を参照してください)
ダウンロードした .whl ファイルはコマンドプロンプトから以下のようにしてインストールしま
す。
Code 2-1: numpy と scipy のインストール
$p
y
th
o
n-mpipinstall"C:\pub\nu
mp
y1.
11.
1+
mkl
-c
p3
5-c
p3
5m
-w
in3
2.
whl
"
$py
t
ho
n-mpipinstall"C:\pub\sci
py
-0.
18
.0
-cp
35
-cp
35
mwin
32
.w
hl
"
matplotlib はコマンドプロンプトから以下のようにしてインストールします。
Code 2-2: matplotlib のインストール
$p
y
th
o
n-mpipinstallmatplotlib
(C) 2016, Morning Project Samurai
Page 3
MPS - Yokohama
2.2. Mac 編
NOTE: 後で調べます。
2.3. Linux 編
NOTE: 後で調べます。
3. Deep Learning
3.1. Deep Learning とは
機械学習の⼿法のひとつで、特定タスクをうまくこなすコンピューター (特徴量抽出) を⾃動構成し
てくれますが、その構成は帰納7 的 (経験的) なものになります。
何が特徴量であるかを⼈間が考え与えなくても、⾃動的に特徴量を抽出できます。
理由を明確にして「演繹8 的」に構築する技術ではなく、過去の経験から「帰納的」に推測
した⽅法です。
このことから、Deep Learning は以下のように⾔われることがあります。
従来の機械学習分野ではアルゴリズムよりも「何を特徴量にするか」を考えることが重要と
⾔われてきましたが Deep Learning により特徴量抽出が不要になりました。
Haar-Like9 や SIFT10 、HOG11 といった特徴量を機械学習したい対象に合わせて変
える必要がありません。
Deep Learning が間違った答えを出した際に「どうして?」と理由を⾒つけようとしても、
そういう学習をしてきたからとしか⾔えません。
Deep Learning は⾮常に優秀ですが、結果を保証するものではありません。
Page 4
(C) 2016, Morning Project Samurai
MPS - Yokohama
演繹と帰納:
演繹とは「A ならば B であるという条件があるとき、C が A であるなら C は B と等しい」とい
うようなロジカルな考え⽅を⽰します。 ⼀⽅、帰納とは「A は C と似ていて、A と B も似ている
のであれば、C と B は同じかもしれない」という考え⽅を⽰します。 良く Deep Learning による
識別結果には理由がないと⾔われているのは帰納的推測であるからです。
3.2. 多層ニューラルネットワーク
Deep Learning では以下のような多層ネットワークを⽤います。
Fig u re 3-1: 多層ネットワーク
備考:
Deep Learning は多層ネットワークを⽤いた機械学習の⼿法の概念のひとつです。したがって、
ここに記述されているものが Deep Learning の全てではありません。
この多層ネットワーク構造を構成するひとつひとつのネットワークをニューラルネットワーク
(Neural Network = NN) といいます。 ニューラルネットワークは⼈間のニューロン (神経細胞) 同⼠の
構 造 を 模 し た も の で 、 W. McCulloch と W. Pitts が 1943 年 に A logical calculus of the ideas
immanent in nervous activity 12 という論⽂を紹介したことに端を発しています。 ⼀般的に Deep
Learning のネットワーク構造は多層ニューラルネットワーク (Deep Neural Network = DNN) を⽰
し、この講座で最終的に扱っていくネットワーク構造も DNN です。
3.3. Deep Learning の応⽤
Deep Learning は様々な分野に応⽤されています。
(C) 2016, Morning Project Samurai
Page 5
MPS - Yokohama
画像認識
Google, Facebook の顔認識による個⼈特定, etc.
⾳声認識
Google, Apple の Siri, etc.
⽂字認識
⼿書き⽂字認識、⽂脈認識、etc.
多センサーからの情報の認識 (センサーフュージョン)
⾃動運転、etc.
備考:
なぜ Deep Learning がここまで注⽬されているのでしょうか。 それは 2012 年の画像認識コンテ
スト ILSVRC 2012 (ImageNet Large Scale Visual Recognition Competition)13 で Deep Learning
による画像認識率の⾼さが注⽬されたからです。その後も Deep Learning は優秀な成績を残して
おり主に画像認識の分野で注⽬を集めています。
3.4. 教師あり学習と教師なし学習
⼀般的に機械学習には「教師あり学習」と「教師なし学習」があります。
教師あり学習:
あらかじめ答えが分かっているもの (教師データ) を学習させる機械学習の⼿法です。
教師なし学習:
答えが分かっていないものを学習させる機械学習の⼿法です。特徴量の抽出や次元圧縮 (次
元削減) で⽤いられます。
今回は教師あり学習について説明していきます。 ⼀般的に Deep Learning と⾔えば教師あり学習を
指すことがほとんどです。
Page 6
(C) 2016, Morning Project Samurai
MPS - Yokohama
備考:
Google の猫14 というのを聞いた⼈もいると思います。 あたかも猫をコンピュータがひとりでに
学習したように記述されている記事もありますが、猫が映っている画像だけを学習させています
ので教師あり学習のひとつとして考えるのが⼀般的です。
4. ニューラルネットワーク
4.1. ニューラルネットワークとは
ニューラルネットワークを構築するニューロンの仕組みを考えてみます。 ある刺激 (⼊⼒) に対して
関数
f
を通して出⼒を得るというものです。
Fig u re 4-1: ⼊⼒が
n
の場合のニューロンのモデル
このニューロンは以下のような数式で表記することが可能なモデルとなっています。
yi = f (∑ w ij xj + bi )
i
備考:
いきなり難しい式が出てきましたが、⾮常に簡単に書けば
y = Wx + b
となり、直線の⽅程式
に似ています。 機械学習の基本はデータをうまく直線の⽅程式で分割していくことなのです。 た
だし、直線だけではうまく分割できない場合もあるため、その場合には関数
f
に適切な関数を与
えていきます。
これを単層のニューラルネットワークにしたものが以下の図になります。
(C) 2016, Morning Project Samurai
Page 7
MPS - Yokohama
Fig u re 4-2: 単層のニューラルネットワークモデル
毎回
yi = f (∑ w ij xj + bi )
i
と記述すると複雑なので、ベクトルを使って記述すると以下のように
なります。
y = f (W x + b)
備考:
⾼校までの授業ではベクトル
v
を
v ⃗ というように⽂字の上に⽮印を付けるように習ったと思い
ます。 ただし、ここでは数学的な記述に従い太字で
v
と記述します。 ベクトルを意味する場合
には太字であることと斜体でないことに注意してください。 もちろん
⃗ y ⃗ = f (W x ⃗ + b)
と書
いても問題ありません。
また、⾏列は⼤⽂字で
W
と記述し、⾏列の各要素は⼩⽂字で添え字を付けて
wij
と表現して
います。
4.2. TensorFlow で⼿書き⽂字認識
Deep Learning を⼿軽に扱えるようにするため、さまざまなフレームワークがリリースされまし
た。 Preferred Networks 社15 の Chainer16 、Google 社の TensorFlow17 などがあります。 これらの
フレームワークを活⽤することで簡単に Deep Learning を扱えるようになってきました。
ここでは Google の TensorFlow を使って 28 x 28 ピクセル (合計 784 ピクセル) の⼿書き⽂字を
Deep Learning で学習させる例を取り上げます。
Page 8
(C) 2016, Morning Project Samurai
MPS - Yokohama
Fig u re 4-3: ⼿書き⽂字認識の例
これを認識させるのに以下のようなニューラルネットワークを構成します。
Fig u re 4-4: ⼿書き⽂字認識での単層ニューラルネットワーク
ここで上の図の丸い円の部分に相当する活性化関数
f
として Softmax 関数を⽤います。 Softmax
関数は主にフィードフォワード型のニューラルネットワークの活性化関数として使われ、以下のよう
な関数です。
exp( ∑
j
w 0j xj + bi )
y0 =
∑ exp( ∑
i
j
w 0j xj + bi )
⾮常に複雑な関数ですが、既に TensorFlow では⽤意されていて、 so
ft
max
() と記述するだけで計
算してくれます。 実際に TensorFlow に実装したものが以下のものになります。
(C) 2016, Morning Project Samurai
Page 9
MPS - Yokohama
Code 4-1: TensorFlow での⼿書き⽂字認識
#!/
u
sr
/
b
i
n/
e
nvpython
#c
o
di
n
g:U
TF
8
#T
h
isco
d
ei
srelatedtogoogle'sTenso
rFl
owT
uto
ri
alDo
cu
men
t.
#h
t
tp
s
:/
/
w
ww
.
tensorflow.org/versions/r0
.7/
tu
to
ria
ls
/in
de
x.
htm
l
from t
e
ns
o
r
fl
o
w.examples.tutorials.mnistimport i
npu
t_
da
ta
import te
n
s
or
flowas tf
__a
u
th
o
r_
_='
JunyaKaneko<jyuneko@hotm
ail
.c
om
>'
mni
s
t=i
n
p
ut
_
data.read_data_sets("MNIST
_da
ta
/"
,o
ne
_ho
t=
True)
#入力となる xは 784次元とする
x=tf
.
pl
a
c
eh
o
lder(tf.float32,[None,78
4
])
#重み行列は 7
84x10とし、初期値として 0で埋めておく
W=tf
.
Va
r
i
ab
l
e(tf.zeros([784,10]))
#バイアスは 1
0次元とし、初期値として 0で埋めておく
b=tf
.
Va
r
i
ab
l
e(tf.zeros([10]))
#活性化関数として Softmax関数を用い、評価式は Wx+bとする
y=tf
.
nn
.
s
of
t
max(tf.matmul(x,W)+b)
y_=t
f
.p
l
a
ce
h
older(tf.float32,[None,1
0
])
cro
s
s_
e
nt
r
o
py=-tf.reduce_sum(y_*tf.l
og(
y)
)
tra
i
n_
s
te
p=t
f.train.GradientDescentOpt
imi
ze
r(
0.0
1)
.mi
ni
mi
ze(
cr
oss
_e
nt
rop
y)
ini
t=tf
.
i
ni
t
ialize_all_variables()
ses
s=tf
.
S
es
s
ion()
ses
s
.r
u
n(
i
n
it
)
for iin r
an
g
e(1000):
ba
t
ch
_
x
s,batch_ys=mnist.train.nex
t_b
at
ch
(10
0)
se
s
s.
r
u
n(
t
rain_step,feed_dict={x:b
atc
h_
xs
,y
_:ba
tc
h_
ys}
)
cor
r
ec
t
_p
r
e
di
c
tion=tf.equal(tf.argmax(
y, 1
),tf
.a
rgm
ax
(y
_,1
))
acc
u
ra
c
y=tf
.
reduce_mean(tf.cast(correc
t_p
re
di
cti
on
,t
f.
fl
oat
32
))
pri
n
t(
s
es
s
.
ru
n
(accuracy,feed_dict={x:m
nis
t.
te
st.
im
age
s,y
_:mn
ist
.t
es
t.l
ab
els
})
)
TensorFlow を⽤いると少ない⾏数で Deep Learning を記述することができます。 しかも数秒で 90
% を超える認識率を表⽰してくれます。 ただし、ここでは Deep Learning ライブラリを⽤いずにオ
ブジェクト指向プログラミング⾔語 Python 5 および NumPy 18 と matplotlib19 のみを⽤いて記述して
いきます。 プリミティブなライブラリのみを⽤いて Deep Learning を習得することで、さまざまな学
Page 10
(C) 2016, Morning Project Samurai
MPS - Yokohama
習したいデータに対して Deep Learning を⾃分で実装することができるようにしていきます。 しか
も、先ほどの Deep Learning のフレームワークの Chainer も TensorFlow も Python で記述しますの
で、フレームワークに独⾃の拡張を加える際にも役に⽴つことでしょう。
5. 単⼀ニューロンの表現⽅法
Fig u re 5-1: ⼊⼒が 3 つの場合のニューロンのモデル
この単⼀ニューロンに対して⼊⼒が
n
個の⼀般的な数式で表現すると以下のようになります。
n−1
y0 = f (∑ w ij xj + b0 )
i=0
5.1. ニューロンオブジェクト
これから Python がオブジェクト指向プログラミング⾔語20 であることを最⼤限に活⽤してプログ
ラムを組んでいきますが、オブジェクト指向プログラミングするためには「何をオブジェクトとする
かを決めることが重要」になってきます。 適切にオブジェクトを決めることでプログラミングしやす
くなります。
オブジェクトとは?:
オブジェクトは「性質」と「機能」を含んでいるものを⽰します。
ここでは「ニューロンをひとつのオブジェクト」としてプログラムを組んでいきます。 ニューロン
の場合には「性質」として重み
y = f (W x + b)
W
やバイアス
b
があり、「機能」として関数
f
や刺激
x
に対して
を計算して出⼒するものがあります。
(C) 2016, Morning Project Samurai
Page 11
MPS - Yokohama
ニューロンの性質:
重み
W
、バイアス
b
ニューロンの機能:
関数
f
、刺激
x
に対して
y = f (W x + b)
を計算して出⼒する機能
この条件を元にしてニューロンのクラスのモックアップを作成すると以下のようになります。
Code 5-1: ニューロンのクラスのモックアップ
#!/
u
sr
/
b
i
n/
e
nvpython
#c
o
di
n
g:U
TF
8
import nu
m
p
yas np
class Neuron:
def __init__(self,w,b):
#性質
s
e
l
f.
w=w
#性質:W
s
e
l
f.
b=b
#性質:b
def calc(
self,x):
#機能
a
r
r
_x=np.array(x)
a
r
r
_w=np.array(self.w)
a
r
r
_b=np.array(self.b)
return np.dot(arr_x,arr_w)+a
rr
_b
n=Ne
u
ro
n
(
[0
.
5,0.5],[0.5])
res
u
lt=n
.
ca
l
c([0.5,0.5])
#インスタンスの生成
#計算
pri
n
t(
r
es
u
l
t)
6. 活性化関数
6.1. 活性化関数の役割
活性化関数とは何でしょうか。 ここでは活性化関数の役割を⾒ていくために
合のニューラルネットワークの表現⼒を考えてみます。
f (u)
が何もしないとは
とを意味しています。
Page 12
f (u)
(C) 2016, Morning Project Samurai
が何もしない場
f (u) = u
というこ
MPS - Yokohama
Fig u re 6-1:
f (u)
f (u)
が何もしない場合のニューロン
が何もしない場合の 2 層のニューラルネットワークを 3 つのニューロンで構成してみます。
この場合のニューラルネットワークは以下のようになります。
Fig u re 6-2: 2 層のニューラルネットワーク
まず、第 1 層⽬のニューラルネットワークについて⾒ていきます。
Fig u re 6-3: 2 層のニューラルネットワークの 1 層⽬
⼊⼒
x
に対して重み⾏列
W
とバイアス
b
で計算されますので、以下のように記述することがで
きます。
(C) 2016, Morning Project Samurai
Page 13
MPS - Yokohama
y0
y
=
w 00 × x0 + w 01 × x1 + b0
=
( w 00 w 01 ) (
=
x0
) + b0
x1
Wx + b
次に第 2 層⽬のニューラルネットワークの出⼒である
z0
について注⽬します。
Fig u re 6-4: 2 層ニューラルネットワークの 2 層⽬
ここで
z0
は同様に重み⾏列
z0
=
=
=
c
を⽤いて以下のように記述できます。
v00 × y0 + v01 × y1 + c
v00
(
T
)
(
v01
=
とバイアス
V
T
) + c
y1
( v00 v01 ) (
V
y0
y0
) + c
y1
y + c
備考
⾏列
A
の転置⾏列は
つまり、この
A
f (u) = u
T
=
Wx + b
z0
=
V
T
T
を付けて記述します。 この T は Transpose の略です。
のニューラルネットワークは以下の 2 つの式で表現できます。
y
{
と右肩に
y + c
これを変形していきます。
z0
=
=
ここで、 y と
Page 14
T
V
T
V
z0
(W x + b) + c
T
Wx + V
b + c
は何になるでしょうか。 分かりやすくするために⾏列で表記してみましょう。
(C) 2016, Morning Project Samurai
MPS - Yokohama
y
(
=
y0
)
y1
(
=
(
=
w 00
w 01
w 10
w 11
)(
x0
) + (
x1
b0
)
b1
w 00 × x0 + w 01 × x1
) + (
w 10 × x0 + w 11 × x1
(
=
w 00 × x0 + w 01 × x1 + b0
b0
)
b1
)
w 10 × x0 + w 11 × x1 + b1
=
z0
T
V
Wx
Vector
=
v10 ) (
( v00
y0
) + c
y1
=
v00 × y0 + v10 × y1 + c
=
Scalar
はベクトル ( 1 × 2 の⾏列) になり、 VT b + c はスカラー (値) になりますので、以下のよ
うに置き換えます。
⎧
⎪
⎨
⎩
⎪
z0
T
V
Wx
=
Px = (
p00
)x
p10
T
V
=
=
b + c
=
r
p00 × x0 + p10 × x1 + r
(
p00
T
)
p10
=
=
(
x0
( p00 p01 ) (
P
T
) + r
x1
x0
) + r
x1
x + r
この式は元々の単⼀のニューロンと同じ式の構成になってしまうことに気が付きます。
Fig u re 6-5:
z0 = p
T
x + r0
で表現されるニューラルネットワーク
2 層ニューラルネットワークを 3 つのニューロンを使って構成してみましたが、結果的に 1 つのニ
ューロンを使った時と同じ式の構成になります。 つまり、 f (u)
= u
とすると結果的にどんなに多く
のニューロンを使っても 1 つのニューロンと変わらない結果になってしまいます。
この
f (u) = u
(C) 2016, Morning Project Samurai
Page 15
MPS - Yokohama
は⾮常に簡単なニューロンのモデルですが、これが機械学習の基本になっています。つまり、重み⾏
列
W
に ⼊⼒
x
の内積を取ったものにバイアス
b
を⾜した
y = Wx + b
の 考 え ⽅ は Deep
Learning でも共通です。
Deep Learning はこの関数
f
に適当な関数が⾒つかったため、ニューラルネットワークに対してさ
らに複雑な学習ができるようになったのです。
7. 学習するニューロンを作る
ここからは学習するニューロンを作っていきます。
7.1. 様々な活性化関数
ニューロンの活性化関数としては以下のようなものが良く知られています。 それぞれついて、その
特徴と⼀緒に例題を解いていきます。
ステップ関数
1 (u > θ)
0 (otherwise)
f (u) = {
Fig u re 7-1: ステップ関数でのニューロン
シグモイド関数
1
f (u) =
1 + e
Page 16
−αu
(C) 2016, Morning Project Samurai
MPS - Yokohama
ソフトマックス関数
f (u) = e
u
を正規化したもの。
exp( ∑
j
W0j xj + bi )
y0 =
∑ exp( ∑
i
j
W0j xj + bi )
7.2. 単⼀のニューロンを動かす
Fig u re 7-2: 刺激が 3 つの場合のニューロン
刺激が
n
個の場合の単⼀のニューロンの式は以下のように記述できることを学んできました。
n−1
y0
=
f (∑ w 0i xi + b)
i=0
=
T
f (W
x + b)
これを Python の NumPy で表現すると以下のようになります。
y=f(
n
um
py.dot(w,x)+b)
この Python の記述⽅法には次元 (添え字) が含まれていないことに注⽬してください。 つまり
NumPy で記述する際には次元を気にする必要がないという利点があります。 もしも、次元を考慮す
る必要があるプログラム⾔語で記述するのであれば、for ⽂などでループさせる必要があるでしょう。
7.3. ステップ関数での記述
7.3.1. ひとつの内積だけで計算する
⼊⼒が 3 つの場合には以下のように
T
W
x + b
(C) 2016, Morning Project Samurai
Page 17
MPS - Yokohama
を記述することができます。
T
W
この式の
b
x + b = w 00 × x0 + w 01 × x1 + w 02 × x2 + b
を
T
W
b × 1
x + b
に変形します。
=
w 00 × x0 + w 01 × x1 + w 02 × x2 + b
=
w 00 × x0 + w 01 × x1 + w 02 × x2 + b × 1
このように記述することでひとつの⾏列の演算と同じように扱うことができます。
T
W
x + b
=
w 00 × x0 + w 01 × x1 + w 02 × x2 + b × 1
⎛
=
これは
T
W
x + b
⎞
⎜ x1 ⎟
( w 00 w 01 w 02 b ) ⎜
⎟
⎜ x2 ⎟
⎝
=
x0
′T
W
x
という式は
1
⎠
′
′T
W
x
′
というひとつの⾏列の内積だけで表現できることを意味して
います。
7.3.2. NumPy での⾏列の表記
さて、Python の NumPy では⾏列をどのように表現するのでしょうか。例えば、以下の 2 × 2 の⾏
列を考えてみます。
1 2
W = (
)
3 4
これをプログラムで表現してみましょう。
Code 7-1: ⾏列の表現⽅法
#!/
u
sr
/
b
i
n/
e
nvpython
#c
o
di
n
g:U
TF
8
import nu
m
p
yas np
W=np
.
ar
r
a
y(
[
[1,2],[3,4]])
pri
n
t(
W
)
Page 18
(C) 2016, Morning Project Samurai
MPS - Yokohama
Code 7-2: プログラムの計算結果
[[
12]
[
34
]]
このように NumPy ではカギ括弧で⾏単位を括り、⾏列全体をまたカギ括弧で括ることで NumPy
が⾏列として理解できることが分かります。
Fig u re 7-3: 刺激が 3 つの場合のニューロン
3 つの刺激を考えると
W = (w 00 w 01 w 02 )
と 1 × 3 の⾏列で表現できますが、これを NumPy で
記述すると W=np.array
([[w00,w01,w
02]
]) のように記述できます。
では
b
はどのように表現すればいいでしょうか。
b
は値 (スカラー) ですが、⾔い換えると 1 × 1 の
⾏列とも⾔えます。 つまり、NumPy では np
.a
rr
ay(
[[
b]]
) と表現します。
備考
ただし、 np.array([[b]]) という表現だと NumPy のバージョンによっては認識できない場合が
あるので、ここでは np.array([[b,]
,]
) と余分なカンマ , を付けることで⾏列であることを
明⽰しています。
#!/
us
r
/b
in/envpython
#co
d
in
g
:UTF-8
import numpyas np
b=n
p.
a
rray([[1,],])
p
r
in
t
(b
)
また
b
を⾏列として考えておくことで同じ⾏列である
す。 実際に
b
と
W
で⾏いたい演算は
W
W = (w 00 w 01 w 02 )
との演算が簡単に⾏えるようになりま
の後に
b = (b)
を付けて新しい
′
W
を作ることです。 この演算を簡単に⾏うメソッドが n
p.
con
ca
ten
ate
() です。
(C) 2016, Morning Project Samurai
Page 19
MPS - Yokohama
7.3.3. NumPy での⾏列の連接
np
.
co
n
ca
te
n
ate() は第 1 引数に連接される⾏列、第 2 引数に連接する⾏列を記述し、第 3 引数に
連接する⽅向を記述します。 ここでは例として以下のような
W
⎧
⎪
⎪
⎪
⎪
⎪
⎪
⎪
⎪
⎪
x
⎨
⎪
⎪
⎪
⎪
⎪
b
⎪
⎪
⎪
⎩
⎪
E
=
W
,
,
E
を考えてみます。
の列に
b
を追加します。
x
,
b
( w 00 w 01 w 02 )
⎛
=
x0
⎞
⎜ x1 ⎟
⎝
x2
=
( b)
=
(1)
⎠
ここで np
.
co
n
catenate(W,b,axis=1) は以下のように
W
( w 00 w 01 w 02 b )
同様に n
p.
c
on
catenate(x,E) または np.
c
onc
at
ena
te
(x
,E
,ax
is=0
) は以下のように
⽅向に
E
x
の⾏
を追加します。
⎛
x0
⎞
⎜ x1 ⎟
⎜
⎟
⎜ x2 ⎟
⎝
1
⎠
つまり、この np.concatenate() メソッドを⽤いることで先ほどの以下の式を表現できそうです。
T
W
x + b
=
w 00 × x0 + w 01 × x1 + w 02 × x2 + b × 1
⎛
=
⎞
⎜ x1 ⎟
( w 00 w 01 w 02 b ) ⎜
⎟
⎜x ⎟
2
⎝
=
x0
′T
W
x
1
⎠
′
では、これをプログラムしてみましょう。
Page 20
(C) 2016, Morning Project Samurai
MPS - Yokohama
#!/
us
r
/b
in/envpython
#co
d
in
g
:UTF-8
#Nu
m
Pyを以後 npと略して利用する
import numpyas np
#Ne
u
ro
nクラスの定義
class Neuron:
#性質として w,b,fを定義する
def __init__(self,w,b,f):
self.w=np.concatenate((w,b
),ax
is=1)
self.f=f
#機能として outputを定義する
def output(self,x):
x=np.concatenate((x,[[1,]
,])
)
return self.f(self.w.dot(
x)
)
#関数 fを定義する
def f(
u)
:
u
[u>0] = 1
u
[u<=0]=-1
return u
関数 f の と こ ろ は 独 特 な 表 現 に な っ て い ま す 。 変 数 u は ベ ク ト ル ま た は ⾏ 列 で す か ら
(u0 u1 u2 ⋯ un )
し、 ui
≤ 0
のような形式になっています。 この各要素を全て探索して
ui > 0
のものは 1 と
のものは -1 とすることを意味しています。 もちろん for ⽂でも記述することができます
が、NumPy を⽤いることで簡単に記述することができます。
それでは今までの内容を⽤いて問題を解いてみましょう。
7.3.4. 問題
問題:
W = (1.0 2.0) , b = 1.0 , x = (
0.5
)
の場合について計算せよ。 また Python のプログ
−0.5
ラムが合っているかどうかを⼿計算でも求めよ。
(C) 2016, Morning Project Samurai
Page 21
MPS - Yokohama
#co
d
in
g
:UT
F
-8
#N
u
mP
yを以後 npと略して利用する
import nu
m
p
yas np
#N
e
ur
o
nクラスの定義
class Neuron:
#性質として w,b,fを定義する
def __init__(self,w,b,f):
s
e
l
f.
w=np.concatenate((w,b),axi
s=1)
s
e
l
f.
f=f
#機能として outputを定義する
def output(self,x):
x=n
p
.concatenate((x,[[1,],])
)
return self.f(self.w.dot(x))
#関数 fを定義する
def f(
u
):
u[
u>0
] = 1
u[
u<
=0]=-1
return u
if _
_n
a
me
_
_=
="__main__":
n=N
e
u
ro
n
([[1.0,-2.0],],[[1.0,],]
,f
)
pr
i
nt
(
n
.o
u
tput([[0.5],[-0.5],]))
⼿で計算すると以下のようになります。
T
W
0.5
x + b
=
( 1.0 2.0 ) (
) + 1.0
−0.5
T
W
x + b
=
1.0 × 0.5 + 2.0 × −0.5 + 1.0
=
0.5
の値が 2.5 ということはステップ関数
f (u)
の引数
になります。
Page 22
(C) 2016, Morning Project Samurai
u
が正になるため、 f (u) の値は 1
MPS - Yokohama
7.4. 単⼀のニューロンを動かす (ステップ関数編)
7.4.1. ニューロンに学習させる
次は実際にニューロンに学習をさせてみますが、その前に「学習」とは何かを考えてみましょう。
7.4.1.1. 学 習 っ て 何 ?
「学習」とは何でしょうか。 それが分からないとニューロンに学習させることができませんね。 こ
こでは学習を以下のように定義します。
学習:
試⾏錯誤して何かがうまくなること。その試⾏錯誤のプロセスを学習と⾔う。
では「試⾏錯誤」とはどういうことでしょうか。
試⾏錯誤:
試みと失敗を繰り返しながら次第に⾒つけ出す。
ここではこのように「学習」と「試⾏錯誤」を定義づけします。
7.4.1.2. 試 ⾏ 錯 誤 に 必 要 な も の
永遠と試みと失敗を繰り返しをしていても何も進歩はありません。 ⼈間の学習と同様に試⾏錯誤を
してうまくなるには、さらに必要なものがあります。
1. ゴール
到達したい状態 (Deep Learning の場合には教師データが該当します)
2. 学習の仕⽅
アルゴリズム (既に学習してきた関数
f
などのことです)
3. 今の状態とゴールとの距離
評価関数
これらを決めた上で学習を⾏って⾏きましょう。
(C) 2016, Morning Project Samurai
Page 23
MPS - Yokohama
コラム:
TEX
21
の開発者として有名な Donald E. Knuth22 の⾔葉に以下のようなものがあります。
It has been often said that a person does not really understand something until he teaches it to
someone else. Actually a person does not really understand something until he can teach it to a
computer, i.e., express it as an algorithm. (⼈は誰かに教えるまで本当には理解していないとよく
⾔われます。例えばアルゴリズムとして表現して、コンピュータに教えることができるまで、実
際には理解していないのです。)
まさにこれが今みなさんがやっている内容を⽰しています。
7.4.1.3. ビ ッ ト 反 転 問 題
今まで学んだことを元にして、例題として「ビット反転問題」を解いてみましょう。
7.4.1.3.1. ビ ッ ト 反 転 問 題 の ゴ ー ル
まず、ゴールを定めます。
ビット反転とは「0 を⼊⼒した際に 1 を返し、0 以外を⼊⼒した際に 0 を返す」ものです。 つま
り、これが今回のゴールです。
7.4.1.3.2. ビ ッ ト 反 転 問 題 の ア ル ゴ リ ズ ム
次にアルゴリズムですが、これまでに学んだ関数
1 (u ≥ 0)
0 (otherwise)
f
は以下のようなステップ関数だけです。
f (u) = {
7.4.1.3.3. ビ ッ ト 反 転 問 題 の 評 価 関 数
では、以下の状態とゴールとの距離はどのように考えれば良いでしょうか。 ゴールの値を
字の
t
は正解の truth の略です) とし現在の値を
y
−
−−−
−−−
2
= |yt − y|
また、数学的に距離とは正であるため
Page 24
yt − y
(添え
とすると、通常の 2 点間の距離 ( |d| ) 同様に以下
のように記述することができます。
|d| = √(yt − y)
yt
の絶対値を取ります。
(C) 2016, Morning Project Samurai
MPS - Yokohama
7.4.1.3.4. ど う や っ て プ ロ グ ラ ム す る か
次元数が 1 次元なので、作っていくニューロンは以下のように記述することができます。
y0 = f (w 00 x + b)
また、今回は簡単にするためにバイアス
を定数として
b
w 00
のみで学習していきます。
プログラムを作るために、いくつかの場合を考えてみます。
1.
x0 = 1
で
w00 x + b > 0
x0 = 1
の場合のゴール
yt
は 0 になります。
の場合の
f
は 1 を返すので、 y
w 00 x + b > 0
したがって、評価関数
この場合には
2.
x0 = 1
で
で
f
は 0 を返すので、 y
w 00
で
x0 = 0
が適切であると判断し
f
は 1 を返すので、 y
|d|
w 00
は
が適切であると判断し
は 1 になります。
の場合の
f
は 0 を返すので、 y
この場合には
= f (w 00 x + b) = 0
w 00
となります。
となります。
を変化させません。
= f (w 00 x + b) = 1
w 00
となります。
となります。
を変化させません。
の時
yt
したがって、評価関数
づつ⼩さくします。
|d| = |yt − y| = |1 − 1| = 0
の場合のゴール
w 00 x + b ≤ 0
α
となります。
の時
の場合の
w00 x + b ≤ 0
を
|d| = |yt − y| = |0 − 0| = 0
は 1 になります。
この場合には
x0 = 0
は
yt
したがって、評価関数
4.
|d|
の場合のゴール
w 00 x + b ≤ 0
w 00
となります。
の時
の場合の
w00 x + b > 0
x0 = 0
が⼤きすぎると判断し
は 0 になります。
この場合には
= f (w 00 x + b) = 1
|d| = |yt − y| = |0 − 1| = 1
yt
したがって、評価関数
x0 = 0
は
の場合のゴール
w 00 x + b ≤ 0
3.
|d|
w 00
w00 x + b ≤ 0
x0 = 1
の時
|d|
w 00
は
= f (w 00 x + b) = 0
|d| = |yt − y| = |1 − 0| = 1
が⼩さすぎると判断し
(C) 2016, Morning Project Samurai
w 00
を
α
となります。
となります。
づつ⼤きくします。
Page 25
MPS - Yokohama
⽂書で記述すると分かりにくいかもしれませんので、これを表にまとめると以下のようになりま
す。
Table 7-1: ビット反転問題のプログラム
x0
w 00 x + b
f (w 00 x + b)
yt
|d|
w 00
1
> 0
1
0
1
−α
1
≤ 0
0
0
0
何もしない
0
> 0
1
1
0
何もしない
0
≤ 0
0
1
1
+α
この場合分けにしたがってプログラムを組んでいくことになります。
Fig u re 7-4: ビット反転問題におけるニューロン
例えば、 w00
り、 0.3x + 0.1
= 0.3
b = 0.1
とした場合を考えます。 ここで
= 0.3 × 0.1 + 0.1 = 0.4
す。 この場合には
|d|
,
w 00
x = 1
となります。 活性化関数
f
を代⼊すると
を通すと
f (0.4) = 1
にな
となりま
が⼤きすぎるので、 w00 から 0.01 を減らしていきます。 これを繰り返して
が 0 になるまで続けます。
7.4.1.3.5. 演 習
これを Python でプログラムを組んでいきます。
1. ゴール
0 を⼊⼒した際に 1 を返し、0 以外を⼊⼒した際に 0 を返します。
Page 26
yt = 0
(C) 2016, Morning Project Samurai
MPS - Yokohama
2. 学習の仕⽅
評価関数としてステップ関数を⽤います。
w 00
の初期値は 0.3 とする。
w 00
を変化させる量
α
は 0.01 とする。
3. 今の状態とゴールとの距離
|d| = |yt − y|
で判断します。
既に作ったニューロンのプログラムを元にしてプログラムを組んでいくと以下のようになります。
(C) 2016, Morning Project Samurai
Page 27
MPS - Yokohama
Code 7-3: step_neuron.py
#!/
u
sr
/
b
i
n/
e
nvpython
#c
o
di
n
g:U
TF
8
#N
u
mP
yを以後 npと略して利用する
import nu
m
p
yas np
#N
e
ur
o
nクラスの定義
class Neuron:
#性質として w,b,fを定義する
def __init__(self,w,b,f,a):
s
e
l
f.
w=np.concatenate((w,b),axi
s=1)
s
e
l
f.
f=f
s
e
l
f.
a=a
#機能として outputを定義する
def output(self,x):
x=n
p
.concatenate((x,[[1,],])
)
return self.f(self.w.dot(x))
#機能として learnを定義する
def learn(
self,x,y):
d=y-self.output(x)
#x
0=1で w00x+b>0の時
if d<0:
s
e
lf.w[0][0]-=self.a
#x
0=0で w00x+b<=0の時
elif d>0:
s
e
lf.w[0][0]+=self.a
p
r
i
nt
(
self.w,np.abs(d))
#評価値として距離を用いる
return np.abs(d)
#関数 fを定義する
def f(
u
):
u[
u> 0]=1
u[
u<
=0]=0
return u
if _
_n
a
me
_
_=
="__main__":
Page 28
(C) 2016, Morning Project Samurai
MPS - Yokohama
w=[
[0.3,],]
b=[[0.1,],]
a=0.01
n=Neuron(w,b,f,a)
for iin range(100):
n.learn([[0.0,],],[[1.0,],
])
n.learn([[1.0,],],[[0.0,],
])
実際に実⾏して確認してみましょう。
Code 7-4: 実⾏結果
$p
y
th
o
n20160409_01.py
(
a
rr
a
y(
[
[0.3, 0.1]]),array([[0.
]]
))
(
a
rr
a
y(
[
[0.29, 0.1]]),array([[1.
]])
)
(
a
rr
a
y(
[
[0.29, 0.1]]),array([[0.
]])
)
(
a
rr
a
y(
[
[0.28, 0.1]]),array([[1.
]])
)
<
s
ni
p
>
(
a
rr
a
y(
[
[0.01, 0.1]]),array([[1.
]])
)
(
a
rr
a
y(
[
[0.01, 0.1]]),array([[0.
]])
)
(
a
rr
a
y(
[
[-1.42247325e-16,
(
a
rr
a
y(
[
[-1.42247325e-16,
1.0000
00
00e
-0
1]
]),a
rra
y(
[[1.
]]
))
1.0000
00
00e
-0
1]
]),a
rra
y(
[[0.
]]
))
(
a
rr
a
y(
[
[-0.01, 0.1]]),array([[1.
]])
)
(
a
rr
a
y(
[
[-0.01, 0.1]]),array([[0.
]])
)
<
s
ni
p
>
(
a
rr
a
y(
[
[-0.09, 0.1]]),array([[1.
]])
)
(
a
rr
a
y(
[
[-0.09, 0.1]]),array([[0.
]])
)
(
a
rr
a
y(
[
[-0.1, 0.1]]),array([[1.
]]
))
(
a
rr
a
y(
[
[-0.1, 0.1]]),array([[0.
]]
))
(
a
rr
a
y(
[
[-0.1, 0.1]]),array([[0.
]]
))
(
a
rr
a
y(
[
[-0.1, 0.1]]),array([[0.
]]
))
<s
n
ip
> は省略を意味しています。 このように se
lf
.w が [[0.
1, 0
.1
]] となり学習が完了し
たことになります。
(C) 2016, Morning Project Samurai
Page 29
MPS - Yokohama
備考:
本来 s
el
f
.
w が 0 になるべき部分が -1.4
22
47
325
e16 となっています。 時々、計算誤差とい
う表現をしている書籍もありますが、これは計算誤差ではありません。 コンピューターの中では
数 値 は 2 進 数 に 変 換 し て 計 算 さ れ ま す が 、 10 進 数 で 0.01 と 表 さ れ る 数 は 2 進 数 で は
0.0001100110011... と循環してしまうため表現しきれないことによるものです。 これを解決する
⼿段として、ある程度以下に⼩さくなった場合に 0 と⾒なすことを⾏いますが、このプログラム
ではそうした実装を⾏っていないため、このような値になっても驚かないでください。
7.5. 単⼀のニューロンを動かす (シグモイド関数編)
7.5.1. シグモイド関数とは
シグモイド関数23 とは以下のように表現させる関数です。
1
sigmoid(x) = ς (x) =
1 + e
−αx
この関数はどのような関数でしょうか。 Python のライブラリである matplotlib を⽤いてグラフ化
してみましょう。
シグモイド関数はどのような関数でしょうか。
α
を変更してみた際のシグモイド関数の挙動を⾒て
みましょう。
Page 30
(C) 2016, Morning Project Samurai
MPS - Yokohama
Code 7-5: plot_sigmoid_a.py
#!/
us
r
/b
in/envpython
#co
d
in
g
:utf-8
import numpyas np
from m
at
p
lotlibimport pyplotas plt
def sigmoid(alpha,x):
return 1/(1+np.exp(-alpha*x)
)
if _
_
n
am
e__=='__main__':
x=np.linspace(-5.0,5.0,100)
s=np.vectorize(sigmoid)
for iin range(1,5):
plt.plot(x,s(i,x),marker='.
',l
abe
l="
Al
ph
a="+s
tr(
i+0
.0
))
plt.legend(loc=2)
plt.xlabel("x")
plt.ylabel("Sigmoid(x)")
p
lt
.
show()
Fig u re 7-5:
α
α
を可変させた場合のシグモイド関数
が⼤きくなると、傾きが急になっていき、ステップ関数に近づくことが分かります。
備考
Jupyter でプロットするには先頭に %
m
atp
lo
tli
bin
lin
e が必要になります。
「試⾏錯誤して何かがうまくなること。その試⾏錯誤のプロセス」を学習と定義しました。 つま
り、以下の 3 つを定義します。
(C) 2016, Morning Project Samurai
Page 31
MPS - Yokohama
1. ⽬標を持って
2. その⽬標に近づくように
3. ⾒通しを⽴てて試⾏錯誤する
ステップ関数で「ビット反転問題」を解く際にもこの 3 つの要素が揃っていることが重要でした。
7.5.2. シグモイド関数でのビット反転問題
⽬標として以下のようにします。 これはステップ関数の場合と同じです。
x0 = 0
の時
y0 = 1
x0 = 1
の時
y0 = 0
今回求めるものは以下のようになります。
y0
=
f (w 00 x + b)
=
sigmoid(w 00 x + b)
1
=
1 + exp(−α(w 00 x + b))
ここで
は係数 (定数) なので、 exp(a + b)
α
= exp(a) ⋅ exp(b)
という性質を使⽤して
w 00
と
b
に
ついて変形していきます。
1
f (w 00 x + b)
=
1 + exp(−α(w 00 x + b))
1
=
1 + exp(−αw 00 x) ⋅ exp(αb)
1
=
1 + exp(w
ここで
w
′
= −αw
,
b
′
= −αb
′
00
としています。
式が複雑になってきましたが、次にこの
Page 32
′
x) ⋅ exp(b )
b
′
に対して関数
f
がどのようになるか⾒てみましょう。
(C) 2016, Morning Project Samurai
MPS - Yokohama
Code 7-6: plot_sigmoid_b.py
#!/
us
r
/b
in/envpython
#co
d
in
g
:utf-8
import numpyas np
from m
at
p
lotlibimport pyplotas plt
def sigmoid(w,beta,x):
return 1/(1+np.exp(-w*x
)*n
p.
ex
p(b
et
a))
if _
_
n
am
e__=='__main__':
x=np.linspace(-5.0,5.0,100)
s=np.vectorize(sigmoid)
for iin range(0,5):
plt.plot(x,s(1,i,x),mar
ke
r='
.'
,l
ab
el="B
eta="+st
r(
i+0
.0
))
plt.legend(loc=2)
plt.xlabel("x")
plt.ylabel("Sigmoid(x)")
p
lt
.
show()
Fig u re 7-6:
b
を振った際のシグモイド関数の挙動
分かりましたか。 つまり、シグモイド関数は
b
を変化させた際には
x
軸⽅向にシフトする特徴が
あり、 b は⽴ち上がりの開始位置を制御することができるわけです。。
7.6. 評価関数 (⼆乗誤差)
ステップ関数での評価関数は距離
教師 − 出力|
d = |
= |y − y0 |
(C) 2016, Morning Project Samurai
Page 33
MPS - Yokohama
としましたが、今回は評価関数として⼆乗誤差 (Square Error) SE を⽤います。 ⼆乗誤差は以下のよ
うに記述できます。
2
S E = (y − y0 )
これを Python で記述すると np.power(y-y
o,2.
0) ( imp
or
tn
um
pyasnp とした場合) となり
ます。
さて、この評価関数はどのようなグラフになるのでしょうか。
Code 7-7: plot_se.py
#!/
u
sr
/
b
i
n/
e
nvpython
#c
o
di
n
g:u
tf
8
from m
p
l_
t
o
ol
k
its.mplot3dimport Axes3
D
import ma
t
p
lo
tlib.pyplotas plt
import nu
m
p
yas np
def se(
y
,yo
)
:
return np
.power(y-yo,2.0)
def sigmoid(
w,x,b):
return 1/(1+np.exp(-w*x+b))
if _
_n
a
me
_
_=
='__main__':
w=n
p
.
li
n
space(-10,10,100)
b=n
p
.
li
n
space(-20,20,100)
W,B=np
.
meshgrid(w,b)
Z=s
e
(
0,sigmoid(W,1,B))
fi
g=p
lt
.
figure()
ax=A
x
es
3
D(fig)
ax
.
pl
o
t
_w
i
reframe(W,B,Z)
pl
t
.s
h
o
w(
)
Page 34
(C) 2016, Morning Project Samurai
MPS - Yokohama
Fig u re 7-7: ⼆乗誤差のグラフ
上図のような評価関数になることがプロットすることで分かります。
備考
これから扱う数式が複雑になっていきますので、⼿で計算することが難しくなってきます。 しか
し、このようにグラフ化することで、どのような関数を今扱っているのかを明確にしておきまし
ょう。
7.6.1. 最急降下法で最⼩値を求める
今回の内容を再度⾒てみましょう。
Fig u re 7-8: シグモイド関数でビット反転問題を解く⽅法
今回のニューロンは
w 00 x + b0
の出⼒をしますので、以下のような 2 つの⽅程式から成り⽴ちま
す。
z
=
⎪
⎪
⎩ y0
⎪
=
⎧
⎪
⎪
⎪
⎨
w 00 x + b0
1
1 + exp(−z)
(C) 2016, Morning Project Samurai
Page 35
MPS - Yokohama
z
を代⼊して、 exp(a + b)
= exp(a) ⋅ exp(b)
であることを⽤いると以下のように変形できます。
1
y0
=
1 + exp(−(w 00 x + b0 ))
1
=
1 + exp(−w 00 x) ⋅ exp(−b0 )
この場合の評価関数⼆乗誤差を最⼩にすれば良いことが分かります。 ここで、最⼩値を求めるにあ
たり、関数の傾きを考えていきます。
関数
f (x)
の傾きとは
の変化
f(x)
の変化
x
で表すことができます。
Fig u re 7-9: 傾きとは
ただし、上図の右図のようにあまりも
x
の変化が⼤きすぎる場合には傾きとは呼べそうにありませ
ん。 傾きとは局所的な性質になります ので、 x1 を
x0
に近づける ( f (x1 ) を
f (x0)
に近づける) こ
とを意味し、数式で記述すると以下のようになります。
f (x1 ) − f (x0 )
lim
x1 − x0
x 1→x 0
これが傾きになります。 ただし、プログラムで表現する場合には離散的な値しか取れませんので、
以下に
2
f (x) = x
に対して、 x0
= 1
とし、 x1
− x0 = 0.01
とした場合の傾きを求めるプログラム
を載せています。
Page 36
(C) 2016, Morning Project Samurai
MPS - Yokohama
Code 7-8: diff_test.py
#!/
us
r
/b
in/envpython
#co
d
in
g
:utf-8
def diff(f,x0):
d
el
t
a=0.01
x
1=x0+delta
return (f(x1)-f(x0))/delt
a
def f1(
x)
:
return x**2
d=d
if
f
(f1,1)
p
r
in
t
(d
)
Code 7-9: diff_test.py の実⾏結果
2.
0
1
00
0
00
000000007
本当は 2 なのですが、 x1
− x0 = 0.01
と有限の値を持っていることが原因で 2 になっていませ
ん。
7.6.2. 最急降下法
傾きの求め⽅が分かったので、最⼩となる
x
以下の図のように考えると、傾きの符号が
−
の場合には動かす⽅向は
−
を求める⽅法を考えていきます。
の場合には動かす⽅向は
+
になり、傾きの符号が
+
になります。 ⼀⽅、傾きの⼤きさが⼤きい場合には動かすべき⼤きさも
⼤きく、傾きの⼤きさが⼩さい場合には動かすべき⼤きさを⼩さくすると効率良く最⼩値を求めるこ
とができそうです。
(C) 2016, Morning Project Samurai
Page 37
MPS - Yokohama
Fig u re 7-10: 最⼩値の求め⽅
これを数式で表すと以下のようになります。
′
xnew = xold − ε ⋅ f (xold )
備考:
関数
f (x)
の微分は
′
f (x)
の意味は変化量を表し、
ここで
ε
と記述します。または
df(x)
dx
のように記述しますが、この場合の
f(x)の変化量
xの変化量
という意味になります。
を学習率と呼びます。
ここまで学んだことを使って
2
x
を最⼩にするような
x
を求めてみましょう。
#!/
u
sr
/
b
i
n/
e
nvpython
#c
o
di
n
g:u
tf
8
import nu
m
p
yas np
def argmin(f
,epsilon,dx,x,acceptabl
e_
er
ror
):
while True:
d
f=(
f(x+dx)-f(x))/dx
if np
.abs(df)<acceptable_error
:
return x
x=x-epsilon*df
def f(
x
):
return np
.power(x,2.0)
pri
n
t(
a
rg
m
i
n(
f
,0.1,0.01,2.0,0.01))
Page 38
(C) 2016, Morning Project Samurai
d
MPS - Yokohama
備考:
x
2
を微分すると
値が
−
から
+
a ×x
a−1
2
となります。 つまり、 x を微分すると
に変化するところ ( x
= 0
2x
になりますので、この
が最⼩ということになります。 このように簡単なも
のであれば式を⽤いて解くことができます。
7.6.3. SE の微分
今、傾きを求めたい関数 SE (Squared Error) は
w 00
と
b0
の 2 つの変数に対して微分を⾏う必要
があります。
⎧ SE
⎪
⎪
⎪
=
2
(y − y0 )
⎨
⎪
⎪
⎩
⎪
1
y0
=
1 + exp(−w 00 x) ⋅ exp(−b0 )
Fig u re 7-11: 2 変数の微分
つまり、以下のようにまとめられます。
2
1
S E = (y −
)
1 + exp(−w 00 x) ⋅ exp(−b0 )
ここで⼀般的に関数
f (x, y)
の微分を求める⽅法を考えてみましょう。
7.6.3.1. 2 変 数 関 数 の 微 分
まず、基準となる
⾏しているとすると
⎧ Δx
⎪
⎨
⎩
⎪
Δy
(x0 , y0 )
Δx
と
を選びます。 次に、そこから
Δy
Δr
だけ動くとします。
x
軸と
y
軸が直
は以下のように記述できます。
=
||Δr|| ⋅ cos θ
=
||Δr|| ⋅ sin θ
(C) 2016, Morning Project Samurai
Page 39
MPS - Yokohama
Fig u re 7-12: 三⾓関数への置き換え
このように変形することで、全ての
Δx
と
Δy
に対して計算するのではなく、全ての
θ
に対して
計算するだけで良いことになり、変数をひとつ減らすことができます。
備考
||Δr||
の縦⼆本線の記号はノルムと呼ばれます。 ここでは絶対値
|Δr|
と同じですが、ノルム
は距離を⽰します。
ここで求めた
Δx
と
Δy
は後から出てきますので覚えておいてください。
さて、 f (x, y) の傾きはどのように表すことができるでしょうか。 これは以下のように表されま
す。
f (x + Δx, y + Δy) − f (x, y)
lim
−
−−−−
−−−−
2
2
√Δx + Δy
Δx→0,Δy→0
これからこの式を変形していきますが、ここでは
lim Δx→0,Δy→0
という部分は省略して考えます。
f (x + Δx, y + Δy) − f (x, y)
−
−−−−
−−−−
2
2
√Δx + Δy
f(x+Δx,y+Δy)−f(x,y+Δy)
Δx
=
f(x,y+Δy)−f(x,y)
⋅ Δx +
Δy
⋅ Δy
−
−−−−
−−−−
2
2
√Δx + Δy
fx (x, y + Δy) ⋅ Δx + fy (x, y) ⋅ Δy
=
ここで
Page 40
fx
は
−
−−−−
−−−−
2
2
√Δx + Δy
x
に関する微分
f(x+Δx,y)−f(x,y)
Δx
を表し、 fy は
(C) 2016, Morning Project Samurai
y
に関する微分
f(x,y+Δy)−f(x,y)
Δy
MPS - Yokohama
を表しています。 これをさらに変形していきます。
fx (x, y + Δy) ⋅ Δx + fy (x, y) ⋅ Δy
−
−−−−
−−−−
2
2
√Δx + Δy
f (x,y+Δy)−f (x,y)
x
{
x
⋅ Δy + fx (x, y)} ⋅ Δx + fy (x, y) ⋅ Δy
Δy
=
−
−−−−
−−−−
2
2
√Δx + Δy
f (x,y+Δy)−f (x,y)
ここで
x
x
⋅ Δy = fxy (x, y)
Δy
ですから、さらに変形を進めます。
f (x,y+Δy)−f (x,y)
{
x
x
⋅ Δy + fx (x, y)} ⋅ Δx + fy (x, y) ⋅ Δy
Δy
−
−−−−
−−−−
2
2
√Δx + Δy
{fxy (x, y) ⋅ Δy + fx (x, y)} ⋅ Δx + fy (x, y) ⋅ Δy
=
−
−−−−
−−−−
2
2
√Δx + Δy
fxy (x, y) ⋅ Δx ⋅ Δy + fx (x, y) ⋅ Δx + fy (x, y) ⋅ Δy
=
ここで
Δx
−
−−−−
−−−−
2
2
√Δx + Δy
や
Δy
は⾮常に⼩さいと考えているので、 Δx ⋅ Δy は 0 と⾒なすことができます。
fxy (x, y) ⋅ Δx ⋅ Δy + fx (x, y) ⋅ Δx + fy (x, y) ⋅ Δy
−
−−−−
−−−−
2
2
√Δx + Δy
fx (x, y) ⋅ Δx + fy (x, y) ⋅ Δy
=
−
−−−−
−−−−
2
2
√Δx + Δy
式を変形していくことで
fy
x
と
y
を分離して考えることができるようになりました。 つまり
fx
と
が⼤きくなる⽅向に動かしていけば良いことになります。 その際の関数の変化率は
f (x,y)⋅Δx+f (x,y)⋅Δy
x
y
2
√Δx +Δy
2
で表されます。
さて、 fx (x, y) ⋅ Δx + fy (x, y) ⋅ Δy という部分は⾏列に直すことができそうです。
fx (x, y) ⋅ Δx + fy (x, y) ⋅ Δy
−
−−−−
−−−−
2
2
√Δx + Δy
Δx
( fx fy ) ⋅ (
)
Δy
=
この値を
dE
−
−−−−
−−−−
2
2
√Δx + Δy
とします。
また、最初に求めた
r
を⽤いた関係式を使います。
(C) 2016, Morning Project Samurai
Page 41
MPS - Yokohama
⎧ ||Δr||
⎪
⎪
⎪
⎪
⎪
⎪
⎨
⎪
⎪
⎪
⎪
⎪
⎩
⎪
2
2
Δx
Δx
=
||Δr|| ⋅ cos θ
Δy
=
||Δr|| ⋅ sin θ
これらの関係から
dE
+ Δy
2
=
は以下のように記述できます。
||Δr|| ⋅ cos θ
( fx fy ) ⋅ (
)
||Δr|| ⋅ sin θ
dE
=
||Δr||
cos θ
( fx fy ) ⋅ (
=
)
sin θ
随分簡単になってきました。 さらに
g
⎧
⎪
⎪
⎪
=
( fx fy )
=
(
r
と⼤きさが 1 の単位ベクトル
^
r
を導⼊します。
⎨
cos θ
⎪
⎪
r
⎩ ^
⎪
)
sin θ
とすれば、 dE
^
= r ⋅ r
ここで
のなす⾓度を
g
と
^
r
と記述できます。
α
とすると以下のように記述できます。
dE = ||g|| ⋅ ||^
r || ⋅ cos α
このように記述できた際に
dE
を最⼤にする
⼤になることが分かります。 さらに
^
r
α
は
cos α
を最⼤にすれば良いことから
α = 0
が最
は⼤きさが 1 の単位ベクトルであることから、 g を最⼤にす
れば良いことになります。 そのためには
fx
と
fy
を求めれば良いことになります。 つまり、知りた
かった 2 変数の微分は個々の変数での微分が分かれば良いことになります。
7.6.3.2. SE に 適 ⽤ す る
今までの結果を
SE
に適⽤してみましょう。 微分 (傾き) は
Grad
と記述します。
Grad S E(w 00 , b0 ) = (S Ew00 S Eb0 )
さて本来はこれを解いていきますが、シグモイド関数には⾯⽩い性質があります。 シグモイド関数
を
ς (x) =
1
1+exp(−a⋅x)
とするとシグモイド関数の微分は以下のようになります。
dς (x)
= a ⋅ ς (x) ⋅ {1 − ς (x)}
dx
このことから以下のような式が導き出せます。
Page 42
(C) 2016, Morning Project Samurai
MPS - Yokohama
y0 w
⎧
⎪
00
⎪
⎪
⎪
⎪
⎪
⎪
⎪
⎪
⎪
S Ew00
⎪
⎪
=
x0 ⋅ y0 ⋅ (1 − y0 )
=
2 ⋅ (y − y0 ) ⋅ y0 w
=
1 ⋅ y0 ⋅ (1 − y0 )
=
2 ⋅ (y − y0 ) ⋅ y0 b
00
⎨
⎪
⎪
⎪
⎪
⎪
⎪
⎪
⎪
⎪
⎪
⎪
⎩
⎪
y0 b
0
S Eb0
これらを⽤いて傾き
0
Grad S E
は以下のように記述できます。
⎛
x0
Grad S E = s ⋅ (y − y0 ) ⋅ y0 ⋅ (1 − y0 ) ⋅ ⎜
⎝
曲⾯である関数
う。 まず、関数
2
z = f (x, y) = x
f (x, y)
を
x
+ y
2
に対して
⎞
⎟
1
⎠
(x0 , y0 ) = (0.5, 0.5)
での微分を考えてみましょ
に対して微分します。 x に対して微分する場合には
y
は定数として扱
います。
fx = 2 ⋅ x
同様にして
y
に対して微分します。
fy = 2 ⋅ y
微分した値、すなわち傾きが
fx , fy
で
(x0 , y0 )
をとおる関数は以下のように表されます。
fx ⋅ (x − x0 ) + fy ⋅ (y − y0 ) = z − f (x0 , y0 )
これに微分した結果を代⼊します。
2 ⋅ x ⋅ (x − x0 ) + 2 ⋅ y ⋅ (y − y0 ) = z − f (x0 , y0 )
つまり
z
で書き出すと以下のようになります。
z
=
2 ⋅ x ⋅ (x − x0 ) + 2 ⋅ y ⋅ (y − y0 ) + f (x0 , y0 )
z
=
fxy (x0 , y0 ) + f (x0 , y0 )
このことを⽤いて図⽰する Python スクリプトを作成します。
(C) 2016, Morning Project Samurai
Page 43
MPS - Yokohama
Code 7-10: 曲⾯
z = x
2
+y
2
に対する接平⾯
import n
u
m
pyas np
from m
a
tp
l
o
tl
i
bimport pyplotas plt
from m
p
l_
t
o
ol
k
its.mplot3dimport Axes3
D
def z(
x
,y
)
:
return n
p
.p
ower(x,2)+np.power(y,2
)
def dz(
x
,y,x0,y0):
return (
2*x0)*(x-x0)+(2*y0)*(
y-y
0)
if _
_n
a
me
_
_=
='__main__':
x
s=np
.
l
in
s
pace(-2,2,100)
y
s=np
.
l
in
s
pace(-2,2,100)
x
0=0.
5
y
0=0.
5
X
S
,Y
S=np
.
meshgrid(xs,ys)
Z=z
(X
S
,Y
S
)
D
Z=dz
(
X
S,YS,x0,y0)
f
i
g=p
l
t
.f
i
gure()
a
x=Ax
e
s
3D
(
fig)
a
x
.p
l
ot
_
w
ir
e
frame(XS,YS,Z)
a
x
.p
l
ot
_
w
ir
e
frame(XS,YS,z(x0,y0)+DZ)
a
x
.s
e
t_
x
l
ab
e
l('x')
a
x
.s
e
t_
y
l
ab
e
l('y')
a
x
.s
e
t_
z
l
ab
e
l('z')
p
l
t.
s
ho
w
(
)
Page 44
(C) 2016, Morning Project Samurai
MPS - Yokohama
Fig u re 7-13: 実⾏結果
シグモイド関数を使うことで、数値微分をするのではなく、解析的に解を求められます。 このこと
を踏まえた上でシグモイド関数
y =
1
1+exp(−w00x)⋅exp(−b0)
を⽤いて学習率
ε
で学習するニューロンオ
ブジェクトを以下のように定義します。
class Neuron:
def __init__(self,w,epsilon=0
.5
):
s
e
lf._w=w
s
e
lf._epsilon=epsilon
def get_output(self,x):
return sigmoid(self._w.dot(
x)
)
def learn(self,teaching_datum)
:
"
"
"
:
p
aramteaching_datum:[data0
,dat
a1
,dat
a2
,.
..
,ans
we
r]
"
"
"
x=teaching_datum[:-1]
y=teaching_datum[-1]
v
a
l=self.get_output(x)
s
e
lf._w-=self._epsilon*2.
0*(
va
l-y
)*v
al*(1
.0-v
al)*x
8. バックプロパゲーション
今までは「1 ⼊⼒ 1 出⼒」のビット反転問題を扱ってきましたが、これから画像認識する 3 層の
NN を作るための準備をしていきます。 そのためにバックプロパゲーション (Back Propagation) とい
うものを考えていきます。
今までのところまでの学習で何ができるようになったのでしょうか? 今までの学習は多層ネットワー
(C) 2016, Morning Project Samurai
Page 45
MPS - Yokohama
クの最後の出⼒層のみの学習の⽅法でしかありません。 学習を前のニューロンに伝搬させていくのを
バックプロパゲーションといいます。
8.1. バックプロパゲーションと学習
教師データと出⼒のエラーを出⼒から⼊⼒⽅向に向けて伝搬させていきます。
バックプロパゲーションで伝搬されたエラーを元に学習を⾏っていきます。。
重要: バックプロパゲーションと学習は別です。
8.2. フォワードプロパゲーションの復習
まず、普通の伝搬 (フォワードプロパゲーション) を考えていきます。
Fig u re 8-1: フォワードプロパゲーション
z0
の活性化関数
f (z 0 )
がどのように表現できるかを考えます。 ひとつのニューロンの場合は以下
のようなものでした。
z 0 = w 0,0 ⋅ x0 + w 0,1 ⋅ x1
このニューロンからの出⼒が
f (z 0 )
となります。
8.2.1. 1 層⽬のニューロンを考える
次に 3 層ニューラルネットワークに適⽤していきます。
Page 46
(C) 2016, Morning Project Samurai
MPS - Yokohama
1 層⽬ 0 個⽬のニューロンの状態は以下のように記述することができます。
z
(1)
= w
0
この時の出⼒は
(1)
⋅ x0 + w
0,0
f (z
(1)
0
)
(1)
0,1
⋅ x1 + w
(1)
0,2
⋅ x2
となります。 同様に 1 層⽬の 1 個⽬のニューロンの状態も以下のように記
述できます。
z
(1)
= w
1
同様に出⼒は
f (z
(1)
⋅ x0 + w
1,0
(1)
1
(1)
1,1
⋅ x1 + w
(1)
1,2
⋅ x2
となります。
)
3 個分を記述します。
z
z
z
(1)
0
(1)
1
(1)
2
= w
= w
= w
(1)
0,0
(1)
1,0
(1)
2,0
⋅ x0 + w
⋅ x0 + w
⋅ x0 + w
(1)
0,1
(1)
1,1
(1)
2,1
⋅ x1 + w
⋅ x1 + w
⋅ x1 + w
(1)
0,2
(1)
1,2
(1)
2,2
⋅ x2
⋅ x2
⋅ x2
これらをまとめると 1 層⽬の各ニューロンの状態
z
(1)
= ∑w
j
(1)
j,i
z
(1)
j
は以下のように記述できます。
⋅ xi
i
その際の出⼒は以下のようになります。
f (z
(1)
j
)
8.2.2. 2 層⽬のニューロンを考える
同様に 2 層⽬のニューロンの状態は以下のように書けます。
z
(2)
1
= w
(2)
1,0
y1 = f (z
(2)
1
1
(2)
0
1,1
⋅ f (z ) + w
1
(2)
1
1,2
⋅ f (z ) + w
1
⋅ f (z )
2
)
3 個分を記述します。
z
z
z
(2)
0
(2)
1
(2)
2
=
w
=
w
=
w
(2)
0,0
(2)
1,0
(2)
2,0
⋅ f (z
⋅ f (z
⋅ f (z
(1)
0
(1)
0
(1)
0
) + w
) + w
) + w
(2)
0,1
(2)
1,1
(2)
2,1
⋅ f (z
⋅ f (z
⋅ f (z
(1)
1
(1)
1
(1)
1
) + w
) + w
) + w
(2)
0,2
(2)
1,2
(2)
2,2
⋅ f (z
⋅ f (z
⋅ f (z
(1)
2
(1)
2
(1)
2
)
)
)
これをまとめると以下のようになります。
(C) 2016, Morning Project Samurai
Page 47
MPS - Yokohama
z
(2)
k
= ∑w
(2)
k,j
⋅ f (z
(1)
j
)
j
出⼒は以下のようになります。
yk = f (z
(2)
k
)
これが今まで学んできたフォワードプロパゲーションになります。
Fig u re 8-2: フォワードプロパゲーションの考え⽅
8.3. バックプロパゲーション
次にバックプロパゲーションを考えていきます。
Page 48
(C) 2016, Morning Project Samurai
MPS - Yokohama
Fig u re 8-3: バックプロパゲーションの考え⽅
全体のエラーを
E
として表すと、 E
1
=
なるように付けているだけで、実際には
E
となります。
2
∑ k(yk − tk)
2
を⼩さくするという操作と
1
2
E
1
2
は微分した際に簡単に
を⼩さくするという操作
の意味は同じです。
最後の段の 2 層⽬ 0 個⽬のニューロンの状態
z
(2)
0
= w
(2)
0,0
⋅ f (z
(1)
0
またこのニューロンの出⼒
y0 = f (z
(2)
0
このことからエラー
E0
) + w
(2)
0,1
⋅ f (z
(1)
1
z
(2)
0
は以下のように記述することができます。
) + w
(2)
0,2
⋅ f (z
(1)
2
)
は以下のように記述できます。
y0
)
E0
を展開していきます。
2
=
(y0 − t2 )
=
(f (z ) − t0 )
=
(f ( w
2
2
0
(2)
0,0
⋅ f (z
学習していくべき⽅向はこの
E
(1)
0
) + w
を
w
(2)
(2)
0,1
⋅ f (z
(1)
1
) + w
(2)
0,2
⋅ f (z
(1)
2
2
)) − t0 )
で偏微分した⽅向になり、以下のようになります。
∂E
⎛
⎜
⎜
⎜
⎜
⎜
⎜
⎜
⎜
⎜
⎜
⎜
⎝
(2)
∂w
0,0
∂E
(2)
∂w
0,1
∂E
(2)
∂w
⎞
⎟
⎟
⎟
⎟
⎟
⎟
⎟
⎟
⎟
⎟
⎟
⎠
0,2
(C) 2016, Morning Project Samurai
Page 49
MPS - Yokohama
この偏微分
∂E
(2)
,
,
∂E
(2)
∂w
0,0
が分かれば、ニューロンの状態
∂E
(2)
∂w
z
∂w
0,1
(2)
どのくらいトレーニングすれ
0
0,2
ば良いか分かります。 でも、それより前のニューロンはどのようにトレーニングすれば良いのか分か
りません。
そこで個々に
た際に
w
(2)
が変化した時にどれだけ
0,0
(2)
が変化するかを考えて、その後に
0
z
(2)
0
が変化し
がどれだけ変化しているかを考えます。
E
∂E
∂z
∂E
=
∂w
⋅
(2)
∂z
0,0
∂E
(2)
∂z
∂E
∂w
⋅
(2)
∂z
1,0
∂E
(2)
∂z
=
∂w
いきなり
や
δ
⋅
∂z
2,0
μ
0
(2)
(2)
⋅ μ
0
(2)
0,0
0,0
1
= δ
(2)
⋅ μ
1
(2)
(2)
1,0
1,0
(2)
2
∂w
1
= δ
(2)
(2)
∂w
1
∂E
(2)
(2)
∂w
0
=
z
z
= δ
(2)
⋅ μ
2
(2)
(2)
2,0
2,0
のような記号が出てきました。
が変化した際にどのくらい
する偏微分、つまり
w
E
δ
はエラー
E
の状態
z
が変化するかを表した記号です。 同様に
が変化した際にどもくらい
z
に対する偏微分、つまり
μ
は状態
z
の重み
w
に対
が変化するかを表した記号です。 これらの記号
を⽤いることで偏微分の⼀⾒難しそうに⾒える数式を簡単に記述することができます。
これを⼀般的に記述すると以下のようになります。
∂E
∂z
∂E
=
∂w
(2)
k,j
⋅
∂z
(2)
∂w
k
2
k
= δ
(2)
⋅ μ
k
(2)
(2)
k,j
k,j
さて、今回のニューラルネットワークは 3 層なので、もうひとつ前のニューロンを考えていきま
す。 つまり、 w(1) が変化した際の
E
の変化量
を求めます。
∂E
(1)
∂w
0,0
∂E
∂z
∂E
=
∂w
(1)
⋅
∂z
0,0
(1)
(
次に
∂z
z
(δ
(2)
0
(2)
0
∂z
∂z
⋅
0
(2)
+
(1)
⋅
∂z
0
(2)
(1)
+ δ
(2)
1
∂z
1
(2)
0
∂z
∂E
0
∂z
⋅
∂z
0
(2)
+
⋅
(1)
∂z
0
(2)
1
(1)
0
(1)
+ δ
(2)
2
(2)
2
∂z
⋅
∂z
∂z
(2)
2
(1)
0
(2)
2
∂z
) ⋅
(1)
∂z
) ⋅
を考えていきます。 この中の
z
(2)
0
(C) 2016, Morning Project Samurai
(1)
0
∂w
0
(1)
0
∂w
(1)
0,0
を変化させると 2 層全てが影響を受けることを意味しています。
0
Page 50
∂z
∂E
1
(2)
0
∂z
(1)
0,0
∂z
∂z
この式は
(1)
⋅
∂z
=
0
∂w
0
∂E
=
(1)
(1)
0,0
MPS - Yokohama
は以下のように記述できることは既に計算してある。
z
(2)
= w
0
(2)
0,0
⋅ f (z
(1)
) + w
0
∂z
と書き表されますから、偏微分
(2)
0,1
(1)
1
) + w
(2)
0,2
⋅ f (z
(1)
2
)
(2)
0
∂z
⋅ f (z
(1)
は
z
(1)
0
に関係する部分だけが残ることになります。
0
∂z
∂z
∂z
(2)
1
∂z
(1)
∂z
や
0
= w
(1)
∂z
(2)
′
⋅ f (z
0,0
(1)
0
)
0
(2)
についても同様です。
2
0
(1)
0
∂z
∂z
∂z
∂z
ここで
ς (x) =
(2)
w
(2)
1
= w
(1)
(2)
′
⋅ f (z
0,1
(1)
1
)
0
(2)
2
= w
(1)
(2)
′
⋅ f (z
0,2
(1)
2
)
0
は既にフォワードプロパゲーションの際に計算された値ですし、 f はシグモイド関数
(2)
1
1+exp(−a⋅x)
で、この微分
′
f
は
dς(x)
= a ⋅ ς (x) ⋅ {1 − ς (x)}
dx
と記述できることを学んでき
ました。
これを⼀般的に記述すると以下のようになります。
∂E
∂z
∂E
=
∂w
∂z
j,i
(1)
∂w
j
∂z
(2)
δ
j,i
∂z
∂E
⎝
は
(1)
∑
=
∂E
j
⋅
(1)
⎛
ここで、
(1)
(2)
k
⋅
∂z
k
(2)
∂z
k
であり、
∂z
⎞
k
∂z
(1)
j
⋅
(1)
⎠
j
∂w
(1)
j,i
(2)
k
∂z
(2)
(1)
は
w
(2)
k,j
′
⋅ f (z
(1)
j
)
ですから、以下のように簡単に記述するこ
j
k
とができます。
∂E
= (∑ δ
∂w
⋅ w
(2)
k,j
′
⋅ f (z
(1)
j
)) ⋅ μ
(1)
j,i
= δ
(1)
j
j,i
∂ (∑
k
∂E
∂z
(2)
k
(1)
2
0
1
2
(f (z
(2)
k
2
) − tk ) )
=
∂z
(2)
0
これがバックプロパゲーションですが、このままでは実装することはできません。 そこで、実際に
かっせ化関数を導⼊して実装に必要な内容を検討していきます。
(C) 2016, Morning Project Samurai
Page 51
MPS - Yokohama
8.4. 3 層 NN を作る
バックプロパゲーションは情報伝達のためのアルゴリズムであって、バックプロパゲーションで学
習されるわけではないということを思い出してください。 つまり、バックプロパゲーションで伝搬さ
れた結果を元に学習していきます。 ここでは実際に学習するための⼿法を検討していきます。
第 2 層は以下のようになっています。
∂E
∂z
∂E
=
∂w
(2)
⋅
∂z
k,j
zk
=
(2)
(2)
k
∂w
k,j
= δ
(2)
k
(2)
⋅ w
(2)
k,j
k,j
∑ w k,j ⋅ y
(2)
j
j
同様に第 1 層の状態は以下のようになっています。
∂E
∂z
∂E
=
∂w
(1)
⋅
∂z
j,i
(1)
(1)
j,i
∂z
∂E
∑
=
⎝
⋅
∂z
k
∂E
∂w
j
∂w
j
⎛
=
(1)
(∑ δ
(2)
(2)
⋅ w
k
(1)
∂z
k
(2)
k,j
(2)
⎞
k
∂z
⋅
(1)
⎠
∂w
j
′
⋅ f (z
(1)
j
(1)
j
(1)
j,i
)) ⋅ μ
(1)
j,i
= δ
(1)
j
j,i
∂ (∑
∂E
∂z
2
1
k
2
(f (z
(2)
k
2
) − tk ) )
=
∂z
0
ここで欲しい情報は 1 層⽬の重み
(2)
0
w
(1)
が変化した時のエラー
E
の変化量
∂E
(1)
(⼀般化すると
∂w
0,0
∂E
(1)
∂w
)なので、 w0,0 , ( wj,i ) になります。
(1)
(1)
j,i
8.5. 2 層⽬の状態
2 層⽬の状態
z
(2)
z
(2)
が変化した時のエラー
が変化した時のエラー
E
の変化量
E
∂E
(2)
の変化量
を考えます。
∂w
k,j
述できます。
∂E
=
∂w
Page 52
(2)
k,j
∂z
∂E
⋅
∂z
(2)
k,j
(2)
k
∂w
(2)
= δ
(2)
k
⋅ w
(2)
k,j
k,j
(C) 2016, Morning Project Samurai
∂E
(2)
∂w
k,j
は以下のように記
MPS - Yokohama
エラー
は⼆乗誤差を⽤いていますので、これを元に紐解いていきます。
E
1
(y
E =
2
このエラー
E
を
− tk )
k
z
で偏微分します。
(2)
1
∂
∂E
2
(2)
2
(y
(2)
k
2
− tk )
=
∂z
ここで
y
(2)
∂z
k
(2)
= f (z
k
(2)
k
′
f (x(t)) = f (x(t)) ⋅ x (t)
1
∂E
2
k
です。 合成関数の微分を⾏って⾏きますが、合成関数の微分は
)
′
∂
(2)
(y
という式で表すことができます。
(2)
k
2
− tk )
∂y
=
∂z
さらに
y
(2)
⋅
(2)
∂y
k
= f (z
k
(2)
k
1
⋅ 2 ⋅ (y
2
y
(2)
k
)
(2)
k
(2)
∂z
k
(2)
1
k
⋅ 2 ⋅ (y
=
2
(2)
(2)
k
∂z
∂y
k
k
− tk ) ⋅
∂z
(2)
k
= (y
(2)
(2)
k
′
− tk ) ⋅ f (z
(2)
k
)
k
1
) =
1+exp(−z
(2)
k
(2)
(2)
ということを⽤いると以下のように変形できます。
(2)
′
(2)
k
はフォワードプロパゲーションの際に既に分かっている既知の値です。 また活性化関数
− tk
f (z
− tk ) ⋅
k
はシグモイド関数を⽤いていますので、 f (z k
は
∂y
) = (1 − f (z
(2)
k
)) ⋅ f (z
(2)
k
)
です。 シグモイド関数を微分した値
)
のようにシンプルに表現できるということも既に学んできまし
た。
NOTE: シグモイド関数を使うと微分値は元の関数で表現できるため計算コストを低減することが
できのです。
シグモイド関数のような分数の微分は以下のようにして計算することができます。
′
g(x)
=
2
f (x)
つまり、これで
′
g (x) ⋅ f (x) − g(x) ⋅ f (x)
f (x)
を計算するのに必要な材料がそろったことになります。
∂E
∂z
(2)
k
8.6. 重み
z
(2)
k
w
= ∑
j
′
が変化した際の状態
(2)
w
(2)
k,j
′
⋅ y
(1)
j
′
z
(2)
の変化量
と記述できますので、これを
w
2
で偏微分した値は以下のようになります。
(C) 2016, Morning Project Samurai
Page 53
MPS - Yokohama
∂z
(2)
k
∂w
(1)
また、 yj
= y
(2)
(1)
j
k,j
は既にフォワードプロパゲーションの際に計算してあるので、既知の値で更新すること
ができる。
8.7. ⾏列への変換
次に実際に計算をするために⾏列に変換していきます。
∂E
(2)
= δ
(2)
⋅ y
k
∂w
(1)
j
を⾏列に直すと以下のようになります。
k,j
(2)
(2)
⎛ δ0
⋅ y
(1)
δ
(2)
⋅ y
(1)
δ
(2)
⋅ y
(1)
⎛ δ0
⎞
⎜
⎜
⎜
⎜ (2)
⎜ δ1
⎜
⎜
⎜
⎟
⎜
⎟
⎜
⎟
⎜
(1)
(1)
(1)
(2)
(1)
(2)
(1)
(2)
(1)
⎟(
) = ⎜ δ
y
y
y
⋅ y
δ
⋅ y
δ
⋅ y
⎟
⎜ 1
0
1
2
0
1
1
1
2
⎟
⎜
⎟
⎜
⎟
⎜
⎟
⎟
⎟
⎟
⎟
⎟
⎟
⎟
⎝
⎠
⎠
δ
(2)
⎝
2
δ
(2)
2
⋅ y
0
(1)
0
0
δ
(2)
2
⋅ y
1
(1)
1
0
δ
(2)
2
⋅ y
2
(1)
⎞
2
ベクトルを使った表現にすると以下のように記述することができます。
dE ⋅ dW = δ
8.8. バイアス
バイアス
w
(2)
k,b
w
⋅ b
(2)
k,b
(2)
⋅ y
⋅ b
T
について考える
を更新する場合にも
∂E
(2)
を考えることになります。
∂w
k,b
∂E
∂E
∂z
=
∂w
(2)
∂z
k,b
(2)
⋅
(2)
∂w
k
この中で既知でないものは
∂z
(2)
k,b
(2)
(2)
であるが、この値は
b
であり 1 です。 なぜなら、最初に
∂w
k,b
として
b
にかかる重みを
w
(2)
k,j
と定義したからです。
このことを⽤いると以下のように簡単に記述することができます。
∂E
∂E
=
∂w
(2)
k,b
∂z
(2)
⋅
∂z
(2)
k
= δ
∂w
(2)
(2)
k
⋅ b = δ
(2)
k
⋅ 1 = δ
(2)
k
k,b
ここまででプログラムに落とすための必要な情報が揃ったことになります。
Page 54
(C) 2016, Morning Project Samurai
b
を1
MPS - Yokohama
9. 勉強会記録
Table 9-1: 勉強会記録
回
1
2
3
4
5
6
7
8
9
10
11
⽇付
時間
2017 年 02
10:30 〜
⽉ 27 ⽇
12:30
2017 年 03
10:30 〜
⽉ 12 ⽇
12:30
2017 年 03
10:30 〜
⽉ 26 ⽇
12:30
2017 年 04
10:30 〜
⽉ 09 ⽇
12:30
2017 年 04
10:30 〜
⽉ 23 ⽇
12:30
2017 年 05
10:30 〜
⽉ 21 ⽇
12:30
2017 年 06
10:30 〜
⽉ 04 ⽇
12:30
2017 年 06
10:30 〜
⽉ 18 ⽇
12:30
2017 年 07
10:30 〜
⽉ 02 ⽇
12:30
2017 年 07
10:30 〜
⽉ 23 ⽇
12:30
2017 年 08
10:30 〜
⽉ 06 ⽇
12:30
場所
資料
さくら
数学的基礎から学ぶ Deep Learning (with
WORKS
Python) Vol. 124
情報科学専
数学的基礎から学ぶ Deep Learning (with
⾨学校
Python) Vol. 225
情報科学専
数学的基礎から学ぶ Deep Learning (with
⾨学校
Python) Vol. 326
情報科学専
数学的基礎から学ぶ Deep Learning (with
⾨学校
Python) Vol. 427
情報科学専
数学的基礎から学ぶ Deep Learning (with
⾨学校
Python) Vol. 528
情報科学専
数学的基礎から学ぶ Deep Learning (with
⾨学校
Python) Vol. 629
情報科学専
数学的基礎から学ぶ Deep Learning (with
⾨学校
Python) Vol. 730
情報科学専
数学的基礎から学ぶ Deep Learning (with
⾨学校
Python) Vol. 831
情報科学専
数学的基礎から学ぶ Deep Learning (with
⾨学校
Python) Vol. 932
情報科学専
数学的基礎から学ぶ Deep Learning (with
⾨学校
Python) Vol. 1033
情報科学専
⾨学校
Comming Soon
(C) 2016, Morning Project Samurai
Page 55
MPS - Yokohama
Links
1. https://mpsamurai.org/
2. https://twitter.com/hi_saito
3. https://twitter.com/search?f=tweets&vertical=default&q=%23mpsamiurai&src=typd
4. https://www.facebook.com/groups/445908938933917/
5. https://www.python.org/
6. http://www.lfd.uci.edu/~gohlke/pythonlibs/
7. https://ja.wikipedia.org/wiki/%E5%B8%B0%E7%B4%8D
8. https://ja.wikipedia.org/wiki/%E6%BC%94%E7%B9%B9
9. https://en.wikipedia.org/wiki/Haar-like_features
10. https://en.wikipedia.org/wiki/Scale-invariant_feature_transform
11. https://en.wikipedia.org/wiki/Histogram_of_oriented_gradients
12. http://www.minicomplexity.org/pubs/1943-mcculloch-pitts-bmb.pdf
13. http://www.image-net.org/challenges/LSVRC/2012/results.html
14. https://googleblog.blogspot.jp/2012/06/using-large-scale-brain-simulations-for.html
15. https://www.preferred-networks.jp/
16. http://chainer.org/
17. https://www.tensorflow.org/
18. http://www.numpy.org/
19. http://matplotlib.org/
20. https://ja.wikipedia.org/wiki/%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82
%AF%E3%83%88%E6%8C%87%E5%90%91%E3%83%97%E3%83%AD%E3%82%B0%E3
%83%A9%E3%83%9F%E3%83%B3%E3%82%B0
21. https://ja.wikipedia.org/wiki/TeX
22. https://ja.wikipedia.org/wiki/%E3%83%89%E3%83%8A%E3%83%AB%E3%83%89%E3%83
%BB%E3%82%AF%E3%83%8C%E3%83%BC%E3%82%B9
23. https://ja.wikipedia.org/wiki/%E3%82%B7%E3%82%B0%E3%83%A2%E3%82%A4%E3%83
%89%E9%96%A2%E6%95%B0
Page 56
(C) 2016, Morning Project Samurai
MPS - Yokohama
24. http://www.slideshare.net/mpsamurai/deep-learning-with-python-vol-1
25. http://www.slideshare.net/mpsamurai/deep-learning-with-python-vol-2
26. http://www.slideshare.net/mpsamurai/deep-learning-with-python-vol-3
27. http://www.slideshare.net/mpsamurai/deep-learning-with-python-vol-4
28. http://www.slideshare.net/mpsamurai/mpsy20160423
29. http://www.slideshare.net/mpsamurai/deep-learning-with-python-vol-6
30. http://www.slideshare.net/mpsamurai/deep-learning-with-python-vol-7
31. http://www.slideshare.net/mpsamurai/deep-learning-with-python-vol-8
32. http://www.slideshare.net/mpsamurai/deep-learning-with-python-vol-9
33. http://www.slideshare.net/mpsamurai/deep-learning-with-python-vol-10
(C) 2016, Morning Project Samurai
Page 57