本記事は、以下の書籍を参考に「畳み込みニューラルネットワーク (Convolutional Neural Network)」について説明します。
その他のディープラーニング入門記事については、以下をご覧ください。
- 【ディープラーニング入門1】AI・機械学習・ディープラーニングとは
- 【ディープラーニング入門2】パーセプトロン・ニューラルネットワーク
- 【ディープラーニング入門3】バックプロパゲーション (誤差逆伝播法)
- 【ディープラーニング入門4】学習・重み・ハイパーパラメータの最適化
- 【ディープラーニング入門5】畳み込みニューラルネットワーク (CNN) ←イマココ
畳み込みニューラルネットワーク (CNN) とは
畳み込みニューラルネットワーク (Convolutional Neural Network) とは、周辺のニューロンの特徴をまとめて抽出するニューラルネットワークです。
周辺のニューロンをまとめて抽出すると、以下のようにデータの形状を捉えられるようになります。

畳み込みニューラルネットワークは、全結合層 (Affine) の代わりに、畳み込み層 (Convolution) と、プーリング層 (Pooling) を利用します。
従来のニューラルネットワークは以下のように、全結合層 (Affine) を利用します。

畳み込みニューラルネットワークは、以下のように、全結合層 (Affine) の代わりに、畳み込み層 (Convolution) と、プーリング層 (Pooling) を利用します。

なお、出力層に近い場所では、全結合層 (Affine) を利用します。
畳み込み層
畳み込み層で行われる「畳み込み演算」は、画像処理で言う「フィルタ演算」にあたります。
以降では、演算の具体例を見ていきます。
畳み込み演算 (Convolution) とは
畳み込み演算は以下のような演算です。フィルタが重み W に相当します。

畳み込み演算では、以下のようにフィルタと対応する要素を乗算し、その和を求めます。(積和演算)




バイアス B の演算
畳み込みニューラルネットワークでは、以下のようにバイアス B を演算します。

パディング
パディングとは、入力の周囲を0で埋めることで出力のサイズを調整することです。
畳み込み演算を行うと、出力のサイズがどんどん小さくなってしまい、最後は畳み込み演算ができなくなってしまいます。

そこで、入力の周囲を0で埋めることで、出力のサイズを調整します。

ストライド
スライドとは、フィルタの移動させる間隔です。

スライドが大きくなると、出力は小さくなります。
- スライド:1 → 出力 (3,3)
- スライド:2 → 出力 (2,2)
フィルターを増やす

1入力に対して、3つのフィルターでそれぞれ畳み込み演算を行い、3つの出力を得ます。
通常、画像はさまざまな直線・曲線などが組み合わさって構成されるので、1つのフィルタを用いて判別するよりも、複数のフィルタを組み合わせて判別したほうが、識別性能が上がりやすい。
https://www.imagazine.co.jp/%E7%95%B3%E3%81%BF%E8%BE%BC%E3%81%BF%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E3%81%AE%E3%80%8C%E5%9F%BA%E7%A4%8E%E3%81%AE%E5%9F%BA%E7%A4%8E%E3%80%8D%E3%82%92%E7%90%86%E8%A7%A3%E3%81%99/
次元を増やす (カラーの画像認識)
画像の「縦」と「横」の2次元から、「色 (チャンネル)」を追加した3次元を例に見ていきます。
今回、色の表現方法はRGB(Red, Green, Blue)を利用します。

「1入力、1フィルター (1枚のオレンジの7)」です。「色 (チャンネル) = Z 軸方向」に要素を分解してるだけです
入力 X とフィルタ W の要素ごとに畳み込み演算を行い、3つの演算結果 (赤・緑・青) を合計したものが出力となります。
(元々1枚の画像を3つの RGB に分けて計算しただけなので、最後は合計して1枚に戻します。)
畳み込み演算を Python で実装

