概要
今回は、畳み込みニューラルネットワークを利用して、親子丼と牛丼の分類に挑戦しました!
1. CNNとは
1.1 CNNの特徴
CNNは一般的な全結合型ニューラルネットワークと違い、2次元データをそのまま学習に取り込むことができます。例えば、28x28の画像データを学習に利用する場合、全結合ニューラルネットワークでは784x1の1次元ベクトルに変換します。そのため、二次元情報が失われてしまいピクセルが一つずれても、後続データも同様にずらせば同じように学習されてしまいます。CNNでは畳み込み演算という処理によって、2次元空間の情報を取り出します。
1.2 畳み込み
畳み込み演算とは、画像の値とフィルタとの積の和を元の画像に書き込む処理のことです。ここのフィルタとは演算によって画像を加工するもので、例えば3x3の上下方向のエッジを検知するフィルタは以下のようになります。
このフィルタを画像に畳み込み演算を行っていく、下の図のようになる。
例えば、左上の3x3の部分にフィルタを先のフィルタを適用すると、最終的にな和は6となり元の画像の中心に書き込んでいきます。そして、フィルタを1ピクセルずつずらして適用し、画像全体に行っていきます。
このように、縦方向のエッジが存在する領域の数値が高くなります。また、これを見ると複数のフィルタを連続して適用すると、出力がどんどん小さくなっていくことがわかります。これを防ぐために、ゼロパディングという手法をとります。これは、周りをゼロで埋めてからフィルタを適用する手法で、何もしない時より画像の端の情報が反映されやすくなります。
1.2 プーリング
プーリングは、画像の歪みや連れの影響を減らすために行われる処理です。例として、6x6の画像に2x2の最大プーリングを行っていきます。
上図のように2x2の最大プーリングを行うと、出力は元の画像の4分の1サイズになるので、この分の情報がなくなります。
2. PytorchによるCNN実装
2.1データ収集
データ収集は、CookPadから行いました。CookPadでは、レシピカテゴリが下図のように階層構造になっています。今回は、「どんぶりもの」カテゴリの「牛丼」カテゴリと「親子丼」カテゴリから画像を取得しました。
2.2前処理
続いて画像データを学習に利用できるように前処理を行った。画像認識のタスクでは、よく拡張処理を行いデータの水増しを行う。今回は、学習データをtorchvisionというライブラリを利用しました。
- RandomResizedCrop: ランダムにトリミング
- RandomHorizontalFlip: 水平方向反転。(今回は0.2の確率)
- RandomRotation: ランダムに回転(今回は15度の範囲)
- ColorJitter: 明度(brightness)、彩度(saturation)を変化(変化係数0.3に設定)
- Normalize: 平均、標準偏差で正規化
そしてデータを読み込んで、Dataloaderオブジェクトを生成してミニバッチのサイズなどを登録する。学習やテストはこのDataLoaderを呼び出してモデルに入力します。
batch_sizeは64に設定しています。
2.3モデルの作成
今回構築したモデルは以下のような構成になります。
畳み込み層6,プーリング層3,全結合層1, 出力層(全結合層)1の計11層で、活性化関数にReLU関数を利用しています。
2.4モデルの評価
エポックごとのlossとaccuracyのグラフを確認してみました。
かなりいい感じですね。最後にテストデータの結果を調べてみました。
テストデータの結果は84.38%でした。結構いい感じです^^
3.まとめ
今回は、CNNをPytorchを利用して実装し、親子丼と牛丼の画像分類を実施しました。テストデータの結果に関しては、まだ向上が期待できそうなので次回は転移学習を実施してみようと思います。