ai4r 1.3 → 1.4
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.
- data/README.rdoc +6 -12
- data/examples/neural_network/backpropagation_example.rb +18 -16
- data/examples/neural_network/xor_example.rb +30 -20
- data/lib/ai4r/classifiers/classifier.rb +15 -4
- data/lib/ai4r/classifiers/id3.rb +31 -31
- data/lib/ai4r/clusterers/clusterer.rb +5 -24
- data/lib/ai4r/clusterers/k_means.rb +7 -38
- data/lib/ai4r/data/data_set.rb +4 -2
- data/lib/ai4r/data/parameterizable.rb +64 -0
- data/lib/ai4r/neural_network/backpropagation.rb +233 -210
- data/site/build/site/en/downloads.html +3 -3
- data/site/build/site/en/geneticAlgorithms.html +3 -3
- data/site/build/site/en/index.html +32 -15
- data/site/build/site/en/index.pdf +126 -100
- data/site/build/site/en/linkmap.html +7 -9
- data/site/build/site/en/linkmap.pdf +12 -12
- data/site/build/site/en/machineLearning.html +7 -6
- data/site/build/site/en/machineLearning.pdf +29 -29
- data/site/build/site/en/neuralNetworks.html +164 -127
- data/site/build/site/en/neuralNetworks.pdf +267 -200
- data/site/build/site/en/svn.html +4 -4
- data/site/build/tmp/cocoon-work/cache-dir/cocoon-ehcache-1.data +0 -0
- data/site/build/tmp/cocoon-work/cache-dir/cocoon-ehcache-1.index +0 -0
- data/site/build/tmp/projfilters.properties +1 -1
- data/site/build/webapp/WEB-INF/logs/core.log +670 -489
- data/site/build/webapp/WEB-INF/logs/error.log +213 -364
- data/site/build/webapp/WEB-INF/logs/sitemap.log +0 -368
- data/site/src/documentation/content/xdocs/index.xml +1 -1
- data/site/src/documentation/content/xdocs/neuralNetworks.xml +118 -90
- data/site/src/documentation/content/xdocs/site.xml +2 -3
- data/test/neural_network/backpropagation_test.rb +23 -0
- metadata +5 -7
- data/site/build/site/en/forum.html +0 -197
- data/site/build/site/en/forum.pdf +0 -151
- data/site/build/site/en/wholesite.pdf +0 -1915
data/README.rdoc
CHANGED
@@ -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
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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
|
-
|
21
|
-
|
22
|
-
|
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 /
|
29
|
-
sq_with_base_noise = SQUARE_WITH_BASE_NOISE.flatten.collect { |input| input.to_f /
|
30
|
-
cr_with_base_noise = CROSS_WITH_BASE_NOISE.flatten.collect { |input| input.to_f /
|
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
|
-
|
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
|
-
|
67
|
+
puts "Elapsed time: #{times}"
|
@@ -1,25 +1,35 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
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
|
-
|
7
|
-
|
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
|
-
|
13
|
+
times = Benchmark.measure do
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
-
|
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
|
-
|
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
|
-
#
|
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
|
data/lib/ai4r/classifiers/id3.rb
CHANGED
@@ -28,24 +28,26 @@ module Ai4r
|
|
28
28
|
#
|
29
29
|
# DATA_LABELS = [ 'city', 'age_range', 'gender', 'marketing_target' ]
|
30
30
|
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
42
|
-
#
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
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
|
-
#
|
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
|
-
#
|
68
|
-
#
|
69
|
-
#
|
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(
|
78
|
-
#
|
79
|
-
#
|
80
|
-
#
|
81
|
-
#
|
82
|
-
#
|
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
|
-
|
27
|
-
|
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.
|
data/lib/ai4r/data/data_set.rb
CHANGED
@@ -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
|
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
|
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
|
+
|