ai4r 1.3 → 1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. data/README.rdoc +6 -12
  2. data/examples/neural_network/backpropagation_example.rb +18 -16
  3. data/examples/neural_network/xor_example.rb +30 -20
  4. data/lib/ai4r/classifiers/classifier.rb +15 -4
  5. data/lib/ai4r/classifiers/id3.rb +31 -31
  6. data/lib/ai4r/clusterers/clusterer.rb +5 -24
  7. data/lib/ai4r/clusterers/k_means.rb +7 -38
  8. data/lib/ai4r/data/data_set.rb +4 -2
  9. data/lib/ai4r/data/parameterizable.rb +64 -0
  10. data/lib/ai4r/neural_network/backpropagation.rb +233 -210
  11. data/site/build/site/en/downloads.html +3 -3
  12. data/site/build/site/en/geneticAlgorithms.html +3 -3
  13. data/site/build/site/en/index.html +32 -15
  14. data/site/build/site/en/index.pdf +126 -100
  15. data/site/build/site/en/linkmap.html +7 -9
  16. data/site/build/site/en/linkmap.pdf +12 -12
  17. data/site/build/site/en/machineLearning.html +7 -6
  18. data/site/build/site/en/machineLearning.pdf +29 -29
  19. data/site/build/site/en/neuralNetworks.html +164 -127
  20. data/site/build/site/en/neuralNetworks.pdf +267 -200
  21. data/site/build/site/en/svn.html +4 -4
  22. data/site/build/tmp/cocoon-work/cache-dir/cocoon-ehcache-1.data +0 -0
  23. data/site/build/tmp/cocoon-work/cache-dir/cocoon-ehcache-1.index +0 -0
  24. data/site/build/tmp/projfilters.properties +1 -1
  25. data/site/build/webapp/WEB-INF/logs/core.log +670 -489
  26. data/site/build/webapp/WEB-INF/logs/error.log +213 -364
  27. data/site/build/webapp/WEB-INF/logs/sitemap.log +0 -368
  28. data/site/src/documentation/content/xdocs/index.xml +1 -1
  29. data/site/src/documentation/content/xdocs/neuralNetworks.xml +118 -90
  30. data/site/src/documentation/content/xdocs/site.xml +2 -3
  31. data/test/neural_network/backpropagation_test.rb +23 -0
  32. metadata +5 -7
  33. data/site/build/site/en/forum.html +0 -197
  34. data/site/build/site/en/forum.pdf +0 -151
  35. data/site/build/site/en/wholesite.pdf +0 -1915
@@ -16,18 +16,12 @@ http://ai4r.rubyforge.org
16
16
  2. Include require statements in your code:
17
17
 
18
18
  require "rubygems"
19
- require "ai4r/classifiers/id3"en
20
- require "ai4r/classifiers/prism"
21
- require "ai4r/classifiers/one_r"
22
- require "ai4r/classifiers/zero_r"
23
- require "ai4r/neural_network/backpropagation"
24
- require "ai4r/genetic_algorithm/genetic_algorithm"
25
-
26
- = Feedback
27
-
28
- If you have questions or constructive comments about this project,
29
- please post them in the forum. If you do not want to make it public,
30
- send it to me: Sergio Fierens (sergio(dot)fierens(at)gmail(dot)com)
19
+ require "ai4r"
20
+
21
+ = More Info
22
+
23
+ * AI4R wiki: http://wiki.jadeferret.com/Category:AI4R
24
+ * AI4R Project site: http://ai4r.rubyforge.org
31
25
 
32
26
  = Warranty
33
27
 
@@ -15,25 +15,28 @@ require 'benchmark'
15
15
 
16
16
  times = Benchmark.measure do
17
17
 
18
+ srand 1
19
+
18
20
  net = Ai4r::NeuralNetwork::Backpropagation.new([256, 3])
