• 検索結果がありません。

http//umercalbra.org/lectures/deep-learg/ z l l-1 = f w l 1 z l 1 1 f x = 1 + e x x x > 0 f x = 0 x 0 z l l-1 = f w l 1 z l 1

N/A
N/A
Protected

Academic year: 2021

シェア "http//umercalbra.org/lectures/deep-learg/ z l l-1 = f w l 1 z l 1 1 f x = 1 + e x x x > 0 f x = 0 x 0 z l l-1 = f w l 1 z l 1"

Copied!
13
0
0

読み込み中.... (全文を見る)

全文

(1)

2018年度 MI/CS実験第二

匡 (MIコース)

「作ってわかる深層学習」

1回目スライド資料

ありがとうございます

はじめに

「深層学習でやってみた」はもう古い!

「深層学習を作ってみた」が熱い!

教科書レベルの数理を理解して、かつ

プログラムに落とし込む能力を鍛える

内容

深層学習のプログラムをC言語で一から書く

・パーセプトロン

・誤差逆伝播法

・自己符号化器

・手書き文字認識

スケジュール

第1回 (10/03): ガイダンス、ニューラルネット概論と肩慣らし

第2回 (10/08): 誤差逆伝播のミニ講義と実装

第3回 (10/10): 手書き文字認識のテスト

第4回 (10/15): 自己符号化器のミニ講義と実装

第5回 (10/17): 実装

第6回 (10/22): 実装

第7回 (10/24): 実装

参考文献

TODO: 本を持参する

実験の進め方

一人でやらない

ただしレポートは自分の言葉で書く

相談しながらやる

成績のつけ方

出席 + レポート

実験なので必ず出席する

誤差逆伝播まで → 可

手書き文字認識まで → 良

自己符号化器まで → 優

ボーナス課題もやる → 秀 (ただし出来映えによる)

提出場所と締切は後日メーリングリストで

(2)

メーリングリスト

http://numericalbrain.org/lectures/deep-learning/

研究室ホームページ 「講義関連」

「ニューラルネット概論」

これがニューラルネットだ!

z

i

(

l)

= f

#

j

w

ij

(

l−1)

z

(

j

l−1)

これがニューラルネットだ!

l-1のニューロンjの活動

結合重み (実数)

活性化関数

(正の実数)

f (x) =

1

1 +

e

−x

f (x) =

!

x x > 0

0

x ≤ 0

シグモイド関数

Rectified Linear Unit (ReLU)

活性化関数

z

i

(

l)

= f

#

j

w

ij

(

l−1)

z

(

j

l−1)

これがニューラルネットだ!

l-1のニューロンjの活動

結合重み (実数)

活性化関数

(正の実数)

順伝播 (Forward Propagation)

入力層のニューロンを活性化し、

出力層に向かって順番に活動を

伝播させる

逆伝播 (Backward Propagation)

出力層のニューロンにある値を

持たせ、入力層に向かって順番

にその値を伝播させる

(もしくはバックプロパゲーション)

(3)

「ニューラルネット概論」

以上。これくらい単純で無いとブームは来ない。

実装の仕方

色んな実装の仕方がある

「doubleと配列を生で使う」から「抽象化の鬼」まで

雛形 (skel.c) を用意しました (資料の付録A)

typedef struct { Layer *layer; Connection *connection; sfmt_t rng; int n; } Network;

typedef struct { Neuron *z; int n; } Layer;

typedef struct { Weight *w; int n_pre; int n_post; } Connection;

データ構造

typedef double Neuron, Weight;

ネットワークの作り方

void createNetwork ( Network *network, const int number_of_layers, const sfmt_t rng ) {

network -> layer = ( Layer * ) malloc ( number_of_layers * sizeof ( Layer ) );

network -> connection = ( Connection * ) malloc ( number_of_layers * sizeof ( Connection ) ); network -> n = number_of_layers;

network -> rng = rng; }

void deleteNetwork ( Network *network ) {

free ( network -> layer ); free ( network -> connection ); }

層の作り方

void createLayer ( Network *network, const int layer_id, const int number_of_neurons ) {

Layer *layer = &network -> layer [ layer_id ]; layer -> n = number_of_neurons;

layer -> z = ( Neuron * ) malloc ( number_of_neurons * sizeof ( Neuron ) ); for ( int i = 0; i < layer -> n; i++) { layer -> z [ i ] = 0.; } }

