-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNeuralFabric.cs
136 lines (112 loc) · 5.47 KB
/
NeuralFabric.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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NeuralNetwork
{
class NeuralFabric
{
private EntryLevelNeural _firstEntry;
private EntryLevelNeural _secondEntry;
private ExternalEnvironmentNeural _firstExternal = new ExternalEnvironmentNeural(1);
private ExternalEnvironmentNeural _secondExternal = new ExternalEnvironmentNeural(1);
private AssasinLevelNeural _firstAssasin = new AssasinLevelNeural(); // лучше не сокращать
private AssasinLevelNeural _secondAssasin = new AssasinLevelNeural();
private AssasinLevelNeural _exitNeural = new AssasinLevelNeural();
private double _exitValue;
// Коллекция образцов: входной, входной, выходной
private List<Tuple<double, double, double>> _pairTuples = new List<Tuple<double, double, double>>
{
Tuple.Create(0.0, 0.0, 0.0),
Tuple.Create(1.0, 1.0, 0.0),
Tuple.Create(0.0, 1.0, 1.0),
Tuple.Create(1.0, 0.0, 1.0)
};
public double ExitValue
{
get { return _exitValue; }
}
// создаём класс и генерим его веса рандомными значениями (-0.3; 0.3)
public NeuralFabric()
{
_firstEntry = new EntryLevelNeural(0.0);
_secondEntry = new EntryLevelNeural(1.0);
// следует сделать просто сетРандомВес. Видимо, сетВес не понадобится
Random rand = new Random((int)DateTime.Now.Ticks);
_setWeights(rand);
_exitValue = _exitNeural.Exit;
}
private void _initialize(double enter1, double enter2)
{
_firstEntry.Initialize(enter1);
_firstEntry.Initialize(enter2);
_directPassage();
//Console.WriteLine(enter1 + " " + enter2 + " = " + _exitValue);
}
public void TeachMe()
{
foreach (var pairTuple in _pairTuples)
{
_initialize(pairTuple.Item1, pairTuple.Item2);
while (Math.Abs(_exitValue - pairTuple.Item3) > 0.1)
{
_reversePassage(pairTuple.Item3);
_directPassage();
}
Console.WriteLine(pairTuple.Item1 + " " + pairTuple.Item2 + " " + _exitValue);
}
}
// прямой ход. по сути это обновление значений весов элементов и их подсчёт.
private void _directPassage()
{
_firstAssasin.CreateNeural();
_secondAssasin.CreateNeural();
_exitNeural.CreateNeural();
_exitValue = _exitNeural.Exit;
}
// первый, рандомный.
private void _setWeights(Random rand)
{
_firstAssasin.Weights.Add(_firstEntry, _nextRandom(rand));
_firstAssasin.Weights.Add(_secondEntry, _nextRandom(rand));
_firstAssasin.Weights.Add(_firstExternal, _nextRandom(rand));
_firstAssasin.CreateNeural();
_secondAssasin.Weights.Add(_firstEntry, _nextRandom(rand));
_secondAssasin.Weights.Add(_secondEntry, _nextRandom(rand));
_secondAssasin.Weights.Add(_firstExternal, _nextRandom(rand));
_secondAssasin.CreateNeural();
_exitNeural.Weights.Add(_firstAssasin, _nextRandom(rand));
_exitNeural.Weights.Add(_secondAssasin, _nextRandom(rand));
_exitNeural.Weights.Add(_secondExternal, _nextRandom(rand));
_exitNeural.CreateNeural();
}
private double _nextRandom(Random rand)
{
return 0.3 * (rand.NextDouble() * 2 - 1);
}
private void _reversePassage(double real)
{
// выходной слой
_exitNeural.Error = (1 - _exitNeural.Exit) * (real - _exitNeural.Exit) * _exitNeural.Exit;
_exitNeural.Weights[_firstAssasin] += _exitNeural.Error*_firstAssasin.Exit;
_exitNeural.Weights[_secondAssasin] += _exitNeural.Error*_secondAssasin.Exit;
_exitNeural.Weights[_secondExternal] += _exitNeural.Error*_secondExternal.Exit;
// скрытый слой
_firstAssasin.Error = _firstAssasin.Exit * (1 - _firstAssasin.Exit) *
(_exitNeural.Error * _exitNeural.Weights[_firstAssasin] + _exitNeural.Error * _exitNeural.Weights[_secondAssasin]);
_secondAssasin.Error = _secondAssasin.Exit * (1 - _secondAssasin.Exit) *
(_exitNeural.Error * _exitNeural.Weights[_firstAssasin] + _exitNeural.Error * _exitNeural.Weights[_secondAssasin]);
_firstAssasin.Weights[_firstEntry] += _firstAssasin.Error*_firstEntry.Exit;
_firstAssasin.Weights[_secondEntry] += _firstAssasin.Error*_secondEntry.Exit;
_firstAssasin.Weights[_firstExternal] += _firstAssasin.Error*_firstExternal.Exit;
_secondAssasin.Weights[_firstEntry] += _secondAssasin.Error*_firstEntry.Exit;
_secondAssasin.Weights[_secondEntry] += _secondAssasin.Error*_secondEntry.Exit;
_secondAssasin.Weights[_firstExternal] += _secondAssasin.Error*_firstExternal.Exit;
}
public void Print()
{
//TODO
}
}
}