C#でDeep Learning(Accord.NETによる方法)

流行りのDeep LearningをC#で試してみる.機械学習やコンピュータビジョン,信号処理等の.NET向けのオープンソースのライブラリであるAccord.NET FrameworkにDeep Learningが実装されているのでそれを使う.

Deep Belief Networks(DBN), Deep Neural Networks(DNNs)とおまけにRestricted Boltzmann Machine(RBM)を単体で動かしてみる.

Deep Learning自体については以下のページ等を参考に.
MIRU2014 tutorial deeplearning
Deep Learning技術の今
ディープラーニング チュートリアル(もしくは研究動向報告)

Accord.NETのインストール

NuGet経由でインストール可能.プロジェクトを右クリックして「NuGetパッケージの管理」を選択する.オンラインから「Accord.Neuro」を検索・インストール.

f:id:whoopsidaisies:20140819013518p:plain

ソースコード

を動かすサンプルコードを載せていくが,いずれのサンプルでも以下のusingを書いておくこと.

using Accord.Neuro;
using Accord.Neuro.Networks;
using Accord.Neuro.Learning;
using AForge.Neuro.Learning;
using Accord.Neuro.ActivationFunctions;
using Accord.Math;

Deep Belief Networks(DBN) - 教師あり学習(Back propagation)

// トレーニングデータ
double[][] inputs = {
    new double[] { 1, 1, 1, 0, 0, 0 },
    new double[] { 1, 0, 1, 0, 0, 0 },
    new double[] { 1, 1, 1, 0, 0, 0 },
    new double[] { 0, 0, 1, 1, 1, 0 },
    new double[] { 0, 0, 1, 1, 0, 0 },
    new double[] { 0, 0, 1, 1, 1, 0 },
};
double[][] outputs = {
    new double[] { 1, 0 },
    new double[] { 1, 0 },
    new double[] { 1, 0 },
    new double[] { 0, 1 },
    new double[] { 0, 1 },
    new double[] { 0, 1 },
};

// DBNの生成
var network = new DeepBeliefNetwork(
    inputsCount: inputs.Length,         // 入力層の次元
    hiddenNeurons: new int[] { 4, 2 }); // 隠れ層と出力層の次元

// ネットワークの重みをガウス分布で初期化する
new GaussianWeights(network).Randomize();
network.UpdateVisibleWeights();

// DBNの学習アルゴリズムの生成  5000回繰り返し入力
var teacher = new BackPropagationLearning(network);                        
for (int i = 0; i < 5000; i++)
    teacher.RunEpoch(inputs, outputs);

// 重みの更新
network.UpdateVisibleWeights();

// 学習されたネットワークでテストデータが各クラスに属する確率を計算
double[] input = { 1, 1, 1, 1, 0, 0 };
var output = network.Compute(input);

//  一番確率の高いクラスのインデックスを得る
int imax; output.Max(out imax);

// 結果出力
Console.WriteLine("class : {0}", imax);
foreach (var o in output)
{
    Console.Write("{0} ", o);
}

実行結果

class : 0
0.883118949465337 0.115560850111682

Deep Belief Networks(DBN) - 教師なし学習(Contrastive Divergence)

// トレーニングデータ
double[][] inputs = {
    new double[] { 1, 1, 1, 0, 0, 0 },
    new double[] { 1, 0, 1, 0, 0, 0 },
    new double[] { 1, 1, 1, 0, 0, 0 },
    new double[] { 0, 0, 1, 1, 1, 0 },
    new double[] { 0, 0, 1, 1, 0, 0 },
    new double[] { 0, 0, 1, 1, 1, 0 },
};

// DBNの生成
var network = new DeepBeliefNetwork(
    inputsCount: 6,
    hiddenNeurons: new int[] { 4, 2 });

// ネットワークの重みをガウス分布で初期化する
new GaussianWeights(network).Randomize();
network.UpdateVisibleWeights();

// DBNの学習アルゴリズムの生成  5000回繰り返し入力
var teacher = new DeepBeliefNetworkLearning(network)
{
    Algorithm = (h, v, i) => new ContrastiveDivergenceLearning(h, v)
};
var layerData = teacher.GetLayerInput(inputs);
for (int i = 0; i < 5000; i++)
    teacher.RunEpoch(layerData);
