alexandrebrillant_perceptron 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Alexandre Brillant
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,153 @@
1
+ # Perceptron
2
+
3
+ A Simple JavaScript Implementation of the Perceptron AI Algorithm
4
+
5
+ ## Usage
6
+
7
+ Add any sample using the **addTrainingSample**. A Sample is a set of values with a label. You can have only two labels. A label is a free string.
8
+
9
+ Calling **train** will update the inner weights of the perceptron. You can specify
10
+ too a max training size. It return an error rate. 1 (100%) means it can't train the samples and 0 (0%) means this is perfect.
11
+
12
+ After training the perceptron, you can use the **predict** method with a set of values. It will return the label for this values.
13
+
14
+ In the following sample, we have two labels: green and red. Green represents a negative value, and red represents a positive one. We let the perceptron find the correct weights during training to predict them.
15
+
16
+ ![Perceptron result](doc/result.png)
17
+
18
+ ```javascript
19
+
20
+ import { Perceptron } from "../dist/perceptron.mjs";
21
+
22
+ const perceptron = new Perceptron();
23
+
24
+ const sample1 = {
25
+ sample: [],
26
+ label:"red"
27
+ }
28
+
29
+ for ( let sample = 0; sample < 100; sample++ )
30
+ sample1.sample.push( Math.random() * 100 );
31
+
32
+ const sample2 = {
33
+ sample : [],
34
+ label:"green"
35
+ };
36
+
37
+ for ( let sample = 0; sample < 100; sample++ )
38
+ sample2.sample.push( -Math.random() * 100 );
39
+
40
+ perceptron.addTrainingSample( sample1 );
41
+ perceptron.addTrainingSample( sample2 );
42
+
43
+ const errorRate = perceptron.train();
44
+
45
+ console.log( "Training good result rate " + ( 100 - errorRate ) + "%" );
46
+
47
+ console.log( perceptron.predict( [-10,-2] ) ); // green
48
+
49
+ console.log( perceptron.predict( [200,30] ) ); // red
50
+ ```
51
+
52
+ ## Draw the result separator
53
+
54
+ In this example, we have two sets of points. We display the points and the separator line found by the perceptron.
55
+
56
+
57
+ ```html
58
+ <!DOCTYPE html>
59
+ <html>
60
+ <head>
61
+
62
+ <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
63
+
64
+ <script type="module">
65
+
66
+ import { Perceptron } from "../dist/perceptron.mjs";
67
+
68
+ const perceptron = new Perceptron();
69
+
70
+ const trace1 = {
71
+ x:[],
72
+ y:[],
73
+ mode:'markers',
74
+ type:'scatter'
75
+ };
76
+
77
+ const trace2 = {
78
+ x:[],
79
+ y:[],
80
+ mode:'markers',
81
+ type:'scatter'
82
+ };
83
+
84
+ for ( let sample = 0; sample < 100; sample++ ) {
85
+
86
+ let x1,y1;
87
+ let x2,y2;
88
+
89
+ const sample1 = {
90
+ sample: [ x1 = ( Math.random() * 100 ) + 20, y1 = ( Math.random() * 100 ) + 20 ],
91
+ label:"red"
92
+ }
93
+
94
+ const sample2 = {
95
+ sample: [ x2 = ( Math.random() * 100 ) - 50, y2 = ( Math.random() * 100 ) - 50 ],
96
+ label : "green"
97
+ }
98
+
99
+ trace1.x.push( x1 );
100
+ trace1.y.push( y1 );
101
+
102
+ trace2.x.push( x2 );
103
+ trace2.y.push( y2 );
104
+
105
+ perceptron.addTrainingSample( sample1 );
106
+ perceptron.addTrainingSample( sample2 );
107
+ }
108
+
109
+ const errorRate = perceptron.train();
110
+
111
+ const a1 = -50;
112
+ const a2 = 120;
113
+ const w1 = perceptron.weight( 0 );
114
+ const w2 = perceptron.weight( 1 );
115
+
116
+ const b = perceptron.biais();
117
+
118
+ const b1 = (-w1 * a1 - b) / w2;
119
+ const b2 = (-w1 * a2 - b) / w2;
120
+
121
+ const trace3 =
122
+ {
123
+ x: [a1, a2],
124
+ y: [b1, b2],
125
+ mode: 'lines',
126
+ type: 'scatter',
127
+ name: 'Separator',
128
+ line: { color: 'blue', dash: 'dash' }
129
+ };
130
+
131
+ let data = [ trace1, trace2, trace3 ];
132
+
133
+ Plotly.newPlot( 'plots', data );
134
+
135
+ </script>
136
+ </head>
137
+
138
+ <body>
139
+
140
+ <h1>Perceptron result</h1>
141
+
142
+ <div id="plots">
143
+
144
+ </div>
145
+ </body>
146
+
147
+ </html>
148
+
149
+ ```
150
+
151
+
152
+
153
+ (c) 2026 Alexandre Brillant
@@ -0,0 +1 @@
1
+ export class Perceptron{#samples=[];#weights=null;#biais=0;scalarProduct(sample){let scalar=this.#biais;for(let i=0;i<sample.length;i++){scalar+=sample[i]*this.#weights[i]}return scalar}#outputs={};#output=-1;#labels=[];weight(index){return this.#weights[index]}biais(){return this.#biais}addTrainingSample({sample:sample,label:label}){if(!Array.isArray(sample))throw"Invalid sample, must be an Array";if(this.#samples.length>0){const previousLength=this.#samples.at(-1).sample.length;if(previousLength!=sample.length)throw"Invalid sample size, must have a x"+previousLength+" size"}this.#weights=this.#weights??new Array(sample.length).fill(0);if(!(label in this.#outputs)){this.#outputs[label]=this.#output;this.#labels.push(label);this.#output+=2;if(this.#output>4)throw"Illegal label, must have only 2 labels"}this.#samples.push({sample:sample,output:this.#outputs[label]})}#updateWeights({sample:sample,output:output}){this.#biais+=output;for(let i=0;i<sample.length;i++){this.#weights[i]+=output*sample[i]}}train(trainingSize=100){if(this.#samples.length==0)throw"No training data ?";let errorFound=false;let totalError=0;do{errorFound=false;totalError=0;this.#samples.forEach(({sample:sample,output:output})=>{if(output*this.scalarProduct(sample)<=0){errorFound=true;totalError++;this.#updateWeights({sample:sample,output:output})}});trainingSize--}while(trainingSize>0&&errorFound);return totalError/this.#samples.length}predict(sample){const result=this.scalarProduct(sample);if(result>=0)return this.#labels[1];return this.#labels[0]}}
@@ -0,0 +1,110 @@
1
+ /*
2
+ * Perceptron.mjs
3
+ * Copyright 2026 Alexandre Brillant
4
+ */
5
+
6
+ /*
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the &quot;Software&quot;), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in all
15
+ copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ SOFTWARE.
24
+ */
25
+
26
+ export class Perceptron {
27
+
28
+ #samples = [];
29
+ #weights = null;
30
+ #biais = 0;
31
+
32
+ // W*X
33
+ scalarProduct( sample ) {
34
+ let scalar = this.#biais;
35
+ for ( let i = 0; i < sample.length; i++ ) {
36
+ scalar += sample[ i ] * this.#weights[ i ];
37
+ }
38
+ return scalar;
39
+ }
40
+
41
+ #outputs = {};
42
+ #output = -1;
43
+ #labels = [];
44
+
45
+ weight( index ) {
46
+ return this.#weights[ index ];
47
+ }
48
+
49
+ biais() {
50
+ return this.#biais;
51
+ }
52
+
53
+ addTrainingSample( {sample, label} ) {
54
+ if ( !Array.isArray( sample ) )
55
+ throw "Invalid sample, must be an Array";
56
+
57
+ if ( this.#samples.length > 0 ) {
58
+ const previousLength = this.#samples.at( -1 ).sample.length;
59
+ if ( previousLength != sample.length )
60
+ throw "Invalid sample size, must have a x" + previousLength + " size";
61
+ }
62
+
63
+ this.#weights = this.#weights ?? new Array( sample.length ).fill( 0.0 );
64
+
65
+ if ( !( label in this.#outputs ) ) {
66
+ this.#outputs[ label ] = this.#output;
67
+ this.#labels.push( label );
68
+ this.#output += 2;
69
+ if ( this.#output > 4 )
70
+ throw "Illegal label, must have only 2 labels"
71
+ }
72
+ this.#samples.push( { sample, output:this.#outputs[ label ] } );
73
+ }
74
+
75
+ #updateWeights( { sample, output } ) {
76
+ this.#biais += output;
77
+ for ( let i = 0; i < sample.length; i++ ) {
78
+ this.#weights[ i ] += output * sample[ i ];
79
+ }
80
+ }
81
+
82
+ train( trainingSize = 100 ) {
83
+ if ( this.#samples.length == 0 )
84
+ throw "No training data ?";
85
+ let errorFound = false;
86
+ let totalError = 0;
87
+ do {
88
+ errorFound = false;
89
+ totalError = 0;
90
+ this.#samples.forEach(
91
+ ( { sample, output } ) => {
92
+ if ( output * this.scalarProduct( sample ) <= 0 ) {
93
+ errorFound = true;
94
+ totalError++;
95
+ this.#updateWeights( { sample, output } );
96
+ }
97
+ }
98
+ );
99
+ trainingSize--;
100
+ } while ( trainingSize > 0 && errorFound );
101
+ return totalError / this.#samples.length;
102
+ }
103
+
104
+ predict( sample ) {
105
+ const result = this.scalarProduct( sample );
106
+ if ( result >= 0 ) return this.#labels[ 1 ];
107
+ return this.#labels[ 0 ];
108
+ }
109
+
110
+ }
package/doc/result.png ADDED
Binary file
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "alexandrebrillant_perceptron",
3
+ "version": "1.0.0",
4
+ "description": "A Simple JavaScript Implementation of the Perceptron Algorithm",
5
+ "keywords": [
6
+ "perceptron",
7
+ "percepton javascript",
8
+ "artificial neuron",
9
+ "supervised learning",
10
+ "neuron",
11
+ "ia",
12
+ "ai"
13
+ ],
14
+ "homepage": "https://github.com/AlexandreBrillant/perceptron#readme",
15
+ "bugs": {
16
+ "url": "https://github.com/AlexandreBrillant/perceptron/issues"
17
+ },
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/AlexandreBrillant/perceptron.git"
21
+ },
22
+ "license": "MIT",
23
+ "author": "Alexandre Brillant",
24
+ "type": "module",
25
+ "main": "perceptron.mjs",
26
+ "scripts": {
27
+ "test": "node test/test.js",
28
+ "predeploy": "node --check src/perceptron.mjs",
29
+ "deploy": "cp src/perceptron.mjs dist",
30
+ "postdeploy": "npx terser dist/perceptron.mjs > dist/perceptron.min.mjs"
31
+ },
32
+ "devDependencies": {
33
+ "http-server": "^14.1.1",
34
+ "terser": "^5.46.1"
35
+ }
36
+ }
@@ -0,0 +1,110 @@
1
+ /*
2
+ * Perceptron.mjs
3
+ * Copyright 2026 Alexandre Brillant
4
+ */
5
+
6
+ /*
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the &quot;Software&quot;), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in all
15
+ copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ SOFTWARE.
24
+ */
25
+
26
+ export class Perceptron {
27
+
28
+ #samples = [];
29
+ #weights = null;
30
+ #biais = 0;
31
+
32
+ // W*X
33
+ scalarProduct( sample ) {
34
+ let scalar = this.#biais;
35
+ for ( let i = 0; i < sample.length; i++ ) {
36
+ scalar += sample[ i ] * this.#weights[ i ];
37
+ }
38
+ return scalar;
39
+ }
40
+
41
+ #outputs = {};
42
+ #output = -1;
43
+ #labels = [];
44
+
45
+ weight( index ) {
46
+ return this.#weights[ index ];
47
+ }
48
+
49
+ biais() {
50
+ return this.#biais;
51
+ }
52
+
53
+ addTrainingSample( {sample, label} ) {
54
+ if ( !Array.isArray( sample ) )
55
+ throw "Invalid sample, must be an Array";
56
+
57
+ if ( this.#samples.length > 0 ) {
58
+ const previousLength = this.#samples.at( -1 ).sample.length;
59
+ if ( previousLength != sample.length )
60
+ throw "Invalid sample size, must have a x" + previousLength + " size";
61
+ }
62
+
63
+ this.#weights = this.#weights ?? new Array( sample.length ).fill( 0.0 );
64
+
65
+ if ( !( label in this.#outputs ) ) {
66
+ this.#outputs[ label ] = this.#output;
67
+ this.#labels.push( label );
68
+ this.#output += 2;
69
+ if ( this.#output > 4 )
70
+ throw "Illegal label, must have only 2 labels"
71
+ }
72
+ this.#samples.push( { sample, output:this.#outputs[ label ] } );
73
+ }
74
+
75
+ #updateWeights( { sample, output } ) {
76
+ this.#biais += output;
77
+ for ( let i = 0; i < sample.length; i++ ) {
78
+ this.#weights[ i ] += output * sample[ i ];
79
+ }
80
+ }
81
+
82
+ train( trainingSize = 100 ) {
83
+ if ( this.#samples.length == 0 )
84
+ throw "No training data ?";
85
+ let errorFound = false;
86
+ let totalError = 0;
87
+ do {
88
+ errorFound = false;
89
+ totalError = 0;
90
+ this.#samples.forEach(
91
+ ( { sample, output } ) => {
92
+ if ( output * this.scalarProduct( sample ) <= 0 ) {
93
+ errorFound = true;
94
+ totalError++;
95
+ this.#updateWeights( { sample, output } );
96
+ }
97
+ }
98
+ );
99
+ trainingSize--;
100
+ } while ( trainingSize > 0 && errorFound );
101
+ return totalError / this.#samples.length;
102
+ }
103
+
104
+ predict( sample ) {
105
+ const result = this.scalarProduct( sample );
106
+ if ( result >= 0 ) return this.#labels[ 1 ];
107
+ return this.#labels[ 0 ];
108
+ }
109
+
110
+ }
package/test/test.html ADDED
@@ -0,0 +1,118 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+
5
+ <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
6
+
7
+ <script type="module">
8
+
9
+ /*
10
+ * test.html
11
+ *
12
+ * Draw points and the result line of the perceptron
13
+ *
14
+ * Copyright 2026 Alexandre Brillant
15
+ */
16
+
17
+ /*
18
+ Permission is hereby granted, free of charge, to any person obtaining a copy
19
+ of this software and associated documentation files (the &quot;Software&quot;), to deal
20
+ in the Software without restriction, including without limitation the rights
21
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22
+ copies of the Software, and to permit persons to whom the Software is
23
+ furnished to do so, subject to the following conditions:
24
+
25
+ The above copyright notice and this permission notice shall be included in all
26
+ copies or substantial portions of the Software.
27
+
28
+ THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
31
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
33
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
34
+ SOFTWARE.
35
+ */
36
+
37
+ import { Perceptron } from "../dist/perceptron.mjs";
38
+
39
+ const perceptron = new Perceptron();
40
+
41
+ const trace1 = {
42
+ x:[],
43
+ y:[],
44
+ mode:'markers',
45
+ type:'scatter'
46
+ };
47
+
48
+ const trace2 = {
49
+ x:[],
50
+ y:[],
51
+ mode:'markers',
52
+ type:'scatter'
53
+ };
54
+
55
+ for ( let sample = 0; sample < 100; sample++ ) {
56
+
57
+ let x1,y1;
58
+ let x2,y2;
59
+
60
+ const sample1 = {
61
+ sample: [ x1 = ( Math.random() * 100 ) + 20, y1 = ( Math.random() * 100 ) + 20 ],
62
+ label:"red"
63
+ }
64
+
65
+ const sample2 = {
66
+ sample: [ x2 = ( Math.random() * 100 ) - 50, y2 = ( Math.random() * 100 ) - 50 ],
67
+ label : "green"
68
+ }
69
+
70
+ trace1.x.push( x1 );
71
+ trace1.y.push( y1 );
72
+
73
+ trace2.x.push( x2 );
74
+ trace2.y.push( y2 );
75
+
76
+ perceptron.addTrainingSample( sample1 );
77
+ perceptron.addTrainingSample( sample2 );
78
+ }
79
+
80
+ const errorRate = perceptron.train();
81
+
82
+ const a1 = -50;
83
+ const a2 = 120;
84
+ const w1 = perceptron.weight( 0 );
85
+ const w2 = perceptron.weight( 1 );
86
+
87
+ const b = perceptron.biais();
88
+
89
+ const b1 = (-w1 * a1 - b) / w2;
90
+ const b2 = (-w1 * a2 - b) / w2;
91
+
92
+ const trace3 =
93
+ {
94
+ x: [a1, a2],
95
+ y: [b1, b2],
96
+ mode: 'lines',
97
+ type: 'scatter',
98
+ name: 'Separator',
99
+ line: { color: 'blue', dash: 'dash' }
100
+ };
101
+
102
+ let data = [ trace1, trace2, trace3 ];
103
+
104
+ Plotly.newPlot( 'plots', data );
105
+
106
+ </script>
107
+ </head>
108
+
109
+ <body>
110
+
111
+ <h1>Perceptron result</h1>
112
+
113
+ <div id="plots">
114
+
115
+ </div>
116
+ </body>
117
+
118
+ </html>
package/test/test.js ADDED
@@ -0,0 +1,55 @@
1
+ /*
2
+ * test.js
3
+ * Copyright 2026 Alexandre Brillant
4
+ */
5
+
6
+ /*
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the &quot;Software&quot;), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in all
15
+ copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ SOFTWARE.
24
+ */
25
+
26
+ import { Perceptron } from "../dist/perceptron.mjs";
27
+
28
+ const perceptron = new Perceptron();
29
+
30
+ const sample1 = {
31
+ sample: [],
32
+ label:"red"
33
+ }
34
+
35
+ for ( let sample = 0; sample < 100; sample++ )
36
+ sample1.sample.push( Math.random() * 100 );
37
+
38
+ const sample2 = {
39
+ sample : [],
40
+ label:"green"
41
+ };
42
+
43
+ for ( let sample = 0; sample < 100; sample++ )
44
+ sample2.sample.push( -Math.random() * 100 );
45
+
46
+ perceptron.addTrainingSample( sample1 );
47
+ perceptron.addTrainingSample( sample2 );
48
+
49
+ const errorRate = perceptron.train();
50
+
51
+ console.log( "Training good result rate " + ( 100 - errorRate ) + "%" );
52
+
53
+ console.log( perceptron.predict( [-10,-2] ) ); // green
54
+
55
+ console.log( perceptron.predict( [200,30] ) ); // red