Sansan Tech Blog

Sansanのものづくりを支えるメンバーの技術やデザイン、プロダクトマネジメントの情報を発信

歴史をたどってディープラーニングを学ぶ第十四回 C#で書かれたシンプルなコンボリューショナルネット(CNN)のコードをGitHubで公開してみる

こんにちは、ニューラルネット老人こと糟谷勇児です。

前回はパーセプトロンのコードを紹介しました。
まあパーセプトロンは誰でもかけるし、ここからが本番。CNNのコードをアップしていきます。


前回はテストデータを同梱していなかったのでダウンロードが必要でしたが、今回は人文学オープンデータ共同利用センターのKuzushiji-MNISTというデータを北本様の許可をメールでいただき、同梱させていただきました。なお、同梱させていただいたデータは最新でない可能性があるため、研究などで理由する場合は本家からダウンロードしていただければと思います。
Kuzushiji-MNISTのデータはこちらからダウンロードできます。
codh.rois.ac.jp

今回公開する、大体LeNetぽいコードは1000行ぐらいで書けるので、皆様にもおすすめです。
大体と書いたのは、ちょっと原作に忠実に作っていなくて、AlexNetを目指して作っていたので

  • プーリング層がサブサンプリングでなくMaxプーリング
  • 2回目のコンボリューション層で出力平面を合体させて数を減らすところがあるがそれが未実装

というあたりです。
詳しくは当時のブログを参照いただければと思います。
buildersbox.corp-sansan.com
もう、ほぼ一年前ですね。

コードはこちらです。
github.com

実装としては

  • NeuralImageという独自の画像を定義するクラスを作り、MaxフィルタやN*Nのフィルタなどの画像処理部分はそのクラスに実装
  • Layerというクラスを継承した、ConvolutionalLayer(コンボリューション層), MaxPoolingLayer(Maxプーリング層), FullyConnectedLayer(全結合層)を実装し、それらのインスタンスをListに詰めていくとニューラルネットが作れる

というような感じです。

VGGまで作ってみて思ったのは、結構実装は自由度高いなということです。というのも、VGG以降は3*3のコンボリューション層を重ねまくったニューラルネットが基本になるため、3*3のコンボリューション層さえ高速化できれば他の部分や5*5など他のパラメータの場合は遅くてもあんまり問題ないんですよね。
なので割と好きに実装していっていいし、もうLeNet, AlexNetを飛ばして3*3のコンボリューション層のみ実装するということでもいいかもしれません。

実際コンボリューション層のバックプロパゲーションの実装で、どのピクセルからどのピクセルにフィードバックがあるかは複雑なので事前にマップを作るというオリジナルの実装になっています。

MNISTで動かしてみるとこんな感じ
f:id:kasuya_ug:20210209113236p:plain
学習は100エポックだけしかしていなく、学習データも2000件だけですが、それでもパーセプトロンより高い精度が出ています。
作ってみると、そんなに実装が難しくないのに結構精度が出るので感動すると思います。

Kuzushiji-MNISTの場合はちょっとバリエーションが多いみたいで4000件を200エポック学習させると80%ぐらいです。

f:id:kasuya_ug:20210209113317p:plain

パーセプトロンの場合は66%だったので、まあまあコンボリューショナルネットのほうが性能いいかなという感じです。


ここの実装の意図が分からないとか、間違っているとかありましたらお気軽にGit Hubにコメントもらえればと思います。
しかし、データを使わせていただけるのはありがたいですね。Sansanでも自由に使えるようなデータを整備していければと思います。



▼本シリーズのほかの記事はこちら
buildersbox.corp-sansan.com

© Sansan, Inc.