svmkit 0.3.2 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/HISTORY.md +6 -0
- data/README.md +1 -1
- data/lib/svmkit.rb +2 -0
- data/lib/svmkit/ensemble/random_forest_classifier.rb +1 -1
- data/lib/svmkit/ensemble/random_forest_regressor.rb +1 -2
- data/lib/svmkit/linear_model/lasso.rb +199 -0
- data/lib/svmkit/linear_model/ridge.rb +185 -0
- data/lib/svmkit/linear_model/svr.rb +3 -3
- data/lib/svmkit/polynomial_model/factorization_machine_classifier.rb +1 -1
- data/lib/svmkit/polynomial_model/factorization_machine_regressor.rb +5 -2
- data/lib/svmkit/version.rb +1 -1
- data/svmkit.gemspec +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9c0a64cc46c00a252946033b072b4d9498fb4d5cf7131830333483a336c29315
|
4
|
+
data.tar.gz: 1eb9415f08167772764f1eba4e67f6a3479768db75efcc32a8de85276440d41c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2f994dad593e5b752c2a062507f849483a9e4dbdd90190313b672c2f8cd9c9ed102b2fc088823665812f44e6b549bc67cab7d16fb545031bae0b57e713c3c3c3
|
7
|
+
data.tar.gz: d6da2f56721b8d264898fea922e2bee016987d898b4169f12bc6963044b69a4952f25d1b75380a93ce1fccd9854bb86e085c18fdf9535e273bd2eb1a328d3b98
|
data/HISTORY.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
# 0.3.3
|
2
|
+
- Add class for Ridge regressor.
|
3
|
+
- Add class for Lasso regressor.
|
4
|
+
- Fix bug on gradient calculation of FactorizationMachineRegressor.
|
5
|
+
- Fix some documents.
|
6
|
+
|
1
7
|
# 0.3.2
|
2
8
|
- Add class for Factorization Machine regressor.
|
3
9
|
- Add class for Decision Tree regressor.
|
data/README.md
CHANGED
@@ -8,7 +8,7 @@
|
|
8
8
|
SVMKit is a machine learninig library in Ruby.
|
9
9
|
SVMKit provides machine learning algorithms with interfaces similar to Scikit-Learn in Python.
|
10
10
|
SVMKit currently supports Linear / Kernel Support Vector Machine,
|
11
|
-
Logistic Regression, Factorization Machine, Naive Bayes, Decision Tree, Random Forest,
|
11
|
+
Logistic Regression, Ridge, Lasso, Factorization Machine, Naive Bayes, Decision Tree, Random Forest,
|
12
12
|
K-nearest neighbor classifier, and cross-validation.
|
13
13
|
|
14
14
|
## Installation
|
data/lib/svmkit.rb
CHANGED
@@ -17,6 +17,8 @@ require 'svmkit/kernel_approximation/rbf'
|
|
17
17
|
require 'svmkit/linear_model/svc'
|
18
18
|
require 'svmkit/linear_model/svr'
|
19
19
|
require 'svmkit/linear_model/logistic_regression'
|
20
|
+
require 'svmkit/linear_model/ridge'
|
21
|
+
require 'svmkit/linear_model/lasso'
|
20
22
|
require 'svmkit/kernel_machine/kernel_svc'
|
21
23
|
require 'svmkit/polynomial_model/factorization_machine_classifier'
|
22
24
|
require 'svmkit/polynomial_model/factorization_machine_regressor'
|
@@ -155,7 +155,7 @@ module SVMKit
|
|
155
155
|
end
|
156
156
|
|
157
157
|
# Dump marshal data.
|
158
|
-
# @return [Hash] The marshal data about RandomForestClassifier
|
158
|
+
# @return [Hash] The marshal data about RandomForestClassifier.
|
159
159
|
def marshal_dump
|
160
160
|
{ params: @params, estimators: @estimators, classes: @classes,
|
161
161
|
feature_importances: @feature_importances, rng: @rng }
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'pp'
|
4
3
|
require 'svmkit/validation'
|
5
4
|
require 'svmkit/base/base_estimator'
|
6
5
|
require 'svmkit/base/regressor'
|
@@ -119,7 +118,7 @@ module SVMKit
|
|
119
118
|
end
|
120
119
|
|
121
120
|
# Dump marshal data.
|
122
|
-
# @return [Hash] The marshal data about RandomForestRegressor
|
121
|
+
# @return [Hash] The marshal data about RandomForestRegressor.
|
123
122
|
def marshal_dump
|
124
123
|
{ params: @params,
|
125
124
|
estimators: @estimators,
|
@@ -0,0 +1,199 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'svmkit/validation'
|
4
|
+
require 'svmkit/base/base_estimator'
|
5
|
+
require 'svmkit/base/regressor'
|
6
|
+
|
7
|
+
module SVMKit
|
8
|
+
module LinearModel
|
9
|
+
# Lasso is a class that implements Lasso Regression
|
10
|
+
# with stochastic gradient descent (SGD) optimization.
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
# estimator =
|
14
|
+
# SVMKit::LinearModel::Lasso.new(reg_param: 0.1, max_iter: 5000, batch_size: 50, random_seed: 1)
|
15
|
+
# estimator.fit(training_samples, traininig_values)
|
16
|
+
# results = estimator.predict(testing_samples)
|
17
|
+
#
|
18
|
+
# *Reference*
|
19
|
+
# - S. Shalev-Shwartz and Y. Singer, "Pegasos: Primal Estimated sub-GrAdient SOlver for SVM," Proc. ICML'07, pp. 807--814, 2007.
|
20
|
+
# - L. Bottou, "Large-Scale Machine Learning with Stochastic Gradient Descent," Proc. COMPSTAT'10, pp. 177--186, 2010.
|
21
|
+
# - I. Sutskever, J. Martens, G. Dahl, and G. Hinton, "On the importance of initialization and momentum in deep learning," Proc. ICML'13, pp. 1139--1147, 2013.
|
22
|
+
# - G. Hinton, N. Srivastava, and K. Swersky, "Lecture 6e rmsprop," Neural Networks for Machine Learning, 2012.
|
23
|
+
class Lasso
|
24
|
+
include Base::BaseEstimator
|
25
|
+
include Base::Regressor
|
26
|
+
include Validation
|
27
|
+
|
28
|
+
# Return the weight vector.
|
29
|
+
# @return [Numo::DFloat] (shape: [n_outputs, n_features])
|
30
|
+
attr_reader :weight_vec
|
31
|
+
|
32
|
+
# Return the bias term (a.k.a. intercept).
|
33
|
+
# @return [Numo::DFloat] (shape: [n_outputs])
|
34
|
+
attr_reader :bias_term
|
35
|
+
|
36
|
+
# Return the random generator for random sampling.
|
37
|
+
# @return [Random]
|
38
|
+
attr_reader :rng
|
39
|
+
|
40
|
+
# Create a new Lasso regressor.
|
41
|
+
#
|
42
|
+
# @param reg_param [Float] The regularization parameter.
|
43
|
+
# @param fit_bias [Boolean] The flag indicating whether to fit the bias term.
|
44
|
+
# @param learning_rate [Float] The learning rate for optimization.
|
45
|
+
# @param decay [Float] The discounting factor for RMS prop optimization.
|
46
|
+
# @param momentum [Float] The momentum for optimization.
|
47
|
+
# @param max_iter [Integer] The maximum number of iterations.
|
48
|
+
# @param batch_size [Integer] The size of the mini batches.
|
49
|
+
# @param random_seed [Integer] The seed value using to initialize the random generator.
|
50
|
+
def initialize(reg_param: 1.0, fit_bias: false, learning_rate: 0.01, decay: 0.9, momentum: 0.9,
|
51
|
+
max_iter: 1000, batch_size: 10, random_seed: nil)
|
52
|
+
check_params_float(reg_param: reg_param,
|
53
|
+
learning_rate: learning_rate, decay: decay, momentum: momentum)
|
54
|
+
check_params_integer(max_iter: max_iter, batch_size: batch_size)
|
55
|
+
check_params_boolean(fit_bias: fit_bias)
|
56
|
+
check_params_type_or_nil(Integer, random_seed: random_seed)
|
57
|
+
check_params_positive(reg_param: reg_param,
|
58
|
+
learning_rate: learning_rate, decay: decay, momentum: momentum,
|
59
|
+
max_iter: max_iter, batch_size: batch_size)
|
60
|
+
@params = {}
|
61
|
+
@params[:reg_param] = reg_param
|
62
|
+
@params[:fit_bias] = fit_bias
|
63
|
+
@params[:learning_rate] = learning_rate
|
64
|
+
@params[:decay] = decay
|
65
|
+
@params[:momentum] = momentum
|
66
|
+
@params[:max_iter] = max_iter
|
67
|
+
@params[:batch_size] = batch_size
|
68
|
+
@params[:random_seed] = random_seed
|
69
|
+
@params[:random_seed] ||= srand
|
70
|
+
@weight_vec = nil
|
71
|
+
@bias_term = nil
|
72
|
+
@rng = Random.new(@params[:random_seed])
|
73
|
+
end
|
74
|
+
|
75
|
+
# Fit the model with given training data.
|
76
|
+
#
|
77
|
+
# @param x [Numo::DFloat] (shape: [n_samples, n_features]) The training data to be used for fitting the model.
|
78
|
+
# @param y [Numo::Int32] (shape: [n_samples, n_outputs]) The target values to be used for fitting the model.
|
79
|
+
# @return [Lasso] The learned regressor itself.
|
80
|
+
def fit(x, y)
|
81
|
+
check_sample_array(x)
|
82
|
+
check_tvalue_array(y)
|
83
|
+
check_sample_tvalue_size(x, y)
|
84
|
+
|
85
|
+
n_outputs = y.shape[1].nil? ? 1 : y.shape[1]
|
86
|
+
_n_samples, n_features = x.shape
|
87
|
+
|
88
|
+
if n_outputs > 1
|
89
|
+
@weight_vec = Numo::DFloat.zeros(n_outputs, n_features)
|
90
|
+
@bias_term = Numo::DFloat.zeros(n_outputs)
|
91
|
+
n_outputs.times do |n|
|
92
|
+
weight, bias = single_fit(x, y[true, n])
|
93
|
+
@weight_vec[n, true] = weight
|
94
|
+
@bias_term[n] = bias
|
95
|
+
end
|
96
|
+
else
|
97
|
+
@weight_vec, @bias_term = single_fit(x, y)
|
98
|
+
end
|
99
|
+
|
100
|
+
self
|
101
|
+
end
|
102
|
+
|
103
|
+
# Predict values for samples.
|
104
|
+
#
|
105
|
+
# @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to predict the values.
|
106
|
+
# @return [Numo::DFloat] (shape: [n_samples, n_outputs]) Predicted values per sample.
|
107
|
+
def predict(x)
|
108
|
+
check_sample_array(x)
|
109
|
+
x.dot(@weight_vec.transpose) + @bias_term
|
110
|
+
end
|
111
|
+
|
112
|
+
# Dump marshal data.
|
113
|
+
# @return [Hash] The marshal data about Lasso.
|
114
|
+
def marshal_dump
|
115
|
+
{ params: @params,
|
116
|
+
weight_vec: @weight_vec,
|
117
|
+
bias_term: @bias_term,
|
118
|
+
rng: @rng }
|
119
|
+
end
|
120
|
+
|
121
|
+
# Load marshal data.
|
122
|
+
# @return [nil]
|
123
|
+
def marshal_load(obj)
|
124
|
+
@params = obj[:params]
|
125
|
+
@weight_vec = obj[:weight_vec]
|
126
|
+
@bias_term = obj[:bias_term]
|
127
|
+
@rng = obj[:rng]
|
128
|
+
nil
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
132
|
+
|
133
|
+
def single_fit(x, y)
|
134
|
+
# Expand feature vectors for bias term.
|
135
|
+
samples = @params[:fit_bias] ? expand_feature(x) : x
|
136
|
+
# Initialize some variables.
|
137
|
+
n_samples, n_features = samples.shape
|
138
|
+
rand_ids = [*0...n_samples].shuffle(random: @rng)
|
139
|
+
weight_vec = Numo::DFloat.zeros(n_features)
|
140
|
+
left_weight_vec = Numo::DFloat.zeros(n_features)
|
141
|
+
left_weight_sqrsum = Numo::DFloat.zeros(n_features)
|
142
|
+
left_weight_update = Numo::DFloat.zeros(n_features)
|
143
|
+
right_weight_vec = Numo::DFloat.zeros(n_features)
|
144
|
+
right_weight_sqrsum = Numo::DFloat.zeros(n_features)
|
145
|
+
right_weight_update = Numo::DFloat.zeros(n_features)
|
146
|
+
# Start optimization.
|
147
|
+
@params[:max_iter].times do |_t|
|
148
|
+
# Random sampling.
|
149
|
+
subset_ids = rand_ids.shift(@params[:batch_size])
|
150
|
+
rand_ids.concat(subset_ids)
|
151
|
+
data = samples[subset_ids, true]
|
152
|
+
values = y[subset_ids]
|
153
|
+
# Calculate gradients for loss function.
|
154
|
+
loss_grad = loss_gradient(data, values, weight_vec)
|
155
|
+
next if loss_grad.ne(0.0).count.zero?
|
156
|
+
# Update weight.
|
157
|
+
left_weight_vec, left_weight_sqrsum, left_weight_update =
|
158
|
+
update_weight(left_weight_vec, left_weight_sqrsum, left_weight_update,
|
159
|
+
left_weight_gradient(loss_grad, data))
|
160
|
+
right_weight_vec, right_weight_sqrsum, right_weight_update =
|
161
|
+
update_weight(right_weight_vec, right_weight_sqrsum, right_weight_update,
|
162
|
+
right_weight_gradient(loss_grad, data))
|
163
|
+
weight_vec = left_weight_vec - right_weight_vec
|
164
|
+
end
|
165
|
+
split_weight_vec_bias(weight_vec)
|
166
|
+
end
|
167
|
+
|
168
|
+
def loss_gradient(x, y, weight)
|
169
|
+
2.0 * (x.dot(weight) - y)
|
170
|
+
end
|
171
|
+
|
172
|
+
def left_weight_gradient(loss_grad, data)
|
173
|
+
((@params[:reg_param] + loss_grad).expand_dims(1) * data).mean(0)
|
174
|
+
end
|
175
|
+
|
176
|
+
def right_weight_gradient(loss_grad, data)
|
177
|
+
((@params[:reg_param] - loss_grad).expand_dims(1) * data).mean(0)
|
178
|
+
end
|
179
|
+
|
180
|
+
def update_weight(weight, sqrsum, update, gr)
|
181
|
+
new_sqrsum = @params[:decay] * sqrsum + (1.0 - @params[:decay]) * gr**2
|
182
|
+
new_update = (@params[:learning_rate] / ((new_sqrsum + 1.0e-8)**0.5)) * gr
|
183
|
+
new_weight = weight - (new_update + @params[:momentum] * update)
|
184
|
+
new_weight = 0.5 * (new_weight + new_weight.abs)
|
185
|
+
[new_weight, new_sqrsum, new_update]
|
186
|
+
end
|
187
|
+
|
188
|
+
def expand_feature(x)
|
189
|
+
Numo::NArray.hstack([x, Numo::DFloat.ones([x.shape[0], 1])])
|
190
|
+
end
|
191
|
+
|
192
|
+
def split_weight_vec_bias(weight_vec)
|
193
|
+
weights = @params[:fit_bias] ? weight_vec[0...-1] : weight_vec
|
194
|
+
bias = @params[:fit_bias] ? weight_vec[-1] : 0.0
|
195
|
+
[weights, bias]
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
@@ -0,0 +1,185 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'svmkit/validation'
|
4
|
+
require 'svmkit/base/base_estimator'
|
5
|
+
require 'svmkit/base/regressor'
|
6
|
+
|
7
|
+
module SVMKit
|
8
|
+
module LinearModel
|
9
|
+
# Ridge is a class that implements Ridge Regression
|
10
|
+
# with stochastic gradient descent (SGD) optimization.
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
# estimator =
|
14
|
+
# SVMKit::LinearModel::Ridge.new(reg_param: 0.1, max_iter: 5000, batch_size: 50, random_seed: 1)
|
15
|
+
# estimator.fit(training_samples, traininig_values)
|
16
|
+
# results = estimator.predict(testing_samples)
|
17
|
+
#
|
18
|
+
# *Reference*
|
19
|
+
# - S. Shalev-Shwartz and Y. Singer, "Pegasos: Primal Estimated sub-GrAdient SOlver for SVM," Proc. ICML'07, pp. 807--814, 2007.
|
20
|
+
# - I. Sutskever, J. Martens, G. Dahl, and G. Hinton, "On the importance of initialization and momentum in deep learning," Proc. ICML'13, pp. 1139--1147, 2013.
|
21
|
+
# - G. Hinton, N. Srivastava, and K. Swersky, "Lecture 6e rmsprop," Neural Networks for Machine Learning, 2012.
|
22
|
+
class Ridge
|
23
|
+
include Base::BaseEstimator
|
24
|
+
include Base::Regressor
|
25
|
+
include Validation
|
26
|
+
|
27
|
+
# Return the weight vector.
|
28
|
+
# @return [Numo::DFloat] (shape: [n_outputs, n_features])
|
29
|
+
attr_reader :weight_vec
|
30
|
+
|
31
|
+
# Return the bias term (a.k.a. intercept).
|
32
|
+
# @return [Numo::DFloat] (shape: [n_outputs])
|
33
|
+
attr_reader :bias_term
|
34
|
+
|
35
|
+
# Return the random generator for random sampling.
|
36
|
+
# @return [Random]
|
37
|
+
attr_reader :rng
|
38
|
+
|
39
|
+
# Create a new Ridge regressor.
|
40
|
+
#
|
41
|
+
# @param reg_param [Float] The regularization parameter.
|
42
|
+
# @param fit_bias [Boolean] The flag indicating whether to fit the bias term.
|
43
|
+
# @param learning_rate [Float] The learning rate for optimization.
|
44
|
+
# @param decay [Float] The discounting factor for RMS prop optimization.
|
45
|
+
# @param momentum [Float] The Nesterov momentum for optimization.
|
46
|
+
# @param max_iter [Integer] The maximum number of iterations.
|
47
|
+
# @param batch_size [Integer] The size of the mini batches.
|
48
|
+
# @param random_seed [Integer] The seed value using to initialize the random generator.
|
49
|
+
def initialize(reg_param: 1.0, fit_bias: false, learning_rate: 0.01, decay: 0.9, momentum: 0.9,
|
50
|
+
max_iter: 1000, batch_size: 10, random_seed: nil)
|
51
|
+
check_params_float(reg_param: reg_param,
|
52
|
+
learning_rate: learning_rate, decay: decay, momentum: momentum)
|
53
|
+
check_params_integer(max_iter: max_iter, batch_size: batch_size)
|
54
|
+
check_params_boolean(fit_bias: fit_bias)
|
55
|
+
check_params_type_or_nil(Integer, random_seed: random_seed)
|
56
|
+
check_params_positive(reg_param: reg_param,
|
57
|
+
learning_rate: learning_rate, decay: decay, momentum: momentum,
|
58
|
+
max_iter: max_iter, batch_size: batch_size)
|
59
|
+
@params = {}
|
60
|
+
@params[:reg_param] = reg_param
|
61
|
+
@params[:fit_bias] = fit_bias
|
62
|
+
@params[:learning_rate] = learning_rate
|
63
|
+
@params[:decay] = decay
|
64
|
+
@params[:momentum] = momentum
|
65
|
+
@params[:max_iter] = max_iter
|
66
|
+
@params[:batch_size] = batch_size
|
67
|
+
@params[:random_seed] = random_seed
|
68
|
+
@params[:random_seed] ||= srand
|
69
|
+
@weight_vec = nil
|
70
|
+
@bias_term = nil
|
71
|
+
@rng = Random.new(@params[:random_seed])
|
72
|
+
end
|
73
|
+
|
74
|
+
# Fit the model with given training data.
|
75
|
+
#
|
76
|
+
# @param x [Numo::DFloat] (shape: [n_samples, n_features]) The training data to be used for fitting the model.
|
77
|
+
# @param y [Numo::Int32] (shape: [n_samples, n_outputs]) The target values to be used for fitting the model.
|
78
|
+
# @return [Ridge] The learned regressor itself.
|
79
|
+
def fit(x, y)
|
80
|
+
check_sample_array(x)
|
81
|
+
check_tvalue_array(y)
|
82
|
+
check_sample_tvalue_size(x, y)
|
83
|
+
|
84
|
+
n_outputs = y.shape[1].nil? ? 1 : y.shape[1]
|
85
|
+
_n_samples, n_features = x.shape
|
86
|
+
|
87
|
+
if n_outputs > 1
|
88
|
+
@weight_vec = Numo::DFloat.zeros(n_outputs, n_features)
|
89
|
+
@bias_term = Numo::DFloat.zeros(n_outputs)
|
90
|
+
n_outputs.times do |n|
|
91
|
+
weight, bias = single_fit(x, y[true, n])
|
92
|
+
@weight_vec[n, true] = weight
|
93
|
+
@bias_term[n] = bias
|
94
|
+
end
|
95
|
+
else
|
96
|
+
@weight_vec, @bias_term = single_fit(x, y)
|
97
|
+
end
|
98
|
+
|
99
|
+
self
|
100
|
+
end
|
101
|
+
|
102
|
+
# Predict values for samples.
|
103
|
+
#
|
104
|
+
# @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to predict the values.
|
105
|
+
# @return [Numo::DFloat] (shape: [n_samples, n_outputs]) Predicted values per sample.
|
106
|
+
def predict(x)
|
107
|
+
check_sample_array(x)
|
108
|
+
x.dot(@weight_vec.transpose) + @bias_term
|
109
|
+
end
|
110
|
+
|
111
|
+
# Dump marshal data.
|
112
|
+
# @return [Hash] The marshal data about Ridge.
|
113
|
+
def marshal_dump
|
114
|
+
{ params: @params,
|
115
|
+
weight_vec: @weight_vec,
|
116
|
+
bias_term: @bias_term,
|
117
|
+
rng: @rng }
|
118
|
+
end
|
119
|
+
|
120
|
+
# Load marshal data.
|
121
|
+
# @return [nil]
|
122
|
+
def marshal_load(obj)
|
123
|
+
@params = obj[:params]
|
124
|
+
@weight_vec = obj[:weight_vec]
|
125
|
+
@bias_term = obj[:bias_term]
|
126
|
+
@rng = obj[:rng]
|
127
|
+
nil
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
|
132
|
+
def single_fit(x, y)
|
133
|
+
# Expand feature vectors for bias term.
|
134
|
+
samples = @params[:fit_bias] ? expand_feature(x) : x
|
135
|
+
# Initialize some variables.
|
136
|
+
n_samples, n_features = samples.shape
|
137
|
+
rand_ids = [*0...n_samples].shuffle(random: @rng)
|
138
|
+
weight_vec = Numo::DFloat.zeros(n_features)
|
139
|
+
weight_sqrsum = Numo::DFloat.zeros(n_features)
|
140
|
+
weight_update = Numo::DFloat.zeros(n_features)
|
141
|
+
# Start optimization.
|
142
|
+
@params[:max_iter].times do |_t|
|
143
|
+
# Random sampling.
|
144
|
+
subset_ids = rand_ids.shift(@params[:batch_size])
|
145
|
+
rand_ids.concat(subset_ids)
|
146
|
+
data = samples[subset_ids, true]
|
147
|
+
values = y[subset_ids]
|
148
|
+
# Calculate gradients for loss function.
|
149
|
+
loss_grad = loss_gradient(data, values, weight_vec - @params[:momentum] * weight_update)
|
150
|
+
next if loss_grad.ne(0.0).count.zero?
|
151
|
+
# Update weight.
|
152
|
+
weight_vec, weight_sqrsum, weight_update =
|
153
|
+
update_weight(weight_vec, weight_sqrsum, weight_update,
|
154
|
+
weight_gradient(loss_grad, data, weight_vec - @params[:momentum] * weight_update))
|
155
|
+
end
|
156
|
+
split_weight_vec_bias(weight_vec)
|
157
|
+
end
|
158
|
+
|
159
|
+
def loss_gradient(x, y, weight)
|
160
|
+
2.0 * (x.dot(weight) - y)
|
161
|
+
end
|
162
|
+
|
163
|
+
def weight_gradient(loss_grad, data, weight)
|
164
|
+
(loss_grad.expand_dims(1) * data).mean(0) + @params[:reg_param] * weight
|
165
|
+
end
|
166
|
+
|
167
|
+
def update_weight(weight, sqrsum, update, gr)
|
168
|
+
new_sqrsum = @params[:decay] * sqrsum + (1.0 - @params[:decay]) * gr**2
|
169
|
+
new_update = (@params[:learning_rate] / ((new_sqrsum + 1.0e-8)**0.5)) * gr
|
170
|
+
new_weight = weight - (new_update + @params[:momentum] * update)
|
171
|
+
[new_weight, new_sqrsum, new_update]
|
172
|
+
end
|
173
|
+
|
174
|
+
def expand_feature(x)
|
175
|
+
Numo::NArray.hstack([x, Numo::DFloat.ones([x.shape[0], 1])])
|
176
|
+
end
|
177
|
+
|
178
|
+
def split_weight_vec_bias(weight_vec)
|
179
|
+
weights = @params[:fit_bias] ? weight_vec[0...-1] : weight_vec
|
180
|
+
bias = @params[:fit_bias] ? weight_vec[-1] : 0.0
|
181
|
+
[weights, bias]
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
@@ -21,11 +21,11 @@ module SVMKit
|
|
21
21
|
include Base::BaseEstimator
|
22
22
|
include Base::Regressor
|
23
23
|
|
24
|
-
# Return the weight vector for
|
24
|
+
# Return the weight vector for SVR.
|
25
25
|
# @return [Numo::DFloat] (shape: [n_outputs, n_features])
|
26
26
|
attr_reader :weight_vec
|
27
27
|
|
28
|
-
# Return the bias term (a.k.a. intercept) for
|
28
|
+
# Return the bias term (a.k.a. intercept) for SVR.
|
29
29
|
# @return [Numo::DFloat] (shape: [n_outputs])
|
30
30
|
attr_reader :bias_term
|
31
31
|
|
@@ -104,7 +104,7 @@ module SVMKit
|
|
104
104
|
end
|
105
105
|
|
106
106
|
# Dump marshal data.
|
107
|
-
# @return [Hash] The marshal data about
|
107
|
+
# @return [Hash] The marshal data about SVR.
|
108
108
|
def marshal_dump
|
109
109
|
{ params: @params,
|
110
110
|
weight_vec: @weight_vec,
|
@@ -164,7 +164,7 @@ module SVMKit
|
|
164
164
|
end
|
165
165
|
|
166
166
|
# Dump marshal data.
|
167
|
-
# @return [Hash] The marshal data about FactorizationMachineClassifier
|
167
|
+
# @return [Hash] The marshal data about FactorizationMachineClassifier.
|
168
168
|
def marshal_dump
|
169
169
|
{ params: @params,
|
170
170
|
factor_mat: @factor_mat,
|
@@ -134,7 +134,7 @@ module SVMKit
|
|
134
134
|
end
|
135
135
|
|
136
136
|
# Dump marshal data.
|
137
|
-
# @return [Hash] The marshal data about FactorizationMachineRegressor
|
137
|
+
# @return [Hash] The marshal data about FactorizationMachineRegressor.
|
138
138
|
def marshal_dump
|
139
139
|
{ params: @params,
|
140
140
|
factor_mat: @factor_mat,
|
@@ -177,7 +177,10 @@ module SVMKit
|
|
177
177
|
data = x[subset_ids, true]
|
178
178
|
values = y[subset_ids]
|
179
179
|
# Calculate gradients for loss function.
|
180
|
-
loss_grad = loss_gradient(data, values,
|
180
|
+
loss_grad = loss_gradient(data, values,
|
181
|
+
factor_mat - @params[:momentum] * factor_update,
|
182
|
+
weight_vec - @params[:momentum] * weight_update,
|
183
|
+
bias_term - @params[:momentum] * bias_update)
|
181
184
|
next if loss_grad.ne(0.0).count.zero?
|
182
185
|
# Update each parameter.
|
183
186
|
bias_term, bias_sqrsum, bias_update =
|
data/lib/svmkit/version.rb
CHANGED
data/svmkit.gemspec
CHANGED
@@ -17,7 +17,7 @@ MSG
|
|
17
17
|
SVMKit is a machine learninig library in Ruby.
|
18
18
|
SVMKit provides machine learning algorithms with interfaces similar to Scikit-Learn in Python.
|
19
19
|
SVMKit currently supports Linear / Kernel Support Vector Machine,
|
20
|
-
Logistic Regression, Factorization Machine, Naive Bayes, Decision Tree, Random Forest,
|
20
|
+
Logistic Regression, Ridge, Lasso, Factorization Machine, Naive Bayes, Decision Tree, Random Forest,
|
21
21
|
K-nearest neighbor algorithm, and cross-validation.
|
22
22
|
MSG
|
23
23
|
spec.homepage = 'https://github.com/yoshoku/svmkit'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: svmkit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- yoshoku
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-05-
|
11
|
+
date: 2018-05-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: numo-narray
|
@@ -84,7 +84,7 @@ description: |
|
|
84
84
|
SVMKit is a machine learninig library in Ruby.
|
85
85
|
SVMKit provides machine learning algorithms with interfaces similar to Scikit-Learn in Python.
|
86
86
|
SVMKit currently supports Linear / Kernel Support Vector Machine,
|
87
|
-
Logistic Regression, Factorization Machine, Naive Bayes, Decision Tree, Random Forest,
|
87
|
+
Logistic Regression, Ridge, Lasso, Factorization Machine, Naive Bayes, Decision Tree, Random Forest,
|
88
88
|
K-nearest neighbor algorithm, and cross-validation.
|
89
89
|
email:
|
90
90
|
- yoshoku@outlook.com
|
@@ -127,7 +127,9 @@ files:
|
|
127
127
|
- lib/svmkit/evaluation_measure/recall.rb
|
128
128
|
- lib/svmkit/kernel_approximation/rbf.rb
|
129
129
|
- lib/svmkit/kernel_machine/kernel_svc.rb
|
130
|
+
- lib/svmkit/linear_model/lasso.rb
|
130
131
|
- lib/svmkit/linear_model/logistic_regression.rb
|
132
|
+
- lib/svmkit/linear_model/ridge.rb
|
131
133
|
- lib/svmkit/linear_model/svc.rb
|
132
134
|
- lib/svmkit/linear_model/svr.rb
|
133
135
|
- lib/svmkit/model_selection/cross_validation.rb
|