2015年9月2日水曜日

Caffeによるシーン認識(8分類問題)2


はじめに


 先のページで caffeを使ってシーン認識(8分類問題)を試みた。今回は、caffe が提供する pre-training モデルを用いて、同じ問題を考察する。

計算機環境


 AmazonのEC2を利用した。インスタンス名は g2.2xlarge である。GPUを搭載したマシーンである。

データセット


 データセットは前回と同じである。ただし、pre-trainingモデルに合わせるため、画像サイズを256$\times$256に、チャンネル数を3に変更した。

caffe用データの作成


 ここも前回と同じである。 以下のコマンドにより caffe 用の入力データを作成する。 前回はグレー画像を扱ったのでコマンドオプションに -gray を付けたが、今回は3チャンネルなので -gray は付けない。

ネットワークの設計


 caffeのソースコードを納めたディレクトリ
/home/ubuntu/buildspace/caffe-master/models/bvlc_reference_caffenet
にある train_val.prototxt を下敷きにして以下のようなネットワーク構造を定義した(model/scene_recognition/train_val.prototxt)。 変更部分は、data 層と fc8 層の2つである(fc8 層を scene_fc8 層に置き換えた)。 また、このページの解説に従って、scene_fc8 層のパラメータ lr_mult を変更した。

solverの作成


 訓練を行なうためのテキストファイル model/scene_recognition/solver.prototxt を以下のように記述した。caffe の提供するサンプルファイル(models/bvlc_reference_caffenet/solver.prototxt)を下敷きにした。 現在の test 画像の枚数は730枚、batch size を10としたので73(=test_iter)回で一通り画像を走査することになる。また、testの実行はtrainを500(=test_interval)回まわすごとに行なうようにした。

訓練


 以下を実行する。 コマンドオプション -weights の引数として与えられている models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel がcaffeが提供するpre-trainingモデルである。上記のコマンドにより、大規模データであらかじめ作られた pre-training モデルを、私のデータで fine-tuning することができる。

結果


 以下に結果を示す。
test画像:
train画像:
縦軸はaccuracy(正解率)、横軸は iteration(繰り返し数)である。いまの場合、繰り返し数の総数が44238である。500回ごとにtest画像でテストするようにしたので、test画像の結果の横軸は89(=44238/500)まで表示されている。一方、 trainに対しては、73(=display)回ごとに出力するようにしたので、607(=44238/73)個の結果が表示されている。前回、test画像に対する正解率は88%であったが、今回は97%となり大幅に改善していることが分る。

検出器の作成


 ここまでの計算で、ファイル scene_train_iter_40000.caffemodel ができている。ここには、fine-tuning によりパラメータの確定したネットワーク構造が納められている。このファイルから検出器を作るには、以下のようなdeploy.prototxt ファイルが必要である。 これは、先に定義した model/scene_recognition/train_val.prototxt のデータ層を取り除き を追加し、最終層にある loss 層と accuracy 層を取り除き を追加したものである。データ層の代わりに挿入した input_dim の意味は以下の通りである。
  1. input_dim: 10 --- バッチサイズ
  2. input_dim: 3 --- 入力画像のチャンネル数
  3. input_dim: 227 --- 入力画像の幅
  4. input_dim: 227 --- 入力画像の高さ
検出器を使って、ファイルを識別するコードを以下に示す。 実行するとこうなる。 パーフェクトである。

2015年7月30日木曜日

Caffeによるシーン認識(8分類問題)


はじめに


 先のページで theano を使ってシーン認識(8分類問題)を試みた。今回は、caffe を取り上げ、同じ問題に適用する。

計算環境


 AmazonのEC2を利用した。インスタンス名は g2.2xlarge である。GPUを搭載したマシーンである。

データセット


 データセットは前回と同じである。
                     
ラベル 名前 枚数(train) 枚数(test)
0 MITcoast 610 100
1 MIThighway 440 70
2 MITmountain 630 100
3 MITstreet 490 80
4 MITforest 550 90
5 MITinsidecity 520 80
6 MITopencountry 690 110
7 MITtallbuilding 600 100
4530 730

