mlpnn 0.0.1

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.
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: []