21
+
22
+ tr_input = TRIANGLE.flatten.collect { |input| input.to_f / 5.0}
23
+ sq_input = SQUARE.flatten.collect { |input| input.to_f / 5.0}
24
+ cr_input = CROSS.flatten.collect { |input| input.to_f / 5.0}
19
25
 
20
- tr_input = TRIANGLE.flatten.collect { |input| input.to_f / 10}
21
- sq_input = SQUARE.flatten.collect { |input| input.to_f / 10}
22
- cr_input = CROSS.flatten.collect { |input| input.to_f / 10}
23
-
24
- tr_with_noise = TRIANGLE_WITH_NOISE.flatten.collect { |input| input.to_f / 10}
25
- sq_with_noise = SQUARE_WITH_NOISE.flatten.collect { |input| input.to_f / 10}
26
- cr_with_noise = CROSS_WITH_NOISE.flatten.collect { |input| input.to_f / 10}
26
+ tr_with_noise = TRIANGLE_WITH_NOISE.flatten.collect { |input| input.to_f / 5.0}
27
+ sq_with_noise = SQUARE_WITH_NOISE.flatten.collect { |input| input.to_f / 5.0}
28
+ cr_with_noise = CROSS_WITH_NOISE.flatten.collect { |input| input.to_f / 5.0}
27
29
 
28
- tr_with_base_noise = TRIANGLE_WITH_BASE_NOISE.flatten.collect { |input| input.to_f / 10}
29
- sq_with_base_noise = SQUARE_WITH_BASE_NOISE.flatten.collect { |input| input.to_f / 10}
30
- cr_with_base_noise = CROSS_WITH_BASE_NOISE.flatten.collect { |input| input.to_f / 10}
30
+ tr_with_base_noise = TRIANGLE_WITH_BASE_NOISE.flatten.collect { |input| input.to_f / 5.0}
31
+ sq_with_base_noise = SQUARE_WITH_BASE_NOISE.flatten.collect { |input| input.to_f / 5.0}
32
+ cr_with_base_noise = CROSS_WITH_BASE_NOISE.flatten.collect { |input| input.to_f / 5.0}
31
33
 
32
34
  puts "Training the network, please wait."
33
- 200.times do
34
- net.train(tr_input, [1,0,0])
35
- net.train(sq_input, [0,1,0])
36
- net.train(cr_input, [0,0,1])
35
+ 101.times do |i|
36
+ error = net.train(tr_input, [1,0,0])
37
+ error = net.train(sq_input, [0,1,0])
38
+ error = net.train(cr_input, [0,0,1])
39
+ puts "Error after iteration #{i}:\t#{error}" if i%20 == 0
37
40
  end
38
41
 
39
42
  def result_label(result)
@@ -58,8 +61,7 @@ times = Benchmark.measure do
58
61
  puts "#{net.eval(tr_with_base_noise).inspect} => #{result_label(net.eval(tr_with_base_noise))}"
59
62
  puts "#{net.eval(sq_with_base_noise).inspect} => #{result_label(net.eval(sq_with_base_noise))}"
60
63
  puts "#{net.eval(cr_with_base_noise).inspect} => #{result_label(net.eval(cr_with_base_noise))}"
61
-
62
64
 
63
65
  end
64
66
 
65
- puts "Elapsed time: #{times}"
67
+ puts "Elapsed time: #{times}"
@@ -1,25 +1,35 @@
1
- require File.dirname(__FILE__) + '/training_patterns'
2
- require File.dirname(__FILE__) + '/patterns_with_noise'
3
- require File.dirname(__FILE__) + '/patterns_with_base_noise'
4
- require File.dirname(__FILE__) + '/../../lib/ai4r/neural_network/backpropagation'
1
+ # Author:: Sergio Fierens
2
+ # License:: MPL 1.1
3
+ # Project:: ai4r
4
+ # Url:: http://ai4r.rubyforge.org/
5
+ #
6
+ # You can redistribute it and/or modify it under the terms of
7
+ # the Mozilla Public License version 1.1 as published by the
8
+ # Mozilla Foundation at http://www.mozilla.org/MPL/MPL-1.1.txt
5
9
 