これまでと同様に左右反転画像を追加してある。theano を用いた時は、データセットを train / validation / test の3つに分けたが、今回は train と validation を1つにまとめ改めて train とした。また、画像サイズは 126$\times$126 に変更し、画像の枚数も10で割り切れるよう調節した。

caffe用データの作成


 caffeが必要とするものは以下の4つである。
  1. train 画像を納めたディレクトリへのパス
  2. test 画像を納めたディレクトリへのパス
  3. train 画像名とラベルを記したテキストファイル
  4. test 画像名とラベルを記したテキストファイル
実行環境では、以下の場所にディレクトリとテキストファイルを作成した。
  1. /home/ubuntu/data/caffe/train
  2. /home/ubuntu/data/caffe/test
  3. /home/ubuntu/data/caffe/train.txt
  4. /home/ubuntu/data/caffe/test.txt
テキストファイルには、各行にファイル名とラベルを記述する。各ファイルの中身は以下の通りである。
test.txt
MITtallbuilding_image_0332_flipped.jpg 7
MITopencountry_image_0195.jpg 6
MITstreet_image_0176_flipped.jpg 3
MITmountain_image_0042.jpg 2
MITcoast_image_0195.jpg 0
MITmountain_image_0063_flipped.jpg 2
MITopencountry_image_0366_flipped.jpg 6
MITmountain_image_0229.jpg 2
MITtallbuilding_image_0354_flipped.jpg 7
MITforest_image_0086.jpg 4
MITcoast_image_0085.jpg 0
MITstreet_image_0094.jpg 3
MITopencountry_image_0401.jpg 6
MITmountain_image_0025_flipped.jpg 2
MITcoast_image_0075_flipped.jpg 0
MITforest_image_0227_flipped.jpg 4
....
train.txt
MITstreet_image_0253_flipped.jpg 3
MITcoast_image_0023.jpg 0
MITstreet_image_0256_flipped.jpg 3
MIThighway_image_0228_flipped.jpg 1
MITopencountry_image_0045_flipped.jpg 6
MITmountain_image_0314.jpg 2
MITtallbuilding_image_0078.jpg 7
MITmountain_image_0337.jpg 2
MITforest_image_0120.jpg 4
MITcoast_image_0088.jpg 0
MITmountain_image_0211_flipped.jpg 2
MITforest_image_0133_flipped.jpg 4
MITcoast_image_0356.jpg 0
MIThighway_image_0081_flipped.jpg 1
MITcoast_image_0115_flipped.jpg 0
MITmountain_image_0218_flipped.jpg 2
MITforest_image_0196_flipped.jpg 4
MITforest_image_0281_flipped.jpg 4
...
ディレクトリ内にテキストファイルに記述した画像を納め、以下のコマンドにより caffe 用の入力データを作成する。 以下の場所にデータベース test_leveldb と train_leveldb が出力される。

ネットワークの設計


 ここでは、caffeのサンプル(caffe-master/examples/mnist/lenet_train_test.prototxt)を下敷きにして以下のようなネットワーク構造を定義した(scene_train_test.prototxt)。

solverの作成


 訓練を行なうためのテキストファイル scene_solver.prototxt を以下のように記述する。caffe の提供するサンプルファイル(caffe-mater/examples/mnist/lenet_solver.prototxt)を下敷きにした。 現在の test 画像の枚数は730枚、batch size を10としたので73回で一通り画像を走査することになる。従って、73回ごとに正解率を出力するようにした。

訓練


 以下を実行する。

結果


 以下に結果を示す。
縦軸はaccuracy(正解率)、横軸は iteration(繰り返し数)である。いまの場合73回に1回ずつaccuracyを出力するので1370(=100000/73=1369.86...)個の値がプロットされる。 訓練画像については100%の正解率、テスト画像については88%程度の正解率である。

検出器の作成


 ここまでの計算で、ファイル snapshot_iter_100000.caffemodel ができている。ここには、訓練によりパラメータの確定したネットワーク構造が納められている。このファイルから検出器を作るには、以下のようなdeploy.prototxt ファイル(ここではscene_deploy.prototxtとした)が必要である。 これは、先に定義した scene_train_test.prototxt のデータ層を取り除き を追加し、最終層にある loss 層と accuracy 層を取り除き を追加したものである。データ層の代わりに挿入した input_dim の意味は以下の通りである。
  1. input_dim: 10 --- バッチサイズ
  2. input_dim: 1 --- 入力画像のチャンネル数
  3. input_dim: 126 --- 入力画像の幅
  4. input_dim: 126 --- 入力画像の高さ