void deleteLayer ( Network *network, const int layer_id ) {

Layer *layer = &network -> layer [ layer_id ]; free ( layer -> z );

}

層の作り方

void createLayer ( Network *network, const int layer_id, const int number_of_neurons ) {

Layer *layer = &network -> layer [ layer_id ]; layer -> n = number_of_neurons;

layer -> z = ( Neuron * ) malloc ( number_of_neurons * sizeof ( Neuron ) ); for ( int i = 0; i < layer -> n; i++) { layer -> z [ i ] = 0.; } }

void deleteLayer ( Network *network, const int layer_id ) {

Layer *layer = &network -> layer [ layer_id ]; free ( layer -> z );

}

void createLayer ( Network *network, const int layer_id, const int number_of_neurons ) {

Layer *layer = &network -> layer [ layer_id ]; layer -> n = number_of_neurons;

int bias = ( layer_id < network -> n - 1 ) ? 1 : 0; // 出力層以外はバイアスを用意 layer -> z = ( Neuron * ) malloc ( ( number_of_neurons + bias ) * sizeof ( Neuron ) ); for ( int i = 0; i < layer -> n; i++) { layer -> z [ i ] = 0.; }

if ( bias ) { layer -> z [ layer -> n ] = +1.; } // バイアス初期化 }

結合の作り方

void createConnection ( Network *network, const int layer_id, double ( *func ) ( Network *, const int, const int ) )

{

Connection *connection = &network -> connection [ layer_id ]; const int n_pre = network -> layer [ layer_id ] . n + 1; // +1はバイアスの分

const int n_post = ( layer_id == network -> n - 1 ) ? 1 : network -> layer [ layer_id + 1 ] . n; connection -> w = ( Weight * ) malloc ( n_pre * n_post * sizeof ( Weight ) );

for ( int i = 0; i < n_post; i++ ) { for ( int j = 0; j < n_pre; j++ ) {

connection -> w [ j + n_pre * i ] = func ( network, i, j ); }

}

connection -> n_pre = n_pre; connection -> n_post = n_post; }

void deleteConnection ( Network *network, const int layer_id ) {

Connection *connection = &network -> connection [ layer_id ]; free ( connection -> w );

}

(4)

後はmain()を作る

double all_to_all ( Network *n, const int i, const int j ) { return 1.; } int main ( void )

{ sfmt_t rng;

sfmt_init_gen_rand ( &rng, getpid ( ) ); // 作る Network network; createNetwork ( &network, 3, rng ); createLayer ( &network, 0, 2 ); createLayer ( &network, 1, 2 ); createLayer ( &network, 2, 1 );

createConnection ( &network, 0, all_to_all ); createConnection ( &network, 1, all_to_all ); // 消す deleteConnection ( &network, 1 ); deleteConnection ( &network, 0 ); deleteLayer ( &network, 2 ); deleteLayer ( &network, 1 ); deleteLayer ( &network, 0 ); deleteNetwork ( &network ); return 0; }

これで一応動く

順伝播のさせ方

void forwardPropagation ( Network *network, double ( *activation ) ( double ) ) {

for ( int i = 0; i < network -> n - 1; i++ ) { Layer *l_pre = &network -> layer [ i ]; Layer *l_post = &network -> layer [ i + 1 ]; Connection *c = &network -> connection [ i ]; for ( int j = 0; j < c -> n_post; j++ ) { Neuron u = 0.;

for ( int k = 0; k < c -> n_pre; k++ ) {

u += ( c -> w [ k + c -> n_pre * j ] ) * ( l_pre -> z [ k ] ); } l_post -> z [ j ] = activation ( u ); } } }

double sigmoid ( double x ) { return 1. / ( 1. + exp ( - x ) ); } :

:

Neuron x [] = { 0., 1. }; setInput ( &network, x );

forwardPropagation ( &network, sigmoid ); :

void setInput ( Network *network, Neuron x [ ] ) {

Layer *input_layer = &network -> layer [ 0 ]; for ( int i = 0; i < input_layer -> n; i++ ) { input_layer -> z [ i ] = x [ i ]; } }

z

(l) i

= f

#

j

w

(l−1) ij

z

(l−1) j

動かしてみる

[ya000836@purple99 ~/dl]$ gcc -O3 -std=c99 -Wall -I SFMT-src-1.5.1 -D SFMT_MEXP=19937 -o skel skel.c SFMT-src-1.5.1/SFMT.c

[ya000836@purple99 ~/dl]$ ./skel [ya000836@purple99 ~/dl]$

レポート課題 1

ネットワークの状態を出力する関数dumpを作成せよ。

void dump ( Network * );

フォーマットは自由だが、少なくとも

・層の総数

・各層のニューロン数

・各層間の結合重み

・各層のニューロンの活動

は出力すること。

注: コードとMakefileは ya000836/dl/codeにある

以上

質問がなければCEDへGO!

(5)

2018年度 MI/CS実験第二

匡 (MIコース)

「作ってわかる深層学習」

2回目スライド資料

スケジュール

第1回 (10/03): ガイダンス、ニューラルネット概論と肩慣らし

第2回 (10/08): 誤差逆伝播のミニ講義と実装

第3回 (10/10): 手書き文字認識のテスト

第4回 (10/15): 自己符号化器のミニ講義と実装

第5回 (10/17): 実装

第6回 (10/22): 実装

第7回 (10/24): 実装

パーセプトロン

パーセプトロン

Rosenblat (1958)

パーセプトロン

Rosenblat (1958)

世界で最初のニューラルネット

第一次ブームの火付け役

3層構造 (入力・中間・出力)

教師付学習機械

教師信号

パーセプトロンの特徴

中間層に多数のニューロン

入力層∼中間層の結合は

スパースかつランダムで

固定

→ (教師付)学習

教師信号

中間層∼出力層の結合重みを

教師信号を使って変化させる

教師信号

教師付学習

文脈信号 (

x) と教師信号 (z)のペア

n種類

x

(i)

を入力層に入れると

z

(i)

を出力

するように重みを変える

→ (教師付)学習

誤差

を定義して、これを減らす

E =

!

n

1

2

"

"z

(teacher)

n

− z

(output)

n

"

"

2

D = {(x

(1)

, z

(1)

)

, · · · , (x

(

n)

, z

(

n)

)

}

ベクトル

学習ルール (パーセプトロン則)

E =

!

n

1

2

"

"z

(teacher)

n

− z

(output)

n

"

"

2

誤差

dw

(hidden)

dt

= −

∂E

∂w

(hidden)

計算する式

w

(hidden)

(

t + 1) = w

(hidden)

(

t) − η

∂E

∂w

(hidden)

= w

(hidden)

(

t) − η∇E

w

(hidden)

エポック数に

関して離散化

ベクトル

学習係数

w

(hidden)

(

t + 1) = w

(hidden)

(

t) − η

!

n

∂E

n

∂w

(hidden)

= w

(hidden)

(

t) − η

!

n

∇E

n,w

(hidden)

個々のサンプル

に関して書くと

E =

!

n

E

n

E

n

=

1

2

!

i

"

z

(teacher)n i

− z

(output)n i

#

2

(6)

学習ルール (パーセプトロン則)

w

(hidden)

(

t + 1) = w

(hidden)

(

t) − η

!

n

∂E

n

∂w

(hidden)

= w

(hidden)

(

t) − η

!

n

∇E

n,w

(hidden)

個々のサンプル

に関して書くと

E =

!

n

E

n

def

∂En ∂w0

..

.

∂En ∂wl−1

中間層∼出力層の結合一つ一つ

よって、任意の

w

ij

(hidden)

に対して、

を計算

∂E

n

∂w

ij

(hidden)

すれば良い。

∂E

n

∂w

ij

(hidden)

の計算

∂E

n

∂w

(hidden)

ij

=

∂E

n

∂z

(output)

n

i

∂z

(output)

n

i

∂w

(hidden)

ij

E

n

=

1

2

!

i

"

z

(teacher)n i

− z

(output)n i

#

2

∂E

n

∂z

(output)n i

= −

!

z

(teacher)n i

− z

(output)n i

"

z

(output)n i

= f

#

j

w

(hidden) ij

z

(hidden)n j

∂z (output)n i ∂w(hidden) ij = f′ ⎛ ⎝# j w(hidden) ij z (hidden)n j⎠ z(hidden)n j

f (x) =

1

1 +

e

−x

f

(

x) = f (x) (1 − f (x))

まとめると

∂E

n

∂w

hidden ij

= −

!

z

(teacher)n i

− z

(output)n i

"

z

(output)n i

!

1

− z

i(output)n

"

z

(hidden)n j

w

(hidden) ij

(

t + 1) = w

(hidden) ij

(

t) − η

!

n

∂E

n

∂w

(hidden) ij

= w

(hidden) ij

(

t) + η

!

n

"

z

(teacher)n i

− z

(output)i n

#

z

(output)n i

"

1

− z

(output)n i

#

z

(hidden)n j

となるので、更新式は

となる。

勾配降下法

という名前がついている

コード

Layer *output_layer = &network -> layer [ network -> n - 1 ]; Layer *hidden_layer = &network -> layer [ network -> n - 2 ]; Connection *c = &network -> connection [ network -> n - 2 ]; for ( int i = 0; i < c -> n_post; i++ ) {

for ( int j = 0; j < c -> n_pre; j++ ) { double o = output_layer -> z [ i ];

double d = ( z [ i ] - o ) * diff_activation ( o );

c -> dw [ j + c -> n_pre * i ] += Eta * d * ( hidden_layer -> z [ j ] ); } }

w

(hidden) ij

(

t + 1) = w

ij(hidden)

(

t) − η

!

n

∂E

n

∂w

(hidden) ij

= w

(hidden) ij

(

t) + η

!

n

"

z

(teacher)n i

− z

(output) n i

#

z

(output)n i

"

1

− z

(output)n i

#

z

(hidden)n j

double updateByPerceptronRule ( Network *network, Neuron z [ ],

( double ) ( *diff_activation ) ( double ) );

質問は?

例: XORの学習

x

1

x

0

z

0

0

0

0

1

1

1

0

1

1

1

0

1個

128個

2個

Network network; createNetwork ( &network, 3, rng ); createLayer ( &network, 0, 2 ); createLayer ( &network, 1, 128 ); createLayer ( &network, 2, 1 );

createConnection ( &network, 0, sparse_random ); createConnection ( &network, 1, uniform_random );

double uniform_random ( Network *n, const int i, const int j ) {

return 1. - 2. * sfmt_genrand_real2 ( &n -> rng ); }

double sparse_random ( Network *n, const int i, const int j ) {

return ( sfmt_genrand_real2 ( &n -> rng ) < 0.5 ) ? uniform_random ( n, i, j ) : 0.;

}

コード

void createConnection ( Network *network, const int layer_id, double ( *func ) ( Network *, const int, const int ) )

{

Connection *connection = &network -> connection [ layer_id ];

const int n_pre = network -> layer [ layer_id ] . n + 1; // +1はバイアスの分 const int n_post = ( layer_id == network -> n - 1 ) ? 1 : network -> layer [ layer_id + 1 ] . n;

connection -> w = ( Weight * ) malloc ( n_pre * n_post * sizeof ( Weight ) ); for ( int i = 0; i < n_post; i++ ) {

for ( int j = 0; j < n_pre; j++ ) {

connection -> w [ j + n_pre * i ] = func ( network, i, j ); }

}

connection -> dw = ( Weight * ) malloc ( n_pre * n_post * sizeof ( Weight ) ); for ( int i = 0; i < n_post; i++ ) {

for ( int j = 0; j < n_pre; j++ ) { connection -> dw [ j + n_pre * i ] = 0.; }

}

connection -> n_pre = n_pre; connection -> n_post = n_post; }

void deleteConnection ( Network *network, const int layer_id ) {

Connection *connection = &network -> connection [ layer_id ]; free ( connection -> w );

free ( connection -> dw ); }

Neuron x [ 4 ][ 2 ] = { { 0., 0. }, { 0., 1. }, { 1., 0. }, { 1., 1. } }; Neuron z [ 4 ][ 1 ] = { { 0. } , { 1. } , { 1. } , { 0.} };

const int number_of_training_data = 4; // Training

double error = 1.0; // arbitrary large number const double Epsilon = 0.001; // tolerant error rate int i = 0;

while ( error > Epsilon ) { error = 0.;

initializeDW ( &network );

for ( int j = 0; j < number_of_training_data; j++ ) {

//int k = ( int ) ( number_of_training_data * sfmt_genrand_real2 ( &rng ) );

int k = j;

setInput ( &network, x [ k ] ); forwardPropagation ( &network, sigmoid );

error += updateByPerceptronRule ( &network, z [ k ], diff_sigmoid ); }

updateW ( &network ); printf ( "%d %f\n", i, error ); i++;

}

fprintf ( stderr, "# of epochs = %d\n", i );

double diff_sigmoid ( double z ) { return z * ( 1. - z ); }

(7)

// Test

Layer *output_layer = &network . layer [ network. n - 1 ]; const int n = output_layer -> n;

for ( int i = 0; i < number_of_training_data; i++ ) { setInput ( &network, x [ i ] );

forwardPropagation ( &network, sigmoid ); for ( int j = 0; j < n; j++ ) {

fprintf ( stderr, "%f%s", output_layer -> z [ j ], ( j == n - 1 ) ? "\n" : " " );

} }

void initializeDW ( Network *network ) {

Connection *c = &network -> connection [ network -> n - 2 ]; for ( int i = 0; i < c -> n_post; i++ ) {

for ( int j = 0; j < c -> n_pre; j++ ) { c -> dw [ j + c -> n_pre * i ] = 0.; }

} }

void updateW ( Network *network ) {

Connection *c = &network -> connection [ network -> n - 2 ]; for ( int i = 0; i < c -> n_post; i++ ) {

for ( int j = 0; j < c -> n_pre; j++ ) {

c -> w [ j + c -> n_pre * i ] += c -> dw [ j + c -> n_pre * i ]; }

} }

コンパイルして実行

[ya000836@purple99 ~/dl]$ gcc -O3 -std=c99 -Wall -I SFMT-src-1.5.1 -D SFMT_MEXP=19937 -o perceptron perceptron.c SFMT-src-1.5.1/SFMT.c [ya000836@purple99 ~/dl]$ ./perceptron 0 0.879170 1 0.836272 2 0.766234 3 0.658244 4 0.543239 : 4302001 0.001000 4302002 0.001000 4302003 0.001000 4302004 0.001000 4302005 0.001000 # of epochs = 4302006 0.022023 0.977739 0.977538 0.022691

}

学習結果

}

