-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathindex.html
More file actions
213 lines (172 loc) · 8.3 KB
/
index.html
File metadata and controls
213 lines (172 loc) · 8.3 KB
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
<!DOCTYPE html>
<html lang="es">
<head>
<title>Perceptron TP2 - 123105</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<section class="graphic">
<input type="radio" name="nav" id="front" checked>
<input type="radio" name="nav" id="right">
<input type="radio" name="nav" id="back">
<input type="radio" name="nav" id="left">
<input type="radio" name="nav" id="top">
<input type="radio" name="nav" id="bottom">
<header>
<input type="text" name="formula" value="x && y && z" placeholder="x && y && z">
<button onclick="train(document.querySelector('header > input').value)">Aprender</button>
</header>
<article id="output"></article>
<nav>
<label for="front">Frente</label>
<label for="right">Derecha</label>
<label for="back">Atras</label>
<label for="left">Izquierda</label>
<label for="top">Superior</label>
<label for="bottom">Inferior</label>
</nav>
<div class="scene">
<div class="cube">
<div>
<table>
<tbody><tr><td class="v010">X=0</td><td class="v110">X=1</td></tr>
<tr><td class="v000">X=0</td><td class="v100">X=1</td></tr>
</tbody></table>
</div>
<div>
<table>
<tbody><tr><td class="v110">Y=1</td><td class="v111">Y=1</td></tr>
<tr><td class="v100">Y=0</td><td class="v101">Y=0</td></tr>
</tbody></table>
</div>
<div>
<table>
<tbody><tr><td class="v111">X=1</td><td class="v011">X=0</td></tr>
<tr><td class="v101">X=1</td><td class="v001">X=0</td></tr>
</tbody></table>
</div>
<div>
<table>
<tbody><tr><td class="v011">Y=1</td><td class="v010">Y=1</td></tr>
<tr><td class="v001">Y=0</td><td class="v000">Y=0</td></tr>
</tbody></table>
</div>
<div>
<table>
<tbody><tr><td class="v011">Z=1</td><td class="v111">Z=1</td></tr>
<tr><td class="v010">Z=0</td><td class="v110">Z=0</td></tr>
</tbody></table>
</div>
<div>
<table>
<tbody><tr><td class="v000">Z=0</td><td class="v100">Z=0</td></tr>
<tr><td class="v001">Z=1</td><td class="v101">Z=1</td></tr>
</tbody></table>
</div>
</div>
</div>
<article>
<h5>Codificacion:</h5>
<p>
A la hora de codificar el presente algoritmo, se utilizo Javascript con la finalidad de que el mismo pueda publicarse eventualmente en cualquier sitio web a modo demostrativo. La formula logica que debe aprender el perceptron se parametriza de modo que puedan probarse distintas formulas sin inconvenientes.
</p>
<p>
Se programado un Perceptron siple, con 3 metodos:
</p>
<ul>
<li><strong>Train: </strong> Este metodo recibe como primer parametro las entradas del Perceptron en forma de Array y como segundo parametro la salida esperada. Internamente, el perceptron genera un peso aleatorio para cada entrada y almacena los datos de entrenamiento recibidos.</li>
<li><strong>Perceive: </strong> Este metodo recibe un unico parametro que son las entradas del Perceptron, devuelve como salida el resultado (1 o 0) de la activacion del perceptron.</li>
<li><strong>Retrain: </strong> Este metodo revisa para cada conjunto de entradas en el set de entrenamiento, que el Perceptron sea capaz de percibir la salida adecuada, si no es asi, utiliza un algoritmo de aprendizaje supervisado para recalcular los pesos. Si todas las entradas producen la salida correcta, devuelve True, de lo contrario devuelve False.</li>
</ul>
<p>
El Perceptron solo tiene dos valores predefinidos, un threshold = 0.5 y el learnrate = 0.1; No obstante, el peso del threshold (bias) es inicializado aleatoriamente y ajustado en base a una funcion sigma igual que los pesos de las entradas. La formula de ajuste de pesos es de manual: <strong>weight += (expected - result) * learnrate * input</strong>
</p>
<h5>Entrenamiento:</h5>
<p>
Para la fase de entrenamiento, se analizan todas las combinaciones posibles de X, Y y Z y se calcula para cada una de ellas, la salida de la formula proporcionada, acto seguido, se entrena al perceptron con el resultado obtenido.<br>Luego de entrenar todas las combinaciones posibles, se procede a verificar que el perceptron sea capaz de retener la informacion, esto se hace llamando al metodo <strong>Perceive</strong> una cantidad maxima de 1 millon de veces, si pasado esa cantidad de intentos el perceptron no es capaz de retener la informacion, posiblemente se trate de una funcion que no es linealmente separable.
</p>
<h5>Evaluacion:</h5>
<p>
Para la fase de evaluacion, se le pide al perceptron que indique para cada una de las combinaciones de inputs posibles, que indique cual es su salida aprendida, esta salida se grafica en cubo de 2x2x2 tridimensional, las caras en color verde son aquellas que activan al perceptron y aquellas en rojo las que no lo hacen.
</p>
</article>
</section>
<script>
function Perceptron() {
var weights = [],
threshold = 0.5,
learnrate = 0.1,
data = [];
this.retrain = function retrain() {
var success = true;
for (var index=data.length; index > 0; index--) {
var training = data.shift();
success = this.train(training.input, training.target) && success;
}
return success;
}
this.train = function train(inputs, expected) {
while (weights.length <= inputs.length) {
weights.push(Math.random());
}
var result = this.perceive(inputs);
data.push({ input: inputs, target: expected });
if (result == expected) {
return true
}
for(var index=0; index < weights.length; index++) {
var input = (index == inputs.length) ? threshold : inputs[index];
weights[index] += (expected - result) * learnrate * input;
}
return false;
}
this.perceive = function perceive(inputs) {
var result = 0;
for(var i=0; i<inputs.length; i++) {
result += inputs[i] * weights[i];
}
result += threshold * weights[weights.length - 1];
return Number( ( 1 / ( 1 + Math.pow(Math.E, -result) ) ) >= threshold);
}
}
</script>
<script>
function train(calc) {
function result(x, y, z) {
return eval(calc);
}
var fnc = new Perceptron();
var actives = document.querySelectorAll('.cube .active');
for (var idx = 0; idx < actives.length; idx++) {
actives[idx].classList.remove('active');
}
for (var x = 0; x < 2; x++) {
for (var y = 0; y < 2; y++) {
for (var z = 0; z < 2; z++) {
fnc.train([x, y, z], result(x, y, z) ? 1 : 0);
}
}
}
// Aprender
var nro = 0;
while ( !fnc.retrain() && ++nro < 1000000);
if ( !fnc.retrain() ) {
alert('No se pudo aprender la formula ni en un millon de intentos! Seguro que es linealmente separable?');
return;
}
for (var x = 0; x < 2; x++) {
for (var y = 0; y < 2; y++) {
for (var z = 0; z < 2; z++) {
actives = document.querySelectorAll('.v' + x.toString() + y.toString() + z.toString());
for (var idx = 0; idx < actives.length; idx++) {
if (fnc.perceive([x, y, z]) == 1) {
actives[idx].classList.add('active');
}
}
}
}
}
}
</script>
</body>
</html>