前回はネットワークの学習テクニックについて紹介した. 第7章ではCNN (Convolutional Neural Network) について紹介していく.
六章までで, (ニューラル) ネットワークの一般論は一通り扱った. ここでネットワークとは, Layerを表す(殆ど至る所)可微分写像の族と, Loss Function 及び Gradient Function [1]は入力データと訓練データのLoss値を取り, Backpropagationで各Layerにおける重みパラメタの勾配(の族)を返す.の組のことである:
各Layerの重みパラメタ が学習済みかどうかに応じて, しばしばModelとNetworkを使い分けている文脈が存在するが, これらは同じものと考えて良い.[2]検索エンジンの検索結果件数で比較すれば, 学習済みモデル/学習済みネットワーク~35500000/12700000~2.80, 英語だとtrained model/trained … Continue reading
本章の構成は次のようである:
- 全体の構造
- 畳み込み層
- プーリング層
- Convolution / Poolingレイヤの実装
- CNNの実装
- CNNの可視化
- 代表的なCNN
この記事では各項について詳細に触れることはしないが, ある視点で重要と思われる点, 補足があると良いと思われた点についてはその限りではない (このような視点のことを独断と偏見という).
1. 全体の構造について
ここで言う構造とはネットワーク構造のことである.
これまで扱ってきたネットワーク[3]Fully Connected Layersがactivationに受け渡すhidden layersの内, 大半を構成するようなネットワーク.とCNNはある点で全く異なる.
ある点とは, これまで入力となるデータ (通常multi-array) の一つ一つを点と見做してきた — より詳しくは, (例えば次のような3×3の) arrayを考える時, それを平坦化したものと区別をしていなかった:
>>> x
array([[323, 55, 1],
[ 0, 55, 2],
[ 0, 2, 892]])
>>> x.flatten()
array([323, 55, 1, 0, 55, 2, 0, 2, 892])
CNNでは, 入力データの隣接する値の近さや繋がり方を尊重した(重みパラメタと入力データとの二項) 演算を導入することで, 「(真ん中の) 55と892が近い」といった情報が反映された重みパラメータの獲得が期待される. これは画像や映像といった, トポロジーの情報が必要なデータを入力とするネットワークに固有のものだ.[4]座標に関するorder topologyと実数の(subspace)topologyとのproduct topologyが, 有限集合から成る一般次元のmulti-arrayに入るtopologyとしては自然に見えるが, … Continue reading
CNNはまさに画像や映像を入力として扱うために考案された模様.
2. 畳み込み層について
KernelのConvolutionを見てもらえれば詳細が書いてあるが, 昔からある画像フィルタアルゴリズムを利用したLayerの紹介. CNN特有の処理として, Padding / Strideという入力データの空白補填とフィルタ飛び幅によって出力データの次元をコントロールする.
3. プーリング層について
Max PoolingとAverage Poolingがあり[5]それ以外にもあると思うが, 入力データの次元を小さくし, 近傍でのrobustnessを上げ, … Continue reading, 畳み込み層と同様Padding / Strideがある. 重みパラメタは持たない.
4. Convolution / Poolingレイヤの実装
githubレポジトリでソースコードが手に入る. 理論上目新しいものはないが, スクラッチで実装するのは容易ではない. ここでは省略.
5. CNNの実装
実装コードを見ると, 思った通りデータの入出力における次元等, 気にするところが多い. 扱いやすさやmini-batch処理への適用を見据えて, CNNの入力としては以下が良さそうである:
input_data : (データ数, チャンネル, 高さ, 幅)の4次元配列からなる入力データ
この節とは関係ないが, Python 3系のprefixed asterisk
の機能の多さには驚いた. Trey Hunnerの記事が分かりやすい.
unpacking into function call
>>> numbers = [2, 1, 3, 4, 7]
>>> more_numbers = [*numbers, 11, 18]
>>> print(*more_numbers, sep=', ')
2, 1, 3, 4, 7, 11, 18
tuple unpacking
>>> fruits = ['lemon', 'pear', 'watermelon', 'tomato']
>>> first, second, *remaining = fruits
>>> remaining
['watermelon', 'tomato']
>>> first, *remaining = fruits
>>> remaining
['pear', 'watermelon', 'tomato']
>>> first, *middle, last = fruits
>>> middle
['pear', 'watermelon']
理論上は4と同様目新しいものはない.
6. CNNの可視化について
一般物体認識用の8-layered CNNで, 学習過程における重みパラメタでフィルタした結果を逐次表示するという試み.
1層目の畳み込み層では, エッジやブロブ等の低レベルな情報が抽出される.
3層目の畳み込み層では, テクスチャが抽出される.
5層目の畳み込み層では, 車のバンパー, 犬の額等の物体のパーツが抽出される (「反応する」といった方が近い).
出力層では, ダイニングテーブル, 船等の物体クラスを抽出 (反応).
面白いし, そうなるように設計したから説明がつくが, 層を深くすればすぐに説明がつかなくなるだろう.
7. 代表的なCNNについて
手描き数字認識を行うLeNet (1998)とAlexNet (2012)を紹介. AlexNetはDeep Learningの火付け役となったことで業界のトレンドになった. CNNの構成としては, AlexNetから現在の最新のネットワークはそれ程大きく変わっていないとされる.
Footnotes
↑1 | は入力データと訓練データのLoss値を取り, Backpropagationで各Layerにおける重みパラメタの勾配(の族)を返す. |
---|---|
↑2 | 検索エンジンの検索結果件数で比較すれば, 学習済みモデル/学習済みネットワーク~35500000/12700000~2.80 , 英語だとtrained model/trained network~445000000/339000000~1.31 となっており, 「学習済み」対象について, 現時点ではいずれも学習済みモデルと言う方が伝わるのだと思うが, 日本語圏でその差が大きいのはなぜだろう. |
↑3 | Fully Connected Layersがactivationに受け渡すhidden layersの内, 大半を構成するようなネットワーク. |
↑4 | 座標に関するorder topologyと実数の(subspace)topologyとのproduct topologyが, 有限集合から成る一般次元のmulti-arrayに入るtopologyとしては自然に見えるが, そのような議論は既にあるだろうな, きっと. |
↑5 | それ以外にもあると思うが, 入力データの次元を小さくし, 近傍でのrobustnessを上げ, かつ実装が容易で計算効率の良いアルゴリズムと言えばこの二つで良さそう. |