エポック番号と誤差

誤差の減り方を見る

[ya000836@purple99 ~/dl]$ ./perceptron > perceptron.dat 0.022023 0.977739 0.977538 0.022691 [ya000836@purple99 ~/dl]$ gnuplot G N U P L O T

Version 4.6 patchlevel 6 last modified September 2014 Build System: Darwin x86_64

Copyright (C) 1986-1993, 1998, 2004, 2007-2014 Thomas Williams, Colin Kelley and many others gnuplot home: http://www.gnuplot.info faq, bugs, etc: type "help FAQ"

immediate help: type "help" (plot window: hit 'h') Terminal type set to 'x11'

gnuplot> plot 'perceptron.dat'

ボーナス課題 1

2層のパーセプトロンでXORは学習できるか?

単純パーセプトロン

学習できる→具体的にネットワークを呈示せよ

学習できない→なぜなのか理由を考察せよ

ヒント: 「線形分離」についてググれ

色々試すこと

・中間層のニューロン数を変える

・収束までのエポック数を調べる

多層パーセプトロン

多層パーセプトロン

XORのためには中間層のニューロンは何個必要か?

2個で必要十分

(8)

パーセプトロンの問題

中間層にたくさんのニューロンが必要

→ 入力信号を区別可能にするため

解決策:

