ディープラーニング学習メモ #4 誤差の逆伝搬

今日は誤差逆伝搬法(Backpropagation)について書いてみます。

Karpathy先生のCS231nの講義が秀逸すぎるのでそれを見れば十分です! (◍•ᴗ•◍)

これではあんまりなので特に覚えておきたいポイントをまとめてみようと思います。。

global勾配にlocal勾配を掛けて次のノードにエラーの誤差を伝搬させる

f:id:sanshonoki:20170321043543j:plain:w450

微分の連鎖律(チェインルール)です。

基本的な演算での伝搬を覚えよう

Add演算はそのまま誤差を伝搬させる

f:id:sanshonoki:20170322041057j:plain:w450

Mul演算は互いの値をクロスに掛けて誤差を伝搬させる

f:id:sanshonoki:20170322041124j:plain:w450

Max演算は値が大きい方へのみ誤差を伝搬させる

f:id:sanshonoki:20170322041153j:plain:w450

分岐ノードは誤差を加算する

f:id:sanshonoki:20170322050746j:plain:w450

RNNのhiddenノードも出力層からの誤差と次のRNNセルからの誤差が加算されます。(hは次のRNNセルへの入力でもあるため)

f:id:sanshonoki:20170322050844j:plain:w450

ベクトルの場合も同じ

computational graph network layer graph
f:id:sanshonoki:20170323051220j:plain:w400 f:id:sanshonoki:20170323051243j:plain:w200

入力がベクトルの場合も同じです。ただ、行列(W)の次元を考慮する必要があります。 掛け算するために転置(T)をしたり、掛ける順番を考慮しないと怒られます..。

ポイント
  • あるノードでの順方向(X)と逆方向(dX)の次元は同じ(当たり前だけど)
  • 出力されるべき次元に合わせて転置や掛ける順番を考える (紙に書けというアドバイスをよく見かける。地道に慣れろということ)
  • この例では W は (outsize, insize) になっているが実際のフレームワークでは W は基本的に (insize, outsize) という次元になる。バッチ単位で処理するため

個人的には computational グラフで考えると誤差の伝搬が計算しやすいです。

バッチ単位で考えたとき

f:id:sanshonoki:20170323051256j:plain:w300

このようにバッチ単位でまとめて行列計算したいときは W は (insize, outsize) となります。 また、WX ではなく D = XW と掛け算します。

今回はここまでです。 マウスで文字を書くのつらい.. (ノ゚ο゚)ノ

ディープラーニング学習メモ #3 誤差と微分

誤差関数の最小化問題

機械学習が何をやっているか、、一言で言えば 誤差を最小化する Wを見つける ということになります。

関数の最小値を求めると言えば高校の数学でも微分を使って最小値を求めていましたが、機械学習の最小化問題は枠組みが少し違っています。

高校の数学 機械学習
L'(w) = 0 となる w を 直接的に計算する あるwが与えられたとき、L'(w) が 0 に近づく wを動かす向き を見つける
 L = w^{2} のとき  \frac{dL}{dw} = 2w

 \frac{dL}{dw}  = 0 となるのは  w = 0 のとき

このとき、最小値  L(0) = 0
f:id:sanshonoki:20170312073508p:plain:w300

右図のように勾配(gradient)を計算して変数を更新していきます。 実際には誤差関数はいくつかの変数からなる関数なので偏微分(partial derivative)で勾配を求めます。

