
Artificial Intelligence is quickly becoming part of everyday life. Whether you are using your PC or your mobile phone, you are making use of some variation of AI. The Web has given Artificial Intelligence wings and it just keeps on improving.
I have written about AI and .NET before. To understand the underlying concepts of Deep Neural Networks, I recommend that you read the following two articles first. These articles explain how a neural network is put together, as well as setting up a genetic algorithm.
What is Deep Learning?
Deep Learning (or Hierarchical Learning or Deep Structured Learning) is a type of machine learning method that is based on learning data representations instead of task-specific algorithms. Deep Learning can be unsupervised, semi-supervised, or supervised.
Some Deep Learning architectures, such as deep neural networks, deep belief networks, and recurrent neural networks have been applied to the following fields:
- Computer Vision
- Speech Recognition
- Natural Language Processing
- Audio Recognition
- Social Network Filtering
- Machine Translation
- Bioinformatics
What Are Deep Neural Networks?
A Deep Neural Network (DNN) is an artificial neural network that has multiple hidden layers between the input and output layers. Deep Neural Networks models complex non-linear relationships. Deep Neural Networks are usually feedforward networks in which data flows from the input layer to the output layer without looping back.
Read: Machine Learning versus Deep Learning
How to Implement Deep Learning Logic in .NET
The small program that you will build today is a small example of how to implement Deep Learning logic into your application. You can use either C# or VB.NET. Let’s jump right in, shall we?
Create a new Console App and add a class to hold all the Deep Learning Logic. Name this class DeepNeuralNetwork or DNN.
Add the following fields into the class you have just created with the following C# code:
private int intInput;
private int intHiddenA;
private int intHiddenB;
private int intOutput;
private double[] dblInputs;
private double[][] dbliaWeights;
private double[][] dblabWeights;
private double[][] dblboWeights;
private double[] dblaBiases;
private double[] dblbBiases;
private double[] dbloBiases;
private double[] dblaOutputs;
private double[] dblbOutputs;
private double[] dbloutputs;
private static Random rndRand;
You can achieve the same thing using VB.NET:
Private intInput As Integer
Private intHiddenA As Integer
Private intHiddenB As Integer
Private intOutput As Integer
Private dblInputs As Double()
Private dbliaWeights As Double()()
Private dblabWeights As Double()()
Private dblboWeights As Double()()
Private dblaBiases As Double()
Private dblbBiases As Double()
Private dbloBiases As Double()
Private dblaOutputs As Double()
Private dblbOutputs As Double()
Private dbloutputs As Double()
Private Shared rndRand As Random
Adding Constructors in C#
These fields will hold the input Weights and their corresponding biases. Add the Constructor in C#:
public DNN(int iInput, int iHiddenA, int iHiddenB,
int iOutput)
{
intInput = iInput;
intHiddenA = iHiddenA;
intHiddenB = iHiddenB;
intOutput = iOutput;
dblInputs = new double[iInput];
dbliaWeights = CreateMatrix(iInput, iHiddenA);
dblabWeights = CreateMatrix(iHiddenA, iHiddenB);
dblboWeights = CreateMatrix(iHiddenB, iOutput);
dblaBiases = new double[iHiddenA];
dblbBiases = new double[iHiddenB];
dbloBiases = new double[iOutput];
dblaOutputs = new double[iHiddenA];
dblbOutputs = new double[iHiddenB];
dbloutputs = new double[iOutput];
rndRand = new Random(0);
InitWeight();
}
Adding the Constructor in VB.NET
Public Sub New(ByVal iInput As Integer, ByVal iHiddenA _
As Integer, ByVal iHiddenB As Integer, _
ByVal iOutput As Integer)
intInput = iInput
intHiddenA = iHiddenA
intHiddenB = iHiddenB
intOutput = iOutput
dblInputs = New Double(iInput - 1) {}
dbliaWeights = CreateMatrix(iInput, iHiddenA)
dblabWeights = CreateMatrix(iHiddenA, iHiddenB)
dblboWeights = CreateMatrix(iHiddenB, iOutput)
dblaBiases = New Double(iHiddenA - 1) {}
dblbBiases = New Double(iHiddenB - 1) {}
dbloBiases = New Double(iOutput - 1) {}
dblaOutputs = New Double(iHiddenA - 1) {}
dblbOutputs = New Double(iHiddenB - 1) {}
dbloutputs = New Double(iOutput - 1) {}
rndRand = New Random(0)
InitWeight()
End Sub
Read: Machine Learning in .NET
Add the CreateMatrix Function in C#
private static double[][] CreateMatrix(int iRows, int iCols)
{
double[][] dblRes = new double[iRows][];
for (int r = 0; r < dblRes.Length; ++r)
{
dblRes[r] = new double[iCols];
}
return dblRes;
}
Add the CreateMatrix Function in VB.NET
Private Shared Function CreateMatrix(ByVal iRows As Integer, _
ByVal iCols As Integer) As Double()()
Dim dblRes As Double()() = New Double(iRows - 1)() {}
Dim r As Integer
While r < dblRes.Length
dblRes(r) = New Double(iCols - 1) {}
Threading.Interlocked.Increment(r)
End While
Return dblRes
End Function
This creates a matrix for each of our weights. Add the Weight functions to set random values for each weight in C#:
private void InitWeight()
{
int intWeights = (intInput * intHiddenA) + intHiddenA +
(intHiddenA * intHiddenB) + intHiddenB + (intHiddenB *
intOutput) + intOutput;
double[] dblWeights = new double[intWeights];
double dblLO = -0.01;
double dblHI = 0.01;
for (int i = 0; i < dblWeights.Length; ++i)
{
dblWeights[i] = (dblHI - dblLO) * rndRand.NextDouble()
+ dblLO;
}
SetWeight(dblWeights);
}
public void SetWeight(double[] dblWeights)
{
int numWeights = (intInput * intHiddenA) + intHiddenA +
(intHiddenA * intHiddenB) + intHiddenB + (intHiddenB *
intOutput) + intOutput;
if (dblWeights.Length != numWeights)
{
throw new Exception("Weight Length Error");
}
int j = 0;
for (int i = 0; i < intInput; ++i)
{
for (int j = 0; j < intHiddenA; ++j)
{
dbliaWeights[i][j] = dblWeights[j++];
}
}
for (int i = 0; i < intHiddenA; ++i)
{
dblaBiases[i] = dblWeights[j++];
}
for (int i = 0; i < intHiddenA; ++i)
{
for (int j = 0; j < intHiddenB; ++j)
{
dblabWeights[i][j] = dblWeights[j++];
}
}
for (int i = 0; i < intHiddenB; ++i)
{
dblbBiases[i] = dblWeights[j++];
}
for (int i = 0; i < intHiddenB; ++i)
{
for (int j = 0; j < intOutput; ++j)
{
dblboWeights[i][j] = dblWeights[j++];
}
}
for (int i = 0; i < intOutput; ++i)
{
dbloBiases[i] = dblWeights[j++];
}
}
VB.NET
Private Sub InitWeight()
Dim intWeights As Integer = (intInput * intHiddenA) + _
intHiddenA + (intHiddenA * intHiddenB) + intHiddenB + _
(intHiddenB * intOutput) + intOutput
Dim dblWeights As Double() = New Double(intWeights - 1) {}
Dim dblLO As Double = -0.01
Dim dblHI As Double = 0.01
Dim i As Integer
While i < dblWeights.Length
dblWeights(i) = (dblHI - dblLO) * rndRand.NextDouble() + _
dblLO
Threading.Interlocked.Increment(i)
End While
SetWeight(dblWeights)
End Sub
Public Sub SetWeight(ByVal dblWeights As Double())
Dim numWeights As Integer = (intInput * intHiddenA) + _
intHiddenA + (intHiddenA * intHiddenB) + intHiddenB + _
(intHiddenB * intOutput) + intOutput
If dblWeights.Length <> numWeights
Throw New Exception("Weight Length Error")
End If
Dim j As Integer = 0
Dim i As Integer = 0
While i < intInput
While j < intHiddenA
dbliaWeights(i)(j) = dblWeights(Math.Min(Threading. _
Interlocked.Increment(j), j - 1))
Threading.Interlocked.Increment(j)
End While
Threading.Interlocked.Increment(i)
End While
While i < intHiddenA
dblaBiases(i) = dblWeights(Math.Min(Threading. _
Interlocked.Increment(j), j - 1))
Threading.Interlocked.Increment(i)
End While
While i < intHiddenA
While j < intHiddenB
dblabWeights(i)(j) = dblWeights(Math.Min(Threading. _
Interlocked.Increment(j), j - 1))
Threading.Interlocked.Increment(j)
End While
Threading.Interlocked.Increment(i)
End While
While i < intHiddenB
dblbBiases(i) = dblWeights(Math.Min(Threading. _
Interlocked.Increment(j), j - 1))
Threading.Interlocked.Increment(i)
End While
While i < intHiddenB
While j < intOutput
dblboWeights(i)(j) = dblWeights(Math.Min(Threading. _
Interlocked.Increment(j), j - 1))
Threading.Interlocked.Increment(j)
End While
Threading.Interlocked.Increment(i)
End While
While i < intOutput
dbloBiases(i) = dblWeights(Math.Min(Threading. _
Interlocked.Increment(j), j - 1))
Threading.Interlocked.Increment(i)
End While
End Sub
Read: Azure Machine Learning Tutorial
Complete the Class in C#
Add the following C# code to complete the class:
public double[] Compute(double[] dblValues)
{
double[] dblaSums = new double[intHiddenA];
double[] dblbSums = new double[intHiddenB];
double[] dbloSums = new double[intOutput];
for (int i = 0; i < dblValues.Length; ++i)
{
dblInputs[i] = dblValues[i];
}
for (int j = 0; j < intHiddenA; ++j) {
for (int i = 0; i < intInput; ++i)
{
dblaSums[j] += dblInputs[i] * dbliaWeights[i][j];
}
}
for (int i = 0; i < intHiddenA; ++i)
{
dblaSums[i] += dblaBiases[i];
}
Console.WriteLine("nInternal aSums:");
Program.ShowGrid(dblaSums, dblaSums.Length, 4, true);
for (int i = 0; i < intHiddenA; ++i)
{
dblaOutputs[i] = HyperbolicTangent(dblaSums[i]);
}
Console.WriteLine("nInternal aOutputs:");
Program.ShowGrid(dblaOutputs, dblaOutputs.Length, 4,
true);
for (int j = 0; j < intHiddenB; ++j)
{
for (int i = 0; i < intHiddenA; ++i)
{
dblbSums[j] += dblaOutputs[i] * .dblabWeights[i][j];
}
}
for (int i = 0; i < intHiddenB; ++i)
{
dblbSums[i] += dblbBiases[i];
}
Console.WriteLine("nInternal bSums:");
Program.ShowGrid(dblbSums, dblbSums.Length, 4, true);
for (int i = 0; i < intHiddenB; ++i)
{
dblbOutputs[i] = HyperbolicTangent(dblbSums[i]);
}
Console.WriteLine("nInternal bOutputs:");
Program.ShowGrid(dblbOutputs, dblbOutputs.Length, 4,
true);
for (int j = 0; j < intOutput; ++j)
{
for (int i = 0; i < intHiddenB; ++i)
{
dbloSums[j] += dblbOutputs[i] * dblboWeights[i][j];
}
}
for (int i = 0; i < intOutput; ++i)
{
dbloSums[i] += dbloBiases[i];
}
Console.WriteLine("nInternal oSums:");
Program.ShowGrid(dbloSums, dbloSums.Length, 4, true);
double[] dblAllOut = MaxOutput(dbloSums);
Array.Copy(dblAllOut, dbloutputs, dblAllOut.Length);
double[] dblResult = new double[intOutput];
Array.Copy(this.dbloutputs, dblResult, dblResult.Length);
return dblResult;
}
private static double HyperbolicTangent(double val)
{
if (val < -20.0)
{
return -1.0;
}
else if (val > 20.0)
{
return 1.0;
}
else
{
return Math.Tanh(val);
}
}
private static double[] MaxOutput(double[] oSums)
{
double dblMax = oSums[0];
for (int i = 0; i < oSums.Length; ++i)
{
if (oSums[i] > dblMax)
{
dblMax = oSums[i];
}
}
double dblScale = 0.0;
for (int i = 0; i < oSums.Length; ++i)
{
dblScale += Math.Exp(oSums[i] - dblMax);
}
double[] dblRes = new double[oSums.Length];
for (int i = 0; i < oSums.Length; ++i)
{
dblRes[i] = Math.Exp(oSums[i] - dblMax) / dblScale;
}
return dblRes;
}
Complete the Class in VB.NET
Add the following code to complete the class in VB.NET:
Public Function Compute(ByVal dblValues As Double()) As Double()
Dim dblaSums As Double() = New Double(intHiddenA - 1) {}
Dim dblbSums As Double() = New Double(intHiddenB - 1) {}
Dim dbloSums As Double() = New Double(intOutput - 1) {}
Dim i As Integer
Dim j As Integer
While i < dblValues.Length
dblInputs(i) = dblValues(i)
Threading.Interlocked.Increment(i)
End While
While j < intHiddenA
While i < intInput
dblaSums(j) += dblInputs(i) * dbliaWeights(i)(j)
Threading.Interlocked.Increment(i)
End While
Threading.Interlocked.Increment(j)
End While
While i < intHiddenA
dblaSums(i) += dblaBiases(i)
Threading.Interlocked.Increment(i)
End While
Console.WriteLine(vbLf & "Internal aSums:")
ShowGrid(dblaSums, dblaSums.Length, 4, True)
While i < intHiddenA
dblaOutputs(i) = HyperbolicTangent(dblaSums(i))
Threading.Interlocked.Increment(i)
End While
Console.WriteLine(vbLf & "Internal aOutputs:")
ShowGrid(dblaOutputs, dblaOutputs.Length, 4, True)
While j < intHiddenB
While i < intHiddenA
dblbSums(j) += dblaOutputs(i) * dblabWeights(i)(j)
Threading.Interlocked.Increment(i)
End While
Threading.Interlocked.Increment(j)
End While
While i < intHiddenB
dblbSums(i) += dblbBiases(i)
Threading.Interlocked.Increment(i)
End While
Console.WriteLine(vbLf & "Internal bSums:")
ShowGrid(dblbSums, dblbSums.Length, 4, True)
While i < intHiddenB
dblbOutputs(i) = HyperbolicTangent(dblbSums(i))
Threading.Interlocked.Increment(i)
End While
Console.WriteLine(vbLf & "Internal bOutputs:")
ShowGrid(dblbOutputs, dblbOutputs.Length, 4, True)
While j < intOutput
While i < intHiddenB
dbloSums(j) += dblbOutputs(i) * dblboWeights(i)(j)
Threading.Interlocked.Increment(i)
End While
Threading.Interlocked.Increment(j)
End While
While i < intOutput
dbloSums(i) += dbloBiases(i)
Threading.Interlocked.Increment(i)
End While
Console.WriteLine(vbLf & "Internal oSums:")
ShowGrid(dbloSums, dbloSums.Length, 4, True)
Dim dblAllOut As Double() = MaxOutput(dbloSums
Array.Copy(dblAllOut, dbloutputs, dblAllOut.Length)
Dim dblResult As Double() = New Double(intOutput - 1) {}
Array.Copy(Me.dbloutputs, dblResult, dblResult.Length)
Return dblResult
End Function
Private Shared Function HyperbolicTangent(ByVal val As Double) _
As Double
If val < -20 Then
Return -1
ElseIf val > 20 Then
Return 1
Else
Return Math.Tanh(val)
End If
End Function
Private Shared Function MaxOutput(ByVal oSums As Double()) _
As Double()
Dim dblMax As Double = oSums(0)
Dim i As Integer
While i < oSums.Length
If oSums(i) > dblMax Then
dblMax = oSums(i)
End If
Threading.Interlocked.Increment(i)
End While
Dim dblScale As Double = 0
While i < oSums.Length
dblScale += Math.Exp(oSums(i) - dblMax)
Threading.Interlocked.Increment(i)
End While
Dim dblRes As Double() = New Double(oSums.Length - 1) {}
While i < oSums.Length
dblRes(i) = Math.Exp(oSums(i) - dblMax) / dblScale
Threading.Interlocked.Increment(i)
End While
Return dblRes
End Function
The calculated inputs, along with the biases, get computed and outputted. Add the code for the Program class or the Module to make use of the DeepNeuralNetwork Class.
C#
static void Main(string[] args)
{
Console.WriteLine("nStart Creating a 3-4-5-2 neural
network");
int intInput = 3;
int intHiddenA = 4;
int intHiddenB = 5;
int intOutput = 2;
DNN dnn = new DNN(intInput, intHiddenA, intHiddenB,
intOutput);
double[] dblWeights = new double[] {
0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09,
0.10,
0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19,
0.20,
0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29,
0.30,
0.31, 0.32, 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39,
0.40,
0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49,
0.50,
};
dnn.SetWeight(dblWeights);
double[] dblX = new double[] { 1.0, 2.0, 3.0 };
Console.WriteLine("nDummy Weights + Bias Values");
ShowGrid(dblWeights, 10, 2, true);
Console.WriteLine("nDummy Inputs");
ShowGrid(dblX, 3, 1, true);
double[] dblY = dnn.Compute(dblX);
Console.WriteLine("nComputed Outputs");
ShowGrid(dblY, 2, 4, true);
Console.WriteLine("nEnd");
Console.ReadLine();
}
static public void ShowGrid(double[] dblVector, int intCols,
int intDec, bool blnNewLine)
{
for (int i = 0; i < dblVector.Length; ++i)
{
if (i % intCols == 0)
{
Console.WriteLine("");
}
Console.Write(dblVector[i].ToString("F" +
intDec).PadLeft(intDec + 4) + " ");
}
if (blnNewLine == true)
{
Console.WriteLine("");
}
}
VB.NET
Sub Main(ByVal args As String())
Console.WriteLine(vbLf & "Start Creating a 3-4-5-2 _
neural network")
Dim intInput As Integer = 3
Dim intHiddenA As Integer = 4
Dim intHiddenB As Integer = 5
Dim intOutput As Integer = 2
Dim dnn As DNN = New DNN(intInput, intHiddenA, intHiddenB, _
intOutput)
Dim dblWeights As Double() = New Double() {
0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1,
0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.2,
0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.3,
0.31, 0.32, 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.4,
0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.5
}
dnn.SetWeight(dblWeights)
Dim dblX As Double() = New Double() {1, 2, 3}
Console.WriteLine(vbLf & "Dummy Weights + Bias Values")
ShowGrid(dblWeights, 10, 2, True)
Console.WriteLine(vbLf & "Dummy Inputs")
ShowGrid(dblX, 3, 1, True)
Dim dblY As Double() = dnn.Compute(dblX)
Console.WriteLine(vbLf & "Computed Outputs")
ShowGrid(dblY, 2, 4, True)
Console.WriteLine(vbLf & "End")
Console.ReadLine()
End Sub
Public Sub ShowGrid(ByVal dblVector As Double(), _
ByVal intCols As Integer, ByVal intDec As Integer, _
ByVal blnNewLine As Boolean)
Dim i As Integer
While i < dblVector.Length
If i Mod intCols = 0 Then
Console.WriteLine("")
End If
Console.Write(dblVector(i).ToString("F" & intDec) _
.PadLeft(intDec + 4) & " ")
Threading.Interlocked.Increment(i)
End While
If blnNewLine = True Then
Console.WriteLine("")
End If
End Sub
Here you supply values for the weights. The ShowGrid procedure displays the results.
Conclusion to Deep Neural Networks Programming
Deep Neural Networks are not too complicated. They are just the beginning. Hopefully, in a future article, I can delve a bit deeper. Until then, goodbye.