上記の畳み込み演算を実装した結果が以下のとおりです。
def im2col(input_data, filter_h, filter_w, stride=1, pad=0): """ Parameters ---------- input_data : (データ数, チャンネル, 高さ, 幅)の4次元配列からなる入力データ filter_h : フィルターの高さ filter_w : フィルターの幅 stride : ストライド pad : パディング Returns ------- col : 2次元配列 """ N, C, H, W = input_data.shape out_h = (H + 2*pad - filter_h)//stride + 1 out_w = (W + 2*pad - filter_w)//stride + 1 img = np.pad(input_data, [(0,0), (0,0), (pad, pad), (pad, pad)], 'constant') col = np.zeros((N, C, filter_h, filter_w, out_h, out_w)) for y in range(filter_h): y_max = y + stride*out_h for x in range(filter_w): x_max = x + stride*out_w col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride] col = col.transpose(0, 4, 5, 1, 2, 3).reshape(N*out_h*out_w, -1) return col input = np.array([[[[0,1,2,3],[1,2,3,0],[2,3,0,1],[3,0,1,2]]]]) #入力 X filter = np.array([[0,1,2],[1,2,0],[2,0,1]]) #フィルタ W input_col = im2col(input,3,3,1,1) #引数の詳細はim2col 参照 filter_col = filter.reshape(1, -1).T output = np.dot(input_col,filter_col) #出力 Z print(output.reshape(4,4)) #出力Z の形
im2col の実装は以下より
https://github.com/oreilly-japan/deep-learning-from-scratch/blob/master/common/util.py
プーリング層 (Pooling)
今回はプーリング層でよく利用される、Max プーリングについて説明します。
なお、「プーリング」とは、画像処理で言う「ダウンサンプリング」にあたります。
Max プーリングとは
Max プーリングとは、フィルタの位置ズレを吸収するものです。
Max プーリングはプーリングウィンドウ (ここでは出力) のうち、最も値の大きいものを選択します。
これは、フィルタに一致するニューロンが最も発火しやすい (高い値となる) からです。
(言い換えると、フィルタに一致する要素があるか無いかを見たいので、一番高い値以外は要らない)


Max プーリングにより、フィルタの位置ズレを吸収し、「7」を検出できていることがわかります。
畳み込みニューラルネットワーク
CNN アーキテクチャの種類
CNN アーキテクチャについて、改良の歴史順に紹介します。
LeNet in 1998

Subsampling がプーリングに相当します。
LeNet は以下の7層から構成されます。
- 畳み込み演算層 (Convolutions + sigmoid 関数) を1層
- サブサンプリング層 Subsampling (プーリングに相当) を1層
- 畳み込み演算層 (Convolutions + sigmoid 関数) を1層
- サブサンプリング層 Subsampling (プーリングに相当) を1層
- 中間層 (全結合層 + sigmoid) を2層
- 出力層 (全結合層 + Softmax) を1層
AlexNet in 2012

MATLAB では入力を 227 * 227 としている
上下2つに分かれている理由は、当時の GPU では1枚に全てのデータが載らなかったからです。
AlexNet は以下の8層から構成されます。
- 畳み込み演算層 (Convolutions + ReLU + Max Pooling) で5層
- 中間層 (全結合層 + ReLU + Dropout) を2層
- 出力層 (全結合層 + Softmax) を1層
VGG in 2014

詳細:https://qiita.com/mhiro216/items/e54c2ff204512d877f98
Convolutions (畳み込み演算) を連続で行うことでフィルターサイズを小さくする手法です。
VGG は以下の計 16 層から構成されます。(VGG-16 の場合)
- 畳み込み演算層 ( (Convolutions + ReLU) * 2 + Max Pooling) を2回で4層
- 畳み込み演算層 ( (Convolutions + ReLU) * 3 + Max Pooling) を3回で9層
- 中間層 (全結合層 + ReLU + Dropout) を2層
- 出力層 (全結合層 + Softmax) を1層
なお、各処理の詳細は以下のとおりです。
- Convolutions のパディングは (1, 1) なので出力のサイズは同じ (64→64, ... ,512→512→512)
- Convolutions フィルター数の増加により、チャンネルの次元を増加 (64→128...→512)
- Max Pooling (= ストライド2) により、出力のサイズを半分に (224→112...→7)
AlexNet のフィルター (11, 11) と比較して、VGG のフィルターは (3, 3) なので、少ないハイパーパラメータで学習可能です。
GoogLeNet in 2014