いずれにせよ、微分は知っておく必要があります。。┗(`・∀・´●)

合成関数の偏微分

実際にはいくつもの演算が組み合わさった結果を微分することになるので目的の変数の勾配を計算するにはチェインルール(連鎖律)を知っておく必要があります。

マストです。。 (゜ロ゜)

計算例

 y = wx + b L(w, b) = \frac{(t - y)^{2}}{2} であるとき

 d = t - y とおくと  L = d^{2} / 2


 \frac{\delta L}{\delta w} = \frac{\delta L}{\delta d} * \frac{\delta d}{\delta w}

 = \frac{\delta (d^{2} / 2) }{\delta d} * ( \frac{\delta d}{\delta y} * \frac{\delta y}{\delta w} )

 = d * \frac{\delta (t - y)}{\delta y} * \frac{\delta (wx + b)}{\delta w}

 = d * -1 * x

 = (y - t) * x

イメージ

個人的にはPFNの岡野原さんのスライドがイメージを掴みやすかったです。

IIBMP2016 深層生成モデルによる表現学習

f:id:sanshonoki:20170313050821j:plain f:id:sanshonoki:20170313050840j:plain

覚えておきたい基本的な微分の計算

とりあえず、以下を知っていれば大抵は何とかなるはず・・・

関数 導関数
 ax  a
 x + c  1
 x^{2}  2x
 \frac{1}{x}  -\frac{1}{x^{2}}
 e^{x}  e^{x}
 \log x  \frac{1}{x}

勾配降下法(gradient descent)の実装サンプル

クラッチで実装すると自信がつく気がします。。 (o・ω・o)

github.com

競走馬の距離適性を計算する

前回パドック画像を収集しました。今回は各パドック画像のラベリングを行い学習データを作ります。

距離適性の計算

これまたnetkeibaにお世話になります。m(._.*)m

netkeibaの各馬のデータには 適性レビュー というデータがあります。 この適性レビューの 距離適性のパラメータ を利用します。

例えば、オルフェーヴルの距離適性のデータは以下のようになっています。 距離適性が 短い/長い のバーの長さの割合で表現されています。

f:id:sanshonoki:20170305072822p:plain:w400

htmlコードを見てみます。

f:id:sanshonoki:20170305073742p:plain

“短い” と “長い” のバーの長さが widthの数値で取得できそうです。(^○^)

  • 短い: 43
  • 長い: 73

距離適性は次式

 73 / (43 + 73) =  0.6293103448275862

で計算します。

この値が 0.0 に近ければ 短距離馬 で 1.0 に近ければ 長距離馬 になります。

距離適性の取得

馬名を入力として 先ほどの距離適性の値を取得します。 使ったコードはこちらにあります。

github.com

結果と分類

2525頭分の計算結果は https://github.com/tanakatsu/netkeiba_distance_aptitude/blob/master/sample.sorted_score.txt

になります。

私の肌感覚でざっくり分類すると、

category score
長距離 0.6-
中距離 0.4-0.59
マイラー 0.2-0.39
短距離 -0.19

っていうところでしょうか。

ただ、明確に線引きすることは難しそうなので長距離と短距離の分類(Classification)とかではなく回帰(Regression)として扱うのがよさそうです。

次はいよいよ学習です。 ((((o゚▽゚)o)))

ディープラーニング学習メモ #2 行列の積

UdacityのDeepLearning基礎コース、Week3以降は週5-6時間程度でレッスンコンテンツは一通りはこなせています。 ただ、後でしっかり復習しないと身につかない感じはあります。。 そりゃそうですよね、、世の中そんなに甘くない。(;^_^A

今日は行列の積についてメモを残します。

dot演算とelementwise演算

dot演算

学校の授業で習ったいわゆる行列の掛け算はdot演算と呼ばれるものになります。

  • 行列A (m,n) * 行列B (n, p) = 行列C (m, p)
  • Aの列数とBの行数を合わせる必要がある
  • 積ABの要素ij は Aのi行とBのj列の畳み込み

f:id:sanshonoki:20170301050110p:plain:w400

elementwise演算 (*演算)

elementwise演算は 単純に要素同士を掛け算するだけです。

  • 積ABの要素ij は Aの要素ijとBの要素ijの掛け算
  • 厳密には A、Bの行数と列数が同じでないと掛け算できない
  • ただし、numpyにはブロードキャストという仕組みがあるので列数と行数が一致していなくても演算可能(な場合がある)

f:id:sanshonoki:20170301050124p:plain:w400

numpyにはブロードキャストという仕組みがあるので列数と行数が一致していなくても演算可能になっています。ここが混乱しどころです。これは numpyが演算するときにサイズを変換してくれるためです。

ブロードキャスト

ブロードキャストできるかどうか? Broadcasting — NumPy v1.12 Manual

  • ベクトル (n,) は行ベクトル (1,n) として扱う
  • 各軸の次元が同じまたはどちらかが1
*演算 dot演算
(m, 1) x (1, n) ok ok
(m, 1) x (n, 1) NG NG
(m, 1) x (n,) ok NG
(n,) x (m, 1) ok NG

okのパターンでは (m, n)の行列が出力されます。

使いどころ

ディープラーニングで出てくる計算の中で2種類の掛け算をどう使い分けるのか、、、

ざっくりまとめてみました。

*演算 dot演算
1つのノード内での計算
(シグモイドの微分計算etc)
複数ノード間の計算
(重みWとベクトルとの計算)
例1: シグモイドの微分  \sigma'(h) = \sigma(h) * (1 - \sigma(h))
例2: 入力誤差の伝搬  (\delta W^{T}) * \sigma'(h)
例1: 順伝搬  {Wx}
例2: 入力誤差の計算  \delta W^{T}
例3: 誤差から {\Delta W}を計算  \delta x^{T}

入力の次元数と出力の次元数が同じときは *演算 と考えていいです。

dot演算の例3では 入力が1次元のベクトルの場合に、*演算としても計算可能ですが2次元以上の場合に計算できないので dot演算として考えるのが無難でしょう。

競走馬のパドック画像を収集する

次の例のようにCNN (Convolutional Neural Network) で何か面白い分類をやってみたい

gigazine.net

MNISTやCifar10と言ったような練習用のありきたりのデータではなく何かcoolな題材はないかな〜と考えていたところ、、

馬体から短距離馬と長距離馬を見分けられたら面白いのではないか?(また、競馬かよ)

そう、短距離馬と長距離馬は首筋の長さ、太さで特徴が違うのです。

もしかしたらディープラーニングで見分けられるかも〜?!   ¨キ(o゚Д゚o)¨キ

ということで、パドック画像を探してみます。パドック画像だけを取りまとめているリソースがなかなか見つかりませんでしたが、、、

ありました! 競馬道のサイトの競馬ブックコーナーです。ヽ( ´¬`)ノ