6
- examples = [
7
- [[0, 0], [0, 1]],
8
- [[0, 1], [1, 0]],
9
- [[1, 0], [1, 0]],
10
- [[1, 1], [0, 0]]
11
- ]
10
+ require File.dirname(__FILE__) + '/../../lib/ai4r/neural_network/backpropagation'
11
+ require 'benchmark'
12
12
 
13
- net = Ai4r::NeuralNetwork::Backpropagation.new([2, 1, 2, 1])
13
+ times = Benchmark.measure do
14
14
 
15
- i=0
16
- 200.times {
17
- examples.each do |ex|
18
- 2000.times {net.train(ex[0], [ex[1].first])}
15
+ srand 1
16
+
17
+ net = Ai4r::NeuralNetwork::Backpropagation.new([2, 2, 1])
18
+
19
+ puts "Training the network, please wait."
20
+ 2001.times do |i|
21
+ net.train([0,0], [0])
22
+ net.train([0,1], [1])
23
+ net.train([1,0], [1])
24
+ error = net.train([1,1], [0])
25
+ puts "Error after iteration #{i}:\t#{error}" if i%200 == 0
19
26
  end
20
- puts(i=i+1)
21
- }
27
+
28
+ puts "Test data"
29
+ puts "[0,0] = > #{net.eval([0,0]).inspect}"
30
+ puts "[0,1] = > #{net.eval([0,1]).inspect}"
31
+ puts "[1,0] = > #{net.eval([1,0]).inspect}"
32
+ puts "[1,1] = > #{net.eval([1,1]).inspect}"
33
+ end
22
34
 
23
- examples.each do |ex|
24
- print ex[0], ' => ', net.eval(ex[0]).inspect, ', should be ', ex[1].first, "\n"
25
- end
35
+ puts "Elapsed time: #{times}"
@@ -1,19 +1,23 @@
1
1
  # Author:: Sergio Fierens
2
2
  # License:: MPL 1.1
3
3
  # Project:: ai4r
4
- # Url:: http://ai4r.rubyforge.org/
4
+ # Url:: http://ai4r.rubyforge.org
5
5
  #
6
6
  # You can redistribute it and/or modify it under the terms of
7
7
  # the Mozilla Public License version 1.1 as published by the
8
8
  # Mozilla Foundation at http://www.mozilla.org/MPL/MPL-1.1.txt
9
9
 
10
+ require File.dirname(__FILE__) + '/../data/parameterizable'
11
+
10
12
  module Ai4r
11
13
  module Classifiers
12
-
13
- # The only purpose of this class is to define a common API for classifiers.
14
+
15
+ # This class defines a common API for classifiers.
14
16
  # All methods in this class must be implemented in subclasses.
15
17
  class Classifier
16
18
 
19
+ include Ai4r::Data::Parameterizable
20
+
17
21
  # Build a new classifier, using data examples found in data_set.
18
22
  def build(data_set)
19
23
  raise NotImplementedError
@@ -30,9 +34,16 @@ module Ai4r
30
34
  # e.g.
31
35
  #
32
36
  # classifier.get_rules
33
- # # => marketing_target='Y'
37
+ # # => if age_range=='<30' then marketing_target='Y'
38
+ # elsif age_range=='[30-50)' and city=='Chicago' then marketing_target='Y'
39
+ # elsif age_range=='[30-50)' and city=='New York' then marketing_target='N'
40
+ # elsif age_range=='[50-80]' then marketing_target='N'
41
+ # elsif age_range=='>80' then marketing_target='Y'
42
+ # else raise 'There was not enough information during training to do a proper induction for this data element' end
34
43
  #
35
44
  # It is a nice way to inspect induction results, and also to execute them:
45
+ # age_range = '<30'
46
+ # city='New York'
36
47
  # marketing_target = nil
