人工知能に関する断創録スマートフォン用の表示で見るスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。ロボティクス、生物学などに興味を持っています。このブログでは人工知能のさまざまな分野について調査したことをまとめています。Learning、Kerasに関する記事が多いです。Learning機械学習コンピュータビジョンTheanoTheanoによる多層パーセプトロンの実装(2015/6/18)のつづき。ConvNet)を実装してみる。Learningアルゴリズムである。ImageNetの物体認識コンテストでぶっちぎりの成果を上げた手法はさまざまな工夫があるもののこのCNNをベースにしている。本当は一般物体認識の実験をやりたいところだけどお楽しみは後に残しておいて、まずはMNISTの手書き数字認識を追試して感触をつかみたい。ソースコード全体はここに置いた。layer)を何回か繰り返したあと最後に全結合した多層パーセプトロンが配置される構成になっている。前回実験した(2015/6/18)多層パーセプトロンは一番右側の部分にあたる。なんか一気に複雑になった・・・理解できんのこれ?というわけでチュートリアルの実装に即して自分なりに理解したことをまとめてみたい。畳み込み層は入力画像に対してフィルタをかける(畳み込む)層である。画像の畳み込みによって画像内のパターンが検出できるようになる。畳み込みの数式は参考文献に書いてあるがここでは省略。Theanoではtheano.tensor.nnet.conv.conv2d()という関数が提供されているので実装する上ではあまり問題にならない。先の図では28x28ピクセルの「7」という入力画像に対して5x5のそれぞれ異なるフィルタを20個かけて24x24の20枚の画像を出力している。フィルタをかけると画像サイズが少し小さくなる。入力画像サイズがでフィルタがだと出力画像サイズはになる。ここでは小数点以下切り下げて整数化する演算。H=5なので上式で計算すると24になる。フィルタをかけた出力画像は特徴マップと呼ばれることが多いようだ。フィルタは4次元テンソルW[20,1,5,5]で表せる(テンソルの扱いnumpyのndarrayとほとんど同じ)この意味は5x5のフィルタで入力画像の枚数(チャネル数)が1で出力画像の枚数が20ということを意味している。MNISTのデータは白黒画像なので入力画像は1チャネルになる。入力がカラー画像のときはRGBの3チャネルである。今回の実装では1チャネルのフィルタが20枚使われる。フィルタを1つでなく、複数使うのがポイント。フィルタを増やすことで入力画像のさまざまな特徴を捉えられるようになる。CNNがすごいのはこのフィルタを開発者が手動で設計するのではなく、学習によって自動獲得できるという点にある。最初、Wはランダムな値が入っていてよくわからない特徴にしか反応しないが、学習が進むと縦線や横線など画像認識に重要な特徴に強く反応するようになっていく。Learningの力の源で表現学習と呼ばれる。これまでの説明からわかるようにCNNで更新(学習)するパラメータはフィルタWになる。学習する前のランダムな値が入ったフィルタを可視化すると下のようになる。5x5のサイズのフィルタが20個ある。ランダムなパターンでなんかよくわからない(笑)CNNの学習が完了した後の同じ場所のフィルタを可視化すると下のようになる。わかりにくいが縦線や斜めの線が強調されるフィルタパターンが学習されたのががわかる。この20個のフィルタを数字の「7」の画像に畳み込むと下のような畳み込み層の出力画像が得られる。先の図で左から2つめの24x24ピクセルの20枚の画像がこれである。フィルタや畳み込み層の出力を可視化するコードはこの記事の最後に載せた。プーリング層プーリング層は畳み込み層の直後に置かれ、抽出された特徴の位置感度を低下させる働きがある。数字の「7」が画像の真ん中に書かれていても少し左や右にずれていても同じように「7」と判定するために必要ってこと。すごく難しそうだが処理自体は畳み込みよりずっと単純で2x2(poolsizeで指定)の矩形フィルタを入力画像内でずらしていき矩形内の最大の値を取り出して新しい画像を出力するような処理を行う。最大値に置き換える方法はmaxpoolingと呼ばれる。このプーリング層でも入力画像に比べて出力画像サイズは小さくなる。先の例では24x24の20枚の画像が12x12の20枚の画像になっている。画像のサイズは小さくなるが枚数は変わらない。Theanoではtheano.tensor.signal.downsample.max_pool_2d()という関数が用意されている。数式や動作の詳細は参考文献参照。なんでプーリングって名前が付いたのかよくわからないな。Tutorialでは、畳み込み層とプーリング層のペアをLeNetConvPoolLayerというクラスで表現している。実際はペアである必要はなく、畳み込み層を3つ続けてプーリング層1つとかでもいいみたい。その場合はこのクラスは使えない。分けたほうがよいかもね。LeNetというのは、畳み込みニューラルネットを発明したLeCunの最初のニューラルネットの名前に基づいているようだ。self.b]入力される画像がinputでフィルターはWで表現している。フィルタの値は多層パーセプトロンと同じくランダムな値で初期化される。bはバイアスでプーリングの後に各画像に対して加えられる。bはフィルタ数と同じ数の1次元配列なのでpooled_outの4Dテンソルと足し合わせるようにdimshuffleで次元を調整している。pooled_outの2つめの次元がbの次元数と一致するのがポイント。バイアスを加えたあとに活性化関数tanhを適用している。Unit)というのが最近ではよく使われるらしい。あとで置き換えて結果を比較してみたい。Tutorialではプーリング層の出力に対してバイアスを加えて活性化関数を通すような実装になっているが、論文によっては畳み込み層の出力に対してバイアスを加えて活性化関数を通した後にプーリング層へというように説明されていることもある。どちらでもよいのかな?このクラスは下のように使う。2))先の図では入力画像は「7」だけでたった1つのように描いたが、学習するときはミニバッチ単位でbatch_size=500枚の画像をまとめて渡す。このミニバッチ単位でフィルタのパラメータWとバイアスbを更新するためだ。ここまでで先の図のlayer0がやっと終わった。2つめの畳み込み層とプーリング層layer0の出力は12x12ピクセルの画像(特徴マップ)が20枚になる。次はこの画像を入力としてlayer1でさらに畳み込み層とプーリング層に通す。layer0と異なり、複数チャネルの画像が入力される。入力は20枚の画像から成るので20チャネルの画像と考えられる。この場合、畳み込みに使用するフィルタも20チャネル分用意する必要がある。複数チャネルの画像に複数チャネルのフィルタを畳み込むと1つの画像が出力される。はじめここを勘違いして理解するのに混乱していた・・・チュートリアルでは20チャネルのフィルタを50個用意しているので最終的に畳み込み層の出力として50個の画像(特徴マップ)が出力される。フィルタは4次元テンソルW[50,20,5,5]で表せる。この意味は5x5のフィルタで入力画像のチャネル数が20で出力画像のチャネル数が50ということを意味している。前と同様に畳み込むと画像のサイズは少し小さくなり、8x8ピクセルになる。この50枚の画像をプーリング層に通すことでサイズが小さくなり、4x4ピクセルの画像が50枚出力される。コードで書くと下のようになる。前と同じくLeNetConvPoolLayerを再利用できる。入力はlayer0の出力なのでlayer0.outputが指定されている。2))ここまでで先の図のlayer1が終わった。最後の多層パーセプトロン畳み込みニューラルネットワークでは最後に全結合した多層パーセプトロンを配置して認識を行う。layer1の出力は4x4ピクセルの画像が50枚である。2次元の画像のままでは多層パーセプトロンに入力できないので、4x4x50=800次元のベクトルに変換する。layer1.output.flatten(2)多層パーセプトロンは前回(2015/6/18)作成したHiddenLayerとLogisticRegressionクラスを組み合わせて実装する。チュートリアルでは入力層が800ユニット、隠れ層(layer2)が500ユニット、出力層(layer3)が10ユニット(MNISTの手書き数字認識なので0-9の10種類)の多層パーセプトロンを構成している。n_out=10)確率的勾配降下法によるモデル訓練モデルの訓練は多層パーセプトロンと同じく確率的勾配降下法によって行う。畳み込みニューラルネットワークは深い層構造を持つがプレトレーニング(各層を順番に学習して積み上げる方法)を使わずに古典的な勾配降下法だけで問題なく学習が行えることがわかっている。いくつ層構造が積み重なってもTheanoの実装は非常にシンプル。})更新すべきパラメータが増えているだけで他は多層パーセプトロンと同じ。(2015/5/26)のときとほとんど同じなので省略。実行時間の計測CPUとGPUで実行時間を比較してみよう。552.67m学習に552分かかった。約9時間!夜寝るまえに動かして朝起きたらまだ動いてた。その間、ずっとファンが回ってたので電気代が心配だよ・・・エラー率は0.92%なので正解率99.08%。多層パーセプトロンのエラー率が1.65%で正解率が98.35%なのでさらに超えてる。MNISTでは限界値に近いかな。次にGPUを使って同じ学習をしてみる。41.39m学習は41分で終わった。CPUに比べて約13倍速い。畳み込みニューラルネットワークの実験にはGPUが必須だな。フィルタと畳み込み層の出力の可視化チュートリアルにはないけどおまけでフィルタと畳み込み層の出力を可視化するスクリプトを書いた。学習の最後でlayer0とlayer1のオブジェクトをcPickleでファイルにダンプしておくコードを追加した。&quot;wb&quot;))こうして学習結果をファイルにダンプしておけばまた最初から学習しなおさなくてすむ。学習したフィルタの重みとバイアスはこのオブジェクトのインスタンス変数Wやbで取得できる。汎用的ではないけどフィルタと畳み込み層(プーリング層ではない)の出力画像を可視化するスクリプト。学習したフィルタ重みとバイアスをもとに再度畳み込みニューラルネットを構築しなおしている。layer0.outputやlayer1.outputがそのまま使えると期待したけどTheanoのエラーが出てうまいくいかなかった。あとでもっとよい方法が思いついたら書き直すかも。TutorialのCNNの説明はわかりにくく、これだけでは理解できなかった。次のサイト、書籍、論文で何とか自分なりに理解できたと思う。Theanoで実装する上での補足説明がわかりやすい。6章の説明が一番わかりやすい。上の本と同じく岡谷さんの解説論文。専門的だが上の本の後に読んだらすんなり理解できた。Stanford大学の講義資料。Tutorialと表記法が違うので混乱するかも。»プロフィールid:aidiary人工知能とその関連分野に興味があります。Blog|ブログを報告する。