検出器を使って、ファイルを識別するコードを以下に示す。 実行するとこうなる。1つ間違えている。

2015年4月29日水曜日

boost/range/adaptor 覚え書き

出力は以下の通り。

2015年4月2日木曜日

Convolutional Neural Network によるシーン認識


はじめに


 先のページで Convolutional Neural Network(CNN)を解説した。今回は、CNN をシーン認識に適用した結果を示す。

データセット


 このページに置いてある データ(LSP15)を使用した。このデータは15個のディレクトリから構成される。
  1. bedroom
  2. CALsuburb
  3. industrial
  4. kitchen
  5. livingroom
  6. MITcoast
  7. MITforest
  8. MIThighway
  9. MITinsidecity
  10. MITmountain
  11. MITopencountry
  12. MITstreet
  13. MITtallbuilding
  14. PARoffice
  15. store
各ディレクトリ内にはその名前が表すシーンの画像が複数枚おさめられている。 今回のシーン識別では「MIT」の付くディレクトリだけを利用した。画像の大きさが統一されており扱い易かったからである。今回あつかう問題は8分類問題である。

データセットの増量


 各シーンの画像の枚数は以下の通りである。

シーン名 枚数
MITcoast360(720)
MIThighway260(520)
MITmountain374(748)
MITstreet292(584)
MITforest328(656)
MITinsidecity308(616)
MITopencountry410(820)
MITtallbuilding356(712)
総数2688(5376)

画像の枚数を増やすため、各画像の左右反転画像を追加した。括弧内が追加後の枚数である。

データセットの分割


 データセットを train、validation、test の3つに分割する。枚数の比を train : validation : test = 5 : 1 : 1 とした。 以下に具体的な枚数を示す。
 
ラベル名 シーン名 train validation test
0MITcoast514102102
1MIThighway3717474
2MITmountain534106106
3MITstreet4178383
4MITforest4689393
5MITinsidecity4408888
6MITopencountry585117117
7MITtallbuilding508101101
総数3837764764

また、シーン認識時に使用するラベルを上図の第1列のように定義した。 左右反転画像は元の画像とは独立した画像として扱い、train / validation / test の3つに分ける際は乱数を用いた。

ネットワークの構造


 今回使用したネットワークの構造は以下の通りである。
convolutional 層と pooling 層の対を4つ、隠れ層を1つとした。 各種パラメータは以下の通りである。
           
層名 フィルタサイズ フィルタの個数 pooling
0cp 5$\times$5 2 2$\times$2
1cp 6$\times$6 10 2$\times$2
2cp 6$\times$6 50 2$\times$2
3cp 5$\times$5 200 2$\times$2

フィルタサイズとは、convolution 時に使用する矩形画像のサイズのことである(フィルタの各要素の値は訓練時に決定される)。また、convolution時の stride は全て1とした。poolingはmax poolingを採用した。poolingのあと画像サイズは縦横ともに1/2になる。 隠れ層と出力層のユニット数は以下の通りである。
         
層名 ユニット数
隠れ層500
出力層8

各層における画素数の変遷は次のようになる。
           
層名 入力サイズ conv後のサイズ pooling後のサイズ
0cp 146$\times$146 142$\times$142 71$\times$71
1cp 71$\times$71 66$\times$66 33$\times$33
2cp 33$\times$33 28$\times$28 14$\times$14
3cp 14$\times$14 10$\times$10 5$\times$5

0cp層への入力画像に対しては、画素値を255で割ったあと、平均値が0、分散が1となるように正規化した。 3cp層から出力される画素の数は5000=(5$\times$5$\times$200)である。これが隠れ層への入力値となる。今考えているラベルの総数は8であるから出力層のユニット数は8となる。