37
48
  # eval classifier.get_rules
38
49
  # puts marketing_target
@@ -28,24 +28,26 @@ module Ai4r
28
28
  #
29
29
  # DATA_LABELS = [ 'city', 'age_range', 'gender', 'marketing_target' ]
30
30
  #
31
- # DATA_SET = [ ['New York', '<30', 'M', 'Y'],
32
- # ['Chicago', '<30', 'M', 'Y'],
33
- # ['Chicago', '<30', 'F', 'Y'],
34
- # ['New York', '<30', 'M', 'Y'],
35
- # ['New York', '<30', 'M', 'Y'],
36
- # ['Chicago', '[30-50)', 'M', 'Y'],
37
- # ['New York', '[30-50)', 'F', 'N'],
38
- # ['Chicago', '[30-50)', 'F', 'Y'],
39
- # ['New York', '[30-50)', 'F', 'N'],
40
- # ['Chicago', '[50-80]', 'M', 'N'],
41
- # ['New York', '[50-80]', 'F', 'N'],
42
- # ['New York', '[50-80]', 'M', 'N'],
43
- # ['Chicago', '[50-80]', 'M', 'N'],
44
- # ['New York', '[50-80]', 'F', 'N'],
45
- # ['Chicago', '>80', 'F', 'Y']
46
- # ]
31
+ # DATA_ITEMS = [
32
+ # ['New York', '<30', 'M', 'Y'],
33
+ # ['Chicago', '<30', 'M', 'Y'],
34
+ # ['Chicago', '<30', 'F', 'Y'],
35
+ # ['New York', '<30', 'M', 'Y'],
36
+ # ['New York', '<30', 'M', 'Y'],
37
+ # ['Chicago', '[30-50)', 'M', 'Y'],
38
+ # ['New York', '[30-50)', 'F', 'N'],
39
+ # ['Chicago', '[30-50)', 'F', 'Y'],
40
+ # ['New York', '[30-50)', 'F', 'N'],
41
+ # ['Chicago', '[50-80]', 'M', 'N'],
42
+ # ['New York', '[50-80]', 'F', 'N'],
43
+ # ['New York', '[50-80]', 'M', 'N'],
44
+ # ['Chicago', '[50-80]', 'M', 'N'],
45
+ # ['New York', '[50-80]', 'F', 'N'],
46
+ # ['Chicago', '>80', 'F', 'Y']
47
+ # ]
47
48
  #
48
- # id3 = Ai4r::Classifiers::ID3.new(DATA_SET, DATA_LABELS)
49
+ # data_set = DataSet.new(:data_items=>DATA_SET, :data_labels=>DATA_LABELS)
50
+ # id3 = Ai4r::Classifiers::ID3.new.build(data_set)
49
51
  #
50
52
  # id3.get_rules
51
53
  # # => if age_range=='<30' then marketing_target='Y'
@@ -64,22 +66,20 @@ module Ai4r
64
66
  # attributes. Consider moving your data to an external CSV (comma separate
65
67
  # values) file.
66
68
  #
67
- # data_set = []
68
- # CSV::Reader.parse(File.open("#{File.dirname(__FILE__)}/data_set.csv", 'r')) do |row|
69
- # data_set << row
70
- # end
71
- # data_labels = data_set.shift
72
- #
73
- # id3 = Ai4r::Classifiers::ID3.new(data_set, data_labels)
69
+ # data_file = "#{File.dirname(__FILE__)}/data_set.csv"
70
+ # data_set = DataSet.load_data_and_labels_from_csv data_file
71
+ # id3 = Ai4r::Classifiers::ID3.new.build(data_set)
74
72
  #
75
73
  # = A nice tip for data evaluation
76
74
  #