// 重みの更新
network.UpdateVisibleWeights();

// 学習されたネットワークでテストデータが各クラスに属する確率を計算
double[] input = { 1, 1, 1, 1, 0, 0 };
var output = network.Compute(input);

//  一番確率の高いクラスのインデックスを得る
int imax; output.Max(out imax);

// 結果出力
Console.WriteLine("class : {0}", imax);
foreach (var o in output)
{
    Console.Write("{0} ", o);
}

実行結果

class : 1
0.529437183967883 0.554114047128916

Deep Neural Networks(DNNs)

// トレーニングデータ
double[][] inputs = {
    new double[] { 1, 1, 1, 0, 0, 0 },
    new double[] { 1, 0, 1, 0, 0, 0 },
    new double[] { 1, 1, 1, 0, 0, 0 },
    new double[] { 0, 0, 1, 1, 1, 0 },
    new double[] { 0, 0, 1, 1, 0, 0 },
    new double[] { 0, 0, 1, 1, 1, 0 },
};
double[][] outputs = {
    new double[] { 1, 0 },
    new double[] { 1, 0 },
    new double[] { 1, 0 },
    new double[] { 0, 1 },
    new double[] { 0, 1 },
    new double[] { 0, 1 },
};

// ネットワークの生成
var network = new DeepBeliefNetwork(
    inputsCount: inputs.Length,         // 入力層の次元
    hiddenNeurons: new int[] { 4, 2 }); // 隠れ層と出力層の次元

// DNNの学習アルゴリズムの生成
var teacher = new DeepNeuralNetworkLearning(network)
{
    Algorithm = (ann, i) => new ParallelResilientBackpropagationLearning(ann),
    LayerIndex = network.Machines.Count - 1,
};

// 5000回繰り返し学習
var layerData = teacher.GetLayerInput(inputs);
for (int i = 0; i < 5000; i++)
    teacher.RunEpoch(layerData, outputs);

// 重みの更新
network.UpdateVisibleWeights();

// 学習されたネットワークでテストデータが各クラスに属する確率を計算
double[] input = { 1, 1, 1, 1, 0, 0 };
var output = network.Compute(input);

//  一番確率の高いクラスのインデックスを得る
int imax; output.Max(out imax);

// 結果出力
Console.WriteLine("class : {0}", imax);
foreach (var o in output)
{
    Console.Write("{0} ", o);
}

実行結果

class : 0
0.999680477117216 0.00120961077917418

Restricted Boltzmann Machine(RBM)

// トレーニングデータ
double[][] inputs = {
    new double[] { 1, 1, 1, 0, 0, 0 },
    new double[] { 1, 0, 1, 0, 0, 0 },
    new double[] { 1, 1, 1, 0, 0, 0 },
    new double[] { 0, 0, 1, 1, 1, 0 },
    new double[] { 0, 0, 1, 1, 0, 0 },
    new double[] { 0, 0, 1, 1, 1, 0 },
};
double[][] outputs = {
    new double[] { 1, 0 },
    new double[] { 1, 0 },
    new double[] { 1, 0 },
    new double[] { 0, 1 },
    new double[] { 0, 1 },
    new double[] { 0, 1 },
};

// RBMの生成
var rbm = new RestrictedBoltzmannMachine(
    inputsCount: 6, 
    hiddenNeurons: 2);

// トレーニングデータで学習
var teacher = new ContrastiveDivergenceLearning(rbm);
for (int i = 0; i < 5000; i++)
    teacher.RunEpoch(inputs);

// テストデータ
double[] input = { 1, 1, 1, 1, 0, 0 };

// 学習されたネットワークで各クラスに属する確率を計算
var output = rbm.Compute(input);

//  一番確率の高いクラスのインデックスを得る
int imax; output.Max(out imax);

// 結果出力
Console.WriteLine("class : {0}", imax);
foreach (var o in output)
{
    Console.Write("{0} ", o);
}

実行結果

class : 1
0.133832413712274 0.906343089146992