GoogLeNet の最大の特徴は、サイズの異なるフィルター + Max Pooling の結果を結合する「インセプション構造」を持つことです。

上記の図 (b) では、すべての要素に (1, 1) のフィルターを適用していますが、これはチャネル方向の次元を減らすためです。これにより、ハイパーパラメータの数を削減したり、処理を高速化可能です。
なお、インセプション構造を利用するモチベーションは以下のサイトにわかりやすく解説されています。
2013-2014 年当時、層を深くしたり、各層に存在しているユニットの数を増やしたりすることで、分類の性能が上がることが知られ始めた。しかし、少ないデータの中で、層数やユニット数を増やすことで、過学習を起こしてしまう。そこで、開発者らは Inception と呼ばれるモジュールを作り、その Inception モジュールを重ねていくことで、層を深くすることができた。
これまでのアーキテクチャは、畳み込み層を順列に繋げていた。このため、畳み込み層が深くなるにつれ、画像サイズが小さくなっていき、層を深くすることができなかった。これに対して、GoogLeNet では、1 つの入力画像に対して、複数の畳み込み層(1×1, 3×3, 5×5)を並列に適用し、それぞれの畳み込み計算の結果を最後に連結している。この一連の作業をモジュールとしてまとめられ、Inception モジュールと呼ばれている。
https://axa.biopapyrus.jp/deep-learning/cnn/image-classification/googlenet.html
ResNet in 2015

詳細:https://qiita.com/kenmaro/items/008051dae0bf0ad718cb
ResNet では、Convolutions 処理をスキップ可能な「スキップ構造」を採用しています。

これにより、認識精度が上がる場合に層を深くし、学習がうまく行かない場合に畳み込み演算層をスキップ可能になりました。
ディープラーニング (深層学習)
ディープラーニング (深層学習) とは、4層以上のニューラルネットワークを利用して学習する方法です。
深層学習として最も普及した手法は、(狭義には4層以上[2][注釈 2]の)多層の人工ニューラルネットワーク(ディープニューラルネットワーク、英: deep neural network; DNN)による機械学習手法である[3]。
https://ja.wikipedia.org/wiki/%E3%83%87%E3%82%A3%E3%83%BC%E3%83%97%E3%83%A9%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0
「層を深くする」有用性について理論的にはまだまだわからないことが多いのが現状です。
一方で、「層を深くする」ことで「error 率が下がる (推論精度が良くなる)」 という経験則があります。

層を深くする利点
層を深くする利点は以下の3つです。
- パラメータの数を削減
- 少ない学習データで学習可能
- 特徴を他のパターン認識に流用可能
パラメータ数を削減
層を深くした場合は以下のように、少ないパラメータ数で同様以上の表現力を得ることができます。
フィルターサイズ | 層 | パラメータ数 |
---|---|---|
(5, 5) | 1層 | 5 * 5 = 25 |
(3, 3) | 2層 | 3 * 3 * 2 = 18 |

少ない学習データで学習可能
以下はすべて「7」を表します。

これらを1層で学習する場合は10種類の画像を学習する必要があります。
一方で、層を深く場合は1層目で以下のように4種類のパーツを学習します。
2層目では、1層目のパーツを組み合わせることで「7」を認識します。

このように、層を深くすると簡単な特徴を学習するだけで良いため、少ないデータでも学習可能となります。
特徴を他のパターン認識に流用可能
層を深くすると、以下のように最小の特徴から学習します。

そのため、以下のように抽出した特徴を他のパターン認識に流用可能です。

1層目で抽出した特徴は、「7」以外でも流用可能なことがわかります。
終わりに
ディープラーニング入門記事
その他のディープラーニング入門記事は以下のとおりです。
- 【ディープラーニング入門1】AI・機械学習・ディープラーニングとは
- 【ディープラーニング入門2】パーセプトロン・ニューラルネットワーク
- 【ディープラーニング入門3】バックプロパゲーション (誤差逆伝播法)
- 【ディープラーニング入門4】学習・重み・ハイパーパラメータの最適化
- 【ディープラーニング入門5】畳み込みニューラルネットワーク (CNN) ←イマココ
参考資料
