ml 0.3.0 → 0.4.0
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.md +3 -0
- data/VERSION +1 -1
- data/lib/data/generator.rb +7 -3
- data/lib/method/adaptive_perceptron.rb +3 -3
- data/lib/method/cyclic_descent.rb +67 -0
- data/lib/method/decision_stump.rb +31 -9
- data/lib/method/linear_regression.rb +34 -0
- data/lib/method/logistic_regression.rb +50 -0
- data/lib/method/perceptron.rb +6 -42
- data/lib/method/pocket.rb +2 -2
- data/lib/method/toolbox.rb +73 -0
- data/lib/ml.rb +7 -0
- data/lib/util/util.rb +20 -0
- data/ml.gemspec +7 -2
- data/spec/learner_spec.rb +19 -98
- metadata +22 -17
data/README.md
CHANGED
@@ -8,6 +8,9 @@ Machine learning library for ruby
|
|
8
8
|
* Adaptive Perceptron (Adaline) Learning Algorithm
|
9
9
|
* Pocket Learning Algorithm
|
10
10
|
* Decision Stump Learning Algorithm
|
11
|
+
* Linear Regression Algorithm
|
12
|
+
* Logistic Regression Algorithm
|
13
|
+
* Cyclic Coordinate Descent
|
11
14
|
|
12
15
|
# Tools
|
13
16
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.0
|
data/lib/data/generator.rb
CHANGED
@@ -9,8 +9,8 @@ module ML
|
|
9
9
|
# @param [Integer] dim dimension
|
10
10
|
# @param [Numeric] scale the magnitude of the vector
|
11
11
|
# @param [Numeric] noise the percentage of noise
|
12
|
-
# @param [Symbol] model the noise model,
|
13
|
-
# all the element in a probability, while
|
12
|
+
# @param [Symbol] model the noise model, :random for flipping
|
13
|
+
# all the element in a probability, while :flip only flips a
|
14
14
|
# portion of elements randomly
|
15
15
|
def initialize dim, scale = 1, noise = 0, model = :random
|
16
16
|
@dim = dim
|
@@ -85,10 +85,14 @@ module ML
|
|
85
85
|
# @param [Integer] x_range x range
|
86
86
|
# @param [Integer] y_range y range
|
87
87
|
# @param [Numeric] noise the percentage of noise
|
88
|
-
|
88
|
+
# @param [Symbol] model the noise model, :random for flipping
|
89
|
+
# all the element in a probability, while :flip only flips a
|
90
|
+
# portion of elements randomly
|
91
|
+
def initialize x_range = 100, y_range = 100, noise = 0, model = :random
|
89
92
|
@x_range = x_range
|
90
93
|
@y_range = y_range
|
91
94
|
@noise = noise
|
95
|
+
@model = model
|
92
96
|
end
|
93
97
|
|
94
98
|
# Generate two groups of points on 2d plain
|
@@ -8,18 +8,18 @@ module ML
|
|
8
8
|
#
|
9
9
|
# @param [Integer] dim the number of dimension
|
10
10
|
# @param [Float] the eta parameter
|
11
|
-
def initialize dim, eta
|
11
|
+
def initialize dim, eta = 0.1
|
12
12
|
super(dim)
|
13
13
|
@eta = eta
|
14
14
|
end
|
15
15
|
|
16
16
|
protected
|
17
17
|
def wrongly_classify x, y
|
18
|
-
|
18
|
+
classify_inner(x) * y <= 1
|
19
19
|
end
|
20
20
|
|
21
21
|
def update_vector x, y
|
22
|
-
|
22
|
+
self.current_vector += @eta * (y - classify_inner(x))* x
|
23
23
|
end
|
24
24
|
end
|
25
25
|
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'matrix'
|
2
|
+
|
3
|
+
module ML
|
4
|
+
module Learner
|
5
|
+
# Implementation of cyclic coordinate descent learner
|
6
|
+
class CyclicDescentLearner
|
7
|
+
include Toolbox
|
8
|
+
include LinearToolbox
|
9
|
+
|
10
|
+
# Initialize a learner
|
11
|
+
#
|
12
|
+
# @param [Integer] dim dimension
|
13
|
+
def initialize dim, model = :basis
|
14
|
+
@dim = dim
|
15
|
+
@model = model
|
16
|
+
end
|
17
|
+
|
18
|
+
# Train with a supervised data
|
19
|
+
#
|
20
|
+
# @param [Hash] data supervised input data (mapping from array to integer)
|
21
|
+
# @param [Integer] iteration the desired iteration number
|
22
|
+
def train! data, iteration = 1000
|
23
|
+
self.current_vector = Matrix.column_vector(Array.new(@dim + 1, 0))
|
24
|
+
iteration.times do |i|
|
25
|
+
v = calc_v i
|
26
|
+
eta = calc_eta data, v
|
27
|
+
self.current_vector += eta * v
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def calc_eta data, v
|
34
|
+
v_t = v.transpose
|
35
|
+
w_t = self.current_vector.transpose
|
36
|
+
train = {}
|
37
|
+
|
38
|
+
for xn, yn in data
|
39
|
+
x_n = Matrix.column_vector(xn)
|
40
|
+
dot = (v_t * x_n)[0,0] * yn
|
41
|
+
thr = (w_t * x_n)[0,0] * (-yn) / dot
|
42
|
+
|
43
|
+
next if dot == 0
|
44
|
+
if dot > 0
|
45
|
+
train[[thr]] = 1
|
46
|
+
else
|
47
|
+
train[[thr]] = -1
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
learner = DecisionStumpLearner.new(1)
|
52
|
+
learner.train! train
|
53
|
+
learner.hypothesis[2]
|
54
|
+
end
|
55
|
+
|
56
|
+
def calc_v iteration
|
57
|
+
v = Array.new(@dim + 1, 0)
|
58
|
+
if @model == :basis
|
59
|
+
v[iteration % @dim] = 1
|
60
|
+
else
|
61
|
+
v[iteration % @dim] = Util.normal_distribution 0,1
|
62
|
+
end
|
63
|
+
Matrix.column_vector(v)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -2,6 +2,7 @@ module ML
|
|
2
2
|
module Learner
|
3
3
|
# Implementation of decision stump learning
|
4
4
|
class DecisionStumpLearner
|
5
|
+
include Toolbox
|
5
6
|
# Initialize a decision stump learner
|
6
7
|
#
|
7
8
|
# @param [Integer] dim dimension
|
@@ -14,15 +15,12 @@ module ML
|
|
14
15
|
# Train with a supervised data
|
15
16
|
#
|
16
17
|
# @param [Hash] data supervised input data (mapping from array to integer)
|
17
|
-
# @return [Hash] {error} error of the training data
|
18
18
|
def train! data
|
19
19
|
for i in 0...@dim
|
20
20
|
hypo, error = search data, i
|
21
21
|
update_hypo hypo, error
|
22
22
|
@error_vector[i] = error
|
23
23
|
end
|
24
|
-
|
25
|
-
{:error => @min_error}
|
26
24
|
end
|
27
25
|
|
28
26
|
# Predict certain data
|
@@ -67,8 +65,9 @@ module ML
|
|
67
65
|
def search data, dim
|
68
66
|
pool = data.to_a.sort_by {|line| line[0][dim]}
|
69
67
|
max_diff, index = 0, nil
|
70
|
-
pcount, ncount = 0, 0
|
71
68
|
|
69
|
+
# in order search
|
70
|
+
pcount, ncount = 0, 0
|
72
71
|
pool.each_with_index do |dat, i|
|
73
72
|
if dat[1] == 1
|
74
73
|
pcount += 1
|
@@ -82,10 +81,33 @@ module ML
|
|
82
81
|
end
|
83
82
|
end
|
84
83
|
|
85
|
-
|
86
|
-
|
84
|
+
# reverse search
|
85
|
+
pcount, ncount = 0, 0
|
86
|
+
pool.reverse.each_with_index do |dat, i|
|
87
|
+
if dat[1] == 1
|
88
|
+
pcount += 1
|
89
|
+
else
|
90
|
+
ncount += 1
|
91
|
+
end
|
92
|
+
|
93
|
+
if (ncount - pcount).abs > max_diff.abs
|
94
|
+
max_diff = ncount - pcount
|
95
|
+
index = pool.size - i - 1
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
thres = if max_diff > 0
|
100
|
+
if index == pool.size - 1
|
101
|
+
pool[-1][0][dim] + 0.01
|
102
|
+
else
|
103
|
+
(pool[index][0][dim] + pool[index+1][0][dim]) / 2.0
|
104
|
+
end
|
87
105
|
else
|
88
|
-
|
106
|
+
if index == 0
|
107
|
+
pool[0][0][dim] - 0.01
|
108
|
+
else
|
109
|
+
(pool[index][0][dim] + pool[index-1][0][dim]) / 2.0
|
110
|
+
end
|
89
111
|
end
|
90
112
|
hypo = if max_diff > 0
|
91
113
|
[-1, dim, thres]
|
@@ -93,10 +115,10 @@ module ML
|
|
93
115
|
[1, dim, thres]
|
94
116
|
end
|
95
117
|
|
96
|
-
[hypo,
|
118
|
+
[hypo, hypo_error(pool, hypo)]
|
97
119
|
end
|
98
120
|
|
99
|
-
def
|
121
|
+
def hypo_error data, hypo
|
100
122
|
error = 0
|
101
123
|
for dat, result in data
|
102
124
|
error += 1 unless classify(dat, hypo) == result
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'matrix'
|
2
|
+
|
3
|
+
module ML
|
4
|
+
module Learner
|
5
|
+
# Implementation of linear regression
|
6
|
+
class LinearRegressionLearner
|
7
|
+
include Toolbox
|
8
|
+
include LinearToolbox
|
9
|
+
|
10
|
+
# Intialize linear regression
|
11
|
+
#
|
12
|
+
# @param [Integer] dim the input dimension
|
13
|
+
def initialize dim
|
14
|
+
@dim = dim
|
15
|
+
end
|
16
|
+
|
17
|
+
# Train with supervised data
|
18
|
+
#
|
19
|
+
# @param [Hash] data supervised input data (mapping from array to integer)
|
20
|
+
def train! data
|
21
|
+
x = Matrix.rows(data.keys)
|
22
|
+
ary_y = []
|
23
|
+
for k in data.keys
|
24
|
+
ary_y << data[k]
|
25
|
+
end
|
26
|
+
y = Matrix.column_vector(ary_y)
|
27
|
+
|
28
|
+
x_t = x.transpose
|
29
|
+
x_dag = (x_t * x).inverse * x_t
|
30
|
+
self.current_vector = x_dag * y
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module ML
|
2
|
+
module Learner
|
3
|
+
# Implementing logistic regression
|
4
|
+
class LogisticRegressionLearner
|
5
|
+
include Toolbox
|
6
|
+
include LinearToolbox
|
7
|
+
|
8
|
+
# Intialize logistic regression
|
9
|
+
#
|
10
|
+
# @param [Integer] dim the input dimension
|
11
|
+
# @param [Numeric] eta the eta parameter
|
12
|
+
# @param [Symbol] model the learning model, :variate for variating
|
13
|
+
# learning rate and :fixed for fixed learning rate
|
14
|
+
def initialize dim, eta = 0.01, model = :variate
|
15
|
+
@dim = dim
|
16
|
+
@eta = eta
|
17
|
+
@model = model
|
18
|
+
end
|
19
|
+
|
20
|
+
# Train with supervised data
|
21
|
+
#
|
22
|
+
# @param [Hash] data supervised input data (mapping from array to integer)
|
23
|
+
# @param [Integer] iteration the number of the iterations
|
24
|
+
def train! data, iteration = 1000
|
25
|
+
self.current_vector = Matrix.column_vector(Array.new(@dim + 1, 0))
|
26
|
+
|
27
|
+
iteration.times do
|
28
|
+
if @model == :variate
|
29
|
+
n = (rand * data.size).to_i
|
30
|
+
key = data.keys[n]
|
31
|
+
self.current_vector -= gradiant(key, data[key]).map {|e| e * @eta }
|
32
|
+
else
|
33
|
+
sum = Matrix.column_vector(Array.new(@dim + 1, 0))
|
34
|
+
for key, value in data
|
35
|
+
sum += gradiant key, value
|
36
|
+
end
|
37
|
+
self.current_vector -= sum.map {|e| e * @eta / data.size }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
protected
|
43
|
+
def gradiant x, y
|
44
|
+
exp = Math.exp(-y * 2 * (self.current_vector.transpose * Matrix.column_vector(x))[0,0])
|
45
|
+
coef = exp * (-2 * y) / (1 + exp)
|
46
|
+
Matrix.column_vector(x).map {|e| e * coef}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/method/perceptron.rb
CHANGED
@@ -4,12 +4,15 @@ module ML
|
|
4
4
|
module Learner
|
5
5
|
# Implementation of Perceptron Learning Algorithm
|
6
6
|
class PerceptronLearner
|
7
|
+
include Toolbox
|
8
|
+
include LinearToolbox
|
9
|
+
|
7
10
|
# Initialize a perceptron learner
|
8
11
|
#
|
9
12
|
# @param [Integer] dim the number of dimension
|
10
13
|
def initialize dim
|
11
14
|
@dim = dim
|
12
|
-
|
15
|
+
self.current_vector = Matrix.column_vector(Array.new(dim + 1, 0))
|
13
16
|
end
|
14
17
|
|
15
18
|
# Train with supervised data
|
@@ -41,54 +44,15 @@ module ML
|
|
41
44
|
|
42
45
|
break unless misclassified
|
43
46
|
end
|
44
|
-
|
45
|
-
# check out errors
|
46
|
-
error = if update >= threshold
|
47
|
-
classify_error pool
|
48
|
-
else
|
49
|
-
0
|
50
|
-
end
|
51
|
-
|
52
|
-
{:error => error, :update_count => update}
|
53
|
-
end
|
54
|
-
|
55
|
-
# The final coefficient of the line
|
56
|
-
#
|
57
|
-
# @return [Array] [a,b,c] for ax+by+c=0
|
58
|
-
def line
|
59
|
-
@w.column(0).to_a
|
60
|
-
end
|
61
|
-
|
62
|
-
# Predict certain data
|
63
|
-
#
|
64
|
-
# @param [Array] data data in question
|
65
|
-
# @return [Integer] prediction
|
66
|
-
def predict data
|
67
|
-
classify(Matrix.column_vector(data + [1.0])) <=> 0
|
68
47
|
end
|
69
48
|
|
70
49
|
protected
|
71
|
-
def classify data
|
72
|
-
(@w.transpose * data)[0,0]
|
73
|
-
end
|
74
|
-
|
75
50
|
def wrongly_classify x, y
|
76
|
-
|
51
|
+
classify_inner(x) * y <= 0
|
77
52
|
end
|
78
53
|
|
79
54
|
def update_vector x, y
|
80
|
-
|
81
|
-
end
|
82
|
-
|
83
|
-
def classify_error supervised_data
|
84
|
-
error = 0
|
85
|
-
|
86
|
-
for data, result in supervised_data
|
87
|
-
classified_result = (classify(Matrix.column_vector(data)) <=> 0)
|
88
|
-
error += 1 unless result == classified_result
|
89
|
-
end
|
90
|
-
|
91
|
-
error
|
55
|
+
self.current_vector += y * x
|
92
56
|
end
|
93
57
|
end
|
94
58
|
end
|
data/lib/method/pocket.rb
CHANGED
@@ -6,7 +6,7 @@ module ML
|
|
6
6
|
#
|
7
7
|
# @param [Hash] data supervised input data (mapping from array to integer)
|
8
8
|
# @param [Integer] iteration the number of the iterations
|
9
|
-
def train! data, iteration
|
9
|
+
def train! data, iteration = 1000
|
10
10
|
pool = data.to_a
|
11
11
|
best_error, pocket = 1.0/0, nil
|
12
12
|
|
@@ -15,7 +15,7 @@ module ML
|
|
15
15
|
error = classify_error pool
|
16
16
|
if error < best_error
|
17
17
|
error = best_error
|
18
|
-
pocket =
|
18
|
+
pocket = current_vector.dup
|
19
19
|
end
|
20
20
|
break if best_error == 0
|
21
21
|
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'matrix'
|
2
|
+
|
3
|
+
module ML
|
4
|
+
module Learner
|
5
|
+
|
6
|
+
# General toolbox for learning methods
|
7
|
+
module Toolbox
|
8
|
+
# Predict a single data with current prediction
|
9
|
+
#
|
10
|
+
# @param [Array] data input vector array
|
11
|
+
# @return [Integer] classified data
|
12
|
+
def predict data
|
13
|
+
raise "Cannot predict"
|
14
|
+
end
|
15
|
+
|
16
|
+
# Calculating model error
|
17
|
+
#
|
18
|
+
# @param [Hash] data
|
19
|
+
# supervised input data (mapping from array to integer)
|
20
|
+
def classify_error supervised_data
|
21
|
+
error = 0
|
22
|
+
|
23
|
+
for data, result in supervised_data
|
24
|
+
classified_result = predict(data)
|
25
|
+
error += 1 unless result == classified_result
|
26
|
+
end
|
27
|
+
|
28
|
+
error.to_f / supervised_data.size
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Learner toolbox for linear model
|
33
|
+
#
|
34
|
+
# The prediction is a vector of dimension d+1 where d is the
|
35
|
+
# dimension of the input data
|
36
|
+
module LinearToolbox
|
37
|
+
# Current prediction vector
|
38
|
+
attr_accessor :current_vector
|
39
|
+
|
40
|
+
# Predict certain data
|
41
|
+
#
|
42
|
+
# @param [Array] data data in question
|
43
|
+
# @return [Integer] prediction
|
44
|
+
def predict data
|
45
|
+
classify_bool Matrix.column_vector(data)
|
46
|
+
end
|
47
|
+
|
48
|
+
# The final coefficient of the line
|
49
|
+
#
|
50
|
+
# @return [Array] [a,b,c] for ax+by+c=0 for 2-d case
|
51
|
+
def line
|
52
|
+
current_vector.column(0).to_a
|
53
|
+
end
|
54
|
+
|
55
|
+
protected
|
56
|
+
# Classify with single data with 0/1 error
|
57
|
+
#
|
58
|
+
# @param [Matrix] data input column vector
|
59
|
+
# @return [Integer] classified data
|
60
|
+
def classify_bool data
|
61
|
+
classify_inner(data) <=> 0
|
62
|
+
end
|
63
|
+
|
64
|
+
# Classify with single data with inner product
|
65
|
+
#
|
66
|
+
# @param [Matrix] data input column vector
|
67
|
+
# @return [Integer] classified data
|
68
|
+
def classify_inner data
|
69
|
+
(current_vector.transpose * data)[0,0]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/ml.rb
CHANGED
@@ -1,14 +1,21 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'bundler/setup'
|
3
3
|
|
4
|
+
require 'util/util'
|
5
|
+
|
4
6
|
require 'data/plotter'
|
5
7
|
require 'data/generator'
|
6
8
|
require 'data/parser'
|
7
9
|
|
10
|
+
require 'method/toolbox'
|
11
|
+
|
8
12
|
require 'method/perceptron'
|
9
13
|
require 'method/adaptive_perceptron'
|
10
14
|
require 'method/pocket'
|
11
15
|
require 'method/decision_stump'
|
16
|
+
require 'method/linear_regression'
|
17
|
+
require 'method/logistic_regression'
|
18
|
+
require 'method/cyclic_descent'
|
12
19
|
|
13
20
|
# Top namespace for machine learning algorithms
|
14
21
|
module ML
|
data/lib/util/util.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module ML
|
2
|
+
module Util
|
3
|
+
module_function
|
4
|
+
|
5
|
+
def normal_distribution mean, variance
|
6
|
+
if @y
|
7
|
+
y = @y
|
8
|
+
@y = nil
|
9
|
+
return y
|
10
|
+
end
|
11
|
+
|
12
|
+
theta = 2 * Math::PI * rand
|
13
|
+
rho = Math.sqrt(-2 * Math.log(1 - rand))
|
14
|
+
scale = variance * rho
|
15
|
+
x = mean + scale * Math.cos(theta)
|
16
|
+
@y = mean + scale * Math.sin(theta)
|
17
|
+
x
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/ml.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "ml"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.4.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Andrew Liu"]
|
12
|
-
s.date = "2011-
|
12
|
+
s.date = "2011-12-13"
|
13
13
|
s.description = "Machine learning library in Ruby"
|
14
14
|
s.email = "andrewliu33@gmail.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -27,10 +27,15 @@ Gem::Specification.new do |s|
|
|
27
27
|
"lib/data/parser.rb",
|
28
28
|
"lib/data/plotter.rb",
|
29
29
|
"lib/method/adaptive_perceptron.rb",
|
30
|
+
"lib/method/cyclic_descent.rb",
|
30
31
|
"lib/method/decision_stump.rb",
|
32
|
+
"lib/method/linear_regression.rb",
|
33
|
+
"lib/method/logistic_regression.rb",
|
31
34
|
"lib/method/perceptron.rb",
|
32
35
|
"lib/method/pocket.rb",
|
36
|
+
"lib/method/toolbox.rb",
|
33
37
|
"lib/ml.rb",
|
38
|
+
"lib/util/util.rb",
|
34
39
|
"ml.gemspec",
|
35
40
|
"spec/data_spec.rb",
|
36
41
|
"spec/learner_spec.rb",
|
data/spec/learner_spec.rb
CHANGED
@@ -1,111 +1,32 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe "Learner" do
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
[ML::Learner::PerceptronLearner, ML::Learner::DecisionStumpLearner,
|
5
|
+
ML::Learner::AdaptivePerceptronLearner, ML::Learner::PocketLearner,
|
6
|
+
ML::Learner::LinearRegressionLearner, ML::Learner::CyclicDescentLearner,
|
7
|
+
ML::Learner::LogisticRegressionLearner].each do |method|
|
8
|
+
describe method.to_s do
|
9
|
+
it "should run #{method.to_s} in 2d" do
|
10
|
+
learner = method.new(2)
|
7
11
|
|
8
|
-
|
9
|
-
|
12
|
+
generator = ML::Data::Generator2D.new
|
13
|
+
data = generator.points_2d(100)
|
10
14
|
|
11
|
-
|
12
|
-
error = response[:error]
|
13
|
-
update_count = response[:update_count]
|
15
|
+
learner.train! data
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
line.size.should == 3
|
17
|
+
learner.classify_error(data).should < 0.5
|
18
|
+
end
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
it "should run perceptron learning in hyperspace" do
|
23
|
-
learner = ML::Learner::PerceptronLearner.new(4)
|
24
|
-
|
25
|
-
generator = ML::Data::Generator.new(4)
|
26
|
-
data = generator.points(10, ML::Data::Generator.generate_vector(4))
|
27
|
-
|
28
|
-
response = learner.train! data
|
29
|
-
error = response[:error]
|
30
|
-
update_count = response[:update_count]
|
31
|
-
|
32
|
-
line = learner.line
|
33
|
-
line.should.kind_of?(Array).should == true
|
34
|
-
line.size.should == 5
|
35
|
-
|
36
|
-
update_count.should > 0
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
describe "Adpative Perceptron Learner" do
|
41
|
-
it "should run adaptive perceptron learning in hyperspace" do
|
42
|
-
learner = ML::Learner::AdaptivePerceptronLearner.new(4, 0.1)
|
43
|
-
|
44
|
-
generator = ML::Data::Generator.new(4, 100)
|
45
|
-
data = generator.points(10, ML::Data::Generator.generate_vector(4))
|
46
|
-
|
47
|
-
response = learner.train! data, 1000
|
48
|
-
error = response[:error]
|
49
|
-
update_count = response[:update_count]
|
50
|
-
|
51
|
-
line = learner.line
|
52
|
-
line.should.kind_of?(Array).should == true
|
53
|
-
line.size.should == 5
|
54
|
-
|
55
|
-
update_count.should > 0
|
56
|
-
update_count.should < 1000
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
describe "Pocket Learner" do
|
61
|
-
it "should run pocket perceptron learning in hyperspace" do
|
62
|
-
learner = ML::Learner::PocketLearner.new(4)
|
63
|
-
|
64
|
-
generator = ML::Data::Generator.new(4)
|
65
|
-
data = generator.points(10, ML::Data::Generator.generate_vector(4))
|
66
|
-
|
67
|
-
learner.train! data, 1000
|
68
|
-
|
69
|
-
line = learner.line
|
70
|
-
line.should.kind_of?(Array).should == true
|
71
|
-
line.size.should == 5
|
72
|
-
end
|
73
|
-
|
74
|
-
it "should run pocket perceptron learning in noisy data" do
|
75
|
-
learner = ML::Learner::PocketLearner.new(4)
|
76
|
-
|
77
|
-
generator = ML::Data::Generator.new(4, 1, 0.1)
|
78
|
-
data = generator.points(10, ML::Data::Generator.generate_vector(4))
|
79
|
-
|
80
|
-
learner.train! data, 1000
|
81
|
-
|
82
|
-
line = learner.line
|
83
|
-
line.should.kind_of?(Array).should == true
|
84
|
-
line.size.should == 5
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
describe "Decision Stump Learner" do
|
89
|
-
it "should run decision stump learning in hyperspace" do
|
90
|
-
learner = ML::Learner::DecisionStumpLearner.new(4)
|
91
|
-
|
92
|
-
generator = ML::Data::Generator.new(4)
|
93
|
-
data = generator.points(10, ML::Data::Generator.generate_vector(4))
|
94
|
-
|
95
|
-
learner.train! data
|
96
|
-
vector = learner.error_vector
|
97
|
-
vector.size.should == 4
|
98
|
-
end
|
20
|
+
it "should run #{method.to_s} in hyperspace" do
|
21
|
+
learner = method.new(4)
|
99
22
|
|
100
|
-
|
101
|
-
|
23
|
+
generator = ML::Data::Generator.new(4)
|
24
|
+
data = generator.points(100, ML::Data::Generator.generate_vector(4))
|
102
25
|
|
103
|
-
|
104
|
-
data = generator.points(10, ML::Data::Generator.generate_vector(4))
|
26
|
+
learner.train! data
|
105
27
|
|
106
|
-
|
107
|
-
|
108
|
-
vector.size.should == 4
|
28
|
+
learner.classify_error(data).should < 0.5
|
29
|
+
end
|
109
30
|
end
|
110
31
|
end
|
111
32
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-
|
12
|
+
date: 2011-12-13 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rubyvis
|
16
|
-
requirement: &
|
16
|
+
requirement: &2153078140 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *2153078140
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: nokogiri
|
27
|
-
requirement: &
|
27
|
+
requirement: &2153076840 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *2153076840
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: bacon
|
38
|
-
requirement: &
|
38
|
+
requirement: &2153075100 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *2153075100
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: yard
|
49
|
-
requirement: &
|
49
|
+
requirement: &2153060800 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: 0.6.0
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *2153060800
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: bundler
|
60
|
-
requirement: &
|
60
|
+
requirement: &2153059640 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ~>
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: 1.0.0
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *2153059640
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: jeweler
|
71
|
-
requirement: &
|
71
|
+
requirement: &2153058400 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ~>
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: 1.6.4
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *2153058400
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: rcov
|
82
|
-
requirement: &
|
82
|
+
requirement: &2153056540 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,7 +87,7 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *2153056540
|
91
91
|
description: Machine learning library in Ruby
|
92
92
|
email: andrewliu33@gmail.com
|
93
93
|
executables: []
|
@@ -106,10 +106,15 @@ files:
|
|
106
106
|
- lib/data/parser.rb
|
107
107
|
- lib/data/plotter.rb
|
108
108
|
- lib/method/adaptive_perceptron.rb
|
109
|
+
- lib/method/cyclic_descent.rb
|
109
110
|
- lib/method/decision_stump.rb
|
111
|
+
- lib/method/linear_regression.rb
|
112
|
+
- lib/method/logistic_regression.rb
|
110
113
|
- lib/method/perceptron.rb
|
111
114
|
- lib/method/pocket.rb
|
115
|
+
- lib/method/toolbox.rb
|
112
116
|
- lib/ml.rb
|
117
|
+
- lib/util/util.rb
|
113
118
|
- ml.gemspec
|
114
119
|
- spec/data_spec.rb
|
115
120
|
- spec/learner_spec.rb
|
@@ -129,7 +134,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
129
134
|
version: '0'
|
130
135
|
segments:
|
131
136
|
- 0
|
132
|
-
hash:
|
137
|
+
hash: -1343753565689468056
|
133
138
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
134
139
|
none: false
|
135
140
|
requirements:
|