Deep Learningと他の 分類器をRで比べてみよう 
株式会社リクルートコミュニケーションズ 
尾崎 隆 (Takashi J. OZAKI, Ph. D.) 
2014/12/6
今更ですが、自己紹介を… 
ブログやってます 
2014/12/6 
1
ついでに、宣伝を… 
夏に本出しました(もうそろそろ売り切った気がしないでもない) 
2014/12/6 
2
2014/12/6 
3 
1 
Deep Learningって何ぞ
2014/12/6 
4 
えーと、
2014/12/6 
5 
他にもっといい資料あるし 
そっち見た方が良いのでは
2014/12/6 
6 
他にもっといい資料あるし 
そっち見た方が良いのでは
2014/12/6 
7 
一応説明します…
まずは元となったパーセプトロンや3層NN… 
2014/12/6 
8 
参考:http://www.slideshare.net/nlab_utokyo/deep-learning-40959442 
f 
x1 
x2 
x3 
単純パーセプトロン 
単層&線形識別関数 
3層ニューラルネットワーク 
フィードフォワード 
バックプロパゲーション
まずは元となったパーセプトロンや3層NN… 
2014/12/6 
9 
参考:http://www.slideshare.net/nlab_utokyo/deep-learning-40959442 
f 
x1 
x2 
x3 
単純パーセプトロン 
単層&線形識別関数 
3層ニューラルネットワーク 
フィードフォワード 
バックプロパゲーション
Deep Learningとは… 
2014/12/6 
10 
参考:http://www.slideshare.net/nlab_utokyo/deep-learning-40959442 
N層ニューラルネットワーク 
フィードフォワード 
バックプロパゲーション
Deep Learningとは… 
2014/12/6 
11 
参考:http://www.slideshare.net/nlab_utokyo/deep-learning-40959442 
N層ニューラルネットワーク 
フィードフォワード 
バックプロパゲーション
Deep Learning ≒過学習を抑え、特徴表現を強化した多層NN 
2014/12/6 
12 
引用:http://www.slideshare.net/nlab_utokyo/deep-learning-40959442 
N層ニューラルネットワーク 
フィードフォワード 
バックプロパゲーション 
•層が深い方が、必要なパラメータ数が少なくて済むという理論 
•以前の多層NNは「入力に近い層の学習が遅い」「過学習しやすい」 という問題があったが、それを克服した結果がDeep Learning
汎化を支える技術:Pre-training (RBM / autoencoder) 
2014/12/6 
13 
参考:http://www.slideshare.net/nlab_utokyo/deep-learning-40959442 
N層ニューラルネットワーク 
1層ごとに教師なし学習で最適化して汎化性能を高める 
(でも現在では段々用いられなくなりつつあるらしい)
汎化を支える技術:Dropout 
2014/12/6 
14 
参考:http://www.slideshare.net/nlab_utokyo/deep-learning-40959442 
N層ニューラルネットワーク 
1学習サンプルごとにノードor結合をランダムに落とし、 
ランダムフォレストの樹選択のようにすることでsubnetwork間の 
相関を下げ、汎化性能を高める(L2正則化と同じ働きをする)
活性化関数にも工夫がある 
2014/12/6 
15 
引用:http://www.slideshare.net/nlab_utokyo/deep-learning-40959442
ちなみにDeep Learningの今の花形はConvNet 
2014/12/6 
16 
(LeCun et al., ISCAS, 2010) 
引用:http://www.slideshare.net/nlab_utokyo/deep-learning-40959442 
受容野の畳み込みとプーリングを繰り返す多層ネットワーク 
•段階的にスケールを変えながら局所的な相関パターンを抽出 
•プーリングにより局所的な平行移動不変性を確保
Deep Learningの実装 
フルスクラッチ 
根性のある人はどうぞ… 
Python系 
Theano, PyLearn2, etc… 
頑張ってコード組みましょう(今でも人気はある) 
Caffe (C++) 
いくつかの言語にバインディングあり(Python, Matlab…) 
ConvNetが実装されていて、最近では最も評価の高い実装 
http://www.slideshare.net/nlab_utokyo/deep-learning-40959442 
GPU対応 
H2O (Java) 
分散処理が可能でHadoop(Spark)上で動作するとか 
多くの言語にバインディングを持っていて便利 
GPU非対応? 
Rパッケージがある 
2014/12/6 
17
2014/12/6 
18 
2 とりあえずRでやってみよう
2014/12/6 
19 
…どうやるの?
2014/12/6 
20 
H2OならRでいけますよ!!!!!
H2OのRパッケージ{h2o}のインストールは簡単 
2014/12/6 
21 
> install.packages("h2o", + repos=(c("http://s3.amazonaws.com/h2o-release/h2o/master/1542/R", + getOption("repos")))) 
> library("h2o", lib.loc="C:/Program Files/R/R-3.0.2/library") 
要求されたパッケージ RCurl をロード中です 
要求されたパッケージ bitops をロード中です 
要求されたパッケージ rjson をロード中です 
要求されたパッケージ statmod をロード中です 
要求されたパッケージ survival をロード中です 
要求されたパッケージ splines をロード中です 
要求されたパッケージ tools をロード中です 
---------------------------------------------------------------------- 
Your next step is to start H2O and get a connection object (named 
'localH2O', for example): > localH2O = h2o.init() 
For H2O package documentation, ask for help: > ??h2o 
After starting H2O, you can use the Web UI at http://localhost:54321 
For more information visit http://docs.0xdata.com 
---------------------------------------------------------------------- 
# 以下略(これはWindows版のケースです)
H2OインスタンスをRから立ち上げる 
2014/12/6 
22 
> localH2O <- h2o.init(ip = "localhost", port = 54321, startH2O = TRUE, nthreads=-1) 
H2O is not running yet, starting it now... 
Note: In case of errors look at the following log files: 
C:¥Users¥XXX¥AppData¥Local¥Temp¥RtmpghjvGo/h2o_XXX_win_started_from_r.out 
C:¥Users¥XXX¥AppData¥Local¥Temp¥RtmpghjvGo/h2o_XXX_win_started_from_r.err 
java version "1.7.0_67“ 
Java(TM) SE Runtime Environment (build 1.7.0_67-b01) 
Java HotSpot(TM) 64-Bit Server VM (build 24.65-b04, mixed mode) 
Successfully connected to http://localhost:54321 
R is connected to H2O cluster: 
H2O cluster uptime: 1 seconds 506 milliseconds 
H2O cluster version: 2.7.0.1542 
H2O cluster name: H2O_started_from_R 
H2O cluster total nodes: 1 
H2O cluster total memory: 7.10 GB 
H2O cluster total cores: 8 
H2O cluster allowed cores: 8 
H2O cluster healthy: TRUE 
64bit推奨 (32bitだと警告が出る)
ブログでいつも用いている多変量サンプルデータセット 
2014/12/6 
23 
d1 
d2 
d3 
d4 
d5 
d6 
d7 
cv 
0 
0 
0 
1 
0 
0 
0 
0 
1 
0 
0 
1 
1 
0 
0 
0 
0 
1 
1 
1 
1 
1 
0 
1 
0 
0 
1 
1 
0 
1 
1 
1 
1 
0 
1 
0 
1 
1 
1 
1 
0 
0 
0 
1 
1 
1 
0 
0 
… 
… 
… 
… 
… 
… 
… 
… 
ダミー変数7カラム、二値学習ラベル1カラム
{h2o}ではデータは全てh2o.importFileを通すこと 
2014/12/6 
24 
> cfData <- h2o.importFile(localH2O, path = "conflict_sample_wo_header.txt") 
# ここで処理進捗のインジケータが入るが割愛 
> head(cfdata) 
C1 C2 C3 C4 C5 C6 C7 C8 
1 0 1 0 1 0 0 0 No 
2 0 0 1 1 0 0 1 No 
3 1 1 0 1 0 0 0 No 
4 0 1 1 1 0 0 1 No 
5 1 1 1 1 0 0 0 No 
6 0 0 0 1 0 0 1 No 
ブログ記事では「ヘッダを抜いたファイルを用意」としましたが、 
どうやらimportFileの方で勝手にヘッダの有無を判定してくれるようです
h2o.deeplearning + Leave-one-outによる性能確認 
2014/12/6 
25 
> res.err.dl<-rep(0,100) 
# 判定結果を格納する空ベクトルを作る 
> numlist<-sample(3000,100,replace=F) 
# CVのためにどのインデックスから抜いてくるかをランダムに指定する 
> for(i in 1:100){ 
+ cf.train <- cfData[-numlist[i],] 
+ cf.test <- cfData[numlist[i],] 
+ # 学習データとテストデータに分割 
+ res.dl <- h2o.deeplearning(x = 1:7, y = 8, data = cf.train, 
+ activation = "Tanh",hidden=rep(20,2)) 
+ pred.dl <- h2o.predict(object=res.dl,newdata=cf.test[,-8]) 
+ # Deep Learningによる学習と予測 
+ pred.dl.df <- as.data.frame(pred.dl) 
+ test.dl.df <- as.data.frame(cf.test) 
+ # 予測結果の整形 
+ res.err.dl[i] <- ifelse(as.character(pred.dl.df[1,1]) 
+ ==as.character(test.dl.df[1,8]),0,1) 
+ # 結果の格納-正解なら0, 不正解なら1の値が入る 
+ } 
> sum(res.err.dl) 
[1] 5 # この和が不正解の回数(100回中) 
参考:http://www.albert2005.co.jp/analyst_blog/?p=1189
h2o.deeplearning + Leave-one-outによる性能確認 
2014/12/6 
26 
> res.err.dl<-rep(0,100) 
# 判定結果を格納する空ベクトルを作る 
> numlist<-sample(3000,100,replace=F) 
# CVのためにどのインデックスから抜いてくるかをランダムに指定する 
> for(i in 1:100){ 
+ cf.train <- cfData[-numlist[i],] 
+ cf.test <- cfData[numlist[i],] 
+ # 学習データとテストデータに分割 
+ res.dl <- h2o.deeplearning(x = 1:7, y = 8, data = cf.train, 
+ activation = "Tanh",hidden=rep(20,2)) 
+ pred.dl <- h2o.predict(object=res.dl,newdata=cf.test[,-8]) 
+ # Deep Learningによる学習と予測 
+ pred.dl.df <- as.data.frame(pred.dl) 
+ test.dl.df <- as.data.frame(cf.test) 
+ # 予測結果の整形 
+ res.err.dl[i] <- ifelse(as.character(pred.dl.df[1,1]) 
+ ==as.character(test.dl.df[1,8]),0,1) 
+ # 結果の格納-正解なら0, 不正解なら1の値が入る 
+ } 
> sum(res.err.dl) 
[1] 5 # この和が不正解の回数(100回中)
2014/12/6 
27 
h2o.deeplearningは 
パラメータが多い…
パッとすぐいじれるh2o.deeplearningのパラメータ引数 
activation 
肝心要の活性化(閾値)関数 
3種類+Dropout有無の計6種類 
Tanh / TanhWithDropout 
Rectifier / RectifierWithDropout 
Maxout / MaxoutWithDropout 
デフォルトのDropout ratioは0.5 
これでL2正則化効果が最大になる(Baldi, NIPS 2013) 
hidden 
隠れ層の数とユニット数をベクトルで与える 
例えばc(10,20,10)とか、rep(20,5)とか 
epochs 
繰り返し計算回数 
100回とか200回とか 
2014/12/6 
28
h2o.deeplearning + Leave-one-outによる性能確認 
サンプルサイズ3000、7次元素性なので軽めの設定 
そもそもDeep Learningするような内容じゃねーし 
activation 
TanhでDropoutなし 
他の関数だと訳の分かんない結果になった。。。 
hidden 
20ユニット×2層 
7次元しかないのであまりユニット数増やしても効かない 
ちなみに層数増やしたら逆に悪化した。。。 
2014/12/6 
29 
+ res.dl <- h2o.deeplearning(x = 1:7, y = 8, data = cf.train, 
+ activation = "Tanh",hidden=rep(20,2))
h2o.deeplearning + Leave-one-outによる性能確認 
2014/12/6 
30 
> res.err.dl<-rep(0,100) 
# 判定結果を格納する空ベクトルを作る 
> numlist<-sample(3000,100,replace=F) 
# CVのためにどのインデックスから抜いてくるかをランダムに指定する 
> for(i in 1:100){ 
+ cf.train <- cfData[-numlist[i],] 
+ cf.test <- cfData[numlist[i],] 
+ # 学習データとテストデータに分割 
+ res.dl <- h2o.deeplearning(x = 1:7, y = 8, data = cf.train, 
+ activation = "Tanh",hidden=rep(20,2)) 
+ pred.dl <- h2o.predict(object=res.dl,newdata=cf.test[,-8]) 
+ # Deep Learningによる学習と予測 
+ pred.dl.df <- as.data.frame(pred.dl) 
+ test.dl.df <- as.data.frame(cf.test) 
+ # 予測結果の整形 
+ res.err.dl[i] <- ifelse(as.character(pred.dl.df[1,1]) 
+ ==as.character(test.dl.df[1,8]),0,1) 
+ # 結果の格納-正解なら0, 不正解なら1の値が入る 
+ } 
> sum(res.err.dl) 
[1] 5 # この和が不正解の回数(100回中)  正答率95% 
※100回CVに絞ったのはJava VMがOOMで落ちたため…
ちなみにsvm{e1071}で同じことをやると… 
2014/12/6 
31 
> library(e1071) 
> d<-read.table("conflict_sample.txt", header=TRUE, quote="¥"") 
> res.err.svm<-rep(0,100) 
> numlist<-sample(3000,100,replace=F) 
> for(i in 1:100){ 
+ cf.train <- d[-numlist[i],] 
+ cf.test <- d[numlist[i],] 
+ res.svm <- svm(cv~.,cf.train) 
+ pred.svm <- predict(res.svm,newdata=cf.test[,-8]) 
+ res.err.svm[i] <- ifelse(pred.svm==cf.test[,8], 0, 1) 
+ } 
> sum(res.err.svm) 
[1] 7  正答率93% 
とりあえずSVMよりは優秀っぽい
ならば、他の分類器と比較してみると… 
2014/12/6 
32
ならば、他の分類器と比較してみると… 
2014/12/6 
33 
※ランダム抽出なのでスコアは変動し得ます 
一応トップ
2014/12/6 
34 
3 
Rで決定境界を描いてみよう
昔こんなことをやりました 
2014/12/6 
35 
左:シンプルXORパターン 
右:オーバーラップあり 
複雑XORパターン
同じことをh2o.deeplearningでやってみる 
2014/12/6 
36 
> xorc <- read.table("xor_complex.txt", header=T) 
> xors <- read.table("xor_simple.txt", header=T) 
> library(h2o) 
> localH2O <- h2o.init(ip = "localhost", port = 54321, 
+ startH2O = TRUE, nthreads=-1) 
> xorcData<-h2o.importFile(localH2O,path="xor_complex_wo_header.txt") 
> xorsData<-h2o.importFile(localH2O,path="xor_simple_wo_header.txt") 
> pgData<-h2o.importFile(localH2O,path="pgrid_wo_header.txt") 
> res.dl<-h2o.deeplearning(x=1:2,y=3,data=xorsData,classification=T, 
+ activation="Tanh",hidden=c(10,10),epochs=20) 
> prd.dl<-h2o.predict(res.dl,newdata=pgData) 
> prd.dl.df<-as.data.frame(prd.dl) 
> plot(xors[,-3],pch=19,col=c(rep('blue',50),rep('red',50)), 
+ cex=3,xlim=c(-4,4),ylim=c(-4,4), main="Tanh, (10,10)") 
> par(new=T) 
> contour(px,py,array(prd.dl.df[,1],dim=c(length(px),length(py))), 
+ xlim=c(-4,4),ylim=c(-4,4),col="purple",lwd=3,drawlabels=F) 
出典:http://tjo.hatenablog.com/entry/2014/11/07/190314
とりあえずパラメータをいじってみる 
activation 
Tanh / TanhWithDropout 
これだと普通のNNと同じ予感 
Rectifier / RectifierWithDropout 
Deep Learningならではだが動くかどうか不安 
× Maxout 
この規模(100サンプル2次元)だと使い物にならない。。。 
hidden 
2層:c(10, 10) 
NNより1層多いだけで手堅いつもり 
3層:c(5, 5, 10) 
NNより2層多いのでちょっと不安 
2014/12/6 
37
2014/12/6 
38 
※冗長なので良さげな 
ものだけ紹介します
シンプルXORパターン 
2014/12/6 
39 
2層 
3層 
Tanh 
Rectifier
オーバーラップあり複雑XORパターン 
2014/12/6 
40 
2層 
3層 
Tanh 
Rectifier
これはどう解釈すればいいのか? 
汎化という意味では 
SVMみたいにはいかないが 
ランダムフォレストよりは良い感じ 
フィッティングという意味では 
SVMよりは良い気もするが 
ランダムフォレストみたいには追従しない感じ 
あえて言うなれば… 
パラメータ設定次第で好きなようにできる 
※それって元のNNと同じ気が(毒) 
2014/12/6 
41
2014/12/6 
42 
4 RでMNISTデータを 分類してみよう
MNISTとは 
手書き文字(数字)データセット 
機械学習系ではド定番 
フリーで公開されている 
基本的には前処理済み 
どんなデータなのか? 
米国勢調査局職員と高校生から集めた手書き数字のデータ 
これを28×28px, 255階調グレースケールに直したもの 
特徴量は784次元、学習ラベルは0~9の10クラス 
6万サンプルの学習データ+1万サンプルのテストデータ 
学習データとテストデータは書いた個人が異なるようになっている 
中にはヒトの目で見ても判別できないクソ汚い字もある 
どう見ても「0」にしか見えないのに「6」のラベルが振ってあったり 
つまり「ヒトの目視でも100%分類は難しい」データ 
2014/12/6 
43 
http://www.kaggle.com/c/digit-recognizer
ちなみに今年の大晦日までKaggleでコンペやってます 
2014/12/6 
44 
http://www.kaggle.com/c/digit-recognizer
Kaggleで配布されているMNISTデータのCSVの中身 
2014/12/6 
45 
label 
pixel0 
- 
pixel125 
pixel126 
pixel127 
pixel128 
pixel129 
- 
1 
0 
- 
0 
0 
0 
0 
0 
- 
0 
0 
- 
137 
192 
86 
72 
1 
- 
1 
0 
- 
141 
139 
3 
0 
0 
- 
4 
0 
- 
0 
0 
0 
0 
0 
- 
0 
0 
- 
254 
254 
254 
157 
30 
- 
0 
0 
- 
141 
202 
254 
193 
44 
- 
7 
0 
- 
0 
0 
0 
0 
0 
- 
3 
0 
- 
0 
0 
0 
0 
0 
- 
5 
0 
- 
0 
0 
0 
0 
0 
- 
… 
… 
… 
… 
… 
… 
… 
… 
… 
割とスパースな気もするが一旦置いておく 
これは基本的には全てほぼ同じ割合の均衡データ
ちなみに最初の16文字をRで描いた結果がこれ 
2014/12/6 
46 
label 
pixel0 
- 
pixel125 
pixel126 
pixel127 
pixel128 
pixel129 
- 
1 
0 
- 
0 
0 
0 
0 
0 
- 
0 
0 
- 
137 
192 
86 
72 
1 
- 
1 
0 
- 
141 
139 
3 
0 
0 
- 
4 
0 
- 
0 
0 
0 
0 
0 
- 
0 
0 
- 
254 
254 
254 
157 
30 
- 
0 
0 
- 
141 
202 
254 
193 
44 
- 
7 
0 
- 
0 
0 
0 
0 
0 
- 
3 
0 
- 
0 
0 
0 
0 
0 
- 
5 
0 
- 
0 
0 
0 
0 
0 
- 
… 
… 
… 
… 
… 
… 
… 
… 
…
2014/12/6 
47 
MNISTデータの準備
2通りとりあえずやってみました 
Kaggleコンペにそのまま参加する 
http://www.kaggle.com/c/digit-recognizer/data 
ちなみにベンチマークだと多分順位の半分もいきません 
Kaggleの学習データを適当に自前で二分する 
上記train.csvを持ってきて以下のような感じで分ける 
2014/12/6 
48 
> dat<-read.csv("train.csv", header=TRUE) 
> labels<-dat[,1] 
> test_idx<-c() 
> for (i in 1:10) { 
+ tmp1<-which(labels==(i-1)) 
+ tmp2<-sample(tmp1,1000,replace=F) 
+ test_idx<-c(test_idx,tmp2) 
+ } 
> test<-dat[test_idx,] 
> train<-dat[-test_idx,] 
> write.table(train,file="prac_train.csv", 
+ quote=F,col.names=T,row.names=F,sep=",") 
> write.table(test,file="prac_test.csv", 
+ quote=F,col.names=T,row.names=F,sep=",")
ベンチマークに指定されているのでランダムフォレストで試す 
2014/12/6 
49 
> prac_train <- read.csv("prac_train.csv") 
> prac_test <- read.csv("prac_test.csv") 
> library(randomForest) 
> prac_train$label<-as.factor(prac_train$label) 
> prac.rf<-randomForest(label~.,prac_train) 
> prd.rf<-predict(prac.rf,newdata=prac_test[,-1],type="response") 
> sum(diag(table(test_labels,prd.rf))) 
[1] 9658
ベンチマークに指定されているのでランダムフォレストで試す 
2014/12/6 
50 
> prac_train <- read.csv("prac_train.csv") 
> prac_test <- read.csv("prac_test.csv") 
> library(randomForest) 
> prac_train$label<-as.factor(prac_train$label) 
> prac.rf<-randomForest(label~.,prac_train) 
> prd.rf<-predict(prac.rf,newdata=prac_test[,-1],type="response") 
> sum(diag(table(test_labels,prd.rf))) 
[1] 9658  正答率96.58% 
ベンチマークの正答率 
意外と高いんですが(白目
h2o.deeplearningでのベストチューニング結果 
2014/12/6 
51 
> library(h2o) 
> localH2O <- h2o.init(ip = "localhost", port = 54321, 
+ startH2O = TRUE, nthreads=-1) 
> trData<-h2o.importFile(localH2O,path = "prac_train.csv") 
> tsData<-h2o.importFile(localH2O,path = "prac_test.csv") 
> res.dl <- h2o.deeplearning(x = 2:785, y = 1, data = trData, 
+ activation = "RectifierWithDropout", hidden=c(1024,1024,2048), 
+ epochs = 200, adaptive_rate = FALSE, rate=0.01, 
+ rate_annealing = 1.0e-6, + rate_decay = 1.0, momentum_start = 0.5, 
+ momentum_ramp = 42000*12, momentum_stable = 0.99, input_dropout_ratio = 0.2, 
+ l1 = 1.0e-5,l2 = 0.0,max_w2 = 15.0, initial_weight_distribution = "Normal", 
+ initial_weight_scale = 0.01, + nesterov_accelerated_gradient = T, 
+ loss = "CrossEntropy", fast_mode = T, diagnostics = T, 
+ ignore_const_cols = T, + force_load_balance = T) 
> pred.dl<-h2o.predict(object=res.dl,newdata=tsData[,-1]) 
> pred.dl.df<-as.data.frame(pred.dl) 
> sum(diag(table(test_labels,pred.dl.df[,1]))) 
[1] 9816 正答率98.16% 
Kaggle本番でも98.3%
Kaggle本番にsubmitしてみた 
2014/12/6 
52 
たった0.01086上がっただけで 
順位が70位も上がった…
ちなみに11/28現在のKaggle MNISTのLeaderboard 
2014/12/6 
53
ちなみに11/28時点のKaggle MNISTのLeaderboard 
2014/12/6 
54
弊グループの某Deep Learning実装エンジニア曰く 
2014/12/6 
55 
「MNISTで99%超えたかったら ConvNetは必須ですよ」
ということで 
2014/12/6 
56 
来年の今頃は 
ConvNetやってるかも? 
(※ただの願望) 
おしまい
ついでに宣伝 
2014/12/6 
57 
弊社主催で勉強会シリーズやります! http://atnd.org/users/190891 をチェック!

Deep Learningと他の分類器をRで比べてみよう in Japan.R 2014

  • 1.
    Deep Learningと他の 分類器をRで比べてみよう 株式会社リクルートコミュニケーションズ 尾崎 隆 (Takashi J. OZAKI, Ph. D.) 2014/12/6
  • 2.
  • 3.
  • 4.
    2014/12/6 3 1 Deep Learningって何ぞ
  • 5.
  • 6.
    2014/12/6 5 他にもっといい資料あるし そっち見た方が良いのでは
  • 7.
    2014/12/6 6 他にもっといい資料あるし そっち見た方が良いのでは
  • 8.
  • 9.
    まずは元となったパーセプトロンや3層NN… 2014/12/6 8 参考:http://www.slideshare.net/nlab_utokyo/deep-learning-40959442 f x1 x2 x3 単純パーセプトロン 単層&線形識別関数 3層ニューラルネットワーク フィードフォワード バックプロパゲーション
  • 10.
    まずは元となったパーセプトロンや3層NN… 2014/12/6 9 参考:http://www.slideshare.net/nlab_utokyo/deep-learning-40959442 f x1 x2 x3 単純パーセプトロン 単層&線形識別関数 3層ニューラルネットワーク フィードフォワード バックプロパゲーション
  • 11.
    Deep Learningとは… 2014/12/6 10 参考:http://www.slideshare.net/nlab_utokyo/deep-learning-40959442 N層ニューラルネットワーク フィードフォワード バックプロパゲーション
  • 12.
    Deep Learningとは… 2014/12/6 11 参考:http://www.slideshare.net/nlab_utokyo/deep-learning-40959442 N層ニューラルネットワーク フィードフォワード バックプロパゲーション
  • 13.
    Deep Learning ≒過学習を抑え、特徴表現を強化した多層NN 2014/12/6 12 引用:http://www.slideshare.net/nlab_utokyo/deep-learning-40959442 N層ニューラルネットワーク フィードフォワード バックプロパゲーション •層が深い方が、必要なパラメータ数が少なくて済むという理論 •以前の多層NNは「入力に近い層の学習が遅い」「過学習しやすい」 という問題があったが、それを克服した結果がDeep Learning
  • 14.
    汎化を支える技術:Pre-training (RBM /autoencoder) 2014/12/6 13 参考:http://www.slideshare.net/nlab_utokyo/deep-learning-40959442 N層ニューラルネットワーク 1層ごとに教師なし学習で最適化して汎化性能を高める (でも現在では段々用いられなくなりつつあるらしい)
  • 15.
    汎化を支える技術:Dropout 2014/12/6 14 参考:http://www.slideshare.net/nlab_utokyo/deep-learning-40959442 N層ニューラルネットワーク 1学習サンプルごとにノードor結合をランダムに落とし、 ランダムフォレストの樹選択のようにすることでsubnetwork間の 相関を下げ、汎化性能を高める(L2正則化と同じ働きをする)
  • 16.
    活性化関数にも工夫がある 2014/12/6 15 引用:http://www.slideshare.net/nlab_utokyo/deep-learning-40959442
  • 17.
    ちなみにDeep Learningの今の花形はConvNet 2014/12/6 16 (LeCun et al., ISCAS, 2010) 引用:http://www.slideshare.net/nlab_utokyo/deep-learning-40959442 受容野の畳み込みとプーリングを繰り返す多層ネットワーク •段階的にスケールを変えながら局所的な相関パターンを抽出 •プーリングにより局所的な平行移動不変性を確保
  • 18.
    Deep Learningの実装 フルスクラッチ 根性のある人はどうぞ… Python系 Theano, PyLearn2, etc… 頑張ってコード組みましょう(今でも人気はある) Caffe (C++) いくつかの言語にバインディングあり(Python, Matlab…) ConvNetが実装されていて、最近では最も評価の高い実装 http://www.slideshare.net/nlab_utokyo/deep-learning-40959442 GPU対応 H2O (Java) 分散処理が可能でHadoop(Spark)上で動作するとか 多くの言語にバインディングを持っていて便利 GPU非対応? Rパッケージがある 2014/12/6 17
  • 19.
    2014/12/6 18 2とりあえずRでやってみよう
  • 20.
  • 21.
  • 22.
    H2OのRパッケージ{h2o}のインストールは簡単 2014/12/6 21 > install.packages("h2o", + repos=(c("http://s3.amazonaws.com/h2o-release/h2o/master/1542/R", + getOption("repos")))) > library("h2o", lib.loc="C:/Program Files/R/R-3.0.2/library") 要求されたパッケージ RCurl をロード中です 要求されたパッケージ bitops をロード中です 要求されたパッケージ rjson をロード中です 要求されたパッケージ statmod をロード中です 要求されたパッケージ survival をロード中です 要求されたパッケージ splines をロード中です 要求されたパッケージ tools をロード中です ---------------------------------------------------------------------- Your next step is to start H2O and get a connection object (named 'localH2O', for example): > localH2O = h2o.init() For H2O package documentation, ask for help: > ??h2o After starting H2O, you can use the Web UI at http://localhost:54321 For more information visit http://docs.0xdata.com ---------------------------------------------------------------------- # 以下略(これはWindows版のケースです)
  • 23.
    H2OインスタンスをRから立ち上げる 2014/12/6 22 > localH2O <- h2o.init(ip = "localhost", port = 54321, startH2O = TRUE, nthreads=-1) H2O is not running yet, starting it now... Note: In case of errors look at the following log files: C:¥Users¥XXX¥AppData¥Local¥Temp¥RtmpghjvGo/h2o_XXX_win_started_from_r.out C:¥Users¥XXX¥AppData¥Local¥Temp¥RtmpghjvGo/h2o_XXX_win_started_from_r.err java version "1.7.0_67“ Java(TM) SE Runtime Environment (build 1.7.0_67-b01) Java HotSpot(TM) 64-Bit Server VM (build 24.65-b04, mixed mode) Successfully connected to http://localhost:54321 R is connected to H2O cluster: H2O cluster uptime: 1 seconds 506 milliseconds H2O cluster version: 2.7.0.1542 H2O cluster name: H2O_started_from_R H2O cluster total nodes: 1 H2O cluster total memory: 7.10 GB H2O cluster total cores: 8 H2O cluster allowed cores: 8 H2O cluster healthy: TRUE 64bit推奨 (32bitだと警告が出る)
  • 24.
    ブログでいつも用いている多変量サンプルデータセット 2014/12/6 23 d1 d2 d3 d4 d5 d6 d7 cv 0 0 0 1 0 0 0 0 1 0 0 1 1 0 0 0 0 1 1 1 1 1 0 1 0 0 1 1 0 1 1 1 1 0 1 0 1 1 1 1 0 0 0 1 1 1 0 0 … … … … … … … … ダミー変数7カラム、二値学習ラベル1カラム
  • 25.
    {h2o}ではデータは全てh2o.importFileを通すこと 2014/12/6 24 > cfData <- h2o.importFile(localH2O, path = "conflict_sample_wo_header.txt") # ここで処理進捗のインジケータが入るが割愛 > head(cfdata) C1 C2 C3 C4 C5 C6 C7 C8 1 0 1 0 1 0 0 0 No 2 0 0 1 1 0 0 1 No 3 1 1 0 1 0 0 0 No 4 0 1 1 1 0 0 1 No 5 1 1 1 1 0 0 0 No 6 0 0 0 1 0 0 1 No ブログ記事では「ヘッダを抜いたファイルを用意」としましたが、 どうやらimportFileの方で勝手にヘッダの有無を判定してくれるようです
  • 26.
    h2o.deeplearning + Leave-one-outによる性能確認 2014/12/6 25 > res.err.dl<-rep(0,100) # 判定結果を格納する空ベクトルを作る > numlist<-sample(3000,100,replace=F) # CVのためにどのインデックスから抜いてくるかをランダムに指定する > for(i in 1:100){ + cf.train <- cfData[-numlist[i],] + cf.test <- cfData[numlist[i],] + # 学習データとテストデータに分割 + res.dl <- h2o.deeplearning(x = 1:7, y = 8, data = cf.train, + activation = "Tanh",hidden=rep(20,2)) + pred.dl <- h2o.predict(object=res.dl,newdata=cf.test[,-8]) + # Deep Learningによる学習と予測 + pred.dl.df <- as.data.frame(pred.dl) + test.dl.df <- as.data.frame(cf.test) + # 予測結果の整形 + res.err.dl[i] <- ifelse(as.character(pred.dl.df[1,1]) + ==as.character(test.dl.df[1,8]),0,1) + # 結果の格納-正解なら0, 不正解なら1の値が入る + } > sum(res.err.dl) [1] 5 # この和が不正解の回数(100回中) 参考:http://www.albert2005.co.jp/analyst_blog/?p=1189
  • 27.
    h2o.deeplearning + Leave-one-outによる性能確認 2014/12/6 26 > res.err.dl<-rep(0,100) # 判定結果を格納する空ベクトルを作る > numlist<-sample(3000,100,replace=F) # CVのためにどのインデックスから抜いてくるかをランダムに指定する > for(i in 1:100){ + cf.train <- cfData[-numlist[i],] + cf.test <- cfData[numlist[i],] + # 学習データとテストデータに分割 + res.dl <- h2o.deeplearning(x = 1:7, y = 8, data = cf.train, + activation = "Tanh",hidden=rep(20,2)) + pred.dl <- h2o.predict(object=res.dl,newdata=cf.test[,-8]) + # Deep Learningによる学習と予測 + pred.dl.df <- as.data.frame(pred.dl) + test.dl.df <- as.data.frame(cf.test) + # 予測結果の整形 + res.err.dl[i] <- ifelse(as.character(pred.dl.df[1,1]) + ==as.character(test.dl.df[1,8]),0,1) + # 結果の格納-正解なら0, 不正解なら1の値が入る + } > sum(res.err.dl) [1] 5 # この和が不正解の回数(100回中)
  • 28.
    2014/12/6 27 h2o.deeplearningは パラメータが多い…
  • 29.
    パッとすぐいじれるh2o.deeplearningのパラメータ引数 activation 肝心要の活性化(閾値)関数 3種類+Dropout有無の計6種類 Tanh / TanhWithDropout Rectifier / RectifierWithDropout Maxout / MaxoutWithDropout デフォルトのDropout ratioは0.5 これでL2正則化効果が最大になる(Baldi, NIPS 2013) hidden 隠れ層の数とユニット数をベクトルで与える 例えばc(10,20,10)とか、rep(20,5)とか epochs 繰り返し計算回数 100回とか200回とか 2014/12/6 28
  • 30.
    h2o.deeplearning + Leave-one-outによる性能確認 サンプルサイズ3000、7次元素性なので軽めの設定 そもそもDeep Learningするような内容じゃねーし activation TanhでDropoutなし 他の関数だと訳の分かんない結果になった。。。 hidden 20ユニット×2層 7次元しかないのであまりユニット数増やしても効かない ちなみに層数増やしたら逆に悪化した。。。 2014/12/6 29 + res.dl <- h2o.deeplearning(x = 1:7, y = 8, data = cf.train, + activation = "Tanh",hidden=rep(20,2))
  • 31.
    h2o.deeplearning + Leave-one-outによる性能確認 2014/12/6 30 > res.err.dl<-rep(0,100) # 判定結果を格納する空ベクトルを作る > numlist<-sample(3000,100,replace=F) # CVのためにどのインデックスから抜いてくるかをランダムに指定する > for(i in 1:100){ + cf.train <- cfData[-numlist[i],] + cf.test <- cfData[numlist[i],] + # 学習データとテストデータに分割 + res.dl <- h2o.deeplearning(x = 1:7, y = 8, data = cf.train, + activation = "Tanh",hidden=rep(20,2)) + pred.dl <- h2o.predict(object=res.dl,newdata=cf.test[,-8]) + # Deep Learningによる学習と予測 + pred.dl.df <- as.data.frame(pred.dl) + test.dl.df <- as.data.frame(cf.test) + # 予測結果の整形 + res.err.dl[i] <- ifelse(as.character(pred.dl.df[1,1]) + ==as.character(test.dl.df[1,8]),0,1) + # 結果の格納-正解なら0, 不正解なら1の値が入る + } > sum(res.err.dl) [1] 5 # この和が不正解の回数(100回中)  正答率95% ※100回CVに絞ったのはJava VMがOOMで落ちたため…
  • 32.
    ちなみにsvm{e1071}で同じことをやると… 2014/12/6 31 > library(e1071) > d<-read.table("conflict_sample.txt", header=TRUE, quote="¥"") > res.err.svm<-rep(0,100) > numlist<-sample(3000,100,replace=F) > for(i in 1:100){ + cf.train <- d[-numlist[i],] + cf.test <- d[numlist[i],] + res.svm <- svm(cv~.,cf.train) + pred.svm <- predict(res.svm,newdata=cf.test[,-8]) + res.err.svm[i] <- ifelse(pred.svm==cf.test[,8], 0, 1) + } > sum(res.err.svm) [1] 7  正答率93% とりあえずSVMよりは優秀っぽい
  • 33.
  • 34.
    ならば、他の分類器と比較してみると… 2014/12/6 33 ※ランダム抽出なのでスコアは変動し得ます 一応トップ
  • 35.
    2014/12/6 34 3 Rで決定境界を描いてみよう
  • 36.
    昔こんなことをやりました 2014/12/6 35 左:シンプルXORパターン 右:オーバーラップあり 複雑XORパターン
  • 37.
    同じことをh2o.deeplearningでやってみる 2014/12/6 36 > xorc <- read.table("xor_complex.txt", header=T) > xors <- read.table("xor_simple.txt", header=T) > library(h2o) > localH2O <- h2o.init(ip = "localhost", port = 54321, + startH2O = TRUE, nthreads=-1) > xorcData<-h2o.importFile(localH2O,path="xor_complex_wo_header.txt") > xorsData<-h2o.importFile(localH2O,path="xor_simple_wo_header.txt") > pgData<-h2o.importFile(localH2O,path="pgrid_wo_header.txt") > res.dl<-h2o.deeplearning(x=1:2,y=3,data=xorsData,classification=T, + activation="Tanh",hidden=c(10,10),epochs=20) > prd.dl<-h2o.predict(res.dl,newdata=pgData) > prd.dl.df<-as.data.frame(prd.dl) > plot(xors[,-3],pch=19,col=c(rep('blue',50),rep('red',50)), + cex=3,xlim=c(-4,4),ylim=c(-4,4), main="Tanh, (10,10)") > par(new=T) > contour(px,py,array(prd.dl.df[,1],dim=c(length(px),length(py))), + xlim=c(-4,4),ylim=c(-4,4),col="purple",lwd=3,drawlabels=F) 出典:http://tjo.hatenablog.com/entry/2014/11/07/190314
  • 38.
    とりあえずパラメータをいじってみる activation Tanh/ TanhWithDropout これだと普通のNNと同じ予感 Rectifier / RectifierWithDropout Deep Learningならではだが動くかどうか不安 × Maxout この規模(100サンプル2次元)だと使い物にならない。。。 hidden 2層:c(10, 10) NNより1層多いだけで手堅いつもり 3層:c(5, 5, 10) NNより2層多いのでちょっと不安 2014/12/6 37
  • 39.
    2014/12/6 38 ※冗長なので良さげな ものだけ紹介します
  • 40.
  • 41.
  • 42.
    これはどう解釈すればいいのか? 汎化という意味では SVMみたいにはいかないが ランダムフォレストよりは良い感じ フィッティングという意味では SVMよりは良い気もするが ランダムフォレストみたいには追従しない感じ あえて言うなれば… パラメータ設定次第で好きなようにできる ※それって元のNNと同じ気が(毒) 2014/12/6 41
  • 43.
    2014/12/6 42 4RでMNISTデータを 分類してみよう
  • 44.
    MNISTとは 手書き文字(数字)データセット 機械学習系ではド定番 フリーで公開されている 基本的には前処理済み どんなデータなのか? 米国勢調査局職員と高校生から集めた手書き数字のデータ これを28×28px, 255階調グレースケールに直したもの 特徴量は784次元、学習ラベルは0~9の10クラス 6万サンプルの学習データ+1万サンプルのテストデータ 学習データとテストデータは書いた個人が異なるようになっている 中にはヒトの目で見ても判別できないクソ汚い字もある どう見ても「0」にしか見えないのに「6」のラベルが振ってあったり つまり「ヒトの目視でも100%分類は難しい」データ 2014/12/6 43 http://www.kaggle.com/c/digit-recognizer
  • 45.
  • 46.
    Kaggleで配布されているMNISTデータのCSVの中身 2014/12/6 45 label pixel0 - pixel125 pixel126 pixel127 pixel128 pixel129 - 1 0 - 0 0 0 0 0 - 0 0 - 137 192 86 72 1 - 1 0 - 141 139 3 0 0 - 4 0 - 0 0 0 0 0 - 0 0 - 254 254 254 157 30 - 0 0 - 141 202 254 193 44 - 7 0 - 0 0 0 0 0 - 3 0 - 0 0 0 0 0 - 5 0 - 0 0 0 0 0 - … … … … … … … … … 割とスパースな気もするが一旦置いておく これは基本的には全てほぼ同じ割合の均衡データ
  • 47.
    ちなみに最初の16文字をRで描いた結果がこれ 2014/12/6 46 label pixel0 - pixel125 pixel126 pixel127 pixel128 pixel129 - 1 0 - 0 0 0 0 0 - 0 0 - 137 192 86 72 1 - 1 0 - 141 139 3 0 0 - 4 0 - 0 0 0 0 0 - 0 0 - 254 254 254 157 30 - 0 0 - 141 202 254 193 44 - 7 0 - 0 0 0 0 0 - 3 0 - 0 0 0 0 0 - 5 0 - 0 0 0 0 0 - … … … … … … … … …
  • 48.
  • 49.
    2通りとりあえずやってみました Kaggleコンペにそのまま参加する http://www.kaggle.com/c/digit-recognizer/data ちなみにベンチマークだと多分順位の半分もいきません Kaggleの学習データを適当に自前で二分する 上記train.csvを持ってきて以下のような感じで分ける 2014/12/6 48 > dat<-read.csv("train.csv", header=TRUE) > labels<-dat[,1] > test_idx<-c() > for (i in 1:10) { + tmp1<-which(labels==(i-1)) + tmp2<-sample(tmp1,1000,replace=F) + test_idx<-c(test_idx,tmp2) + } > test<-dat[test_idx,] > train<-dat[-test_idx,] > write.table(train,file="prac_train.csv", + quote=F,col.names=T,row.names=F,sep=",") > write.table(test,file="prac_test.csv", + quote=F,col.names=T,row.names=F,sep=",")
  • 50.
    ベンチマークに指定されているのでランダムフォレストで試す 2014/12/6 49 > prac_train <- read.csv("prac_train.csv") > prac_test <- read.csv("prac_test.csv") > library(randomForest) > prac_train$label<-as.factor(prac_train$label) > prac.rf<-randomForest(label~.,prac_train) > prd.rf<-predict(prac.rf,newdata=prac_test[,-1],type="response") > sum(diag(table(test_labels,prd.rf))) [1] 9658
  • 51.
    ベンチマークに指定されているのでランダムフォレストで試す 2014/12/6 50 > prac_train <- read.csv("prac_train.csv") > prac_test <- read.csv("prac_test.csv") > library(randomForest) > prac_train$label<-as.factor(prac_train$label) > prac.rf<-randomForest(label~.,prac_train) > prd.rf<-predict(prac.rf,newdata=prac_test[,-1],type="response") > sum(diag(table(test_labels,prd.rf))) [1] 9658  正答率96.58% ベンチマークの正答率 意外と高いんですが(白目
  • 52.
    h2o.deeplearningでのベストチューニング結果 2014/12/6 51 > library(h2o) > localH2O <- h2o.init(ip = "localhost", port = 54321, + startH2O = TRUE, nthreads=-1) > trData<-h2o.importFile(localH2O,path = "prac_train.csv") > tsData<-h2o.importFile(localH2O,path = "prac_test.csv") > res.dl <- h2o.deeplearning(x = 2:785, y = 1, data = trData, + activation = "RectifierWithDropout", hidden=c(1024,1024,2048), + epochs = 200, adaptive_rate = FALSE, rate=0.01, + rate_annealing = 1.0e-6, + rate_decay = 1.0, momentum_start = 0.5, + momentum_ramp = 42000*12, momentum_stable = 0.99, input_dropout_ratio = 0.2, + l1 = 1.0e-5,l2 = 0.0,max_w2 = 15.0, initial_weight_distribution = "Normal", + initial_weight_scale = 0.01, + nesterov_accelerated_gradient = T, + loss = "CrossEntropy", fast_mode = T, diagnostics = T, + ignore_const_cols = T, + force_load_balance = T) > pred.dl<-h2o.predict(object=res.dl,newdata=tsData[,-1]) > pred.dl.df<-as.data.frame(pred.dl) > sum(diag(table(test_labels,pred.dl.df[,1]))) [1] 9816 正答率98.16% Kaggle本番でも98.3%
  • 53.
    Kaggle本番にsubmitしてみた 2014/12/6 52 たった0.01086上がっただけで 順位が70位も上がった…
  • 54.
  • 55.
  • 56.
    弊グループの某Deep Learning実装エンジニア曰く 2014/12/6 55 「MNISTで99%超えたかったら ConvNetは必須ですよ」
  • 57.
    ということで 2014/12/6 56 来年の今頃は ConvNetやってるかも? (※ただの願望) おしまい
  • 58.
    ついでに宣伝 2014/12/6 57 弊社主催で勉強会シリーズやります! http://atnd.org/users/190891 をチェック!