Skip to content

Commit 4d3a37f

Browse files
committed
add basic digital recognizer
1 parent 34b44dc commit 4d3a37f

File tree

65,400 files changed

+192
-23
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65,400 files changed

+192
-23
lines changed

MLTests/DigitalRecognizer.cs

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
namespace MLTests
2+
{
3+
public class DigitalRecognizer
4+
{
5+
private ImageToVector _vectorReader;
6+
private string _trainDataPath;
7+
private float[][] _weights;
8+
private int _sampleSize;
9+
private int _iterations;
10+
private float _alpha;
11+
private const int DigitsLength = 10;
12+
private const float DefaultAlpha = 0.1f;
13+
private const int DefaultIterations = 10;
14+
private const int DefaultSampleSize = 100;
15+
16+
public DigitalRecognizer(ImageToVector vectorReader, int inputSize, int outputSize, string trainDataPath, int sampleSize = DefaultSampleSize, float alpha = DefaultAlpha, int iterations = DefaultIterations)
17+
{
18+
_sampleSize = sampleSize;
19+
_iterations = iterations;
20+
_alpha = alpha;
21+
22+
_vectorReader = vectorReader;
23+
_trainDataPath = trainDataPath;
24+
25+
_weights = new float[outputSize].Select(element => new float[inputSize]).ToArray();
26+
}
27+
28+
private float MulSVV(float[] vecA, float[] vecB)
29+
{
30+
float result = 0;
31+
for (int i = 0; i < vecA.Length; i++)
32+
{
33+
result = result + vecA[i] * vecB[i];
34+
}
35+
return result;
36+
}
37+
38+
private float[] MulVM(float[] vec, float[][] matrix)
39+
{
40+
var result = new float[matrix.Length];
41+
for (var index = 0; index < result.Length; ++index)
42+
{
43+
result[index] = MulSVV(vec, matrix[index]);
44+
}
45+
return result;
46+
}
47+
48+
private float[] SubVE(float[] vec, float element)
49+
{
50+
var result = new float[vec.Length];
51+
for (int i = 0; i < vec.Length; i++)
52+
{
53+
result[i] = vec[i] - element;
54+
}
55+
return result;
56+
57+
}
58+
59+
private float[] MulVV(float[] vecA, float[] vecB)
60+
{
61+
var result = new float[vecA.Length];
62+
for (int i = 0; i < vecA.Length; i++)
63+
{
64+
result[i] = vecA[i] * vecB[i];
65+
}
66+
return result;
67+
}
68+
69+
private float[] SubVV(float[] vecA, float[] vecB)
70+
{
71+
var result = new float[vecA.Length];
72+
for (int i = 0; i < vecA.Length; i++)
73+
{
74+
result[i] = vecA[i] - vecB[i];
75+
}
76+
return result;
77+
}
78+
79+
private float[][] GradientLearn(float[] input, float[][] weights, float[] predictionGoal, float alpha, int iterations)
80+
{
81+
var result = weights.Select(row => row.ToArray()).ToArray();
82+
for (int i = 0; i < iterations; i++)
83+
{
84+
var prediction = MulVM(input, result);
85+
var deltas = SubVV(prediction, predictionGoal);
86+
var derivatives = MulVV(deltas, input);
87+
for (var row = 0; row < result.Length; ++row)
88+
{
89+
result[row] = SubVE(result[row], derivatives[row] * alpha);
90+
}
91+
}
92+
return result;
93+
}
94+
95+
private float[] GetPredictionGoalVector(int digit)
96+
{
97+
var result = new float[DigitsLength];
98+
return result.Select((e, index) => digit.Equals(index) ? 1.0f : 0.0f).ToArray();
99+
}
100+
101+
public void Learn(int digit)
102+
{
103+
for (var sample = 1; sample <= _sampleSize; ++sample)
104+
{
105+
var predictionGoal = GetPredictionGoalVector(digit);
106+
var dataPath = Path.Combine(_trainDataPath, $"{digit}", $"{sample}.jpg");
107+
var input = _vectorReader.GetVectorOnPath(dataPath);
108+
_weights = GradientLearn(input, _weights, predictionGoal, _alpha, _iterations);
109+
}
110+
}
111+
112+
public (int, float) Predict(string dataPath)
113+
{
114+
var input = _vectorReader.GetVectorOnPath(dataPath);
115+
var resultVector = MulVM(input, _weights);
116+
var result = resultVector
117+
.Select((e, i) => new { Element = e, Index = i })
118+
.OrderBy(element => element.Element).Last();
119+
return (result.Index, result.Element);
120+
}
121+
}
122+
}

