畳み込みニューラルネットワークを初心者にわかりやすく解説

本記事は、以下の書籍を参考に「畳み込みニューラルネットワーク (Convolutional Neural Network)」について説明します。

その他のディープラーニング入門記事については、以下をご覧ください。

スポンサーリンク

畳み込みニューラルネットワーク (CNN) とは

畳み込みニューラルネットワーク (Convolutional Neural Network) とは、周辺のニューロンの特徴をまとめて抽出するニューラルネットワークです。

周辺のニューロンをまとめて抽出すると、以下のようにデータの形状を捉えられるようになります。

「縦」・「横」・「色 (チャンネル)」の3次元の関係を捉えられる

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

従来のニューラルネットワークは以下のように、全結合層 (Affine) を利用します。

Affine = 全結合層ReLU = 中間層の活性化関数Softmax = 出力層の活性化関数

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

Conv = convolution、Affine = 全結合層ReLU = 中間層の活性化関数Softmax = 出力層の活性化関数

なお、出力層に近い場所では、全結合層 (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)を利用します。

オレンジ(FFC000) は、Red = 255, Green =192, Blue =0 です
「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 プーリングはプーリングウィンドウ (ここでは出力) のうち、最も値の大きいものを選択します。

これは、フィルタに一致するニューロンが最も発火しやすい (高い値となる) からです。
(言い換えると、フィルタに一致する要素があるか無いかを見たいので、一番高い値以外は要らない)

7の位置が右にズレている

Max プーリングにより、フィルタの位置ズレを吸収し、「7」を検出できていることがわかります。

畳み込みニューラルネットワーク

CNN アーキテクチャの種類

CNN アーキテクチャについて、改良の歴史順に紹介します。

Evolution of CNN Architectures: LeNet, AlexNet, ZFNet, GoogleNet, VGG and ResNet
It all started with LeNet in 1998 and eventually, after nearly 15 years, lead to ground breaking models winning the ImageNet Large Scale Visual Recognition Chal...

LeNet in 1998

Full connection = 全結合層

Subsampling がプーリングに相当します。

LeNet は以下の7層から構成されます。

AlexNet in 2012

入力は 224 * 224 ピクセルの画像 (227 * 227 の間違いでは?説もある)
MATLAB では入力を 227 * 227 としている

上下2つに分かれている理由は、当時の GPU では1枚に全てのデータが載らなかったからです。

AlexNet は以下の8層から構成されます。

VGG in 2014

conv = Convolutions, 3×3 = フィルターサイズ
詳細:https://qiita.com/mhiro216/items/e54c2ff204512d877f98

Convolutions (畳み込み演算) を連続で行うことでフィルターサイズを小さくする手法です。

VGG は以下の計 16 層から構成されます。(VGG-16 の場合)

なお、各処理の詳細は以下のとおりです。

AlexNet のフィルター (11, 11) と比較して、VGG のフィルターは (3, 3) なので、少ないハイパーパラメータで学習可能です。

GoogLeNet in 2014

22 層で構成

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

https://arxiv.org/pdf/1409.4842.pdf

上記の図 (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

152 層で構成。| ̄↓ 部分がスキップ構造
詳細:https://qiita.com/kenmaro/items/008051dae0bf0ad718cb

ResNet では、Convolutions 処理をスキップ可能な「スキップ構造」を採用しています。

https://arxiv.org/pdf/1512.03385.pdf

これにより、認識精度が上がる場合に層を深くし、学習がうまく行かない場合に畳み込み演算層をスキップ可能になりました。

ディープラーニング (深層学習)

ディープラーニング (深層学習) とは、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 率が下がる (推論精度が良くなる)」 という経験則があります。

https://qiita.com/ikeyasu/items/ea9ced2b8e0fcb3da2be

層を深くする利点

層を深くする利点は以下の3つです。

  • パラメータの数を削減
  • 少ない学習データで学習可能
  • 特徴を他のパターン認識に流用可能

パラメータ数を削減

層を深くした場合は以下のように、少ないパラメータ数で同様以上の表現力を得ることができます。

フィルターサイズパラメータ数
(5, 5)1層5 * 5 = 25
(3, 3)2層3 * 3 * 2 = 18

少ない学習データで学習可能

以下はすべて「7」を表します。

http://yann.lecun.com/exdb/mnist/ より

これらを1層で学習する場合は10種類の画像を学習する必要があります。

一方で、層を深く場合は1層目で以下のように4種類のパーツを学習します。

2層目では、1層目のパーツを組み合わせることで「7」を認識します。

このように、層を深くすると簡単な特徴を学習するだけで良いため、少ないデータでも学習可能となります。

特徴を他のパターン認識に流用可能

層を深くすると、以下のように最小の特徴から学習します。

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

1層目で抽出した特徴は、「7」以外でも流用可能なことがわかります。

終わりに

ディープラーニング入門記事

その他のディープラーニング入門記事は以下のとおりです。

参考資料

畳み込みネットワークの「基礎の基礎」を理解する ~ディープラーニング入門|第2回 - アイマガジン|i Magazine|IS magazine
 ディープラーニングにはいくつかの手法が存在するが、そのなかで最も成功しているのが、畳み込みネットワークである。畳み込みネットワークは主に画像認識で用いられ、その圧倒的な精度ゆえにディープラーニングが注目される1つの要因
畳み込みニューラルネットワーク
畳み込み演算 | 画像や時系列データから特徴を抽出する演算