nirvdrum-ai4r 1.9.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.
Files changed (150) hide show
  1. data/.gitignore +1 -0
  2. data/.rakeTasks +7 -0
  3. data/README.rdoc +56 -0
  4. data/Rakefile.rb +42 -0
  5. data/VERSION +1 -0
  6. data/ai4r.gemspec +221 -0
  7. data/change_log +49 -0
  8. data/examples/classifiers/id3_data.csv +121 -0
  9. data/examples/classifiers/id3_example.rb +29 -0
  10. data/examples/classifiers/naive_bayes_data.csv +11 -0
  11. data/examples/classifiers/naive_bayes_example.rb +16 -0
  12. data/examples/classifiers/results.txt +31 -0
  13. data/examples/genetic_algorithm/genetic_algorithm_example.rb +37 -0
  14. data/examples/genetic_algorithm/travel_cost.csv +16 -0
  15. data/examples/neural_network/backpropagation_example.rb +67 -0
  16. data/examples/neural_network/patterns_with_base_noise.rb +68 -0
  17. data/examples/neural_network/patterns_with_noise.rb +66 -0
  18. data/examples/neural_network/training_patterns.rb +68 -0
  19. data/examples/neural_network/xor_example.rb +35 -0
  20. data/examples/som/som_data.rb +156 -0
  21. data/examples/som/som_multi_node_example.rb +22 -0
  22. data/examples/som/som_single_example.rb +24 -0
  23. data/lib/ai4r.rb +32 -0
  24. data/lib/ai4r/classifiers/classifier.rb +59 -0
  25. data/lib/ai4r/classifiers/hyperpipes.rb +118 -0
  26. data/lib/ai4r/classifiers/id3.rb +326 -0
  27. data/lib/ai4r/classifiers/multilayer_perceptron.rb +135 -0
  28. data/lib/ai4r/classifiers/naive_bayes.rb +259 -0
  29. data/lib/ai4r/classifiers/one_r.rb +110 -0
  30. data/lib/ai4r/classifiers/prism.rb +197 -0
  31. data/lib/ai4r/classifiers/zero_r.rb +73 -0
  32. data/lib/ai4r/clusterers/average_linkage.rb +59 -0
  33. data/lib/ai4r/clusterers/bisecting_k_means.rb +93 -0
  34. data/lib/ai4r/clusterers/centroid_linkage.rb +66 -0
  35. data/lib/ai4r/clusterers/clusterer.rb +61 -0
  36. data/lib/ai4r/clusterers/complete_linkage.rb +67 -0
  37. data/lib/ai4r/clusterers/diana.rb +139 -0
  38. data/lib/ai4r/clusterers/k_means.rb +126 -0
  39. data/lib/ai4r/clusterers/median_linkage.rb +61 -0
  40. data/lib/ai4r/clusterers/single_linkage.rb +194 -0
  41. data/lib/ai4r/clusterers/ward_linkage.rb +64 -0
  42. data/lib/ai4r/clusterers/weighted_average_linkage.rb +61 -0
  43. data/lib/ai4r/data/data_set.rb +266 -0
  44. data/lib/ai4r/data/parameterizable.rb +64 -0
  45. data/lib/ai4r/data/proximity.rb +100 -0
  46. data/lib/ai4r/data/statistics.rb +77 -0
  47. data/lib/ai4r/experiment/classifier_evaluator.rb +95 -0
  48. data/lib/ai4r/genetic_algorithm/genetic_algorithm.rb +270 -0
  49. data/lib/ai4r/neural_network/backpropagation.rb +293 -0
  50. data/lib/ai4r/neural_network/hopfield.rb +149 -0
  51. data/lib/ai4r/som/layer.rb +68 -0
  52. data/lib/ai4r/som/node.rb +96 -0
  53. data/lib/ai4r/som/som.rb +155 -0
  54. data/lib/ai4r/som/two_phase_layer.rb +90 -0
  55. data/site/forrest.properties +152 -0
  56. data/site/forrest.properties.dispatcher.properties +25 -0
  57. data/site/forrest.properties.xml +29 -0
  58. data/site/src/documentation/README.txt +7 -0
  59. data/site/src/documentation/classes/CatalogManager.properties +62 -0
  60. data/site/src/documentation/content/locationmap.xml +72 -0
  61. data/site/src/documentation/content/xdocs/downloads.html +9 -0
  62. data/site/src/documentation/content/xdocs/geneticAlgorithms.xml +294 -0
  63. data/site/src/documentation/content/xdocs/index.xml +155 -0
  64. data/site/src/documentation/content/xdocs/machineLearning.xml +131 -0
  65. data/site/src/documentation/content/xdocs/neuralNetworks.xml +270 -0
  66. data/site/src/documentation/content/xdocs/site.xml +54 -0
  67. data/site/src/documentation/content/xdocs/sourceCode.xml +43 -0
  68. data/site/src/documentation/content/xdocs/tabs.xml +35 -0
  69. data/site/src/documentation/resources/images/ai4r-logo.png +0 -0
  70. data/site/src/documentation/resources/images/c.png +0 -0
  71. data/site/src/documentation/resources/images/c_wbn.png +0 -0
  72. data/site/src/documentation/resources/images/c_wn.png +0 -0
  73. data/site/src/documentation/resources/images/ellipse-2.svg +30 -0
  74. data/site/src/documentation/resources/images/ero.gif +0 -0
  75. data/site/src/documentation/resources/images/europe2.png +0 -0
  76. data/site/src/documentation/resources/images/europe3.png +0 -0
  77. data/site/src/documentation/resources/images/fitness.png +0 -0
  78. data/site/src/documentation/resources/images/genetic_algorithms_example.png +0 -0
  79. data/site/src/documentation/resources/images/icon-a.png +0 -0
  80. data/site/src/documentation/resources/images/icon-b.png +0 -0
  81. data/site/src/documentation/resources/images/icon.png +0 -0
  82. data/site/src/documentation/resources/images/jadeferret.png +0 -0
  83. data/site/src/documentation/resources/images/my_email.png +0 -0
  84. data/site/src/documentation/resources/images/neural_network_example.png +0 -0
  85. data/site/src/documentation/resources/images/project-logo.png +0 -0
  86. data/site/src/documentation/resources/images/rubyforge.png +0 -0
  87. data/site/src/documentation/resources/images/s.png +0 -0
  88. data/site/src/documentation/resources/images/s_wbn.png +0 -0
  89. data/site/src/documentation/resources/images/s_wn.png +0 -0
  90. data/site/src/documentation/resources/images/sigmoid.png +0 -0
  91. data/site/src/documentation/resources/images/sub-dir/icon-c.png +0 -0
  92. data/site/src/documentation/resources/images/t.png +0 -0
  93. data/site/src/documentation/resources/images/t_wbn.png +0 -0
  94. data/site/src/documentation/resources/images/t_wn.png +0 -0
  95. data/site/src/documentation/resources/schema/catalog.xcat +29 -0
  96. data/site/src/documentation/resources/schema/hello-v10.dtd +51 -0
  97. data/site/src/documentation/resources/schema/symbols-project-v10.ent +26 -0
  98. data/site/src/documentation/resources/stylesheets/hello2document.xsl +33 -0
  99. data/site/src/documentation/sitemap.xmap +66 -0
  100. data/site/src/documentation/skinconf.xml +418 -0
  101. data/site/src/documentation/translations/langcode.xml +29 -0
  102. data/site/src/documentation/translations/languages_de.xml +24 -0
  103. data/site/src/documentation/translations/languages_en.xml +24 -0
  104. data/site/src/documentation/translations/languages_es.xml +22 -0
  105. data/site/src/documentation/translations/languages_fr.xml +24 -0
  106. data/site/src/documentation/translations/languages_nl.xml +24 -0
  107. data/site/src/documentation/translations/menu.xml +33 -0
  108. data/site/src/documentation/translations/menu_af.xml +33 -0
  109. data/site/src/documentation/translations/menu_de.xml +33 -0
  110. data/site/src/documentation/translations/menu_es.xml +33 -0
  111. data/site/src/documentation/translations/menu_fr.xml +33 -0
  112. data/site/src/documentation/translations/menu_it.xml +33 -0
  113. data/site/src/documentation/translations/menu_nl.xml +33 -0
  114. data/site/src/documentation/translations/menu_no.xml +33 -0
  115. data/site/src/documentation/translations/menu_ru.xml +33 -0
  116. data/site/src/documentation/translations/menu_sk.xml +33 -0
  117. data/site/src/documentation/translations/tabs.xml +22 -0
  118. data/site/src/documentation/translations/tabs_de.xml +22 -0
  119. data/site/src/documentation/translations/tabs_es.xml +22 -0
  120. data/site/src/documentation/translations/tabs_fr.xml +22 -0
  121. data/site/src/documentation/translations/tabs_nl.xml +22 -0
  122. data/test/classifiers/hyperpipes_test.rb +84 -0
  123. data/test/classifiers/id3_test.rb +208 -0
  124. data/test/classifiers/multilayer_perceptron_test.rb +79 -0
  125. data/test/classifiers/naive_bayes_test.rb +43 -0
  126. data/test/classifiers/one_r_test.rb +62 -0
  127. data/test/classifiers/prism_test.rb +85 -0
  128. data/test/classifiers/zero_r_test.rb +50 -0
  129. data/test/clusterers/average_linkage_test.rb +51 -0
  130. data/test/clusterers/bisecting_k_means_test.rb +66 -0
  131. data/test/clusterers/centroid_linkage_test.rb +53 -0
  132. data/test/clusterers/complete_linkage_test.rb +57 -0
  133. data/test/clusterers/diana_test.rb +69 -0
  134. data/test/clusterers/k_means_test.rb +100 -0
  135. data/test/clusterers/median_linkage_test.rb +53 -0
  136. data/test/clusterers/single_linkage_test.rb +122 -0
  137. data/test/clusterers/ward_linkage_test.rb +53 -0
  138. data/test/clusterers/weighted_average_linkage_test.rb +53 -0
  139. data/test/data/data_set.csv +121 -0
  140. data/test/data/data_set_test.rb +96 -0
  141. data/test/data/proximity_test.rb +81 -0
  142. data/test/data/statistics_data_set.csv +5 -0
  143. data/test/data/statistics_test.rb +65 -0
  144. data/test/experiment/classifier_evaluator_test.rb +76 -0
  145. data/test/genetic_algorithm/chromosome_test.rb +58 -0
  146. data/test/genetic_algorithm/genetic_algorithm_test.rb +81 -0
  147. data/test/neural_network/backpropagation_test.rb +69 -0
  148. data/test/neural_network/hopfield_test.rb +72 -0
  149. data/test/som/som_test.rb +97 -0
  150. metadata +238 -0