MLTests/DigitalRecognizerTests.cs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using FluentAssertions;
2+
using NUnit.Framework;
3+
4+
namespace MLTests
5+
{
6+
public class DigitalRecognizerTests
7+
{
8+
[Test]
9+
public void ShouldRecognizeDigit()
10+
{
11+
var projectPath = "D:/projects.active/LearnML";
12+
var trainDataPath = Path.GetFullPath(@$"{projectPath}/data");
13+
var digitZeroPath = Path.Combine(trainDataPath, "0", "155.jpg");
14+
var digitOnePath = Path.Combine(trainDataPath, "1", "1055.jpg");
15+
var digitTwoPath = Path.Combine(trainDataPath, "2", "1055.jpg");
16+
var digitThreePath = Path.Combine(trainDataPath, "3", "1055.jpg");
17+
var digitFourPath = Path.Combine(trainDataPath, "4", "1055.jpg");
18+
var digitFivePath = Path.Combine(trainDataPath, "5", "1055.jpg");
19+
var digitSixPath = Path.Combine(trainDataPath, "6", "1055.jpg");
20+
var digitSevenPath = Path.Combine(trainDataPath, "7", "1055.jpg");
21+
var digitEightPath = Path.Combine(trainDataPath, "8", "1055.jpg");
22+
var digitNinePath = Path.Combine(trainDataPath, "9", "1055.jpg");
23+
24+
var inputSize = 28 * 28;
25+
var outputSize = 10;
26+
27+
var alpha = 0.1f;
28+
var iterations = 5;
29+
var sampleSize = 5;
30+
31+
var vectorReader = new ImageToVector();
32+
var recognizer = new DigitalRecognizer(vectorReader, inputSize, outputSize, trainDataPath, sampleSize, alpha, iterations);
33+
34+
for (int learnDigit = 0; learnDigit < 10; learnDigit++)
35+
{
36+
recognizer.Learn(learnDigit);
37+
}
38+
39+
var (digit, value) = recognizer.Predict(digitOnePath);
40+
Assert.That(digit, Is.EqualTo(1));
41+
Assert.That(value, Is.AtLeast(0.5f));
42+
43+
//recognizer.Predict(digitOnePath)[zero].Should().BeInRange(0.0f, 0.6f);
44+
//recognizer.Predict(digitZeroPath)[zero].Should().BeInRange(0.8f, 1.2f);
45+
}
46+
}
47+
}

MLTests/ImageToVector.cs

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,33 @@
33

44
namespace MLTests
55
{
6-
public static class ImageToVector
6+
public interface IImageToVector
77
{
8-
private static float[] GetNormalizedVector(float[] vector)
8+
float[] GetVectorOnPath(string path);
9+
}
10+
11+
public class ImageToVector : IImageToVector
12+
{
13+
private const string DefaultImageType = "grayscale";
14+
private static readonly (int, int) DefaultSize = (28, 28);
15+
16+
public ImageToVector()
17+
{
18+
19+
}
20+
float[] GetNormalizedVector(float[] vector)
921
{
1022
var max = vector.Max();
1123
var min = vector.Min();
1224
for(var i = 0; i < vector.Length; i++) vector[i] /= max;
1325
return vector;
1426
}
1527

16-
public static float[] GetVectorOnPath(string path)
28+
public float[] GetVectorOnPath(string path)
1729
{
18-
var image = ImageUtil.LoadImg(path, "grayscale", target_size: (28, 28));
19-
NDarray x = ImageUtil.ImageToArray(image);
20-
var shape = x.shape; // (28, 28, 3)
21-
//var norm = new Keras.Layers.BatchNormalization();
22-
23-
//x = x.reshape(1, x.shape[0], x.shape[1], x.shape[2]);
24-
float[] data = x.GetData<float>();
25-
/*
26-
var array1 = ImageUtil.ImageToArray(image);
27-
28-
var array2 = np.expand_dims(array1, axis: 0);
29-
var array3 = (NDarray)array2;
30-
float[] data = array3.GetData<float>();
31-
*/
32-
return GetNormalizedVector(data);
33-
//return new float[] { };
30+
var image = ImageUtil.LoadImg(path, DefaultImageType, target_size: DefaultSize);
31+
NDarray imageArray = ImageUtil.ImageToArray(image);
32+
return GetNormalizedVector(imageArray.GetData<float>());
3433
}
3534
}
3635
}

MLTests/ImageToVectorTest.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@ namespace MLTests
66
public class ImageToVectorTest
77
{
88
[Test]
9-
public void LoadImage()
9+
public void LoadImageTest()
1010
{
1111
var projectPath = "D:/projects.active/LearnML";
1212
var path = Path.GetFullPath(@$"{projectPath}/data/0/1.jpg");
13-
var vector = ImageToVector.GetVectorOnPath(path);
13+
IImageToVector imgToVector = new ImageToVector();
14+
var vector = imgToVector.GetVectorOnPath(path);
1415
vector.Sum().Should().NotBe(0.0f);
1516
}
1617
}

MLTests/Program.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
using MLTests;
22

3-
var vector = ImageToVector.GetVectorOnPath(@"./data/0/1.jpg");
4-
Console.WriteLine(vector);
3+
//var vector = ImageToVector.GetVectorOnPath(@"./data/0/1.jpg");
4+
Console.WriteLine("ML");
File renamed without changes.
File renamed without changes.

data/0/1000.jpg

79 Bytes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

data/0/1006.jpg

602 Bytes
File renamed without changes.

data/0/1008.jpg

602 Bytes
File renamed without changes.

data/0/101.jpg

588 Bytes

data/0/1010.jpg

