-
Notifications
You must be signed in to change notification settings - Fork 2
/
BamModel.cs
113 lines (97 loc) · 4.12 KB
/
BamModel.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#region License
/*
* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#endregion
using System;
using MathNet.Numerics.LinearAlgebra;
namespace NeuralNetworks.Models
{
public class BamModel
{
public Matrix<float> WeightsMatrix { get; private set; }
private bool _isFirstTraining;
public void Teach(Vector<float> image, Vector<float> name)
{
VerifyVectorsBeforeTraining(image, name);
for (int i = 0; i < image.Count; i++)
{
for (int j = 0; j < name.Count; j++)
{
if ((int)image[i] == (int)name[j])
{
WeightsMatrix[i, j] += 1f;
}
else
{
WeightsMatrix[i, j] += -1f;
}
}
}
}
public Matrix<float> RecoverName(Matrix<float> imagesMatrix)
{
if (imagesMatrix.ColumnCount != WeightsMatrix.RowCount)
{
throw new ArgumentException(
"The number of columns of the given matrix must be equal to the number of rows of the weight's matrix.");
}
Matrix<float> namesMatrix =
Matrix<float>.Build.DenseOfArray(new float[imagesMatrix.RowCount, WeightsMatrix.ColumnCount]);
Matrix<float> previousNamesMatrix;
Matrix<float> previousImagesMatrix;
do
{
previousNamesMatrix = namesMatrix;
previousImagesMatrix = imagesMatrix;
namesMatrix = (imagesMatrix * WeightsMatrix).Map(NormalizeMatrix);
imagesMatrix = (WeightsMatrix * namesMatrix.Map(NormalizeMatrix).Transpose()).Map(NormalizeMatrix).Transpose();
} while (!namesMatrix.Equals(previousNamesMatrix) && !imagesMatrix.Equals(previousImagesMatrix));
return namesMatrix;
}
public Matrix<float> RecoverImage(Matrix<float> namesMatrix)
{
Matrix<float> transposedNamesMatrix = namesMatrix.Transpose();
if (namesMatrix.Transpose().RowCount != WeightsMatrix.ColumnCount)
{
throw new ArgumentException(
"The number of rows(after Transpose) of the given matrix must be equal to the number of columns of the weight's matrix.");
}
var imagesMatrix = Matrix<float>.Build.DenseOfArray(new float[WeightsMatrix.RowCount, namesMatrix.ColumnCount]);
Matrix<float> previousImagesMatrix;
Matrix<float> previousTransposedNamesMatrix;
do
{
previousImagesMatrix = imagesMatrix;
previousTransposedNamesMatrix = transposedNamesMatrix;
imagesMatrix = (WeightsMatrix * transposedNamesMatrix).Map(NormalizeMatrix);
transposedNamesMatrix = (imagesMatrix.Transpose() * WeightsMatrix).Map(NormalizeMatrix).Transpose();
} while (!imagesMatrix.Equals(previousImagesMatrix) && !transposedNamesMatrix.Equals(previousTransposedNamesMatrix));
return imagesMatrix.Transpose();
}
private void VerifyVectorsBeforeTraining(Vector<float> image, Vector<float> name)
{
if (!_isFirstTraining)
{
WeightsMatrix = Matrix<float>.Build.DenseOfArray(new float[image.Count, name.Count]);
_isFirstTraining = true;
}
else
{
if (WeightsMatrix.RowCount != image.Count)
{
throw new ArgumentException("Image vector has a different length than the matrix's number of rows.");
}
if (WeightsMatrix.ColumnCount != name.Count)
{
throw new ArgumentException("Name vector has a different length than the matrix's number of columns.");
}
}
}
private float NormalizeMatrix(float value)
{
return value > 0f ? 1f : 0f;
}
}
}