Excelで作る人工知能

# はじめに

ディープラーニングのフレームワークの自作をしています。
前回記事 : [ディープラーニングのフレームワークの自作](http://qiita.com/teatime77/items/f46dd34a19b7052583ed)

マルチプラットフォームで動作させるのが目標ですが、とりあえずExcelから使えるようにしました。

サンプルアプリとして機械学習ではおなじみのMNISTの手書き数字を認識するプログラムを作りました。
下図のように正解数をグラフにプロットします。

![mnist_screen](http://lkzf.info/mkfn/img/mnist_screen.png)

ネットワークの構成は４層の畳み込みニューラルネットワークでC++版とCUDA版があります。
![mnist_screen](http://lkzf.info/mkfn/img/layers.png)



単純な確率的勾配降下法を使い、ドロップアウトや正則化などは未実装です。
正解率は９８%くらいです。

# 全体の構成

![全体の構成](http://lkzf.info/mkfn/img/overview.png)

以下はフレームワークの全体の流れです。
1. レイヤーの順伝播の式を記述します。(全結合 , 畳み込み(CNN) , 再帰型(RNN) , LSTM など)
2. 逆伝播の式を数式処理で生成します。
3. レイヤーのソースコードを生成します。（順伝播、誤差逆伝播、パラメータ更新)
4. 確率的勾配降下法(SGD)などのメインのルーチンを各プログラミング言語で記述します。

**3**で生成されたC++のソースコードは、**malloc**などのメモリー操作や**exp**などの数学関数しか使ってないので、色々なプラットフォームに簡単に移植できると思っています。

今回のサンプルアプリでは**CUDA**や**C++**のDLLを.NETのラッパーDLLで包んで、それをExcelのVBAからアクセスします。
確率的勾配降下法(SGD)などのメインの ルーチンはVBAで記述します。

VBAのソースは以下にあります。
[http://lkzf.info/mkfn/download/MNIST-VBA.zip](http://lkzf.info/mkfn/download/MNIST-VBA.zip)

# 実行の手順

以下はサンプルの実行の手順です。
1. 実行用のファイルをダウンロードします。
2. .NETとC++のランタイムをインストールします。
3. .NETのラッパーDLLをCOMとして登録します。
4. Excelで空白のブックを作ります。
5. .NETのラッパーDLLの参照設定をします。
6. VBAのソースファイルをインポートします。
7. イミディエイトウィンドウから実行します。

以下で詳しく手順を説明します。
# １．実行用のファイルをダウンロードします。

以下のリンクからZIPファイルをダウンロードして適当なフォルダに解凍します。
**32bit版Excel用** : [http://lkzf.info/mkfn/download/MNIST32.zip](http://lkzf.info/mkfn/download/MNIST32.zip)
**64bit版Excel用** : [http://lkzf.info/mkfn/download/MNIST64.zip](http://lkzf.info/mkfn/download/MNIST64.zip)  
※ OSが64bitでもExcelはデフォルトでは32bit版がインストールされます。
OSが64bitでExcelが32bit版の場合は**32bit版Excel用**を使ってください。
※ 32bit版のCUDAはありませんので、CUDAが使えるPCでは64bit版のExcelがおすすめです。  


# ２．.NETとC++のランタイムをインストールします。

**.NET Framework 4.5.2**
[https://www.microsoft.com/ja-JP/download/details.aspx?id=42643](https://www.microsoft.com/ja-JP/download/details.aspx?id=42643)

**Microsoft Visual C++ 2015 再頒布可能パッケージ Update 3 RC**
[https://www.microsoft.com/ja-jp/download/details.aspx?id=52685](https://www.microsoft.com/ja-jp/download/details.aspx?id=52685)

すでにインストール済みならこの手順は必要ありません。
インストール済みかどうか分からない場合は、とりあえずこの手順をスキップして、エラーになったらインストールしてみてください。

# ３．.NETのラッパーDLLをCOMとして登録します。
管理者権限でコマンドプロンプトを開き、解凍したファイルのフォルダに移動します。

![コマンドプロンプト-管理者](http://lkzf.info/mkfn/img/admin_cmd.png)

コマンドプロンプトで以下のコマンドを入力します。
**`RegAsm.exe LayerNET.dll /codebase /tlb`**  
**RegAsm.exe**は以下のフォルダのものを使います。

32bit版Excelの場合
C:\Windows\Microsoft.NET\Framework\バージョン番号

64bit版Excelの場合
C:\Windows\Microsoft.NET\Framework64\バージョン番号  
バージョン番号は**v4.0**以上のものを使ってください。

![regasm](http://lkzf.info/mkfn/img/regasm.png)


# ４．Excelで空白のブックを作ります。
Excel 2016で空白のブックを新規作成し、解凍したフォルダ(MNIST.basがあるフォルダ)の中に、Excelマクロ有効ブック(*.xlsm)として保存します。
(Excel 2016以外でも動作すると思いますが未確認です。)

# ５．.NETのラッパーDLLの参照設定をします。
Excelの**開発**のリボンで**Visual Basic**をクリックしてVBAの開発ウインドウを表示します。
![開発リボン](http://lkzf.info/mkfn/img/dev_ribbon.png)


開発ウインドウのメニューの**ツール - 参照設定**をクリックします。

![参照設定メニュー](http://lkzf.info/mkfn/img/ref_menu.png)


参照設定画面のリストをスクロールして**LayerNET**をチェックして、**OK**をクリックします。
![.NETのラッパーDLLの参照](http://lkzf.info/mkfn/img/ref_layernet.png)

# ６．VBAのソースファイルをインポートします。
開発ウインドウのメニューの**ファイル - ファイルのインポート**をクリックします。
![インポート メニュー](http://lkzf.info/mkfn/img/import_menu.png)

**MNIST.bas**をインポートします。
![インポート VBA](http://lkzf.info/mkfn/img/import_vba.png)

# ７．イミディエイトウィンドウからサンプルプログラムを実行します。  
**イミディエイト**ウィンドウで**TestMNIST**と入力します。

![TestMNIST](http://lkzf.info/mkfn/img/test_mnist.png)

下図のようにExcelのブックに停止ボタンとグラフが追加され、ミニバッチ内の進行状況が表示されます。
ミニバッチの値が6000になると最初のエポックの正解数が表示されます。
![TestMNIST](http://lkzf.info/mkfn/img/init_screen.png)
パラメータは乱数で初期化しているので、実行結果は毎回違います。
10エポックしても正解率が上がらない場合は、停止ボタンを押してからもう一度**TestMNIST**を実行してください。
VBAのソースの中の**UseCUDA**を**True**にするとCUDA版が動作します。


# 実行用のDLLファイルをソースファイルからビルドする方法
Visual Studio 2015を使います。
CUDA版(**LayerCUDA.dll**)のビルドには**CUDA Toolkit 8.0**が必要です。
[https://developer.nvidia.com/cuda-downloads](https://developer.nvidia.com/cuda-downloads)

1. ソースファイルをダウンロードします。
[http://lkzf.info/mkfn/download/mkfn-master.zip](http://lkzf.info/mkfn/download/mkfn-master.zip)
以下では **MKFN**というフォルダにダウンロードしたとして説明します。

2. **MKFN\mkfn.sln**をビルドして実行すると、CPU版(**Layer.dll**)とCUDA版(**LayerCUDA.dll**)のレイヤーのソースファイルが生成されます。

3. **MKFN\src\Layer\Layer\Layer.sln**をビルドして**Layer.dll**を作ります。

4. **MKFN\src\Layer\LayerCUDA\LayerCUDA.sln**をビルドして**LayerCUDA.dll**を作ります。

5. 管理者権限でVisual Studio 2015を起動して、**MKFN\src\Layer\LayerNET\LayerNET.sln**をビルドして**LayerNET.dll**を作ります。
※ **LayerNET.dll**はビルド時に「COM 相互運用機能の登録」をするので管理者権限が必要です。
6. **Layer.dll**と**LayerCUDA.dll**と**cudart64_80.dll**を、**LayerNET.dll**があるフォルダにコピーします。
※ **cudart64_80.dll**は**CUDA Toolkit 8.0**のDLLです。
※ 32bit版のCUDAはありません。

# おわりに

とりあえず公開しましたが、まだ手つかずの作業が多いです。
  - レイヤーの動作のドキュメント
  - スピードアップ
  - ドロップアウトや正則化など

開発の進捗はTwitterをご覧ください。
[![Twitter_Logo_White_On_Blue20.png](https://qiita-image-store.s3.amazonaws.com/0/118740/af910f48-8c6b-27cb-7951-eaa6e97afa87.png)](https://twitter.com/teatime77)  [teatime77](https://twitter.com/teatime77)

ここまで読んでいただき、ありがとうございます。

何か誤りがありましたら指摘していただければ幸いです。