入力層∼中間層の結合も変化させる

→誤差逆伝播

誤差逆伝播

w

i j

(l −1)

(t + 1) = w

i j

(l −1)

(t) − η

!

n

∂E

n

∂w

i j

(l −1)

∂E

n

∂w

i j

(l −1)

=

∂E

n

∂z

i

(l )

∂z

(l )

i

∂w

i j

(l −1)

l-1から層lへの結合の重みの更新式は同様に

上の層で決まる値

∂z

i(l )

∂w

i j(l −1)

= z

(l )i

!

1 − z

(l )i

"

z

(l −1) j

誤差逆伝播

∂E

n

∂z

(l ) i

= −

!

z

(teacher)n i

z

(l ) i

"

lが出力層の場合はパーセプトロン則と同じで

∂E

n

∂z

(l )

i

=

!

k

∂E

n

∂z

(l +1)

k

∂z

(l +1)

k

∂z

(l )

i

それ以外の場合は

さらに上の層で決まる値

誤差逆伝播

上の層から下の層に向かって順番に計算すれば、

∂E

n

∂z

(l +1)

k

は計算済み (出力層の場合は

∂En ∂z(l ) i = − ! z(teacher)n iz (l ) i "

)

∂E

n

∂z

(l )

i

=

!

k

∂E