計算方法


 Convolutional Neural Networks (LeNet) にあるサンプルソース(theanoによる実装)に手を加え計算を行なった。主な変更点は以下の通りである。
  1. 上に示したネットワーク構造に変更した。
  2. $L_1$正則化項と$L_2$正則化項を追加した。
  3. 各epochごとに学習率が減衰していくようにした。
  4. 隠れ層の活性化関数をsigmoidとした(tanhより精度が良くなった)。
正則化項についてはこちらで説明した。 パラメータは以下の通りである。
   
学習率減衰率 $L_1$正則化項の重み $L_2$正則化項の重み
0.01 0.995 0.0002 0.0002

元のソースでは、early-stoppingと呼ばれる手法を使って訓練を行っている。「訓練データ(train)で学習したあと検証データ(validation)で誤り率を見る」を、検証データで改善が見られなくなるまで繰り返す手法である。この部分はそのまま踏襲した。

計算環境


 アマゾンのEC2インスタンス(g2.2xlarge)を利用した。これは1536CUDA コアと 4GB のビデオメモリを搭載しており、今回の計算ではtheanoを通してGPUを利用した。

結果


 0/1損失(0/1 loss)の結果を以下に示す。
   
best validation score test performance
11.9736842105%10.6578947368%

ここで、best validation score とは、early-stopping の反復計算の過程で得られた「検証データ」に対する最適値である。 「検証データ」に対する最適値を実現したときのモデルを使って「テストデータ」を評価した結果が test performance である。 ただし、反復時の epoch 数の上限値を500とした。計算時間は 182.905974067 分であった。

考察

  1. 左右反転画像を追加する前の誤り率は20%程度であり、これ以上減らすことができなかった。
  2. 左右反転画像を追加した後の誤り率は10%程度となり改善された。
  3. 白色化や隠れ層の追加などを試みたがこれ以上は改善しなかった。
  4. なんとかして誤り率を一桁にしたいのだが。。。

2015年2月26日木曜日

正則化項について


はじめに


 これまでいくつかのNeural Networkを考察してきた( 1次元ロジスティック回帰、 多次元ロジスティック回帰、 多層パーセプトロン、 Convolutional Neural Network)。 どの場合もパラメータを求める際はNegative Log Likelihood(NLL)を最小化した。過学習を防ぐため、正則化項(regularization term)と呼ばれる項をNLLに追加することがある。ここでは、この正則化項の役割についてまとめる。

正則化項


 多次元ロジスティック回帰を例として考える。全観測値の実現確率は次式で与えられた。 \begin{equation} P(W,\vec{b})=\prod_{n=1}^{N}\;p(c^{n}\;|\;\vec{x}^{\;n}\;;\;W,\vec{b}) \end{equation} ここで、$\vec{x}^{\;n}$ は観測値、$c^{n}$ はラベル、$W,\vec{b}$ はモデルを調節するパラメータである。上式におけるパラメータは確率変数とは無関係な量として定義したが、これも確率変数とみなし以下のように事前確率 $p(W,\vec{b})$ を導入することができる。 \begin{equation} P(W,\vec{b})=\prod_{n=1}^{N}\;p(c^{n}\;|\;\vec{x}^{\;n}\;;\;W,\vec{b})\;p(W,\vec{b}) \end{equation} すなわち、パラメータが確率 $p(W,\vec{b})$ で与えられたときの観測値の実現確率を考えるのである。 両辺の対数をとりマイナスを付ける。 \begin{eqnarray} L(W,\vec{b})&=&-\ln{P(W,\vec{b})}\nonumber \\ &=&-\sum_{n=1}^{N}\;\ln{p(c^{n}\;|\;\vec{x}^{\;n}\;;\;W,\vec{b})}-\ln{p(W,\vec{b})} \label{nll} \end{eqnarray} これまで考えてきたNLLに $-\ln{p(W,\vec{b})}$ が付加されることが分る。これが正則化項である。 $p(W,\vec{b})$ として以下の形の正規分布を考えることが多い。 \begin{equation} p(W,\vec{b}) = \exp{\left(-\eta \sum_{i,j}\;|w_{i,j}|^2\right)} \end{equation} ここで、$w_{i,j}$ は $W$ の成分、$\eta$ は正の量である。このとき $L(W,\vec{b})$ は以下のようになる。 \begin{equation} L(W,\vec{b})=-\sum_{n=1}^{N}\;\ln{p(c^{n}\;|\;\vec{x}^{\;n}\;;\;W,\vec{b})}+\eta \sum_{i,j}\;|w_{i,j}|^2 \end{equation} 上式を最小化する過程で、右辺第2項は $w_{i,j}$ を小さくする力となる。すなわち、正則化項はNeural Networkのユニット間の結びつきを 弱めるものであり、これが過学習を抑制するのである。上記のように $|w_{i,j}|$ の2乗のものを $L_2$ 正則化項、1乗のものを $L_1$ 正則化項と呼ぶ。

