Archive
#LSTM cell simulation in c# #ml #ai
Thanks to James Mc Caffrey, code from Test Run for MSDN Magazine April 2018
using System;
namespace LSTM_IO
{
class LSTM_IO_Program
{
static void Main(string[] args)
{
Console.WriteLine(“\nBegin LSTM IO demo \n”);
Console.WriteLine(“Creating an n=2 input, m=3 state LSTM cell”);
Console.WriteLine(“Setting LSTM weights and biases to small arbitrary values \n”);
Console.WriteLine(“Sending input = (1.0, 2.0) to LSTM \n”);
float[][] xt = MatFromArray(new float[] { 1.0f, 2.0f }, 2, 1);
float[][] h_prev = MatFromArray(new float[] { 0.0f, 0.0f, 0.0f }, 3, 1);
float[][] c_prev = MatFromArray(new float[] { 0.0f, 0.0f, 0.0f }, 3, 1);
float[][] W = MatFromArray(new float[] { 0.01f, 0.02f,
0.03f, 0.04f,
0.05f, 0.06f }, 3, 2);
float[][] U = MatFromArray(new float[] { 0.07f, 0.08f, 0.09f,
0.10f, 0.11f, 0.12f,
0.13f, 0.14f, 0.15f }, 3, 3);
float[][] b = MatFromArray(new float[] { 0.16f, 0.17f, 0.18f }, 3, 1);
float[][] Wf = MatCopy(W); float[][] Wi = MatCopy(W);
float[][] Wo = MatCopy(W); float[][] Wc = MatCopy(W);
float[][] Uf = MatCopy(U); float[][] Ui = MatCopy(U);
float[][] Uo = MatCopy(U); float[][] Uc = MatCopy(U);
float[][] bf = MatCopy(b); float[][] bi = MatCopy(b);
float[][] bo = MatCopy(b); float[][] bc = MatCopy(b);
float[][] ht, ct;
float[][][] result;
result = ComputeOutputs(xt, h_prev, c_prev,
Wf, Wi, Wo, Wc, Uf, Ui, Uo, Uc, bf, bi, bo, bc);
ht = result[0]; // output
ct = result[1]; // new cell state
Console.WriteLine(“Output is:”);
MatPrint(ht, 4, true);
Console.WriteLine(“New cell state is:”);
MatPrint(ct, 4, true);
Console.WriteLine(“=====”);
Console.WriteLine(“\nSending input = (3.0, 4.0) to LSTM \n”);
h_prev = MatCopy(ht);
c_prev = MatCopy(ct);
xt = MatFromArray(new float[] { 3.0f, 4.0f }, 2, 1);
result = ComputeOutputs(xt, h_prev, c_prev,
Wf, Wi, Wo, Wc, Uf, Ui, Uo, Uc, bf, bi, bo, bc);
ht = result[0];
ct = result[1];
Console.WriteLine(“Output is:”);
MatPrint(ht, 4, true);
Console.WriteLine(“New cell state is:”);
MatPrint(ct, 4, true);
Console.WriteLine(“End LSTM demo “);
Console.ReadLine();
} // Main
static float[][][] ComputeOutputs(float[][] xt, float[][] h_prev, float[][] c_prev,
float[][] Wf, float[][] Wi, float[][] Wo, float[][] Wc,
float[][] Uf, float[][] Ui, float[][] Uo, float[][] Uc,
float[][] bf, float[][] bi, float[][] bo, float[][] bc)
{
float[][] ft = MatSig(MatSum(MatProd(Wf, xt), MatProd(Uf, h_prev), bf));
float[][] it = MatSig(MatSum(MatProd(Wi, xt), MatProd(Ui, h_prev), bi));
float[][] ot = MatSig(MatSum(MatProd(Wo, xt), MatProd(Uo, h_prev), bo));
float[][] ct = MatSum(MatHada(ft, c_prev),
MatHada(it, MatTanh(MatSum(MatProd(Wc, xt), MatProd(Uc, h_prev), bc))));
float[][] ht = MatHada(ot, MatTanh(ct));
float[][][] result = new float[2][][];
result[0] = MatCopy(ht);
result[1] = MatCopy(ct);
return result;
}
// Matrix routines
static float[][] MatCreate(int rows, int cols)
{
float[][] result = new float[rows][];
for (int i = 0; i < rows; ++i)
result[i] = new float[cols];
return result;
}
static float[][] MatFromArray(float[] arr, int rows, int cols)
{
if (rows * cols != arr.Length)
throw new Exception(“xxx”);
float[][] result = MatCreate(rows, cols);
int k = 0;
for (int i = 0; i < rows; ++i)
for (int j = 0; j < cols; ++j)
result[i][j] = arr[k++];
return result;
}
static float[][] MatCopy(float[][] m)
{
int rows = m.Length; int cols = m[0].Length;
float[][] result = MatCreate(rows, cols);
for (int i = 0; i < rows; ++i)
for (int j = 0; j < cols; ++j)
result[i][j] = m[i][j];
return result;
}
static float[][] MatProd(float[][] a, float[][] b)
{
int aRows = a.Length; int aCols = a[0].Length;
int bRows = b.Length; int bCols = b[0].Length;
if (aCols != bRows)
throw new Exception(“xxx”);
float[][] result = MatCreate(aRows, bCols);
for (int i = 0; i < aRows; ++i) // each row of a
for (int j = 0; j < bCols; ++j) // each col of b
for (int k = 0; k < aCols; ++k) // could use k < bRows
result[i][j] += a[i][k] * b[k][j];
return result;
}
// element-wise functions
static float[][] MatSig(float[][] m)
{
// element-wise sigmoid
int rows = m.Length; int cols = m[0].Length;
float[][] result = MatCreate(rows, cols);
for (int i = 0; i < rows; ++i) // each row
for (int j = 0; j < cols; ++j) // each col
result[i][j] = Sigmoid(m[i][j]);
return result;
}
static float[][] MatTanh(float[][] m)
{
// element-wise tanh
int rows = m.Length; int cols = m[0].Length;
float[][] result = MatCreate(rows, cols);
for (int i = 0; i < rows; ++i) // each row
for (int j = 0; j < cols; ++j) // each col
result[i][j] = Tanh(m[i][j]);
return result;
}
static float Sigmoid(float x)
{
if (x < -10.0) return 0.0f;
else if (x > 10.0) return 1.0f;
return (float)(1.0 / (1.0 + Math.Exp(-x)));
}
static float Tanh(float x)
{
if (x < -10.0) return -1.0f;
else if (x > 10.0) return 1.0f;
return (float)(Math.Tanh(x));
}
static float[][] MatHada(float[][] a, float[][] b)
{
// Hadamard element-wise multiplication
// assumes a, b have same shape
int rows = a.Length; int cols = a[0].Length;
float[][] result = MatCreate(rows, cols);
for (int i = 0; i < rows; ++i)
for (int j = 0; j < cols; ++j)
result[i][j] = a[i][j] * b[i][j];
return result;
}
static float[][] MatSum(float[][] a, float[][] b)
{
int rows = a.Length; int cols = a[0].Length;
float[][] result = MatCreate(rows, cols);
for (int i = 0; i < rows; ++i)
for (int j = 0; j < cols; ++j)
result[i][j] = a[i][j] + b[i][j];
return result;
}
static float[][] MatSum(float[][] a, float[][] b, float[][] c)
{
int rows = a.Length; int cols = a[0].Length;
float[][] result = MatCreate(rows, cols);
for (int i = 0; i < rows; ++i)
for (int j = 0; j < cols; ++j)
result[i][j] = a[i][j] + b[i][j] + c[i][j];
return result;
}
static void MatPrint(float[][] Mat, int dec, bool nl)
{
for (int i = 0; i < Mat.Length; ++i)
{
for (int j = 0; j < Mat[0].Length; ++j)
{
Console.Write(Mat[i][j].ToString(“F” + dec) + ” “);
}
Console.WriteLine(“”);
}
if (nl == true) Console.WriteLine(“”);
}
} // Program
} // ns
Sequence prediction in C# using Machine Learning. (1 of many…)
0.4 + 0.4 = 0.79 … well done!
Jokes aside, this is an example of how to use machine learning in C# to predict sequences, in this case to say the sequence of two inputs should result in the sum of the two inputs.
TLDR; the Github repo is here : https://github.com/infiniteloopltd/SharpML-Recurrent
It is 99.9% based on Andrew Fry’s code, but I have modified the dataset generator, that instead of modelling an XOR gate, it models a simple adder. I noticed that the values have to be between 0 and 1, but I guess, you just shift your range to that.
private static List<DataSequence> GetTrainingData()
{var result = new List<DataSequence>();
for (var a = 0.0; a < 0.5; a += 0.1)
{
for (var b = 0.0; b < 0.5; b += 0.1)
{
var sum = a + b;
result.Add(new DataSequence(new List<DataStep>() { new DataStep(new[] { a, b }, new[] { sum }) }));
}
}return result;
}
This simply provides a dataset of every combination of numbers in 0.1 increments between 0 and 0.5, and indicates the sum.
Obviously this training data can be improved, but it’s just a proof of concept, as you can imagine!
Next step is to add another dimension to the output. But that’s work for another day!
Generate large random dataset in SQL server
If you would like to learn about SQL server indexes, and SQL server performance in general, but can’t get your hands on a large dataset that really tests the limits of your SQL server, then here is a script that generates a huge dataset, based on random data.
create table Test1
(
id int identity(1,1),
guid varchar(36) default newid(),
dateCreated datetime default getdate(),
number float default rand()
)while 1=1
Begin
insert into Test1 default values
end
You just let it run for as long as you like, then stop it whenever you have enough rows.