n

∂z

(l +1)

k

∂z

(l +1)

k

∂z

(l )

i

(再掲)

z(l+1) k = f ! " i w(l) kiz (l) i #

∂z

(l +1)

k

∂z

(l )

i

= f

!

"

i

w

(l )

ki

z

(l )

i

#

w

(l )

ki

= z

k

(l +1)

$

1 − z

(l +1)

k

%

w

(l )

ki

ここで

かつ

fはシグモイド

誤差逆伝播

w

i j(l −1)

(t + 1) = w

i j(l −1)

(t) + η

!

n

∂E

n

∂z

(l )i

&

z

i(l )

&

1 − z

(l )i

'

z

j(l −1)

'

∂E

n

∂z

(l ) i

=

$

z

(teacher)n i

z

(l ) i

%

l

is output layer

&

k ∂En ∂z(l +1) k

z

(l +1) k

$

1 − z

(l +1)k

%

w

(l ) ki

otherwise

まとめると、

とってもきれいな式が導出できる

「デルタ」という名前がついている

質問は?

何層あってもこの方法は使える→多層パーセプトロン

コード

関数updateByBackPropagationを実装しよう

typedef double Neuron, Delta, Weight;

typedef struct { Neuron *z; Delta *delta; int n; } Layer;

void createLayer ( Network *network, const int layer_id, const int number_of_neurons )

