C#の深層学習ライブラリ「KelpNet」

KelpNetは、春条さんによって開発されたC#の深層学習ライブラリです。今回の記事では、このKelpNetとインストール方法を説明します。

この記事は、初めて深層学習のライブラリを使用する方・今まで他のライブラリを使ってきたけどKelpNetも気になる方などを対象としています。この記事を読み終える頃には、「KelpNetとはどのような深層学習ライブラリなのか」「KelpNetの使い方」「KelpNetの導入方法」が分かるようになっており、説明もその順番で行われています。

KelpNet

KelpNetは、C#だけで実装された深層学習のライブラリです。GitHubのページによると、以下のような特徴があります。

  • 行列演算をライブラリに頼らないため全ソースが可読になっており、どこで何をしているかを全て観測できます
  • KerasやChainerが採用している、関数を積み重ねるように記述するコーディングスタイルを採用しています
  • 並列演算にOpenCLを採用しているため、GPUだけでなくCPUやFPGA等の様々な演算装置で処理を並列化できます

また、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種類の方法で使用することが出来ます。

  1. KelpNetのプロジェクトフォルダをそのまま自分のプロジェクトに追加
  2. KelpNetのプロジェクトをビルドしてDLL化し、自分のプロジェクトに追加

そのまま使用する方法は、KelpNet自体のコードを確認しながらコーディングしやすいというメリットがあります。DLL化してから使用する方法は、「複数のソースファイルを1つのファイルにまとめることが出来ること」「コンパイル時間を短縮できる」などのメリットがあります。ここで、DLLとはダイナミックリンクライブラリの略であり、プログラムの実行時にリンクされるライブラリのことです。

今回はVisual Studioを用いて説明を行います。もし同様にVisual Studioを用いる方は、以下からダウンロードが出来ます。

visualstudio.microsoft.com

インストールを行う前に、GitHubからKelpNetのリポジトリをクローンします。以下で、それぞれの方法について説明していきます。

git clone https://github.com/harujoh/KelpNet.git

そのまま使用する方法

まず、KelpNetを使用するプロジェクトを作成します。プロジェクトの形態は「コンソールアプリ」で大丈夫です。

f:id:jinbeizame007:20180820132930p:plain:w700

プロジェクトが作成出来たら、先ほどクローンしたKelpNetのフォルダ内のKelpNet、Clooという2つのフォルダを自分のソリューションのフォルダ内にコピーします。

次に、ソリューションエクスプローラー内のソリューションを右クリックし、追加→既存のプロジェクトを選択し、自分のソリューションのフォルダ内のKelpNetフォルダに入っているKelpNet.csprojを選択して追加します。

f:id:jinbeizame007:20180820171359p:plain:w700

ソリューションエクスプローラーに追加出来たら、ソリューションエクスプローラーのXORプロジェクト内の参照を右クリックし、参照の追加を選択します。

すると参照マネージャーが表示されるので、左側のプロジェクトタブをクリックし、KelpNetにチェックを入れます。これで自分のプロジェクトからKelpNetを参照できます。Clooも同様にCloo.csprojを選択し参照に追加することで使用できます。

f:id:jinbeizame007:20180820171839p:plain:w700

最後に、畳み込み層(Convolution2D)などで必要なSystem.Drawingをプロジェクトの参照に追加します。先ほどと同様に、ソリューションエクスプローラーの参照を右クリックし、参照の追加を選択します。すると参照マネージャーが表示されるので、アセンブリタブをクリックし、System.Drawingにチェックを入れ、OKをクリックします。

f:id:jinbeizame007:20180822191656p:plain:w700

DLL化して使用する方法

はじめにdllを作成する方法を説明し、次に作成したdllを使用する方法を説明します。まず、Visual Studioで先ほどクローンしたフォルダ内のプロジェクトファイルである KelpNet/KelpNet/KelpNet.csproj を開きます。

f:id:jinbeizame007:20180820131533p:plain:w700

次に、ソリューションのビルドを実行します。

f:id:jinbeizame007:20180820132124p:plain:w700

すると、KelpNet/KelpNet/bin/Debugの中にKelpNet.dllとCloo.dllが作成できていると思います。Cloo.dllはOpenCLを用いる際に使用します。

次に、dllを使用する方法を説明します。まず、KelpNetを使用するプロジェクトを作成します。プロジェクトの形態はとりあえず「コンソールアプリ」で大丈夫です。

f:id:jinbeizame007:20180820132930p:plain:w700

プロジェクトが作成出来たら、先ほど作成したKelpNet.dllとCloo.dllをプロジェクトフォルダ内にコピーします。次に、ソリューションエクスプローラーの参照を右クリックし、参照の追加を選択します。すると参照マネージャーが表示されるので、左側の参照タブをクリックし、右下の参照をクリックしてプロジェクトフォルダ内のKelpNet.dllとCloo.dllをそれぞれ追加します。

f:id:jinbeizame007:20180820133546p:plain:w700

最後に、畳み込み層(Convolution2D)などで必要なSystem.Drawingをプロジェクトの参照に追加します。先ほどと同様に、ソリューションエクスプローラーの参照を右クリックし、参照の追加を選択します。すると参照マネージャーが表示されるので、アセンブリタブをクリックし、System.Drawingにチェックを入れ、OKをクリックします。

f:id:jinbeizame007:20180822191656p:plain:w700

これで、KelpNetを使用することが出来るようになります。

以上でKelpNetの導入は終了です。KelpNetは導入から使用までとても簡単に行うことが出来るとても良いライブラリです。私自身もUnityで機械学習を行う際などに使用しています。ご質問やご指摘・改善案などございましたら、私か春条さん(@harujoh)にリプかDMを頂ければ喜んで対応させて頂きます。KelpNetがより多くの方に知られ、利用されるようになるととても嬉しいです。