77
- # id3 = Ai4r::Classifiers::ID3.new(DATA_SET, DATA_LABELS)
78
- # age_range = '<30'
79
- # marketing_target = nil
80
- # eval id3.get_rules
81
- # puts marketing_target
82
- # # => 'Y'
75
+ # id3 = Ai4r::Classifiers::ID3.new.build(data_set)
76
+ #
77
+ # age_range = '<30'
78
+ # marketing_target = nil
79
+ # eval id3.get_rules
80
+ # puts marketing_target
81
+ # # => 'Y'
82
+ #
83
83
  # = More about ID3 and decision trees
84
84
  #
85
85
  # * http://en.wikipedia.org/wiki/Decision_tree
@@ -92,7 +92,7 @@ module Ai4r
92
92
  class ID3 < Classifier
93
93
 
94
94
  attr_reader :data_set
95
-
95
+
96
96
  # Create a new ID3 classifier. You must provide a DataSet instance
97
97
  # as parameter.
98
98
  def build(data_set)
@@ -7,6 +7,8 @@
7
7
  # the Mozilla Public License version 1.1 as published by the
8
8
  # Mozilla Foundation at http://www.mozilla.org/MPL/MPL-1.1.txt
9
9
 
10
+ require File.dirname(__FILE__) + '/../data/parameterizable'
11
+
10
12
  module Ai4r
11
13
  module Clusterers
12
14
 
@@ -14,7 +16,9 @@ module Ai4r
14
16
  # All methods in this class (other than eval) must be implemented in
15
17
  # subclasses.
16
18
  class Clusterer
17
-
19
+
20
+ include Ai4r::Data::Parameterizable
21
+
18
22
  # Build a new clusterer, using data examples found in data_set.
19
23
  # Data items will be clustered in "number_of_clusters" different
20
24
  # clusters.
@@ -27,29 +31,6 @@ module Ai4r
27
31
  raise NotImplementedError
28
32
  end
29
33
 
30
- # Get info on what can be parameterized on this clusterer.
31
- # It returns a hash with the following format:
32
- # { :param_name => "Info on the parameter" }
33
- def get_parameters_info
34
- raise NotImplementedError
35
- end
36
-
37
- # Set parameter values on this clusterer instance.
38
- # You must provide a hash with the folowing format:
39
- # { :param_name => parameter_value }
40
- def set_parameters(parameters)
41
- raise NotImplementedError
42
- end
43
-
44
- # Get parameter values on this clusterer instance.
45
- # Returns a hash with the folowing format:
46
- # { :param_name => parameter_value }
47
- def get_parameters
48
- raise NotImplementedError
49
- end
50
-
51
-
52
34
  end
53
-
54
35
  end
55
36
  end
@@ -23,8 +23,13 @@ module Ai4r
23
23
 
24
24
  attr_reader :data_set, :number_of_clusters
25
25
  attr_reader :clusters, :centroids, :iterations
26
- attr_accessor :max_iterations
27
- attr_accessor :distance_function
26
+
27
+ parameters_info :max_iterations => "Maximum number of iterations to " +
28
+ "build the clusterer. By default it is uncapped.",
29
+ :distance_function => "Custom implementation of distance function. " +
30
+ "It must be a closure receiving two data items and return the " +
31
+ "distance bewteen them. By default, this algorithm uses " +
32
+ "ecuclidean distance of numeric attributes to the power of 2."
28
33
 
29
34
  # Build a new clusterer, using data examples found in data_set.
30
35
  # Items will be clustered in "number_of_clusters" different
@@ -50,42 +55,6 @@ module Ai4r
50
55
  distance(data_item, centroid)})
51
56
  end
52
57
 