{ :

layer -> delta = ( Delta * ) malloc ( ( number_of_neurons + bias ) * sizeof ( Delta ) );

for ( int i = 0; i < layer -> n; i++) { layer -> delta [ i ] = 0.; } if ( bias ) { layer -> delta [ layer -> n ] = 0.; } // バイアス初期化 }

1. デルタの定義を追加

void deleteLayer ( Network *network, const int layer_id ) {

:

free ( layer -> delta ); }

2. デルタの確保と初期化

コード

あとはperceptron.cの

updateByPerceptronRuleを

updateByBackPropagationに

変更する

レポート課題 2

色々試すこと

・中間層のニューロン数を変える (中間層2個でいいか?)

・収束までのエポック数を調べる

updateByBackPropagationを実装して上記を試せ

コードの雛形はdl/code/bp.cにある

(9)

手書き文字認識

XORはあまりにもtoy problemなので、もう少しましな何か

手書き文字認識

MNISTデータベース

・手書き文字画像のデータベース+ラベル付き

・画像は28x28ピクセル256階調グレースケール

・ラベルは 0 から 9 の数字 (そりゃそうだ)

詳しくは付録B

・60000個のトレーニングデータ

・10000個のテストデータ

必ずデータを分ける

データの読み書き

code/mnist.{c, h}を用意した。

code/mnist_test.cをまず試す。

code/mnist/以下にデータがあるのでフォルダ毎コピー。

make mnist_test

mkdir png

./mnist_test

./pngの下にpngファイルが作成される。

手書き文字のテスト

レポート課題 3

誤差逆伝播法を実装した3層のパーセプトロンで、

手書き文字の学習と認識を行え。

やり方はテキストを参照。

以下では多少補足を。

バッチ学習の問題点

E =

!

n

1

2

"

"z

(teacher)

n

− z

(output)

n

"

"

2

誤差 (再掲)

全トレーニングデータに関する和

XORのときは

n=4だった。

MNISTでは

n=60000。←計算が終わらない

学習が局所解に落ちる可能性が高い。

勾配降下法の性質

「最も良い解」はすごく少ない。

「そこそこ良い解」はたくさんある。

勾配降下法は初期値に依存するので、「最も良い解」

の近くから始めない限り「そこそこ良い解」に捕まる。

確率的勾配法とミニバッチ

確率的に勾配を降りることで、「そこそこ良い解」から

脱出できるようにする。

× 全トレーニングデータを使う

トレーニングデータからいくつかをランダムに選んで使う

(バッチ)

(ミニバッチ)

エポック毎にミニバッチを作り直す

ミニバッチのサイズをどうするかに依存

極端な例: サイズ 1 (1データ毎に重みを更新)

ミニバッチへの布石がここに…

while ( error > Epsilon ) { error = 0.;

initializeDW ( &network );

for ( int j = 0; j < number_of_training_data; j++ ) {

//int k = ( int ) ( number_of_training_data * sfmt_genrand_real2 ( &rng ) );

int k = j;

setInput ( &network, x [ k ] ); forwardPropagation ( &network, sigmoid );

error += updateByBackPropagation ( &network, z [ k ], diff_sigmoid ); }

:

while ( error > Epsilon ) { error = 0.;

initializeDW ( &network );

for ( int j = 0; j < MINI_BATCH_SIZE; j++ ) {

int k = ( int ) ( number_of_training_data * sfmt_genrand_real2 ( &rng ) );

setInput ( &network, x [ k ] ); forwardPropagation ( &network, sigmoid );

error += updateByBackPropagation ( &network, z [ k ], diff_sigmoid ); }

(10)

手書き文字のテスト

レポート課題 3

誤差逆伝播法を実装した3層のパーセプトロンで、

手書き文字の学習と認識を行え。

やり方はテキストを参照。

サイズ1のミニバッチでとりあえずやる。その後で

ミニバッチのサイズを色々変えてみる。

手書き文字のテスト

ボーナス課題 2

中間層のニューロンは何を表現しているか?

・入力層∼中間層の結合を可視化する。

・mnist_generate_png関数を参考にすると良い。

質問は?

(参考) バイアスとは何か

教科書的には

閾値

積和と和の計算が必要

2種類の更新式が必要

d θ

(l )

d t

= −

∂E

∂θ

(l )

d w

(l )

d t

= −

∂E

∂w

(l )

バイアスからの重みと考える

z

i

(l )

= f

#

j

w

i j

(l −1)

z

(l −1)

j

− θ

(l )

i

(11)

2018年度 MI/CS実験第二

匡 (MIコース)

「作ってわかる深層学習」

3回目スライド資料

スケジュール

第1回 (10/03): ガイダンス、ニューラルネット概論と肩慣らし

第2回 (10/08): 誤差逆伝播のミニ講義と実装

第3回 (10/10): 手書き文字認識のテスト

第4回 (10/15): 自己符号化器のミニ講義と実装

第5回 (10/17): 実装

第6回 (10/22): 実装

第7回 (10/24): 実装

自己符号化器

自己符号化器 (オートエンコーダ)

符号化

復号化

https://www.slideshare.net/ginrou799/ss-46355460 「フーリエ変換と画像圧縮」武田祐一

例: 画像圧縮

画像をうまく表現する基底を構成する

深層化と勾配消失問題

符号化

復号化

f

(x) =

1

1 + e

x

f

(x) = f (x) (1 − f (x))

< 1/4

逆伝播する度にデルタの値が指数的に小さくなる

深層化と勾配消失問題

ReLUはその点は性質がいい → 一気に普及

深層化と勾配消失問題

f

(x) =

!

x

x >

0

0

x ≤

0

f

(x) =

!

1

x >

0

0

x ≤

0

(12)

汎化と過学習

積層自己符号化器

あとはこれを繰り返せばいくらでも深くできる

コーディング

void copyConnection ( Network *network_src, int layer_id_src, Network *network_dst, int layer_id_dst )

void copyConnectionWithTranspose ( Network *network_src, int layer_id_src, Network *network_dst, int layer_id_dst );

double updateByBackPropagationPartial ( Network *network, Neuron z [ ], ( double ) ( *diff_activation ) ( double ) );

3つの関数を作成する

Network network; createNetwork ( &network1, 3, rng );

createLayer ( &network1, 0, MNIST_IMAGE_SIZE ); createLayer ( &network1, 1, 128 );

createLayer ( &network1, 2, MNIST_IMAGE_SIZE ); createConnection ( &network1, 0, uniform_random ); createConnection ( &network1, 1, uniform_random ); copyConnectionWithTranspose ( &network, 0, &network, 1 );

// Training

for ( int i = 0; i < MNIST_TRAINING_DATA_SIZE; i++ ) { initializeDW ( &network1 );

double error = 0.;

copyConnectionWithTranspose ( &network, 0, &network, 1 );

for ( int j = 0; j < 1; j++ ) {

//int k = ( int ) ( MNIST_TRAINING_DATA_SIZE * sfmt_genrand_real2 ( &rng ) );

int k = i; // Use all training data one by one sequentially setInput ( &network1, training_image [ k ] );

forwardPropagation ( &network1, sigmoid );

error += updateByBackPropagationPartial ( &network1, network1 . layer [ 0 ] . z, diff_sigmoid ); } updateW ( &network1 ); if (i % 100 == 0 ) { printf ( "%d %f\n", i, error ); } }

コーディング

Network network2; createNetwork ( &network2, 4, rng );

createLayer ( &network2, 0, MNIST_IMAGE_SIZE ); createLayer ( &network2, 1, 128 );

createLayer ( &network2, 2, 64 ); createLayer ( &network2, 3, 128 );

createConnection ( &network2, 0, uniform_random ); createConnection ( &network2, 1, uniform_random ); createConnection ( &network2, 2, uniform_random ); copyConnection ( &network1, 0, &network2, 0 );

copyConnectionWithTranspose ( &network2, 1, &network2, 2 ); deleteConnection ( &network1, 1 ); deleteConnection ( &network1, 0 ); deleteLayer ( &network1, 2 ); deleteLayer ( &network1, 1 ); deleteLayer ( &network1, 0 ); deleteNetwork ( &network1 );

コーディング

// Training

for ( int i = 0; i < MNIST_TRAINING_DATA_SIZE; i++ ) { initializeDW ( &network2 );

double error = 0.;

copyConnectionWithTranspose ( &network2, 1, &network2, 2 ); for ( int j = 0; j < 1; j++ ) {

//int k = ( int ) ( MNIST_TRAINING_DATA_SIZE * sfmt_genrand_real2 ( &rng ) );

int k = i; // Use all training data one by one sequentially setInput ( &network2, training_image [ k ] );

forwardPropagation ( &network2, sigmoid );

error += updateByBackPropagationPartial ( &network2, network2 . layer [ 1 ] . z, diff_sigmoid ); } updateW ( &network2 ); if (i % 100 == 0 ) { printf ( "%d %f\n", i, error ); } }

コーディング

最後にもう一度手書き文字認識

これがレポート課題4です

以上でこの実験は一通り終了

事前学習

ボーナス課題: 自由演技

色々用意しました

(13)

参照

関連したドキュメント

They proved that if Y is a (real or complex) rearrangement-invariant nonatomic function space on [0, 1] isometric to L p [0, 1] for some 1 ≤ p &lt; ∞ then the isometric isomorphism

A line bundle as in the right hand side of the definition of Cliff(X ) is said to contribute to the Clifford index and, among them, those L with Cliff(L) = Cliff(X) are said to

In this section, we establish a purity theorem for Zariski and etale weight-two motivic cohomology, generalizing results of [23]... In the general case, we dene the

We prove a continuous embedding that allows us to obtain a boundary trace imbedding result for anisotropic Musielak-Orlicz spaces, which we then apply to obtain an existence result

After that, applying the well-known results for elliptic boundary-value problems (without parameter) in the considered domains, we receive the asymptotic formu- las of the solutions

In the second section, we study the continuity of the functions f p (for the definition of this function see the abstract) when (X, f ) is a dynamical system in which X is a

Secondly, once we have established the solvability of SPDEs within the stochastic parabolic weighted Sobolev spaces H γ,q p,θ (O, T ) , we have to exploit the L q (L p ) –regularity

Global transformations of the kind (1) may serve for investigation of oscilatory behavior of solutions from certain classes of linear differential equations because each of