CNN 1 画像認識基礎

[Aidemy](https://aidemy.net/)　2020/10/2
#はじめに
　こんにちは、んがょぺです！バリバリの文系ですが、AIの可能性に興味を持ったのがきっかけで、AI特化型スクール「Aidemy」に通い、勉強しています。ここで得られた知識を皆さんと共有したいと思い、Qiitaでまとめています。以前のまとめ記事も多くの方に読んでいただけてとても嬉しいです。ありがとうございます！
　今回は、CNNの1つめの投稿になります。どうぞよろしくお願いします。

＊本記事は「Aidemy」での学習内容を「自分の言葉で」まとめたものになります。表現の間違いや勘違いを含む可能性があります。ご了承ください。

今回学ぶこと
・画像認識について
・CNNの実装
・CNNにおけるハイパーパラメータ

#画像認識について
##画像認識とは
・画像認識とは、画像や映像に映る文字や顔などといった「モノ」や「特徴」を検出する技術のことである。
・今回は、__CNN（Convolutional Neural Network:畳み込みニューラルネットワーク）__という、画像認識で広く使われている深層学習方法を学ぶ。

##CNNについて
・CNNは、人間の脳の視覚野と似た構造を持つ__「畳み込み層」__という層を使って特徴抽出を行うニューラルネットワークである。画像認識の分野で特に高い性能を持つ。
・CNNの畳み込み層は、2次元のままの画像データを処理できる。すなわち、__線や角といった2次元的な特徴を抽出するのに優れている__。
・また、畳み込み層の他に、__「プーリング層」__というものもある。プーリング層は、__畳み込み層から得た情報を縮約し、最終的に画像の分類などを行う__。

##畳み込み層について
・畳み込み層は、__入力データの一部分に注目しその部分の画像の特徴を調べる（＝畳みこむ）層である__。
・抽出する特徴については、学習データや損失関数の値によって自動で学習される！
・各特徴（人の顔なら鼻や口など）はプログラム内部では__フィルター(カーネル)__と呼ばれる重み行列として扱われ、各特徴につき一つのフィルターを用いる。

##プーリング層について
・プーリング層は、__畳み込み層からの出力データを縮約（圧縮）し、データ量を削減する層である__。なぜ縮約するのかというと、画像データの特徴のうち、同じ特徴は同じ場所に固まっていることが多く、一方で特徴のない場所も広く分布していることも多いので、__このまま畳み込むと出力に無駄が大きくなるためである__。
・縮約（圧縮）の方法としては、各特徴の最大値をとったり（__Maxプーリング__）、平均をとったり（__Avarageプーリング__）して行う。

##CNNの実装
・Keras+TensorFlowを使ってCNNを実装する。実務上もこれらを使うことがほとんど。
・作成方法は以前やった「教師あり学習」と同じで、__まずSequentialインスタンスを作り、次にaddメソッドで層を一層ずつ追加し、最後にcompileメソッドでコンパイルを行えば良い__。


```python
#インスタンスの作成
model=Sequential()
#層の追加（パラメータは後述）
model.add(Dense(128))
#畳み込み層の追加
model.add(Conv2D(filters=64, kernel_size=(3, 3)))
#プーリング層の追加
model.add(MaxPooling2D(pool_size=(2,2)))
#コンパイル
model.compile(optimizer=sgd,loss="categorical_crossentropy",metrics=["accuracy"])
```

##手書き文字の分類
・CNNを使って手書き文字のデータセットMNISTを分類する。詳しくは省略するが、前項のような流れで行うことができる。
・手書き文字の他に、乗り物や動物の画像のデータセットである「CIFER-10」の分類も行った。

#ハイパーパラメータ
##CNNのハイパーパラメータの概要
・畳み込み層（Conv）のハイパーパラメータ
　・__filters__：抽出する特徴の数
　・__kernel_size__：カーネルの大きさ
　・__strides__：カーネルを動かす距離
　・__padding__：画像の外側に作る余白の大きさ
・プーリング層（Pool）のハイパーパラメータ
　・__pool size__：一度にプーリングする範囲の指定
　・__strides__：プーリング範囲を動かす距離（プーリングの間隔）
　・__padding__：画像の外側に作る余白の大きさ

##畳み込み層（Conv）のハイパーパラメータ
###filters
・filtersは、生成する特徴マップの数、すなわち__抽出する特徴の種類__を指定する。
・filtersは小さすぎると十分に特徴を抽出できず、大きすぎると過学習を引き起こしてしまう。

###kernel_size
・kernel_sizeは、__カーネルの大きさ__を示す。
・カーネルとは、畳み込みに使用する重み行列のことであり、すなわち__特徴を検出するレンズ__のようなものである。
・kernel_sizeが小さすぎると小さな特徴でもレンズに収まりきらずうまく検出できない。逆に大きすぎると本来小さな特徴として検出されるべき特徴も一つの大きな特徴として抽出されてしまう。

###strides
・stridesは、特徴を抽出する間隔、すなわち__カーネルを動かす距離__を指定する。
・stridesの値が小さいほど、特徴を抽出する間隔は短くなるので、細かく特徴量を抽出できる。ただし、重複する部分が多くなるので、同じ箇所の検出が増える。
・しかし、__一般にstridesは小さい方がいい__とされる。デフォルトは最低の（1,1）になっている。

###padding
・paddingとは、__画像の外側に作る余白の大きさ__を示す。余白を作るのは、畳み込み時の意図しない画像の縮小を抑えるためである。また、端のデータの特徴がよく考慮されるようになる、データ更新の頻度が上がる、各層の入出力ユニット数を調整できるなど、様々なメリットがある。
・一般的には追加するピクセルを0にする。これを「ゼロパディング」という。
・__padding=(1,1)__などのように余白の幅を表せる他、Conv2D層では、__padding=valid__,__padding=same__のようにも表せる.前者はパディングを行わず、後者は出力の大きさが入力の大きさと一致するように余白を作る。

##プーリング層（Pool）のハイパーパラメータ
###pool_size
・pool_sizeとは、__一度にプーリングする範囲__のことである。扱いはカーネルと同じで、__レンズのようなものである__。
・pool_sizeが大きければ、特徴の位置が多少変化しても出力が変わらないので、好ましいと言える。__一般的には、（2×2）にする__。

###strides
・stridesは、__プーリング範囲を動かす距離__のことである。畳み込み層のカーネルのときと同じ挙動である。

###padding
・paddingは、畳み込み層のものと同一の働きをする。設定の仕方も同一なので、そちらを参照のこと。

#まとめ
・画像認識の分野では、__CNN(畳み込みニューラルネットワーク)__を使って深層学習する。
・CNNには、画像の一部分を抽出し、特徴を見つける__「畳み込み層（Conv）」__と、データの無駄を減らし精度を上げるために抽出された情報を縮約して分類する__「プーリング層（Pool）」__がある。その他、「教師あり学習」で学んだ「全結合層（Dense）」もある。
・また、ハイパーパラメータも存在する。畳み込み層のハイパーパラメータとしては、抽出する特徴の数を示す__filters__、カーネル(特徴を抽出するレンズ)の大きさを示す__kernel_size__、カーネルを動かす距離を示す__strides__、画像の外側に作る余白の大きさを示す__padding__がある。
・プーリング層（Pool）のハイパーパラメータとしては、一度にプーリングする範囲を示す__pool size__、プーリング範囲を動かす距離を示す__strides__、画像の外側に作る余白の大きさを示す__padding__がある。

今回は以上です。最後まで読んでいただき、ありがとうございました。