2015年2月9日月曜日

Convolutional Neural Network


はじめに


 先のページでは多層パーセプトロンを解説した。今回は、これを拡張することによりConvolutional Neural Networkを導く。

多層パーセプトロン


 隠れ層が一層の多層パーセプトロンは以下のような構造であった。
これに対応する式は以下のように与えられる。 \begin{eqnarray} y_k &=& \pi\left(\;f_k\left( \vec{z}; W^{(2)},\vec{b}^{\;(2)}\right)\;\right) \label{eprob-2}\\ \pi(a_k) &=& \frac{\exp{(a_k)}} {\sum_{j=1}^{K}\;\exp{(a_j)}} \label{softmax-1}\\ \vec{f}\left( \vec{z}; W^{(2)},\vec{b}^{\;(2)}\right) &=& W^{(2)\;T}\;\vec{z} + \vec{b}^{\;(2)}\label{projection-2} \end{eqnarray} \begin{eqnarray} z_h &=& \tanh\left(\;g_h\left( \vec{x}; W^{(1)},\vec{b}^{\;(1)}\right)\;\right) \label{eprob-1}\\ \vec{g}\left( \vec{x}; W^{(1)},\vec{b}^{\;(1)}\right) &=& W^{(1)\;T}\;\vec{x} + \vec{b}^{\;(1)}\label{projection-1} \end{eqnarray} ここで、$W^{(1)}$ は $D\times H$ 行列、$\vec{b}^{\;(1)}$ は $H$ 次元ベクトル、$W^{(2)}$ は $H\times K$ 行列、$\vec{b}^{\;(2)}$ は $K$ 次元ベクトルである。ただし、隠れ層の活性化関数として $\tanh{}$ を採用している。 最下層は入力層であり $D$ 個のユニットから構成される。隠れ層のユニット数は $H$ 個、最上層は出力層であり $K$ 個のユニットから構成される。これを適用する具体例として、$D$ 次元のベクトルとして与えられる観測値を $K$ 個のクラスのいずれかに分類する多分類問題を挙げることができる。
 上図における層間の接続に注目したものが下図である。各ユニットは、下層の全ユニットと接続している。

Convolutional Neural Network(CNN)


 いま、入力層(input layer)と隠れ層(hidden layer)の間に複数の層を挿入する。
上図は、convolution layerと pooling layerの対を2つ挿入したものである。 一般に、この対を任意の数だけ挿入したものをconvolutional neural networkと呼ぶ。以下各層について説明する。

① convolution layer

 多次元ロジスティック回帰や多層パーセプトロンでは、1次元のベクトルを入力値としてきたが、ここでは入力値として2次元ベクトルを考える。具体的には画像が入力値となる場合を考察する。まず最初に、$m$ 番目の入力画像の $l$ 番目のチャンネルを考え、位置 $(i,j)$ にある画素 $x_{m,l,i,j}$ について以下の計算を行なう。 \begin{equation} g_{m,k,i,j} = \sum_{p,q,l} \; w_{k,l,p,q}\;x_{m,l,i+p,j+q} \label{eq1} \end{equation} これは、矩形のフィルタ $w_{k,l}$ を使って convolution を行い、$l$ について和をとることと等価である。カラー画像なら $l$ の総数は3、グレースケールなら1である。convolution を $\circledast$ で表すことにすれば、式(\ref{eq1})は \begin{equation} g_{m,k} = \sum_{l} \; w_{k,l} \circledast x_{m,l} \label{eq2} \end{equation} と書くことができる。

