C#の深層学習ライブラリ「KelpNet」
KelpNetは、春条さんによって開発されたC#の深層学習ライブラリです。今回の記事では、このKelpNetとインストール方法を説明します。
C#だけで実装された深層学習ライブラリ『KelpNet』を公開しています
— 春条 (@harujoh) 2016年12月10日
・『Keras』や『Chainer』のように関数を書き連ねる記述スタイルを採用
・数学が苦手な人でも深層学習の仕組みを理解できる様に行列演算は未使用https://t.co/5NhfIIIHEG
この記事は、初めて深層学習のライブラリを使用する方・今まで他のライブラリを使ってきたけどKelpNetも気になる方などを対象としています。この記事を読み終える頃には、「KelpNetとはどのような深層学習ライブラリなのか」「KelpNetの使い方」「KelpNetの導入方法」が分かるようになっており、説明もその順番で行われています。
KelpNet
KelpNetは、C#だけで実装された深層学習のライブラリです。GitHubのページによると、以下のような特徴があります。
また、C#であることから以下のようなメリットがあります。
- 開発環境の構築が容易で、プログラミング初学者にも学びやすい言語です
- WindowsFormやUnity等、処理結果を視覚的に表示するための選択肢が豊富です
- PCや携帯、組み込み機器等、様々なプラットフォームに向けたアプリケーションの開発ができます
この中でも、個人的には特に「Chainerライクであり簡単に使うことが出来ること」「Unityで使用可能であること」がKelpNetの強みだと思います。
C#の深層学習ライブラリは、KelpNetの他にTensorFlowSharpやNeuralNet.Net、Accord.Netなどがあります。しかし、TensorFlowSharpやNeuralNet.Netは低次元のAPIであるため複雑で初学者には難しく、Accord.Netは複雑なネットワークは実装出来ません。それらと比較してKelpNetはChainerライクの高次元なAPIであるため直観的に簡単に扱うことが出来るだけでなく、複雑なネットワークも設計出来ます。
また、最近Unityで任意の環境とエージェントを構築し、それらを用いて深層強化学習を行うことが盛んになってきています。KelpNetを用いることで、環境・エージェント・ニューラルネットワークをC#だけで比較的簡単に構築することが出来ます。
ネットワークの定義
KelpNetでは、以下のように層や関数をFunctionStackに書き連ねることで定義します。 ネットワークの構成は、次のようになっています。
- ネットワーク構成
- 畳み込み層
- バッチ正規化(BatchNormalization)
- 正規化線形関数(ReLU)
- 全結合層
- バッチ正規化(BatchNormalization)
- 正規化線形関数(ReLU)
- 全結合層
- ソフトマックス関数
- 最適化手法: Adam
FunctionStack model = new FunctionStack( new Convolution2D(inputChannels: 3, outputChannels: 32, kSize: 5, pad: 2, name: "l1 Conv2D"), new BatchNormalization(32, name: "l1 BatchNorm"), new ReLU(name: "l1 ReLU"), new Linear(5 * 5 * 64, 256, name: "l2 Linear"), new BatchNormalization(256, name: "l2 BatchNorm"), new ReLU(name: "l2 ReLU"), new Linear(256, 3, name: "l3 Linear"), new Softmax(name: "l3 Softmax") ); // 最適化手法の設定 model.SetOptimizer(new Adam());
このように、KelpNetではFunctionStackに関数を積み重ねることでネットワークを構築します。また、ネットワークを構築した後にSetOptimizerを用いることで最適化手法を適用することが出来ます。
ネットワークの構築に用いる関数は、現状では以下のものが実装されています。また、KelpNetはC#のみで実装されているので、以下に含まれていない関数も実装済みの関数を参考にして自分で追加することが出来ます。
- Activations: ELU,LeakyReLU,ReLU,Sigmoid,Tanh,Softmax,Softplus,Swish
- Connections: Linear,Convolution2D,Deconvolution2D,EmbedID,LSTM
- Poolings: AveragePooling,MaxPooling
- LossFunctions: MeanSquaredError,SoftmaxCrossEntropy
- Optimizers: SGD,MomentumSG, AdaDelta,AdaGrad,Adam,RMSprop
- Normalize: BatchNormalization,LRN
- Noise: DropOut,StochasticDepth
ネットワークの学習
KelpNetでは、順伝播・損失の計算・誤差逆伝播・更新を1行でまとめて行う方法と別々に行う方法の2種類の方法で学習を行うことが出来ます。
まとめて記述する方法は、以下のようなTrainerのTrainという関数を用います。この方法は、順伝播を行う前に教師データを用意できる教師あり学習を行う際に便利です。
- Trainer.Train(functionStack, input, teach, lossFunction, isUpdate = true)
- Parameters
- functionStack (FunctionStack): ネットワークのモデル
- input (NdArray): ネットワークへの入力
- teach (NdArray): 教師データ
- lossFunction (LossFunction): 損失関数
- isUpdate (bool): ネットワークの更新を行うかどうか
- Return
- sumLoss (Real): 損失の合計
また、別々に記述する場合は損失関数を定義した後に、それぞれForward, lossFunction.Evaluate, Backward, Updateを行うことで実行します。この方法は、順伝播を行う前に教師データを用意できない強化学習を行う際に便利です。
// 訓練データからランダムにデータを取得 TestDataSet dataset = mnistData.GetRandomXSet(BATCH_DATA_COUNT); // 1. まとめて記述する方法 Trainer.Train(model, dataset.Data, dataset.Label, new SoftmaxCrossEntropy()); // 2. 順伝播, 損失の計算, 誤差逆伝播, 更新で別々に記述する方法 LossFunction lossFunction = new SoftmaxCrossEntropy(); NdArray[] output = model.Forward(input); Real loss = lossFunction.Evaluate(output, dataset.Label); model.Backward(output); model.Update();
モデルの保存・読み込み
KelpNetは、ModelIOを用いて以下のような方法でモデルの保存・読み込みが可能です。ModelIO.Save()の第一引数は保存したいモデル(FunctionStack)であり、第二引数は保存時のファイル名です。ModelIO.Load()の引数は読み込みたいモデルのファイル名です。
// 学習の終わったネットワークを保存 ModelIO.Save(model, "test.nn"); // 学習の終わったネットワークを読み込み FunctionStack testModel = ModelIO.Load("test.nn");
インストール方法
KelpNetは、以下の2種類の方法で使用することが出来ます。
- KelpNetのプロジェクトフォルダをそのまま自分のプロジェクトに追加
- KelpNetのプロジェクトをビルドしてDLL化し、自分のプロジェクトに追加
そのまま使用する方法は、KelpNet自体のコードを確認しながらコーディングしやすいというメリットがあります。DLL化してから使用する方法は、「複数のソースファイルを1つのファイルにまとめることが出来ること」「コンパイル時間を短縮できる」などのメリットがあります。ここで、DLLとはダイナミックリンクライブラリの略であり、プログラムの実行時にリンクされるライブラリのことです。
今回はVisual Studioを用いて説明を行います。もし同様にVisual Studioを用いる方は、以下からダウンロードが出来ます。
インストールを行う前に、GitHubからKelpNetのリポジトリをクローンします。以下で、それぞれの方法について説明していきます。
git clone https://github.com/harujoh/KelpNet.git
そのまま使用する方法
まず、KelpNetを使用するプロジェクトを作成します。プロジェクトの形態は「コンソールアプリ」で大丈夫です。
プロジェクトが作成出来たら、先ほどクローンしたKelpNetのフォルダ内のKelpNet、Clooという2つのフォルダを自分のソリューションのフォルダ内にコピーします。
次に、ソリューションエクスプローラー内のソリューションを右クリックし、追加→既存のプロジェクトを選択し、自分のソリューションのフォルダ内のKelpNetフォルダに入っているKelpNet.csprojを選択して追加します。
ソリューションエクスプローラーに追加出来たら、ソリューションエクスプローラーのXORプロジェクト内の参照を右クリックし、参照の追加を選択します。
すると参照マネージャーが表示されるので、左側のプロジェクトタブをクリックし、KelpNetにチェックを入れます。これで自分のプロジェクトからKelpNetを参照できます。Clooも同様にCloo.csprojを選択し参照に追加することで使用できます。
最後に、畳み込み層(Convolution2D)などで必要なSystem.Drawingをプロジェクトの参照に追加します。先ほどと同様に、ソリューションエクスプローラーの参照を右クリックし、参照の追加を選択します。すると参照マネージャーが表示されるので、アセンブリタブをクリックし、System.Drawingにチェックを入れ、OKをクリックします。
DLL化して使用する方法
はじめにdllを作成する方法を説明し、次に作成したdllを使用する方法を説明します。まず、Visual Studioで先ほどクローンしたフォルダ内のプロジェクトファイルである KelpNet/KelpNet/KelpNet.csproj を開きます。
次に、ソリューションのビルドを実行します。
すると、KelpNet/KelpNet/bin/Debugの中にKelpNet.dllとCloo.dllが作成できていると思います。Cloo.dllはOpenCLを用いる際に使用します。
次に、dllを使用する方法を説明します。まず、KelpNetを使用するプロジェクトを作成します。プロジェクトの形態はとりあえず「コンソールアプリ」で大丈夫です。
プロジェクトが作成出来たら、先ほど作成したKelpNet.dllとCloo.dllをプロジェクトフォルダ内にコピーします。次に、ソリューションエクスプローラーの参照を右クリックし、参照の追加を選択します。すると参照マネージャーが表示されるので、左側の参照タブをクリックし、右下の参照をクリックしてプロジェクトフォルダ内のKelpNet.dllとCloo.dllをそれぞれ追加します。
最後に、畳み込み層(Convolution2D)などで必要なSystem.Drawingをプロジェクトの参照に追加します。先ほどと同様に、ソリューションエクスプローラーの参照を右クリックし、参照の追加を選択します。すると参照マネージャーが表示されるので、アセンブリタブをクリックし、System.Drawingにチェックを入れ、OKをクリックします。
これで、KelpNetを使用することが出来るようになります。
以上でKelpNetの導入は終了です。KelpNetは導入から使用までとても簡単に行うことが出来るとても良いライブラリです。私自身もUnityで機械学習を行う際などに使用しています。ご質問やご指摘・改善案などございましたら、私か春条さん(@harujoh)にリプかDMを頂ければ喜んで対応させて頂きます。KelpNetがより多くの方に知られ、利用されるようになるととても嬉しいです。