C# でゼロから Deep Learnig を実装する挑戦の続き。 今回は超単純な 3 層ニューラルネットワークを実装してみた。 といっても、『ゼロから作る Deep Learnig』の 3 章の写経みたいなもの。
C# + Math.NET Numerics で試行錯誤しながら書いたコードは次の通り。
using MathNet.Numerics.LinearAlgebra; using System; namespace ThreeLayerNeuralNetworkSample { class Program { static void Main(string[] args) { var network = new ThreeLayerNeuralNetwork(); var x = Vector<double>.Build.DenseOfArray(new double[] { 1.0, 0.5 }); var y = network.Forward(x); Console.WriteLine(y); Console.ReadLine(); } } /// <summary> /// 3 層ニューラルネットワークを表します。 /// </summary> public class ThreeLayerNeuralNetwork { /// <summary> /// 第 1 層の重み /// </summary> readonly Matrix<double> W1; /// <summary> /// 第 1 層のバイアス /// </summary> readonly Vector<double> B1; /// <summary> /// 第 2 層の重み /// </summary> readonly Matrix<double> W2; /// <summary> /// 第 2 層のバイアス /// </summary> readonly Vector<double> B2; /// <summary> /// 第 3 層の重み /// </summary> readonly Matrix<double> W3; /// <summary> /// 第 3 層のバイアス /// </summary> readonly Vector<double> B3; /// <summary> /// <see cref="ThreeLayerNeuralNetwork"/> /// クラスの新しいインスタンスを初期化します。 /// </summary> public ThreeLayerNeuralNetwork() { W1 = Matrix<double>.Build.DenseOfArray(new double[,] { { 0.1, 0.3, 0.5 }, { 0.2, 0.4, 0.6 } }); B1 = Vector<double>.Build.DenseOfArray(new double[] { 0.1, 0.2, 0.3 }); W2 = Matrix<double>.Build.DenseOfArray(new double[,] { { 0.1, 0.4 }, { 0.2, 0.5 }, { 0.3, 0.6 } }); B2 = Vector<double>.Build.DenseOfArray(new double[] { 0.1, 0.2 }); W3 = Matrix<double>.Build.DenseOfArray(new double[,] { { 0.1, 0.3 }, { 0.2, 0.4 } }); B3 = Vector<double>.Build.DenseOfArray(new double[] { 0.1, 0.2 }); } public Vector<double> Forward(Vector<double> x) { // ベクトルと行列の内積は * で計算できる // 活性化関数にはシグモイド関数を使う var a1 = x * W1 + B1; var z1 = Sigmoid(a1); var a2 = z1 * W2 + B2; var z2 = Sigmoid(a2); // 第 3 層では活性化関数ではなく恒等関数を使う // つまり、そのまま出力層に渡す var a3 = z2 * W3 + B3; var y = IdentityFunction(a3); return y; } /// <summary> /// シグモイド関数 /// </summary> /// <param name="a">ベクトル</param> /// <returns>活性化後のベクトル</returns> private Vector<double> Sigmoid(Vector<double> a) { return a.Map(x => 1 / (1 + Math.Exp(-x))); } /// <summary> /// 恒等関数 /// </summary> /// <param name="a">ベクトル</param> /// <returns><paramref name="a"/> をそのまま返します</returns> private Vector<double> IdentityFunction(Vector<double> a) { return a; } } }
実行結果がこちら。
『ゼロから作る Deep Learnig』と同じ結果が出力できている。
Vector<T>
や Matrix<T>
が演算子をオーバーロードしてくれているおかげで、
ベクトルと行列の内積を良い感じで記述できた。
Math.NET Numerics なかなかやるな。