② max pooling

 次に行なう処理は pooling である。pooling の方法にはいくつかあるが、ここでは max pooling を取り上げる。max pooling とは、 画像を $a\times a$ の領域に細分し、各領域内の最大値でその領域を代表させる処理である。$a=2$ なら $w\times h$の画像は$w/2\times h/2$ のサイズにダウンサンプリングされる。いま形式的に max pooling の処理を $p_{\rm{pooling}}(\cdot)$ と書くことにすれば、この処理の出力値は \begin{equation} q_{m,k} = p_{\rm{pooling}}\left(\sum_{l} \; w_{k,l} \circledast x_{m,l}\right) \label{eq3} \end{equation} となる。

③ 活性化関数

 ここまでの出力値 $q_{m,k}$ にスカラー量であるバイアス項 $b_{k}$ を加え、$\tanh$ で活性化する。 \begin{equation} r_{m,k} = \tanh{(q_{m,k}+b_k)} \label{eq4} \end{equation} 出力値 $r_{m,k}$ は、feature mapと呼ばれる。これを新たな入力値 $x_{m,l}$ とみなして ①②③ の処理を繰り返す。その際、フィルタの数 $k$ を変えることができる。たとえば、最初の処理①②③では20種類のフィルタを使い、次の処理①②③では50種類のフィルタを使うなどである。

 convolution layerとpooling layerの対が2つ、最初の画像サイズが28$\times$28、フィルタサイズが5$\times$5の場合を考える。最初のconvolution layerにより画像サイズは 24$\times$ 24となり、それに引き続く pooling layer により画像サイズは12$\times$12となる。次のconvolution layerへの入力画像のサイズは12$\times$ 12となり、フィルタサイズが最初と同じなら、convolution layerにより画像サイズは8$\times$8、pooling layerにより画像サイズは4$\times$4となる。2つ目のcovolution に使うフィルタの数が50なら、4$\times$4の画像が50個出来上がる。すなわち、1枚の画像(サイズは28$\times$28)から50組の16(=$4\times 4$)画素が作成される。この画素を一列に並べた800($=50\times 16$)次元のベクトルを多層パーセプトロンのhidden layerの入力とみなす。あとの処理は先のページと同じである。

計算を行なう際の留意点

  • CNNの計算量はMLPと比べ著しく多くなる。 私のiMac(3.06GHz Intel Core 2 Duo, 4GB)で、参考文献にあるtheanoコードを実行したところ、MLPで8.32時間、CNNで20.99時間となった。0-1lossの値は、MLPで1.68%、CNNで0.91%であった。
  • 各層の計算時間を同じにするため、(feature mapの数$\times$feature mapを構成する画素の数)を各層でほぼ同じにすることがよく行なわれる。
  • 考察するデータセットごとに最適なフィルタサイズは変わる。入力画像が28$\times$28程度であれば5$\times$5のフィルタがよく使われる。一方、数百画素$\times$数百画素の画像に対しては12$\times$12や15$\times$15程度のフィルタを用いることが多い。
  • max poolingを行なわない選択肢もある。行なうとしても、そのサイズは2$\times$2が限度である。これ以上のdownsamplingを行なうと、多くの情報が失われてしまう。
  • whitening(白色化)を導入することにより識別率は高くなる。
  • 確率的勾配降下法の各イテレーションごとに学習率を小さくすることにより収束速度を上げることができる。

まとめ


 多次元ロジスティック回帰は入力層と出力層の2層からなるNeural Network、多層パーセプトロンはこの2層の間に隠れ層を複数個挿入したNeural Network、そして、Convolutional Neural Networkは、多層パーセプトロンにconvolution層とpooling層の対を複数個挿入したNeural Networkである。多分類問題に適用した際の識別率は、一般的には、入力層と出力層の間の中間層が増える程高くなる。
 

参考文献


Convolutional Neural Networks (LeNet)
Theanoを使った実装が掲載されている。

2015年1月25日日曜日

多層パーセプトロン


はじめに


 先のページでは多次元ロジスティック回帰について考察した。ここでは、これを拡張することにより、多層パーセプトロンを導入する。