53
- # Get info on what can be parameterized on this clusterer algorithm.
54
- # It returns a hash with the following format:
55
- # { :param_name => "Info on the parameter" }
56
- def get_parameters_info
57
- { :max_iterations => "Maximum number of iterations to build the " +
58
- "clusterer. By default it is uncapped.",
59
- :distance_function => "Custom implementation of distance function. " +
60
- "It must be a closure receiving two data items and return the " +
61
- "distance bewteen them. By default, this algorithm uses " +
62
- "ecuclidean distance of numeric attributes to the power of 2."
63
- }
64
- end
65
-
66
- # Set parameters on this clusterer instance.
67
- # You must provide a hash with the folowing format:
68
- # { :param_name => parameter_value }
69
- #
70
- # Use get_parameters_info to know what parameters are accepted.
71
- def set_parameters(parameters)
72
- if parameters.has_key?(:max_iterations)
73
- @max_iterations = parameters[:max_iterations]
74
- end
75
- if parameters.has_key?(:distance_function)
76
- @distance_function = parameters[:distance_function]
77
- end
78
- return self
79
- end
80
-
81
- # Get parameter values on this clusterer instance.
82
- # Returns a hash with the folowing format:
83
- # { :param_name => parameter_value }
84
- def get_parameters
85
- { :max_iterations => @max_iterations,
86
- :distance_function => @distance_function }
87
- end
88
-
89
58
  # This function calculates the distance between 2 different
90
59
  # instances. By default, it returns the euclidean distance to the
91
60
  # power of 2.
@@ -30,9 +30,11 @@ module Ai4r
30
30
  set_data_items(options[:data_items]) if options[:data_items]
31
31
  end
32
32
 
33
- # Retrieve data item(s) by index. You can specify a an index range, too.
33
+ # Retrieve a new DataSet, with the item(s) selected by the provided
34
+ # index. You can specify an index range, too.
34
35
  def [](index)
35
- return @data_items[index]
36
+ return DataSet.new(:data_items=>@data_items[index],
37
+ :data_labels =>@data_labels)
36
38
  end
37
39
 
38
40
  # Load data items from csv file
@@ -0,0 +1,64 @@
1
+ # Author:: Sergio Fierens
2
+ # License:: MPL 1.1
3
+ # Project:: ai4r
4
+ # Url:: http://ai4r.rubyforge.org/
5
+ #
6
+ # You can redistribute it and/or modify it under the terms of
7
+ # the Mozilla Public License version 1.1 as published by the
8
+ # Mozilla Foundation at http://www.mozilla.org/MPL/MPL-1.1.txt
9
+
10
+ module Ai4r
11
+ module Data
12
+ module Parameterizable
13
+
14
+ module ClassMethods
15
+
16
+ # Get info on what can be parameterized on this algorithm.
17
+ # It returns a hash with the following format:
18
+ # { :param_name => "Info on the parameter" }
19
+ def get_parameters_info
20
+ return @_params_info_ || {}
21
+ end
22
+
23
+ # Set info on what can be parameterized on this algorithm.
24
+ # You must provide a hash with the following format:
25
+ # { :param_name => "Info on the parameter" }
26
+ def parameters_info(params_info)
27
+ @_params_info_ = params_info
28
+ params_info.keys.each do |param|
29
+ attr_accessor param
30
+ end
31
+ end
32
+ end
33
+
34
+ # Set parameter values on this algorithm instance.
35
+ # You must provide a hash with the folowing format:
36
+ # { :param_name => parameter_value }
37
+ def set_parameters(params)
38
+ self.class.get_parameters_info.keys.each do | key |
39
+ if self.respond_to?("#{key}=".to_sym)
40
+ send("#{key}=".to_sym, params[key]) if params.has_key? key
41
+ end
42
+ end
43
+ return self
44
+ end
45
+
46
+ # Get parameter values on this algorithm instance.
47
+ # Returns a hash with the folowing format:
48
+ # { :param_name => parameter_value }
49
+ def get_parameters
50
+ params = {}
51
+ self.class.get_parameters_info.keys.each do | key |
52
+ params[key] = send(key) if self.respond_to?(key)
53
+ end
54
+ return params
55
+ end
56
+
57
+ def self.included(base)
58
+ base.extend(ClassMethods)
59
+ end
60
+
61
+ end
62
+ end
63
+ end
64
+