brain 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,10 @@
1
+ == 0.0.2 2008-07-10
2
+ * Implementation of Hopfield net:
3
+ * Specs
4
+ * Code
5
+ * RDoc
6
+
7
+ == 0.0.1 2008-06-26
8
+
9
+ * 1 major enhancement:
10
+ * Initial release
@@ -0,0 +1,53 @@
1
+ = brain
2
+
3
+ * http://brain.rubyforge.org
4
+ * http://github.com/brainopia/brain
5
+
6
+ == DESCRIPTION:
7
+
8
+ Implements several types of Neural Networks such as multilayer perceptron (data classification), Kohonen net (data clusterization), Hopfield net (data association).
9
+
10
+ == FEATURES:
11
+
12
+ Currently supports:
13
+ * Hopfield net
14
+
15
+ == SYNOPSIS:
16
+
17
+ Basic examples:
18
+
19
+ * Hopfield net
20
+
21
+ sample = Brain::Hopfield[[-1, -1, -1, -1], [1, 1, 1, 1]].associate [1, 1, -1, 1]
22
+ sample.run until sample.associated?
23
+ sample.current # => [1, 1, 1, 1]
24
+
25
+
26
+ == INSTALL:
27
+
28
+ sudo gem install brain
29
+
30
+ == LICENSE:
31
+
32
+ (The MIT License)
33
+
34
+ Copyright (c) 2008 Ravil Bayramgalin
35
+
36
+ Permission is hereby granted, free of charge, to any person obtaining
37
+ a copy of this software and associated documentation files (the
38
+ 'Software'), to deal in the Software without restriction, including
39
+ without limitation the rights to use, copy, modify, merge, publish,
40
+ distribute, sublicense, and/or sell copies of the Software, and to
41
+ permit persons to whom the Software is furnished to do so, subject to
42
+ the following conditions:
43
+
44
+ The above copyright notice and this permission notice shall be
45
+ included in all copies or substantial portions of the Software.
46
+
47
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
48
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
49
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
50
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
51
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
52
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
53
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,18 @@
1
+ =begin rdoc
2
+ Defines Brain module.
3
+ =end
4
+
5
+ $:.unshift(File.dirname(__FILE__)) unless
6
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
7
+
8
+ require 'mathn'
9
+
10
+ =begin rdoc
11
+ Contains neural network classes: Brain::Hopfield, Brain::Kohonen and Brain::Perceptron.
12
+
13
+ Classes are autoloaded with the first invoking.
14
+ =end
15
+
16
+ module Brain
17
+ autoload 'Hopfield', 'brain/hopfield'
18
+ end
@@ -0,0 +1,75 @@
1
+ =begin rdoc
2
+ Defines Brain::Hopfield class.
3
+ =end
4
+
5
+ =begin rdoc
6
+ Represents a Hopfield net.
7
+
8
+ net = Brain::Hopfield[[-1, -1, -1, -1], [1, 1, 1, 1]]
9
+ sample = net.associate [1, 1, -1, 1]
10
+ sample.run until sample.associated?
11
+ sample.current # => [1, 1, 1, 1]
12
+ sample.iterations # => 2
13
+
14
+ In this example, it can take up to 4 iterations to associate the sample (actual value depends on a random order of updating neurons).
15
+ =end
16
+ class Brain::Hopfield
17
+ require 'brain/hopfield/sample'
18
+
19
+ # Shortcut for creation of a new Hopfield object.
20
+ def self.[](*learning_samples)
21
+ new learning_samples
22
+ end
23
+
24
+ # Learning samples must be not empty and have same dimension.
25
+ def initialize(learning_samples)
26
+ @learning_samples = learning_samples
27
+ learning_samples_must_be_not_empty!
28
+
29
+ @dimension = @learning_samples.first.size
30
+ learning_samples_must_have_same_dimension!
31
+
32
+ calculate_weight_matrix
33
+ end
34
+
35
+ # Returns a Brain::Hopfield::Sample object which can be used for an association of given sample.
36
+ def associate(sample)
37
+ Sample.new self, sample
38
+ end
39
+
40
+ # Learning samples attribute.
41
+ def learning_samples
42
+ @learning_samples
43
+ end
44
+
45
+ # Weights attribute.
46
+ def weights
47
+ @weights
48
+ end
49
+
50
+ # Dimension attribute.
51
+ def dimension
52
+ @dimension
53
+ end
54
+
55
+ protected
56
+
57
+ def learning_samples_must_be_not_empty!
58
+ raise ArgumentError if learning_samples.empty?
59
+ end
60
+
61
+ def learning_samples_must_have_same_dimension!
62
+ raise ArgumentError unless learning_samples.all? {|sample| sample.size == dimension }
63
+ end
64
+
65
+ def calculate_weight_matrix
66
+ @weights = Matrix.zero(dimension)
67
+
68
+ learning_samples.each do |sample|
69
+ vector = Matrix.row_vector sample
70
+ @weights += vector.transpose * vector
71
+ end
72
+
73
+ @weights = Matrix[*@weights.to_a.each_with_index {|row, i| row[i] = 0 }]
74
+ end
75
+ end
@@ -0,0 +1,107 @@
1
+ =begin rdoc
2
+ Defines Brain::Hopfield::Sample class.
3
+ =end
4
+
5
+ =begin rdoc
6
+ Uses a given Hopfield object for a successive accosiation with a given sample.
7
+
8
+ When there is too much noise in the initial sample, it can associate it with an inverse version of a learning sample. Example:
9
+
10
+ net = Brain::Hopfield[[1, 1, 1, 1]]
11
+ sample = net.associate [1, -1, -1, -1]
12
+ sample.run until sample.associated?
13
+ sample.current # => [-1, -1, -1, -1]
14
+
15
+ Initial sample [1, -1, -1, -1] containes too much noise to be comparable with [1, 1, 1, 1]. So sample is associated with the inverse version of [1, 1, 1, 1] which equals [-1, -1, -1, -1].
16
+ =end
17
+ class Brain::Hopfield::Sample
18
+
19
+ # A sample must have same dimension as a Hopfield object.
20
+ def initialize(net, sample)
21
+ @net, @initial, @indexes = net, sample, []
22
+ @current, @iterations, @associated = initial, 0, false
23
+
24
+ sample_must_have_same_dimension_as_net!
25
+ @associated = true if known_sample?
26
+ end
27
+
28
+ # Returns true if the current sample is accosiated.
29
+ def associated?
30
+ @associated
31
+ end
32
+
33
+ # Used to update a state of the current sample in a random order. A number of updated positions is controlled with a given parameter.
34
+ def run(number = 1)
35
+ number.times do
36
+ break if associated?
37
+ update_next_neuron
38
+ @associated = true if minimal_energy? or known_sample?
39
+ end
40
+ current
41
+ end
42
+
43
+ # Measure of closerness to learning samples. The least energy state corresponds to an association with a learning sample.
44
+ def energy
45
+ (Matrix.row_vector(current) * net.weights).row(0).inner_product current
46
+ end
47
+
48
+ # A corresponding Hopfield object.
49
+ def net
50
+ @net
51
+ end
52
+
53
+ # Initial state of sample.
54
+ def initial
55
+ @initial
56
+ end
57
+
58
+ # Current state of sample.
59
+ def current
60
+ @current
61
+ end
62
+
63
+ # Number of itererations.
64
+ def iterations
65
+ @iterations
66
+ end
67
+
68
+ protected
69
+
70
+ def sample_must_have_same_dimension_as_net!
71
+ raise ArgumentError unless current.size == net.dimension
72
+ end
73
+
74
+ def known_sample?
75
+ net.learning_samples.any? {|sample| sample == current }
76
+ end
77
+
78
+ def minimal_energy?
79
+ @energy_changed = true unless @previous_energy == energy
80
+ if @indexes.empty?
81
+ @energy_changed ? (@energy_changed = false) : true
82
+ end
83
+ end
84
+
85
+ def activation_argument(neuron_index)
86
+ net.weights.row(neuron_index).inner_product current
87
+ end
88
+
89
+ def activation_function(neuron_index)
90
+ activation = activation_argument neuron_index
91
+ return 1 if activation > 0
92
+ return -1 if activation < 0
93
+ current[neuron_index]
94
+ end
95
+
96
+ def next_neuron
97
+ @indexes = Array.new(net.dimension) {|i| i } if @indexes.empty?
98
+ @indexes.delete_at rand(@indexes.size)
99
+ end
100
+
101
+ def update_next_neuron
102
+ @previous_energy = energy
103
+ neuron_index = next_neuron
104
+ current[neuron_index] = activation_function neuron_index
105
+ @iterations += 1
106
+ end
107
+ end
@@ -0,0 +1,9 @@
1
+ module Brain
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 0
5
+ TINY = 2
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
@@ -0,0 +1,87 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe Brain::Hopfield::Sample do
4
+ it "should be initialized with a Hopfield net and a sample" do
5
+ lambda { Hopfield::Sample.new Hopfield[ [1, 1, 1] ], [-1, 1, -1] }.
6
+ should_not raise_error(ArgumentError)
7
+ end
8
+
9
+ it "should raise error if the sample has a different arity then the net" do
10
+ lambda { Hopfield::Sample.new Hopfield[ [1, 1, 1] ], [-1, 1, -1, 1] }.
11
+ should raise_error(ArgumentError)
12
+ end
13
+
14
+ it "should check if the sample belongs to learning samples" do
15
+ sample = Hopfield::Sample.new(Hopfield[ [1, 1, 1] ], [1, 1, 1])
16
+ sample.associated?.should == true
17
+ end
18
+
19
+ describe '(after initialization)' do
20
+ before(:each) do
21
+ @learned_sample = [1, -1, 1, -1, 1, -1, 1, -1, 1, -1]
22
+ @tested_sample = [-1, -1, -1, -1, -1, -1, 1, 1, 1, -1]
23
+
24
+ @net = Hopfield[ @learned_sample ]
25
+ @sample = Hopfield::Sample.new @net, @tested_sample
26
+ end
27
+
28
+ it "should start an iterations count with 0" do
29
+ @sample.iterations.should == 0
30
+ end
31
+
32
+ it "should return a status of training" do
33
+ @sample.associated?.should == false
34
+ end
35
+
36
+ it "should return a current associated sample" do
37
+ @sample.current.should == @tested_sample
38
+ end
39
+
40
+ it "should return an initial sample" do
41
+ @sample.initial.should == @tested_sample
42
+ end
43
+
44
+ it "should be ran a given number of times" do
45
+ @sample.run(50).should == @learned_sample
46
+ end
47
+
48
+ it "should increment iterations after an every run" do
49
+ @sample.stub!(:associated?).and_return(false)
50
+ 3.times { @sample.run(3) }
51
+ @sample.iterations.should == 9
52
+ end
53
+
54
+ it "should stop incrementing iterations after it's associated" do
55
+ @sample.stub!(:associated?).and_return(false)
56
+ @sample.run(4)
57
+ @sample.stub!(:associated?).and_return(true)
58
+ @sample.run(4)
59
+ @sample.iterations.should == 4
60
+ end
61
+
62
+ it "should be ran by default one time" do
63
+ @sample.run
64
+ @sample.iterations.should == 1
65
+ end
66
+
67
+ it "should return an using net" do
68
+ @sample.net.should == @net
69
+ end
70
+
71
+ it "shouldn't increase energy" do
72
+ previous_energy = @sample.energy
73
+ until @sample.associated?
74
+ @sample.run
75
+ previous_energy.should_not > @sample.energy
76
+ previous_energy = @sample.energy
77
+ end
78
+ end
79
+
80
+ it "should return an inverse version of the learning sample if there is too much noise in the initial sample" do
81
+ net = Brain::Hopfield[[1, 1, 1, 1]]
82
+ sample = net.associate [1, -1, -1, -1]
83
+ sample.run until sample.associated?
84
+ sample.current.should == [-1, -1, -1, -1]
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,43 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Brain::Hopfield do
4
+ it "should be created with learning samples" do
5
+ lambda { Hopfield.new }.should raise_error(ArgumentError)
6
+ lambda { Hopfield.new [] }.should raise_error(ArgumentError)
7
+ lambda { Hopfield.new [[1, 1], [1, 1]] }.should_not raise_error
8
+ end
9
+
10
+ it "learning samples should have a same arity" do
11
+ lambda { Hopfield.new [[-1, -1], [1]] }.should raise_error(ArgumentError)
12
+ lambda { Hopfield.new [[-1, -1], [1, 1]] }.should_not raise_error
13
+ end
14
+
15
+ it "should have a shortcut [] for creation" do
16
+ Hopfield[[1, 1], [1, 1]].should be_instance_of(Hopfield)
17
+ end
18
+
19
+ describe '(after initialization)' do
20
+ before(:each) do
21
+ @net = Hopfield[ [-1, 1, -1], [1, -1, 1] ]
22
+ end
23
+
24
+ it "should return a weight matrix" do
25
+ @net.weights.should == Matrix[ [ 0, -2, 2],
26
+ [-2, 0, -2],
27
+ [ 2, -2, 0] ]
28
+ end
29
+
30
+ it "should return an array of learning samples" do
31
+ @net.learning_samples.should == [ [-1, 1, -1], [1, -1, 1] ]
32
+ end
33
+
34
+ it "should return an arity" do
35
+ @net.dimension.should == 3
36
+ end
37
+
38
+ it "should create an object for an association with a given sample" do
39
+ associated_sample = @net.associate([1, 1, 1])
40
+ associated_sample.should be_instance_of(Hopfield::Sample)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1 @@
1
+ --colour
@@ -0,0 +1,11 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ gem 'rspec'
6
+ require 'spec'
7
+ end
8
+
9
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
10
+ require 'brain'
11
+ include Brain
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: brain
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Ravil Bayramgalin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-07-12 00:00:00 +04:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hoe
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.7.0
24
+ version:
25
+ description: Implementation of fundamental types of neural networks which includes multilayer perceptron, Kohonen net and Hopfield net.
26
+ email:
27
+ - ravwar@gmail.com
28
+ executables: []
29
+
30
+ extensions: []
31
+
32
+ extra_rdoc_files:
33
+ - History.txt
34
+ - README.txt
35
+ files:
36
+ - History.txt
37
+ - README.txt
38
+ - lib/brain.rb
39
+ - lib/brain/hopfield.rb
40
+ - lib/brain/hopfield/sample.rb
41
+ - lib/brain/version.rb
42
+ - spec/brain/hopfield/sample_spec.rb
43
+ - spec/brain/hopfield_spec.rb
44
+ - spec/spec.opts
45
+ - spec/spec_helper.rb
46
+ has_rdoc: true
47
+ homepage: http://brain.rubyforge.org
48
+ post_install_message: |-
49
+
50
+ For more information on brain, see http://brain.rubyforge.org
51
+ rdoc_options:
52
+ - --main
53
+ - README.txt
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
67
+ version:
68
+ requirements: []
69
+
70
+ rubyforge_project: brain
71
+ rubygems_version: 1.2.0
72
+ signing_key:
73
+ specification_version: 2
74
+ summary: Implementation of fundamental types of neural networks which includes multilayer perceptron, Kohonen net and Hopfield net.
75
+ test_files:
76
+ - spec/brain/hopfield/sample_spec.rb
77
+ - spec/brain/hopfield_spec.rb