600 Bytes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

data/0/1015.jpg

25 Bytes
File renamed without changes.

data/0/10168.jpg

-584 Bytes
Binary file not shown.
File renamed without changes.

data/0/1018.jpg

62 Bytes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

data/0/10254.jpg

-581 Bytes
Binary file not shown.
File renamed without changes.

data/0/10265.jpg

-572 Bytes
Binary file not shown.
File renamed without changes.

data/0/1028.jpg

-32 Bytes

data/0/1029.jpg

-29 Bytes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

data/0/1036.jpg

603 Bytes

data/0/10366.jpg

-529 Bytes
Binary file not shown.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

data/0/1040.jpg

-53 Bytes

data/0/10407.jpg

-595 Bytes
Binary file not shown.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

data/0/1046.jpg

-20 Bytes
File renamed without changes.

data/0/10479.jpg

-592 Bytes
Binary file not shown.
File renamed without changes.

data/0/1049.jpg

30 Bytes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

data/0/10530.jpg

-607 Bytes
Binary file not shown.

data/0/10531.jpg

-604 Bytes
Binary file not shown.
File renamed without changes.

data/0/1055.jpg

588 Bytes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

data/0/10604.jpg

-595 Bytes
Binary file not shown.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

data/0/107.jpg

586 Bytes
File renamed without changes.

data/0/10700.jpg

-577 Bytes
Binary file not shown.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

data/0/1076.jpg

18 Bytes
File renamed without changes.

data/0/10773.jpg

-578 Bytes
Binary file not shown.

data/0/1078.jpg

-2 Bytes
File renamed without changes.

data/0/108.jpg

-103 Bytes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

data/0/10840.jpg

-569 Bytes
Binary file not shown.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

data/0/1090.jpg

7 Bytes
File renamed without changes.
File renamed without changes.

data/0/1093.jpg

33 Bytes

data/0/10938.jpg

-536 Bytes
Binary file not shown.
File renamed without changes.

data/0/1095.jpg

595 Bytes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

data/0/11019.jpg

-637 Bytes
Binary file not shown.

data/0/1102.jpg

-71 Bytes

data/0/11027.jpg

-586 Bytes
Binary file not shown.

data/0/11029.jpg

-612 Bytes
Binary file not shown.

data/0/1103.jpg

632 Bytes
File renamed without changes.

data/0/11041.jpg

-585 Bytes
Binary file not shown.
File renamed without changes.
File renamed without changes.

data/0/1107.jpg

-12 Bytes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

data/0/1128.jpg

5 Bytes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

data/0/1137.jpg

-83 Bytes

data/0/11379.jpg

-583 Bytes
Binary file not shown.
File renamed without changes.
File renamed without changes.

data/0/114.jpg

28 Bytes
File renamed without changes.
File renamed without changes.

data/0/1142.jpg

584 Bytes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

data/0/115.jpg

601 Bytes

data/0/1150.jpg

584 Bytes
File renamed without changes.

data/0/1152.jpg

7 Bytes

data/0/1153.jpg

629 Bytes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

data/0/1163.jpg

534 Bytes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

data/0/1168.jpg

71 Bytes
File renamed without changes.

data/0/11694.jpg

-598 Bytes
Binary file not shown.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

data/0/1176.jpg

584 Bytes
File renamed without changes.

data/0/1178.jpg

595 Bytes

data/0/1179.jpg

-11 Bytes

data/0/118.jpg

14 Bytes
File renamed without changes.

data/0/1181.jpg

561 Bytes
File renamed without changes.

data/0/1183.jpg

594 Bytes

data/0/11834.jpg

-629 Bytes
Binary file not shown.
File renamed without changes.

data/0/11845.jpg

-584 Bytes
Binary file not shown.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

data/0/11888.jpg

-613 Bytes
Binary file not shown.
File renamed without changes.

data/0/119.jpg

24 Bytes
File renamed without changes.

data/0/1191.jpg

617 Bytes
File renamed without changes.
File renamed without changes.
File renamed without changes.

data/0/1195.jpg

-1 Bytes
File renamed without changes.
File renamed without changes.

data/0/11974.jpg

-540 Bytes
Binary file not shown.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

data/0/12008.jpg

-585 Bytes
Binary file not shown.
File renamed without changes.
File renamed without changes.

data/0/12020.jpg

-564 Bytes
Binary file not shown.

data/0/1203.jpg

589 Bytes

data/0/1204.jpg

570 Bytes

data/0/1205.jpg

597 Bytes

data/0/1206.jpg

620 Bytes
File renamed without changes.
File renamed without changes.

data/0/1209.jpg

17 Bytes

data/0/121.jpg

-68 Bytes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

data/0/12144.jpg

-588 Bytes
Binary file not shown.
File renamed without changes.

data/0/1216.jpg

597 Bytes
File renamed without changes.
File renamed without changes.

data/0/12180.jpg

-635 Bytes
Binary file not shown.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

data/0/1224.jpg

600 Bytes
File renamed without changes.
File renamed without changes.
File renamed without changes.

data/0/12276.jpg

-529 Bytes
Binary file not shown.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)