mlpnn 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 55e005b2fa8211ce8deb2b6b0c72e1658c38e10e
4
+ data.tar.gz: 2521f3894e6125581af1715f9a49858a3b8277ab
5
+ SHA512:
6
+ metadata.gz: 68736aceb98084f6f2d4122756264377ae83f4cce5db5de5ade2ef98ecc9bc117b5de46c0fb173d77bee7d50551e89584f5e19f05b095bffac722d37e16e376c
7
+ data.tar.gz: 23b20e30307018cf3ded7a381c9c9e82004b275cc5a549eac80479c1caca6a4c16a151947ad40b8b378f5670d226f432d415a0ac4987b81b801d894c0459accc
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
data/.rubocop.yml ADDED
@@ -0,0 +1,63 @@
1
+ # This is the configuration used to check the rubocop source code.
2
+
3
+ AllCops:
4
+ Exclude:
5
+ - 'vendor/**/*'
6
+ - 'spec/fixtures/**/*'
7
+ - 'tmp/**/*'
8
+ TargetRubyVersion: 2.4
9
+
10
+ Style/Encoding:
11
+ EnforcedStyle: when_needed
12
+ Enabled: true
13
+
14
+ Style/FrozenStringLiteralComment:
15
+ EnforcedStyle: always
16
+
17
+ Metrics/BlockLength:
18
+ Exclude:
19
+ - 'Rakefile'
20
+ - '**/*.rake'
21
+ - 'spec/**/*.rb'
22
+
23
+ # Offense count: 86
24
+ Metrics/AbcSize:
25
+ Max: 19
26
+
27
+ # Offense count: 32
28
+ # Configuration parameters: CountComments.
29
+ Metrics/ClassLength:
30
+ Max: 178
31
+
32
+ # Offense count: 28
33
+ Metrics/CyclomaticComplexity:
34
+ Max: 7
35
+
36
+ # Offense count: 139
37
+ # Configuration parameters: CountComments.
38
+ Metrics/MethodLength:
39
+ Max: 14
40
+
41
+ # Offense count: 12
42
+ # Configuration parameters: CountComments.
43
+ Metrics/ModuleLength:
44
+ Max: 156
45
+
46
+ Style/BarePercentLiterals:
47
+ EnforcedStyle: bare_percent
48
+ Heredoc:
49
+ Exclude: true
50
+
51
+ Style/TrailingCommaInLiteral:
52
+ EnforcedStyleForMultiline: comma
53
+ Heredoc:
54
+ IncludeKeys:
55
+ - RUBY
56
+
57
+ Metrics/LineLength:
58
+ Max: 90
59
+ Heredoc:
60
+ ExcludeKeys:
61
+ - YAML
62
+ - XML
63
+ - TEXT
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+ source 'https://rubygems.org'
3
+
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,52 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ mlpnn (0.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ activesupport (5.0.1)
10
+ concurrent-ruby (~> 1.0, >= 1.0.2)
11
+ i18n (~> 0.7)
12
+ minitest (~> 5.1)
13
+ tzinfo (~> 1.1)
14
+ ast (2.3.0)
15
+ concurrent-ruby (1.0.4)
16
+ i18n (0.7.0)
17
+ minitest (5.10.1)
18
+ parser (2.3.3.1)
19
+ ast (~> 2.2)
20
+ powerpack (0.1.1)
21
+ rainbow (2.2.1)
22
+ rake (10.5.0)
23
+ rubocop (0.47.1)
24
+ parser (>= 2.3.3.1, < 3.0)
25
+ powerpack (~> 0.1)
26
+ rainbow (>= 1.99.1, < 3.0)
27
+ ruby-progressbar (~> 1.7)
28
+ unicode-display_width (~> 1.0, >= 1.0.1)
29
+ ruby-progressbar (1.8.1)
30
+ shoulda (3.5.0)
31
+ shoulda-context (~> 1.0, >= 1.0.1)
32
+ shoulda-matchers (>= 1.4.1, < 3.0)
33
+ shoulda-context (1.2.2)
34
+ shoulda-matchers (2.8.0)
35
+ activesupport (>= 3.0.0)
36
+ thread_safe (0.3.5)
37
+ tzinfo (1.2.2)
38
+ thread_safe (~> 0.1)
39
+ unicode-display_width (1.1.3)
40
+
41
+ PLATFORMS
42
+ ruby
43
+
44
+ DEPENDENCIES
45
+ bundler (~> 1.13)
46
+ mlpnn!
47
+ rake (~> 10.0)
48
+ rubocop (~> 0.47)
49
+ shoulda (~> 3.5)
50
+
51
+ BUNDLED WITH
52
+ 1.13.7
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 reddavis / 2017 BEaStia
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,44 @@
1
+ = Multi-Layer Perceptron Neural Network
2
+
3
+ I built this to not only learn about the MLP but to also make a very simple, well laid out MLP so other can easily see what's happening.
4
+
5
+ I also suggest checking out http://bit.ly/XEWOc for a great tutorial.
6
+
7
+ == Install
8
+
9
+ gem install mlp
10
+
11
+ == How To Use
12
+ require 'mlp'
13
+
14
+ a = MLP::Network.new(hidden_layers: [2], output_nodes: 1, inputs: 2)
15
+
16
+ 3001.times do |i|
17
+ a.train([0,0], [0])
18
+ a.train([0,1], [1])
19
+ a.train([1,0], [1])
20
+ error = a.train([1,1], [0])
21
+ puts "Error after iteration #{i}:\t#{error}" if i%200 == 0
22
+ end
23
+
24
+ puts "Test data"
25
+ puts "[0,0] = > #{a.feed_forward([0,0]).inspect}"
26
+ puts "[0,1] = > #{a.feed_forward([0,1]).inspect}"
27
+ puts "[1,0] = > #{a.feed_forward([1,0]).inspect}"
28
+ puts "[1,1] = > #{a.feed_forward([1,1]).inspect}"
29
+
30
+ == Benchmarks
31
+
32
+ The above example produces these times
33
+
34
+        user     system      total        real
35
+ MLP 0.820000 0.000000 0.820000 ( 0.837693)
36
+ Ai4R 1.180000 0.010000 1.190000 ( 1.232388)
37
+
38
+ == Thanks
39
+
40
+ * David Richards - For his code reviews and all round helpfulness. - http://github.com/davidrichards
41
+
42
+ == Copyright
43
+
44
+ Copyright (c) 2009 Red Davis, 2017 Igor Pavlov See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |task|
5
+ task.libs << %w(test lib)
6
+ task.pattern = 'test/test_*.rb'
7
+ end
8
+
9
+ task :default => :test
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+ # This test was taken from ai4r gem
3
+
4
+ # Author:: Sergio Fierens
5
+ # License:: MPL 1.1
6
+ # Project:: ai4r
7
+ # Url:: http://ai4r.rubyforge.org/
8
+ #
9
+ # You can redistribute it and/or modify it under the terms of
10
+ # the Mozilla Public License version 1.1 as published by the
11
+ # Mozilla Foundation at http://www.mozilla.org/MPL/MPL-1.1.txt
12
+
13
+ require File.dirname(__FILE__) + '/training_patterns'
14
+ require File.dirname(__FILE__) + '/patterns_with_noise'
15
+ require File.dirname(__FILE__) + '/patterns_with_base_noise'
16
+ require File.dirname(__FILE__) + '/../lib/mlp'
17
+ require 'benchmark'
18
+
19
+ times = Benchmark.measure do
20
+ srand 1
21
+
22
+ net = MLP::Network.new(hidden_layers: [2], output_nodes: 3, inputs: 256)
23
+
24
+ tr_with_noise = TRIANGLE_WITH_NOISE.flatten.collect { |input| input.to_f / 5.0 }
25
+ sq_with_noise = SQUARE_WITH_NOISE.flatten.collect { |input| input.to_f / 5.0 }
26
+ cr_with_noise = CROSS_WITH_NOISE.flatten.collect { |input| input.to_f / 5.0 }
27
+
28
+ tr_with_base_noise = TRIANGLE_WITH_BASE_NOISE.flatten.collect { |input| input.to_f / 5.0 }
29
+ sq_with_base_noise = SQUARE_WITH_BASE_NOISE.flatten.collect { |input| input.to_f / 5.0 }
30
+ cr_with_base_noise = CROSS_WITH_BASE_NOISE.flatten.collect { |input| input.to_f / 5.0 }
31
+
32
+ puts 'Training the network, please wait.'
33
+ 101.times do |i|
34
+ tr_input = TRIANGLE.flatten.collect { |input| input.to_f / 5.0 }
35
+ sq_input = SQUARE.flatten.collect { |input| input.to_f / 5.0 }
36
+ cr_input = CROSS.flatten.collect { |input| input.to_f / 5.0 }
37
+
38
+ error1 = net.train(tr_input, [1, 0, 0])
39
+ error2 = net.train(sq_input, [0, 1, 0])
40
+ error3 = net.train(cr_input, [0, 0, 1])
41
+ puts "Error after iteration #{i}:\t#{error1} - #{error2} - #{error3}" if i % 20 == 0
42
+ end
43
+
44
+ def result_label(result)
45
+ if result[0] > result[1] && result[0] > result[2]
46
+ 'TRIANGLE'
47
+ elsif result[1] > result[2]
48
+ 'SQUARE'
49
+ else
50
+ 'CROSS'
51
+ end
52
+ end
53
+
54
+ tr_input = TRIANGLE.flatten.collect { |input| input.to_f / 5.0 }
55
+ sq_input = SQUARE.flatten.collect { |input| input.to_f / 5.0 }
56
+ cr_input = CROSS.flatten.collect { |input| input.to_f / 5.0 }
57
+
58
+ puts 'Training Examples'
59
+ puts "#{net.feed_forward(tr_input).inspect} => #{result_label(net.feed_forward(tr_input))}"
60
+ puts "#{net.feed_forward(sq_input).inspect} => #{result_label(net.feed_forward(sq_input))}"
61
+ puts "#{net.feed_forward(cr_input).inspect} => #{result_label(net.feed_forward(cr_input))}"
62
+ puts 'Examples with noise'
63
+ puts "#{net.feed_forward(tr_with_noise).inspect} => #{result_label(net.feed_forward(tr_with_noise))}"
64
+ puts "#{net.feed_forward(sq_with_noise).inspect} => #{result_label(net.feed_forward(sq_with_noise))}"
65
+ puts "#{net.feed_forward(cr_with_noise).inspect} => #{result_label(net.feed_forward(cr_with_noise))}"
66
+ puts 'Examples with base noise'
67
+ puts "#{net.feed_forward(tr_with_base_noise).inspect} => #{result_label(net.feed_forward(tr_with_base_noise))}"
68
+ puts "#{net.feed_forward(sq_with_base_noise).inspect} => #{result_label(net.feed_forward(sq_with_base_noise))}"
69
+ puts "#{net.feed_forward(cr_with_base_noise).inspect} => #{result_label(net.feed_forward(cr_with_base_noise))}"
70
+ end
71
+
72
+ puts "Elapsed time: #{times}"
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+ # Author:: Sergio Fierens
3
+ # License:: MPL 1.1
4
+ # Project:: ai4r
5
+ # Url:: http://ai4r.rubyforge.org/
6
+ #
7
+ # You can redistribute it and/or modify it under the terms of
8
+ # the Mozilla Public License version 1.1 as published by the
9
+ # Mozilla Foundation at http://www.mozilla.org/MPL/MPL-1.1.txt
10
+
11
+ TRIANGLE_WITH_BASE_NOISE = [
12
+ [3, 3, 3, 3, 3, 3, 3, 8, 8, 3, 3, 3, 3, 3, 3, 3],
13
+ [3, 3, 3, 3, 3, 3, 4, 10, 10, 4, 3, 3, 3, 3, 3, 3],
14
+ [3, 3, 3, 3, 3, 3, 8, 8, 8, 8, 3, 3, 3, 3, 3, 3],
15
+ [3, 3, 3, 3, 3, 4, 10, 4, 4, 10, 4, 3, 3, 3, 3, 3],
16
+ [3, 3, 3, 3, 3, 8, 8, 3, 3, 8, 8, 3, 3, 3, 3, 3],
17
+ [3, 3, 3, 3, 4, 10, 4, 3, 3, 4, 10, 4, 3, 3, 3, 3],
18
+ [3, 3, 3, 3, 8, 8, 3, 3, 3, 3, 8, 8, 3, 3, 3, 3],
19
+ [3, 3, 3, 4, 10, 4, 3, 3, 3, 3, 4, 10, 4, 3, 3, 3],
20
+ [3, 3, 3, 8, 8, 3, 3, 3, 3, 3, 3, 8, 8, 3, 3, 3],
21
+ [3, 3, 4, 10, 4, 3, 3, 3, 3, 3, 3, 4, 10, 4, 3, 3],
22
+ [3, 3, 8, 8, 3, 3, 3, 3, 3, 3, 3, 3, 8, 8, 3, 3],
23
+ [3, 4, 10, 4, 3, 3, 3, 3, 3, 3, 3, 3, 4, 10, 4, 3],
24
+ [3, 8, 8, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 8, 8, 3],
25
+ [4, 10, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 10, 4],
26
+ [8, 8, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 8, 8],
27
+ [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10],
28
+ ].freeze
29
+
30
+ SQUARE_WITH_BASE_NOISE = [
31
+ [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10],
32
+ [10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 10],
33
+ [10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 10],
34
+ [10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 10],
35
+ [10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 10],
36
+ [10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 10],
37
+ [10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 10],
38
+ [10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 10],
39
+ [10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 10],
40
+ [10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 10],
41
+ [10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 10],
42
+ [10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 10],
43
+ [10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 10],
44
+ [10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 10],
45
+ [10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 10],
46
+ [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10],
47
+
48
+ ].freeze
49
+
50
+ CROSS_WITH_BASE_NOISE = [
51
+ [3, 3, 3, 3, 3, 3, 3, 8, 8, 3, 3, 3, 3, 3, 3, 3],
52
+ [3, 3, 3, 3, 3, 3, 3, 8, 8, 3, 3, 3, 3, 3, 3, 3],
53
+ [3, 3, 3, 3, 3, 3, 3, 8, 8, 3, 3, 3, 3, 3, 3, 3],
54
+ [3, 3, 3, 3, 3, 3, 3, 8, 8, 3, 3, 3, 3, 3, 3, 3],
55
+ [3, 3, 3, 3, 3, 3, 3, 8, 8, 3, 3, 3, 3, 3, 3, 3],
56
+ [3, 3, 3, 3, 3, 3, 3, 8, 8, 3, 3, 3, 3, 3, 3, 3],
57
+ [3, 3, 3, 3, 3, 3, 3, 8, 8, 3, 3, 3, 3, 3, 3, 3],
58
+ [8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8],
59
+ [8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8],
60
+ [3, 3, 3, 3, 3, 3, 3, 8, 8, 3, 3, 3, 3, 3, 3, 3],
61
+ [3, 3, 3, 3, 3, 3, 3, 8, 8, 3, 3, 3, 3, 3, 3, 3],
62
+ [3, 3, 3, 3, 3, 3, 3, 8, 8, 3, 3, 3, 3, 3, 3, 3],
63
+ [3, 3, 3, 3, 3, 3, 3, 8, 8, 3, 3, 3, 3, 3, 3, 3],
64
+ [3, 3, 3, 3, 3, 3, 3, 8, 8, 3, 3, 3, 3, 3, 3, 3],
65
+ [3, 3, 3, 3, 3, 3, 3, 8, 8, 3, 3, 3, 3, 3, 3, 3],
66
+ [3, 3, 3, 3, 3, 3, 3, 8, 8, 3, 3, 3, 3, 3, 3, 3],
67
+ ].freeze
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+ # Author:: Sergio Fierens
3
+ # License:: MPL 1.1
4
+ # Project:: ai4r
5
+ # Url:: http://ai4r.rubyforge.org/
6
+ #
7
+ # You can redistribute it and/or modify it under the terms of
8
+ # the Mozilla Public License version 1.1 as published by the
9
+ # Mozilla Foundation at http://www.mozilla.org/MPL/MPL-1.1.txt
10
+
11
+ TRIANGLE_WITH_NOISE = [
12
+ [1, 0, 0, 0, 0, 0, 0, 1, 5, 0, 0, 1, 0, 0, 0, 0],
13
+ [0, 0, 0, 0, 3, 0, 1, 9, 9, 1, 0, 0, 0, 0, 3, 0],
14
+ [0, 3, 0, 0, 0, 0, 5, 1, 5, 3, 0, 0, 0, 0, 0, 7],
15
+ [0, 0, 0, 7, 0, 1, 9, 1, 1, 9, 1, 0, 0, 0, 3, 0],
16
+ [0, 0, 0, 0, 0, 3, 5, 0, 3, 5, 5, 0, 0, 0, 0, 0],
17
+ [0, 1, 0, 0, 1, 9, 1, 0, 1, 1, 9, 1, 0, 0, 0, 0],
18
+ [1, 0, 0, 0, 5, 5, 0, 0, 0, 0, 5, 5, 7, 0, 0, 3],
19
+ [0, 0, 3, 3, 9, 1, 0, 0, 1, 0, 1, 9, 1, 0, 0, 0],
20
+ [0, 0, 0, 5, 5, 0, 3, 7, 0, 0, 0, 5, 5, 0, 0, 0],
21
+ [0, 0, 1, 9, 1, 0, 0, 0, 0, 0, 0, 1, 9, 1, 0, 0],
22
+ [0, 0, 5, 5, 0, 0, 0, 0, 3, 0, 0, 0, 5, 5, 0, 0],
23
+ [0, 1, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 9, 1, 0],
24
+ [0, 5, 5, 0, 3, 0, 0, 3, 0, 0, 0, 0, 0, 5, 5, 0],
25
+ [1, 9, 1, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 1, 9, 1],
26
+ [5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5],
27
+ [10, 10, 10, 10, 1, 10, 10, 10, 10, 10, 1, 10, 10, 10, 10, 10],
28
+ ].freeze
29
+
30
+ SQUARE_WITH_NOISE = [
31
+ [10, 3, 10, 10, 10, 6, 10, 10, 10, 10, 10, 4, 10, 10, 10, 10],
32
+ [10, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10],
33
+ [10, 0, 3, 0, 0, 0, 0, 7, 0, 6, 1, 0, 0, 0, 0, 0],
34
+ [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10],
35
+ [10, 0, 4, 0, 4, 0, 0, 0, 1, 0, 3, 0, 0, 4, 0, 10],
36
+ [10, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
37
+ [10, 0, 0, 0, 3, 6, 0, 0, 1, 0, 0, 0, 0, 0, 0, 10],
38
+ [10, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 7, 0, 0, 10],
39
+ [10, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10],
40
+ [10, 0, 7, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10],
41
+ [10, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 7, 10],
42
+ [10, 0, 3, 0, 4, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 10],
43
+ [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 10],
44
+ [10, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 10],
45
+ [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10],
46
+ [10, 10, 10, 10, 3, 10, 10, 10, 10, 0, 10, 10, 1, 10, 1, 10],
47
+
48
+ ].freeze
49
+
50
+ CROSS_WITH_NOISE = [
51
+ [0, 0, 0, 0, 0, 0, 3, 3, 5, 0, 3, 0, 0, 0, 1, 0],
52
+ [0, 1, 0, 0, 0, 1, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0],
53
+ [0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 3, 0, 0, 0],
54
+ [0, 0, 1, 8, 0, 0, 0, 5, 5, 0, 4, 0, 0, 0, 1, 0],
55
+ [0, 0, 0, 0, 0, 3, 0, 5, 0, 0, 0, 0, 1, 0, 0, 0],
56
+ [0, 0, 0, 8, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 1],
57
+ [0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 3, 0, 0, 0, 0, 0],
58
+ [5, 5, 5, 8, 5, 3, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5],
59
+ [5, 5, 5, 5, 5, 5, 5, 5, 1, 5, 5, 5, 5, 1, 0, 0],
60
+ [0, 0, 0, 8, 0, 0, 0, 4, 5, 0, 0, 0, 0, 0, 0, 0],
61
+ [0, 0, 0, 0, 0, 0, 0, 5, 5, 4, 0, 0, 0, 0, 0, 0],
62
+ [0, 0, 0, 0, 0, 4, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0],
63
+ [4, 0, 0, 4, 0, 0, 0, 5, 5, 0, 0, 0, 1, 0, 0, 0],
64
+ [0, 0, 0, 0, 0, 1, 0, 5, 4, 4, 3, 0, 0, 0, 0, 0],
65
+ [0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 10, 0, 0, 0],
66
+ [0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0],
67
+ ].freeze
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+ # Author:: Sergio Fierens
3
+ # License:: MPL 1.1
4
+ # Project:: ai4r
5
+ # Url:: http://ai4r.rubyforge.org/
6
+ #
7
+ # You can redistribute it and/or modify it under the terms of
8
+ # the Mozilla Public License version 1.1 as published by the
9
+ # Mozilla Foundation at http://www.mozilla.org/MPL/MPL-1.1.txt
10
+
11
+ TRIANGLE = [
12
+ [0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0],
13
+ [0, 0, 0, 0, 0, 0, 1, 9, 9, 1, 0, 0, 0, 0, 0, 0],
14
+ [0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0],
15
+ [0, 0, 0, 0, 0, 1, 9, 1, 1, 9, 1, 0, 0, 0, 0, 0],
16
+ [0, 0, 0, 0, 0, 5, 5, 0, 0, 5, 5, 0, 0, 0, 0, 0],
17
+ [0, 0, 0, 0, 1, 9, 1, 0, 0, 1, 9, 1, 0, 0, 0, 0],
18
+ [0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0],
19
+ [0, 0, 0, 1, 9, 1, 0, 0, 0, 0, 1, 9, 1, 0, 0, 0],
20
+ [0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0],
21
+ [0, 0, 1, 9, 1, 0, 0, 0, 0, 0, 0, 1, 9, 1, 0, 0],
22
+ [0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0],
23
+ [0, 1, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 9, 1, 0],
24
+ [0, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0],
25
+ [1, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 9, 1],
26
+ [5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5],
27
+ [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10],
28
+ ].freeze
29
+
30
+ SQUARE = [
31
+ [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10],
32
+ [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10],
33
+ [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10],
34
+ [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10],
35
+ [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10],
36
+ [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10],
37
+ [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10],
38
+ [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10],
39
+ [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10],
40
+ [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10],
41
+ [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10],
42
+ [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10],
43
+ [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10],
44
+ [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10],
45
+ [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10],
46
+ [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10],
47
+
48
+ ].freeze
49
+
50
+ CROSS = [
51
+ [0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0],
52
+ [0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0],
53
+ [0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0],
54
+ [0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0],
55
+ [0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0],
56
+ [0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0],
57
+ [0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0],
58
+ [5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5],
59
+ [5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5],
60
+ [0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0],
61
+ [0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0],
62
+ [0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0],
63
+ [0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0],
64
+ [0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0],
65
+ [0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0],
66
+ [0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0],
67
+ ].freeze
data/examples/xor.rb ADDED
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+ # This test was taken from ai4r gem
3
+
4
+ require File.dirname(__FILE__) + '/../lib/mlp'
5
+ require 'benchmark'
6
+
7
+ times = Benchmark.measure do
8
+ srand 1
9
+
10
+ a = MLP::Network.new(hidden_layers: [2], output_nodes: 1, inputs: 2)
11
+
12
+ 3001.times do |i|
13
+ a.train([0, 0], [0])
14
+ a.train([0, 1], [1])
15
+ a.train([1, 0], [1])
16
+ error = a.train([1, 1], [0])
17
+ puts "Error after iteration #{i}:\t#{error}" if i % 200 == 0
18
+ end
19
+
20
+ puts 'Test data'
21
+ puts "[0,0] = > #{a.feed_forward([0, 0]).inspect}"
22
+ puts "[0,1] = > #{a.feed_forward([0, 1]).inspect}"
23
+ puts "[1,0] = > #{a.feed_forward([1, 0]).inspect}"
24
+ puts "[1,1] = > #{a.feed_forward([1, 1]).inspect}"
25
+ end
26
+
27
+ puts "Elapsed time: #{times}"
data/lib/mlp.rb ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mlp/network'
4
+ require 'mlp/neuron'
5
+
6
+ module MLP
7
+
8
+ end
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MLP
4
+ class Network
5
+
6
+ UPDATE_WEIGHT_VALUE = 0.25
7
+
8
+ def initialize(options = {})
9
+ @input_size = options[:inputs]
10
+ @hidden_layers = options[:hidden_layers]
11
+ @number_of_output_nodes = options[:output_nodes]
12
+ setup_network
13
+ end
14
+
15
+ def feed_forward(input)
16
+ @network.each_with_index do |layer, layer_index|
17
+ layer.each do |neuron|
18
+ if layer_index == 0
19
+ neuron.fire(input)
20
+ else
21
+ input = @network[layer_index - 1].map(&:last_output)
22
+ neuron.fire(input)
23
+ end
24
+ end
25
+ end
26
+ @network.last.map(&:last_output)
27
+ end
28
+
29
+ def train(input, targets)
30
+ # To go back we must go forward
31
+ feed_forward(input)
32
+ compute_deltas(targets)
33
+ update_weights(input)
34
+ calculate_error(targets)
35
+ end
36
+
37
+ def inspect
38
+ @network
39
+ end
40
+
41
+ private
42
+
43
+ def update_weights(input)
44
+ reversed_network = @network.reverse
45
+ reversed_network.each_with_index do |layer, layer_index|
46
+ if layer_index == 0
47
+ update_output_weights(layer, layer_index, input)
48
+ else
49
+ update_hidden_weights(layer, layer_index, input)
50
+ end
51
+ end
52
+ end
53
+
54
+ def update_output_weights(layer, _layer_index, input)
55
+ inputs = @hidden_layers.empty? ? input : @network[-2].map(&:last_output)
56
+ layer.each do |neuron|
57
+ neuron.update_weight(inputs, UPDATE_WEIGHT_VALUE)
58
+ end
59
+ end
60
+
61
+ def update_hidden_weights(layer, layer_index, original_input)
62
+ inputs = if layer_index == (@network.size - 1)
63
+ original_input
64
+ else
65
+ @network.reverse[layer_index + 1].map(&:last_output)
66
+ end
67
+ layer.each do |neuron|
68
+ neuron.update_weight(inputs, UPDATE_WEIGHT_VALUE)
69
+ end
70
+ end
71
+
72
+ def compute_deltas(targets)
73
+ reversed_network = @network.reverse
74
+ reversed_network.each_with_index do |layer, layer_index|
75
+ if layer_index == 0
76
+ compute_output_deltas(layer, targets)
77
+ else
78
+ compute_hidden_deltas(layer, targets)
79
+ end
80
+ end
81
+ end
82
+
83
+ def compute_output_deltas(layer, targets)
84
+ layer.each_with_index do |neuron, i|
85
+ output = neuron.last_output
86
+ neuron.delta = output * (1 - output) * (targets[i] - output)
87
+ end
88
+ end
89
+
90
+ def compute_hidden_deltas(layer, _targets)
91
+ layer.each_with_index do |neuron, neuron_index|
92
+ error = 0
93
+ @network.last.each do |output_neuron|
94
+ error += output_neuron.delta * output_neuron.weights[neuron_index]
95
+ end
96
+ output = neuron.last_output
97
+ neuron.delta = output * (1 - output) * error
98
+ end
99
+ end
100
+
101
+ def calculate_error(targets)
102
+ outputs = @network.last.map(&:last_output)
103
+ sum = 0
104
+ targets.each_with_index do |t, index|
105
+ sum += (t - outputs[index])**2
106
+ end
107
+ 0.5 * sum
108
+ end
109
+
110
+ def setup_network
111
+ @network = []
112
+
113
+ # Hidden Layers
114
+ @hidden_layers.each_with_index do |number_of_neurons, index|
115
+ inputs = index == 0 ? @input_size : @hidden_layers[index - 1].size
116
+ @network << Array.new(number_of_neurons) { Neuron.new(inputs) }
117
+ end
118
+
119
+ # Output layer
120
+ inputs = @hidden_layers.empty? ? @input_size : @hidden_layers.last
121
+ @network << Array.new(@number_of_output_nodes) { Neuron.new(inputs) }
122
+ end
123
+ end
124
+ end
data/lib/mlp/neuron.rb ADDED
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ module MLP
5
+ class Neuron
6
+ attr_reader :last_output, :weights
7
+ attr_accessor :delta
8
+
9
+ def initialize(number_of_inputs)
10
+ create_weights(number_of_inputs)
11
+ end
12
+
13
+ def fire(input)
14
+ @last_output = activation_function(input)
15
+ end
16
+
17
+ def update_weight(inputs, training_rate)
18
+ inputs << -1 # Add the bias
19
+ @weights.each_index do |i|
20
+ @weights[i] += training_rate * delta * inputs[i]
21
+ end
22
+ end
23
+
24
+ def inspect
25
+ @weights
26
+ end
27
+
28
+ private
29
+
30
+ def activation_function(input)
31
+ sum = 0
32
+ input.each_with_index do |n, index|
33
+ sum += @weights[index] * n
34
+ end
35
+ sum += @weights.last * -1 # bias node
36
+ sigmoid_function(sum)
37
+ end
38
+
39
+ # g(h) = 1 / (1+exp(-B*h(j)))
40
+ def sigmoid_function(x)
41
+ 1 / (1 + Math.exp(-1 * x))
42
+ end
43
+
44
+ def create_weights(number_of_inputs)
45
+ # Create random weights between 0 & 1
46
+ #  Plus another one for the bias node
47
+ @weights = []
48
+ (number_of_inputs + 1).times do
49
+ @weights << (rand > 0.5 ? -rand : rand)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+ module MLP
3
+ VERSION = '0.0.1'
4
+ end
data/mlpnn.gemspec ADDED
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'mlp/version'
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = 'mlpnn'
9
+ s.version = MLP::VERSION
10
+
11
+ s.authors = %w(reddavis beastia)
12
+ s.date = '2017-01-19'
13
+ s.description = <<~TEXT
14
+ Multi-Layer Perceptron Neural Network in Ruby(remake of reddavis' project by BEaStia)"
15
+ TEXT
16
+ s.email = 'gophan1992@gmail.com'
17
+ s.extra_rdoc_files = %w(LICENSE README.rdoc)
18
+ s.files = `git ls-files -z`.split("\x0").reject do |f|
19
+ f.match(%r{^(test|spec|features)/})
20
+ end
21
+
22
+ s.homepage = 'http://github.com/BEaStia/mlp'
23
+ s.require_paths = ['lib']
24
+ s.summary = 'Multi-Layer Perceptron Neural Network in Ruby'
25
+ s.required_ruby_version = '~> 2.3'
26
+
27
+ s.add_development_dependency 'bundler', '~> 1.13'
28
+ s.add_development_dependency 'rake', '~> 10.0'
29
+ s.add_development_dependency 'rubocop', '~> 0.47'
30
+ s.add_development_dependency 'shoulda', '~> 3.5'
31
+ end
metadata ADDED
@@ -0,0 +1,122 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mlpnn
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - reddavis
8
+ - beastia
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2017-01-19 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '1.13'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '1.13'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rake
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '10.0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '10.0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rubocop
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '0.47'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '0.47'
56
+ - !ruby/object:Gem::Dependency
57
+ name: shoulda
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '3.5'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '3.5'
70
+ description: 'Multi-Layer Perceptron Neural Network in Ruby(remake of reddavis'' project
71
+ by BEaStia)"
72
+
73
+ '
74
+ email: gophan1992@gmail.com
75
+ executables: []
76
+ extensions: []
77
+ extra_rdoc_files:
78
+ - LICENSE
79
+ - README.rdoc
80
+ files:
81
+ - ".gitignore"
82
+ - ".rubocop.yml"
83
+ - Gemfile
84
+ - Gemfile.lock
85
+ - LICENSE
86
+ - README.rdoc
87
+ - Rakefile
88
+ - VERSION
89
+ - examples/backpropagation_example.rb
90
+ - examples/patterns_with_base_noise.rb
91
+ - examples/patterns_with_noise.rb
92
+ - examples/training_patterns.rb
93
+ - examples/xor.rb
94
+ - lib/mlp.rb
95
+ - lib/mlp/network.rb
96
+ - lib/mlp/neuron.rb
97
+ - lib/mlp/version.rb
98
+ - mlpnn.gemspec
99
+ homepage: http://github.com/BEaStia/mlp
100
+ licenses: []
101
+ metadata: {}
102
+ post_install_message:
103
+ rdoc_options: []
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '2.3'
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ requirements: []
117
+ rubyforge_project:
118
+ rubygems_version: 2.6.8
119
+ signing_key:
120
+ specification_version: 4
121
+ summary: Multi-Layer Perceptron Neural Network in Ruby
122
+ test_files: []