@@ -0,0 +1,33 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!--
3
+ Licensed to the Apache Software Foundation (ASF) under one or more
4
+ contributor license agreements. See the NOTICE file distributed with
5
+ this work for additional information regarding copyright ownership.
6
+ The ASF licenses this file to You under the Apache License, Version 2.0
7
+ (the "License"); you may not use this file except in compliance with
8
+ the License. You may obtain a copy of the License at
9
+
10
+ http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+ Unless required by applicable law or agreed to in writing, software
13
+ distributed under the License is distributed on an "AS IS" BASIS,
14
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ See the License for the specific language governing permissions and
16
+ limitations under the License.
17
+ -->
18
+ <catalogue xml:lang="sk">
19
+ <message key="About">O programe</message>
20
+ <message key="Index">Zoznám</message>
21
+ <message key="Changes">Zmeny</message>
22
+ <message key="Todo">Úlohy</message>
23
+ <message key="Samples">Príklady</message>
24
+ <message key="Apache document">Apache Document</message>
25
+ <message key="Static content">Statický Obsah</message>
26
+ <message key="Linking">Linking</message>
27
+ <message key="Wiki page">Wiki stránka</message>
28
+ <message key="ihtml page">ihtml stránka</message>
29
+ <message key="ehtml page">ehtml stránka</message>
30
+ <message key="FAQ">Casté Otázky</message>
31
+ <message key="Simplifed Docbook">Simplifed Docbook stránka</message>
32
+ <message key="XSP page">XSP stránka</message>
33
+ </catalogue>
@@ -0,0 +1,22 @@
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ Licensed to the Apache Software Foundation (ASF) under one or more
4
+ contributor license agreements. See the NOTICE file distributed with
5
+ this work for additional information regarding copyright ownership.
6
+ The ASF licenses this file to You under the Apache License, Version 2.0
7
+ (the "License"); you may not use this file except in compliance with
8
+ the License. You may obtain a copy of the License at
9
+
10
+ http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+ Unless required by applicable law or agreed to in writing, software
13
+ distributed under the License is distributed on an "AS IS" BASIS,
14
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ See the License for the specific language governing permissions and
16
+ limitations under the License.
17
+ -->
18
+ <catalogue xml:lang="en">
19
+ <message key="Home">Home</message>
20
+ <message key="Samples">Samples</message>
21
+ <message key="Apache XML Projects">Apache XML Projects</message>
22
+ </catalogue>
@@ -0,0 +1,22 @@
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ Licensed to the Apache Software Foundation (ASF) under one or more
4
+ contributor license agreements. See the NOTICE file distributed with
5
+ this work for additional information regarding copyright ownership.
6
+ The ASF licenses this file to You under the Apache License, Version 2.0
7
+ (the "License"); you may not use this file except in compliance with
8
+ the License. You may obtain a copy of the License at
9
+
10
+ http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+ Unless required by applicable law or agreed to in writing, software
13
+ distributed under the License is distributed on an "AS IS" BASIS,
14
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ See the License for the specific language governing permissions and
16
+ limitations under the License.
17
+ -->
18
+ <catalogue xml:lang="de">
19
+ <message key="Home">Home</message>
20
+ <message key="Samples">Beispiele</message>
21
+ <message key="Apache XML Projects">Apache XML Projekte</message>
22
+ </catalogue>
@@ -0,0 +1,22 @@
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ Licensed to the Apache Software Foundation (ASF) under one or more
4
+ contributor license agreements. See the NOTICE file distributed with
5
+ this work for additional information regarding copyright ownership.
6
+ The ASF licenses this file to You under the Apache License, Version 2.0
7
+ (the "License"); you may not use this file except in compliance with
8
+ the License. You may obtain a copy of the License at
9
+
10
+ http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+ Unless required by applicable law or agreed to in writing, software
13
+ distributed under the License is distributed on an "AS IS" BASIS,
14
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ See the License for the specific language governing permissions and
16
+ limitations under the License.
17
+ -->
18
+ <catalogue xml:lang="es">
19
+ <message key="Home">Inicio</message>
20
+ <message key="Samples">Ejemplos</message>
21
+ <message key="Apache XML Projects">Projectos XML Apache</message>
22
+ </catalogue>
@@ -0,0 +1,22 @@
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ Licensed to the Apache Software Foundation (ASF) under one or more
4
+ contributor license agreements. See the NOTICE file distributed with
5
+ this work for additional information regarding copyright ownership.
6
+ The ASF licenses this file to You under the Apache License, Version 2.0
7
+ (the "License"); you may not use this file except in compliance with
8
+ the License. You may obtain a copy of the License at
9
+
10
+ http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+ Unless required by applicable law or agreed to in writing, software
13
+ distributed under the License is distributed on an "AS IS" BASIS,
14
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ See the License for the specific language governing permissions and
16
+ limitations under the License.
17
+ -->
18
+ <catalogue xml:lang="fr">
19
+ <message key="Home">Accueil</message>
20
+ <message key="Samples">Exemples</message>
21
+ <message key="Apache XML Projects">Projets Apache XML</message>
22
+ </catalogue>
@@ -0,0 +1,22 @@
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ Licensed to the Apache Software Foundation (ASF) under one or more
4
+ contributor license agreements. See the NOTICE file distributed with
5
+ this work for additional information regarding copyright ownership.
6
+ The ASF licenses this file to You under the Apache License, Version 2.0
7
+ (the "License"); you may not use this file except in compliance with
8
+ the License. You may obtain a copy of the License at
9
+
10
+ http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+ Unless required by applicable law or agreed to in writing, software
13
+ distributed under the License is distributed on an "AS IS" BASIS,
14
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ See the License for the specific language governing permissions and
16
+ limitations under the License.
17
+ -->
18
+ <catalogue xml:lang="nl">
19
+ <message key="Home">Home</message>
20
+ <message key="Samples">Voorbeelden</message>
21
+ <message key="Apache XML Projects">Apache XML Projecten</message>
22
+ </catalogue>
@@ -0,0 +1,84 @@
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
+ require File.dirname(__FILE__) + '/../../lib/ai4r/classifiers/hyperpipes'
11
+ require 'test/unit'
12
+
13
+ class Ai4r::Classifiers::Hyperpipes
14
+ attr_accessor :data_set, :pipes
15
+ end
16
+
17
+ include Ai4r::Classifiers
18
+ include Ai4r::Data
19
+
20
+ class HyperpipesTest < Test::Unit::TestCase
21
+
22
+ @@data_labels = [ 'city', 'age', 'gender', 'marketing_target' ]
23
+
24
+ @@data_items = [['New York', 25, 'M', 'Y'],
25
+ ['New York', 23, 'M', 'Y'],
26
+ ['New York', 18, 'M', 'Y'],
27
+ ['Chicago', 43, 'M', 'Y'],
28
+ ['New York', 34, 'F', 'N'],
29
+ ['Chicago', 33, 'F', 'Y'],
30
+ ['New York', 31, 'F', 'N'],
31
+ ['Chicago', 55, 'M', 'N'],
32
+ ['New York', 58, 'F', 'N'],
33
+ ['New York', 59, 'M', 'N'],
34
+ ['Chicago', 71, 'M', 'N'],
35
+ ['New York', 60, 'F', 'N'],
36
+ ['Chicago', 85, 'F', 'Y']
37
+ ]
38
+
39
+
40
+ def setup
41
+ Hyperpipes.send(:public, *Hyperpipes.protected_instance_methods)
42
+ @data_set = DataSet.new(:data_items => @@data_items, :data_labels => @@data_labels)
43
+ end
44
+
45
+ def test_build_pipe
46
+ classifier = Hyperpipes.new
47
+ assert_equal [{}, {:max=>-1.0/0, :min=>1.0/0}, {}], classifier.build_pipe(@data_set)
48
+ end
49
+
50
+ def test_get_rules
51
+
52
+ end
53
+
54
+ def test_build
55
+ assert_raise(ArgumentError) { Hyperpipes.new.build(DataSet.new) }
56
+ classifier = Hyperpipes.new.build(@data_set)
57
+ assert classifier.pipes.include?("Y")
58
+ assert classifier.pipes.include?("N")
59
+ end
60
+
61
+ def test_eval
62
+ classifier = Hyperpipes.new.build(@data_set)
63
+ assert classifier
64
+ assert_equal('N', classifier.eval(['Chicago', 55, 'M']))
65
+ assert_equal('N', classifier.eval(['New York', 35, 'F']))
66
+ assert_equal('Y', classifier.eval(['New York', 25, 'M']))
67
+ assert_equal('Y', classifier.eval(['Chicago', 85, 'F']))
68
+ end
69
+
70
+ def test_get_rules
71
+ classifier = Hyperpipes.new.build(@data_set)
72
+ age = 28
73
+ gender = "M"
74
+ marketing_target = nil
75
+ eval classifier.get_rules
76
+ assert_equal 'Y', marketing_target
77
+ age = 44
78
+ city='New York'
79
+ eval classifier.get_rules
80
+ assert_equal 'N', marketing_target
81
+ end
82
+ end
83
+
84
+
@@ -0,0 +1,208 @@
1
+ # id3_test.rb
2
+ #
3
+ # This is a unit test file for the ID3 algorithm (Quinlan) implemented
4
+ # in ai4r
5
+ #
6
+ # Author:: Sergio Fierens
7
+ # License:: MPL 1.1
8
+ # Project:: ai4r
9
+ # Url:: http://ai4r.rubyforge.org/
10
+ #
11
+ # You can redistribute it and/or modify it under the terms of
12
+ # the Mozilla Public License version 1.1 as published by the
13
+ # Mozilla Foundation at http://www.mozilla.org/MPL/MPL-1.1.txt
14
+
15
+ require File.dirname(__FILE__) + '/../../lib/ai4r/classifiers/id3'
16
+ require 'test/unit'
17
+
18
+ DATA_LABELS = [ 'city', 'age_range', 'gender', 'marketing_target' ]
19
+
20
+ DATA_ITEMS = [ ['New York', '<30', 'M', 'Y'],
21
+ ['Chicago', '<30', 'M', 'Y'],
22
+ ['Chicago', '<30', 'F', 'Y'],
23
+ ['New York', '<30', 'M', 'Y'],
24
+ ['New York', '<30', 'M', 'Y'],
25
+ ['Chicago', '[30-50)', 'M', 'Y'],
26
+ ['New York', '[30-50)', 'F', 'N'],
27
+ ['Chicago', '[30-50)', 'F', 'Y'],
28
+ ['New York', '[30-50)', 'F', 'N'],
29
+ ['Chicago', '[50-80]', 'M', 'N'],
30
+ ['New York', '[50-80]', 'F', 'N'],
31
+ ['New York', '[50-80]', 'M', 'N'],
32
+ ['Chicago', '[50-80]', 'M', 'N'],
33
+ ['New York', '[50-80]', 'F', 'N'],
34
+ ['Chicago', '>80', 'F', 'Y']
35
+ ]
36
+
37
+ SPLIT_DATA_ITEMS_BY_CITY = [ [
38
+ ["New York", "<30", "M", "Y"],
39
+ ["New York", "<30", "M", "Y"],
40
+ ["New York", "<30", "M", "Y"],
41
+ ["New York", "[30-50)", "F", "N"],
42
+ ["New York", "[30-50)", "F", "N"],
43
+ ["New York", "[50-80]", "F", "N"],
44
+ ["New York", "[50-80]", "M", "N"],
45
+ ["New York", "[50-80]", "F", "N"]],
46
+ [
47
+ ["Chicago", "<30", "M", "Y"],
48
+ ["Chicago", "<30", "F", "Y"],
49
+ ["Chicago", "[30-50)", "M", "Y"],
50
+ ["Chicago", "[30-50)", "F", "Y"],
51
+ ["Chicago", "[50-80]", "M", "N"],
52
+ ["Chicago", "[50-80]", "M", "N"],
53
+ ["Chicago", ">80", "F", "Y"]]
54
+ ]
55
+
56
+ SPLIT_DATA_ITEMS_BY_AGE = [ [
57
+ ["New York", "<30", "M", "Y"],
58
+ ["Chicago", "<30", "M", "Y"],
59
+ ["Chicago", "<30", "F", "Y"],
60
+ ["New York", "<30", "M", "Y"],
61
+ ["New York", "<30", "M", "Y"]],
62
+ [
63
+ ["Chicago", "[30-50)", "M", "Y"],
64
+ ["New York", "[30-50)", "F", "N"],
65
+ ["Chicago", "[30-50)", "F", "Y"],
66
+ ["New York", "[30-50)", "F", "N"]],
67
+ [
68
+ ["Chicago", "[50-80]", "M", "N"],
69
+ ["New York", "[50-80]", "F", "N"],
70
+ ["New York", "[50-80]", "M", "N"],
71
+ ["Chicago", "[50-80]", "M", "N"],
72
+ ["New York", "[50-80]", "F", "N"]],
73
+ [
74
+ ["Chicago", ">80", "F", "Y"]]
75
+ ]
76
+
77
+ EXPECTED_RULES_STRING =
78
+ "if age_range=='<30' then marketing_target='Y'\n"+
79
+ "elsif age_range=='[30-50)' and city=='Chicago' then marketing_target='Y'\n"+
80
+ "elsif age_range=='[30-50)' and city=='New York' then marketing_target='N'\n"+
81
+ "elsif age_range=='[50-80]' then marketing_target='N'\n"+
82
+ "elsif age_range=='>80' then marketing_target='Y'\n"+
83
+ "else raise 'There was not enough information during training to do a proper induction for this data element' end"
84
+
85
+ include Ai4r::Classifiers
86
+ include Ai4r::Data
87
+
88
+ class ID3Test < Test::Unit::TestCase
89
+
90
+ def test_build
91
+ Ai4r::Classifiers::ID3.send(:public, *Ai4r::Classifiers::ID3.protected_instance_methods)
92
+ Ai4r::Classifiers::ID3.send(:public, *Ai4r::Classifiers::ID3.private_instance_methods)
93
+ end
94
+
95
+ def test_log2
96
+ assert_equal 1.0, ID3.log2(2)
97
+ assert_equal 0.0, ID3.log2(0)
98
+ assert 1.585 - ID3.log2(3) < 0.001
99
+ end
100
+
101
+ def test_sum
102
+ assert_equal 28, ID3.sum([5, 0, 22, 1])
103
+ assert_equal 0, ID3.sum([])
104
+ end
105
+
106
+ def test_data_labels
107
+ id3 = ID3.new.build(DataSet.new(:data_items =>DATA_ITEMS))
108
+ expected_default = [ 'attribute_1', 'attribute_2', 'attribute_3', 'class_value' ]
109
+ assert_equal(expected_default, id3.data_set.data_labels)
110
+ id3 = ID3.new.build(DataSet.new(:data_items =>DATA_ITEMS, :data_labels => DATA_LABELS))
111
+ assert_equal(DATA_LABELS, id3.data_set.data_labels)
112
+ end
113
+
114
+ def test_domain
115
+ id3 = ID3.new.build(DataSet.new(:data_items =>DATA_ITEMS, :data_labels => DATA_LABELS))
116
+ expected_domain = [["New York", "Chicago"], ["<30", "[30-50)", "[50-80]", ">80"], ["M", "F"], ["Y", "N"]]
117
+ assert_equal expected_domain, id3.domain(DATA_ITEMS)
118
+ end
119
+
120
+ def test_grid
121
+ id3 = ID3.new.build(DataSet.new(:data_items =>DATA_ITEMS, :data_labels => DATA_LABELS))
122
+ expected_grid = [[3, 5], [5, 2]]
123
+ domain = id3.domain(DATA_ITEMS)
124
+ assert_equal expected_grid, id3.freq_grid(0, DATA_ITEMS, domain)
125
+ expected_grid = [[5, 0], [2, 2], [0, 5], [1, 0]]
126
+ assert_equal expected_grid, id3.freq_grid(1, DATA_ITEMS, domain)
127
+ end
128
+
129
+ def test_entropy
130
+ id3 = ID3.new.build(DataSet.new(:data_items =>DATA_ITEMS, :data_labels => DATA_LABELS))
131
+ expected_entropy = 0.9118
132
+ domain = id3.domain(DATA_ITEMS)
133
+ freq_grid = id3.freq_grid(0, DATA_ITEMS, domain)
134
+ assert expected_entropy - id3.entropy(freq_grid, DATA_ITEMS.length) < 0.0001
135
+ expected_entropy = 0.2667
136
+ freq_grid = id3.freq_grid(1, DATA_ITEMS, domain)
137
+ assert expected_entropy - id3.entropy(freq_grid, DATA_ITEMS.length) < 0.0001
138
+ expected_entropy = 0.9688
139
+ freq_grid = id3.freq_grid(2, DATA_ITEMS, domain)
140
+ assert expected_entropy - id3.entropy(freq_grid, DATA_ITEMS.length) < 0.0001
141
+ end
142
+
143
+ def test_min_entropy_index
144
+ id3 = ID3.new.build(DataSet.new(:data_items =>DATA_ITEMS, :data_labels => DATA_LABELS))
145
+ domain = id3.domain(DATA_ITEMS)
146
+ assert_equal 1, id3.min_entropy_index(DATA_ITEMS, domain)
147
+ assert_equal 0, id3.min_entropy_index(DATA_ITEMS, domain, [1])
148
+ assert_equal 2, id3.min_entropy_index(DATA_ITEMS, domain, [1, 0])
149
+ end
150
+
151
+ def test_split_data_examples
152
+ id3 = ID3.new.build(DataSet.new(:data_items =>DATA_ITEMS, :data_labels => DATA_LABELS))
153
+ domain = id3.domain(DATA_ITEMS)
154
+ res = id3.split_data_examples(DATA_ITEMS, domain, 0)
155
+ assert_equal(SPLIT_DATA_ITEMS_BY_CITY, res)
156
+ res = id3.split_data_examples(DATA_ITEMS, domain, 1)
157
+ assert_equal(SPLIT_DATA_ITEMS_BY_AGE, res)
158
+ end
159
+
160
+ def test_most_freq
161
+ id3 = ID3.new.build(DataSet.new(:data_items =>DATA_ITEMS, :data_labels => DATA_LABELS))
162
+ domain = id3.domain(DATA_ITEMS)
163
+ assert_equal 'Y', id3.most_freq(DATA_ITEMS, domain)
164
+ assert_equal 'Y', id3.most_freq(SPLIT_DATA_ITEMS_BY_AGE[3], domain)
165
+ assert_equal 'N', id3.most_freq(SPLIT_DATA_ITEMS_BY_AGE[2], domain)
166
+ end
167
+
168
+ def test_get_rules
169
+ assert_equal [["marketing_target='N'"]], CategoryNode.new('marketing_target', 'N').get_rules
170
+ id3 = ID3.new.build(DataSet.new(:data_items =>DATA_ITEMS, :data_labels => DATA_LABELS))
171
+ assert_equal EXPECTED_RULES_STRING, id3.get_rules
172
+ end
173
+
174
+ def test_eval
175
+ id3 = ID3.new.build(DataSet.new(:data_items =>DATA_ITEMS, :data_labels => DATA_LABELS))
176
+ #if age_range='<30' then marketing_target='Y'
177
+ assert_equal 'Y', id3.eval(['New York', '<30', 'F'])
178
+ assert_equal 'Y', id3.eval(['Chicago', '<30', 'M'])
179
+ #if age_range='[30-50)' and city='Chicago' then marketing_target='Y'
180
+ assert_equal 'Y', id3.eval(['Chicago', '[30-50)', 'F'])
181
+ assert_equal 'Y', id3.eval(['Chicago', '[30-50)', 'M'])
182
+ #if age_range='[30-50)' and city='New York' then marketing_target='N'
183
+ assert_equal 'N', id3.eval(['New York', '[30-50)', 'F'])
184
+ assert_equal 'N', id3.eval(['New York', '[30-50)', 'M'])
185
+ #if age_range='[50-80]' then marketing_target='N'
186
+ assert_equal 'N', id3.eval(['New York', '[50-80]', 'F'])
187
+ assert_equal 'N', id3.eval(['Chicago', '[50-80]', 'M'])
188
+ #if age_range='>80' then marketing_target='Y'
189
+ assert_equal 'Y', id3.eval(['New York', '>80', 'M'])
190
+ assert_equal 'Y', id3.eval(['Chicago', '>80', 'F'])
191
+ end
192
+
193
+ def test_rules_eval
194
+ id3 = ID3.new.build(DataSet.new(:data_items =>DATA_ITEMS, :data_labels => DATA_LABELS))
195
+ #if age_range='<30' then marketing_target='Y'
196
+ age_range = '<30'
197
+ marketing_target = nil
198
+ eval id3.get_rules
199
+ assert_equal 'Y', marketing_target
200
+ #if age_range='[30-50)' and city='New York' then marketing_target='N'
201
+ age_range='[30-50)'
202
+ city='New York'
203
+ eval id3.get_rules
204
+ assert_equal 'N', marketing_target
205
+ end
206
+ end
207
+
208
+
@@ -0,0 +1,79 @@
1
+ require 'test/unit'
2
+ require File.dirname(__FILE__) + '/../../lib/ai4r/classifiers/multilayer_perceptron'
3
+ require File.dirname(__FILE__) + '/../../lib/ai4r/data/data_set'
4
+
5
+ # Make all accessors and methods public
6
+ class Ai4r::Classifiers::MultilayerPerceptron
7
+ attr_accessor :data_set, :class_value, :network, :domains, :outputs
8
+ public :get_max_index
9
+ public :data_to_output
10
+ end
11
+
12
+ class MultilayerPerceptronTest < Test::Unit::TestCase
13
+
14
+ include Ai4r::Classifiers
15
+ include Ai4r::Data
16
+
17
+ @@data_set = DataSet.new(:data_items =>[ ['New York', '<30', 'M', 'Y'],
18
+ ['Chicago', '<30', 'M', 'Y'],
19
+ ['New York', '<30', 'M', 'Y'],
20
+ ['New York', '[30-50)', 'F', 'N'],
21
+ ['Chicago', '[30-50)', 'F', 'Y'],
22
+ ['New York', '[30-50)', 'F', 'N'],
23
+ ['Chicago', '[50-80]', 'M', 'N'],
24
+ ])
25
+
26
+ def test_initialize
27
+ classifier = MultilayerPerceptron.new
28
+ assert_equal 1, classifier.active_node_value
29
+ assert_equal 0, classifier.inactive_node_value
30
+ assert_equal Ai4r::NeuralNetwork::Backpropagation, classifier.network_class
31
+ assert_equal [], classifier.hidden_layers
32
+ assert classifier.network_parameters
33
+ assert classifier.network_parameters.empty?
34
+ assert classifier.training_iterations > 1
35
+ end
36
+
37
+ def test_build
38
+ assert_raise(ArgumentError) { MultilayerPerceptron.new.build(DataSet.new) }
39
+ classifier = MultilayerPerceptron.new
40
+ classifier.training_iterations = 1
41
+ classifier.build(@@data_set)
42
+ assert_equal [7,2], classifier.network.structure
43
+ classifier.hidden_layers = [6, 4]
44
+ classifier.build(@@data_set)
45
+ assert_equal [7,6,4,2], classifier.network.structure
46
+ end
47
+
48
+ def test_eval
49
+ classifier = MultilayerPerceptron.new.build(@@data_set)
50
+ assert classifier
51
+ assert_equal('N', classifier.eval(['Chicago', '[50-80]', 'M']))
52
+ assert_equal('N', classifier.eval(['New York', '[30-50)', 'F']))
53
+ assert_equal('Y', classifier.eval(['New York', '<30', 'M']))
54
+ assert_equal('Y', classifier.eval(['Chicago', '[30-50)', 'F']))
55
+ end
56
+
57
+ def test_get_rules
58
+ assert_match(/raise/, MultilayerPerceptron.new.get_rules)
59
+ end
60
+
61
+ def test_get_max_index
62
+ classifier = MultilayerPerceptron.new
63
+ assert_equal(0, classifier.get_max_index([3, 1, 0.2, -9, 0, 2.99]))
64
+ assert_equal(2, classifier.get_max_index([3, 1, 5, -9, 0, 2.99]))
65
+ assert_equal(5, classifier.get_max_index([3, 1, 5, -9, 0, 6]))
66
+ end
67
+
68
+ def test_data_to_output
69
+ classifier = MultilayerPerceptron.new
70
+ classifier.outputs = 4
71
+ classifier.outputs = 4
72
+ classifier.domains = [nil, nil, nil, ["A", "B", "C", "D"]]
73
+ assert_equal([1,0,0,0], classifier.data_to_output("A"))
74
+ assert_equal([0,0,1,0], classifier.data_to_output("C"))
75
+ assert_equal([0,0,0,1], classifier.data_to_output("D"))
76
+ end
77
+
78
+ end
79
+