早速、クローラを実装して画像を収集させていただきました。ソースコードはこちらにあります。

github.com

2001年より前はフォーマットが違っていて以下のように写真の中に文字も含まれてしまうので2002年以降の写真を収集しました。

http://www.keibado.ne.jp/keibabook/010109/photop.html http://www.keibado.ne.jp/keibabook/010109/images/pp01.jpg

2017年1/23時点で のべ頭数 8707頭、ユニーク頭数としては 2528頭分の画像を収集できました。

収集した画像はこちらからダウンロードできます。

今回はここまでです。

ディープラーニング学習メモ #1 行列

Udacityの Deep Learning Nanodegree Foundation の Week1 が終わりました。

シラバスでは学習時間の目安は 3-4 hours per week と書いてありましたがかれこれ20時間近く費やしています。。ヽ(;´Д`)ノ

誤差の逆伝搬の詳しい仕組みとか今までスルーしてきたところなのでそれなりに理解に時間がかかるのは仕方ない…とは思いつつも Week2以降大丈夫だろうか? 不安。。

それはおいとき、自分自身の理解をより深めるために少しずつ学習メモを残していきたいと思います。

1回目は 行列です。

行と列とrowとcolumn

どちらが行でどちらが列か、、

イメージで覚えると忘れにくいです。次の図が分かりやすかったです。

http://sci.tea-nifty.com/blog/2014/12/row-column-f052.html

http://sci.tea-nifty.com/photos/uncategorized/2014/12/06/b4ffosxciaazysl.jpg

http://id.fnshr.info/2015/10/17/matrix/

http://id.fnshr.info/wp-content/uploads/sites/2/2015/10/column.png

http://id.fnshr.info/wp-content/uploads/sites/2/2015/10/row.png

http://lambdalisue.hatenablog.com/entry/2013/07/18/134507

http://cdn-ak.f.st-hatena.com/images/fotolife/l/lambdalisue/20130718/20130718131854.png

行と列の関係は 画像処理に慣れている人は混乱するかもしれません。(私だけ??)

というのも、画像のサイズは通常、 W (横の大きさ) x H (縦の大きさ) と表現しますがこれを行列にすると逆になります。

つまり、W x H の画像は H x W の行列で表現されます。

f:id:sanshonoki:20170214062324p:plain:w400

numpyでの行ベクトルと列ベクトル

numpyの次の3つの構造のイメージつくでしょうか..?

(m, )

(m, 1)

(1, m)

正解・・・

(m, ) は 1次元ベクトル、

https://wikimedia.org/api/rest_v1/media/math/render/svg/507111acf945f5fe57c45ecc563ec02a4aff4a1b

(m, 1) は 列ベクトル

https://wikimedia.org/api/rest_v1/media/math/render/svg/32bf4d54c8e316178fca0b9f4a79dd0a0a34f34f

(1, m) は 行ベクトル

https://wikimedia.org/api/rest_v1/media/math/render/svg/507111acf945f5fe57c45ecc563ec02a4aff4a1b

(m, 1) はついつい横方向のベクトル、行ベクトルと思ってしまいますがこれは落とし穴で列ベクトルです。 慣れだとは思いますが。。

1次元ベクトルを列ベクトルに変換する方法

いったん2次元にしてから転置(transpose)する必要があります。 記述は 2パターンあります。

>>> data = np.array([1,2,3])
>>> data
array([1, 2, 3])

# 方法1
>>> data[:, None]
array([[1],
       [2],
       [3]])

# 方法1'
>>> data[:, np.newaxis]
array([[1],
       [2],
       [3]])

# 方法2
>>> np.array(data, ndmin=2).T
array([[1],
       [2],
       [3]])

2回目へ続く(はず。。)

ダースベイダー

4才の息子が"パパの大好きなスターウォーズ"のダースベイダーを作ってくれました。

f:id:sanshonoki:20170206063618j:plain:w300

おぉ、言われるとそう見えてきます。。(^ ^)

ちなみに、おしっこもできるように穴を開けた そうです。

子どもの頭の柔軟さを改めて感じた週末でした。