多次元ロジスティック回帰


 先のページでは、観測値として $D$ 次元のベクトル $\vec{x}$ を考え、これが $K$ 個のクラスのいずれかに属する多分類問題を考えた。式を書き下ろすと、 \begin{eqnarray} y_k &=& \pi\left(\;f_k\left( \vec{x}; W,\vec{b}\right)\;\right) \label{eprob}\\ \pi(a_k) &=& \frac{\exp{(a_k)}} {\sum_{j=1}^{K}\;\exp{(a_j)}} \label{softmax}\\ \vec{f}\left( \vec{x}; W,\vec{b}\right) &=& W^{T}\;\vec{x} + \vec{b}\label{projection} \end{eqnarray} となる。ただし、$(W,\vec{b})$ はモデルを記述するパラメータであり、前者は $D\times K$ 行列、後者は $K$ 次元ベクトルである。 これを図で示したものが下図である。
この図から、多次元ロジスティック回帰は入力層と出力層の2層からなるNeural Networkであることが分る。

多層パーセプトロン


 上記の構造に、中間層(隠れ層と呼ぶ)を挿入する。
これに対応する式は以下のように与えられる。 \begin{eqnarray} y_k &=& \pi\left(\;f_k\left( \vec{z}; W^{(2)},\vec{b}^{\;(2)}\right)\;\right) \label{eprob-2}\\ \pi(a_k) &=& \frac{\exp{(a_k)}} {\sum_{j=1}^{K}\;\exp{(a_j)}} \label{softmax-1}\\ \vec{f}\left( \vec{z}; W^{(2)},\vec{b}^{\;(2)}\right) &=& W^{(2)\;T}\;\vec{z} + \vec{b}^{\;(2)}\label{projection-2} \end{eqnarray} \begin{eqnarray} z_h &=& \tanh\left(\;g_h\left( \vec{x}; W^{(1)},\vec{b}^{\;(1)}\right)\;\right) \label{eprob-1}\\ \vec{g}\left( \vec{x}; W^{(1)},\vec{b}^{\;(1)}\right) &=& W^{(1)\;T}\;\vec{x} + \vec{b}^{\;(1)}\label{projection-1} \end{eqnarray} ここで、$W^{(1)}$ は $D\times H$ 行列、$\vec{b}^{\;(1)}$ は $H$ 次元ベクトル、$W^{(2)}$ は $H\times K$ 行列、$\vec{b}^{\;(2)}$ は $K$ 次元ベクトルである。隠れ層の活性化関数として、$\tanh{}$ を採用したが、他にsigmoid関数を考えることもできる。一般に、隠れ層の数を任意にした構造を多層パーセプトロンと呼ぶ。多次元ロジスティック回帰の場合と同様に、確率的勾配降下法を用いて解くことができ、多次元ロジスティック回帰よりも精度の良い識別率を実現できる。

計算を行なう際の留意点


  • 勾配降下法では、大域的最小値を求めることはできない。
  • 活性化関数としてよく用いられる関数は、$\tanh$とsigmoidの2つである。原点について対称な関数が好まれる理由は、次の層への入力値の平均値を0に近い値にできるからである。経験的にsigmoidよりも$\tanh$の方が収束性が良い。
  • 行列$W$の初期値は、0近傍の十分小さな値とする。0近傍であれば、活性化関数の線形部分が適用されるので、勾配を大きくすることができる。
  • 活性化関数を$\tanh$とするときは$[-\frac{\sqrt{6}}{\sqrt{N_{\rm in}+N_{\rm out}}}, \frac{\sqrt{6}}{\sqrt{N_{\rm in}+N_{\rm out}}}]$の範囲で、sigmoidを活性化関数とするときは$[-4\frac{\sqrt{6}}{\sqrt{N_{\rm in}+N_{\rm out}}}, 4\frac{\sqrt{6}}{\sqrt{N_{\rm in}+N_{\rm out}}}]$の範囲で一様乱数を発生させ、$W$を初期化すればよい。ここで、$N_{\rm in}$は入力層にあるユニットの数、$N_{\rm out}$は隠れ層にあるユニットの数である。

参考文献


Multilayer Perceptron
Theanoを使った実装が掲載されている。