svmkit 0.2.3 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6271a50754a13199f7c3c12c6f1b9e2a0a2075d5
4
- data.tar.gz: ecdc84a2987f22d49ad1b8435397862771f96f37
3
+ metadata.gz: 22a165e3fa579d5a5d0dbd9095d208dd09d5fbd0
4
+ data.tar.gz: c3f7fa2f4fe115dc821ec5050cf7c1f0fdd75a36
5
5
  SHA512:
6
- metadata.gz: 9974eb62cd19ebca32ca92cafbcbf2e34a978d41c0aa9bb0765c001d56963189aa43f71806fa5a2492a4b3e50bcd939a018aa784198f5aef08e2159682682dd2
7
- data.tar.gz: eee0f089449a71f79576165aa083c41fe1d9812fcc251c31c2a5c7cf06e6dfd4293dddd6685fa6285c8d89a3744bb3a72bd9db6f36b7cbc586b7a71800c1fb78
6
+ metadata.gz: 4002a03944871f2fd9cf305fd64b02d4a1899b291167289d2f78112f977c54b33fc60041b2d2c506d755fb938e4d226002b1d6dc41ea74ad28d0e215adc0ee2b
7
+ data.tar.gz: 59dc53541aee6832ea66b826cc5f92e1329adba108aa2683ddba9105d8ac28fba7fae483ce1d2c092c60d83e9d3b3adfb574bf11401ad74f24435f237d262871
data/.rubocop.yml CHANGED
@@ -9,6 +9,7 @@ Metrics/AbcSize:
9
9
 
10
10
  Metrics/LineLength:
11
11
  Max: 120
12
+ IgnoredPatterns: ['(\A|\s)#']
12
13
 
13
14
  Metrics/ModuleLength:
14
15
  Max: 200
data/HISTORY.md CHANGED
@@ -1,3 +1,8 @@
1
+ # 0.2.4
2
+ - Added class for Factorization Machine classifier.
3
+ - Added classes for evaluation measures.
4
+ - Fixed the method for prediction of class probability in Logistic Regression.
5
+
1
6
  # 0.2.3
2
7
  - Added class for cross validation.
3
8
  - Added specs for base modules.
data/README.md CHANGED
@@ -4,9 +4,11 @@
4
4
  [![Gem Version](https://badge.fury.io/rb/svmkit.svg)](https://badge.fury.io/rb/svmkit)
5
5
  [![BSD 2-Clause License](https://img.shields.io/badge/License-BSD%202--Clause-orange.svg)](https://github.com/yoshoku/SVMKit/blob/master/LICENSE.txt)
6
6
 
7
- SVMKit is a library for machine learninig in Ruby.
8
- SVMKit implements machine learning algorithms with an interface similar to Scikit-Learn in Python.
9
- However, since SVMKit is an experimental library, there are few machine learning algorithms implemented.
7
+ SVMKit is a machine learninig library in Ruby.
8
+ SVMKit implements machine learning algorithms with interfaces similar to Scikit-Learn in Python.
9
+ Since the development of SVMKit has just getting started,
10
+ the methods implemented in SVMKit are only Linear / Kernel SVC,
11
+ Logistic Regression, Factorization Machine, K-nearest neighbor classifier, and cross-validation.
10
12
 
11
13
  ## Installation
12
14
 
@@ -0,0 +1,12 @@
1
+
2
+ module SVMKit
3
+ module Base
4
+ # Module for all evaluation measures in SVMKit.
5
+ module Evaluator
6
+ # An abstract method for evaluation of model.
7
+ def score
8
+ raise NotImplementedError, "#{__method__} has to be implemented in #{self.class}."
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,24 @@
1
+ require 'svmkit/base/evaluator'
2
+
3
+ module SVMKit
4
+ # This module consists of the classes for model evaluation.
5
+ module EvaluationMeasure
6
+ # Accuracy is a class that calculates the accuracy of classifier from the predicted labels.
7
+ #
8
+ # @example
9
+ # evaluator = SVMKit::EvaluationMeasure::Accuracy.new
10
+ # puts evaluator.score(ground_truth, predicted)
11
+ class Accuracy
12
+ include Base::Evaluator
13
+
14
+ # Claculate mean accuracy.
15
+ #
16
+ # @param y_true [Numo::Int32] (shape: [n_samples]) Ground truth labels.
17
+ # @param y_pred [Numo::Int32] (shape: [n_samples]) Predicted labels.
18
+ # @return [Float] Mean accuracy
19
+ def score(y_true, y_pred)
20
+ (y_true.to_a.map.with_index { |label, n| label == y_pred[n] ? 1 : 0 }).inject(:+) / y_true.size.to_f
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,44 @@
1
+ require 'svmkit/base/evaluator'
2
+ require 'svmkit/evaluation_measure/precision_recall'
3
+
4
+ module SVMKit
5
+ # This module consists of the classes for model evaluation.
6
+ module EvaluationMeasure
7
+ # FScore is a class that calculates the F1-score of the predicted labels.
8
+ #
9
+ # @example
10
+ # evaluator = SVMKit::EvaluationMeasure::FScore.new
11
+ # puts evaluator.score(ground_truth, predicted)
12
+ class FScore
13
+ include Base::Evaluator
14
+ include EvaluationMeasure::PrecisionRecall
15
+
16
+ # Return the average type for calculation of F1-score.
17
+ # @return [String] ('binary', 'micro', 'macro')
18
+ attr_reader :average
19
+
20
+ # Create a new evaluation measure calculater for F1-score.
21
+ #
22
+ # @param average [String] The average type ('binary', 'micro', 'macro')
23
+ def initialize(average: 'binary')
24
+ @average = average
25
+ end
26
+
27
+ # Claculate average F1-score
28
+ #
29
+ # @param y_true [Numo::Int32] (shape: [n_samples]) Ground truth labels.
30
+ # @param y_pred [Numo::Int32] (shape: [n_samples]) Predicted labels.
31
+ # @return [Float] Average F1-score
32
+ def score(y_true, y_pred)
33
+ case @average
34
+ when 'binary'
35
+ f_score_each_class(y_true, y_pred).last
36
+ when 'micro'
37
+ micro_average_f_score(y_true, y_pred)
38
+ when 'macro'
39
+ macro_average_f_score(y_true, y_pred)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,44 @@
1
+ require 'svmkit/base/evaluator'
2
+ require 'svmkit/evaluation_measure/precision_recall'
3
+
4
+ module SVMKit
5
+ # This module consists of the classes for model evaluation.
6
+ module EvaluationMeasure
7
+ # Precision is a class that calculates the preicision of the predicted labels.
8
+ #
9
+ # @example
10
+ # evaluator = SVMKit::EvaluationMeasure::Precision.new
11
+ # puts evaluator.score(ground_truth, predicted)
12
+ class Precision
13
+ include Base::Evaluator
14
+ include EvaluationMeasure::PrecisionRecall
15
+
16
+ # Return the average type for calculation of precision.
17
+ # @return [String] ('binary', 'micro', 'macro')
18
+ attr_reader :average
19
+
20
+ # Create a new evaluation measure calculater for precision score.
21
+ #
22
+ # @param average [String] The average type ('binary', 'micro', 'macro')
23
+ def initialize(average: 'binary')
24
+ @average = average
25
+ end
26
+
27
+ # Claculate average precision.
28
+ #
29
+ # @param y_true [Numo::Int32] (shape: [n_samples]) Ground truth labels.
30
+ # @param y_pred [Numo::Int32] (shape: [n_samples]) Predicted labels.
31
+ # @return [Float] Average precision
32
+ def score(y_true, y_pred)
33
+ case @average
34
+ when 'binary'
35
+ precision_each_class(y_true, y_pred).last
36
+ when 'micro'
37
+ micro_average_precision(y_true, y_pred)
38
+ when 'macro'
39
+ macro_average_precision(y_true, y_pred)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,89 @@
1
+ require 'svmkit/base/evaluator'
2
+
3
+ module SVMKit
4
+ # This module consists of the classes for model evaluation.
5
+ module EvaluationMeasure
6
+ # @!visibility private
7
+ module PrecisionRecall
8
+ module_function
9
+
10
+ # @!visibility private
11
+ def precision_each_class(y_true, y_pred)
12
+ y_true.sort.to_a.uniq.map do |label|
13
+ target_positions = y_pred.eq(label)
14
+ next 0.0 if y_pred[target_positions].empty?
15
+ n_true_positives = Numo::Int32.cast(y_true[target_positions].eq(y_pred[target_positions])).sum.to_f
16
+ n_false_positives = Numo::Int32.cast(y_true[target_positions].ne(y_pred[target_positions])).sum.to_f
17
+ n_true_positives / (n_true_positives + n_false_positives)
18
+ end
19
+ end
20
+
21
+ # @!visibility private
22
+ def recall_each_class(y_true, y_pred)
23
+ y_true.sort.to_a.uniq.map do |label|
24
+ target_positions = y_true.eq(label)
25
+ next 0.0 if y_pred[target_positions].empty?
26
+ n_true_positives = Numo::Int32.cast(y_true[target_positions].eq(y_pred[target_positions])).sum.to_f
27
+ n_false_negatives = Numo::Int32.cast(y_true[target_positions].ne(y_pred[target_positions])).sum.to_f
28
+ n_true_positives / (n_true_positives + n_false_negatives)
29
+ end
30
+ end
31
+
32
+ # @!visibility private
33
+ def f_score_each_class(y_true, y_pred)
34
+ precision_each_class(y_true, y_pred).zip(recall_each_class(y_true, y_pred)).map do |p, r|
35
+ next 0.0 if p.zero? && r.zero?
36
+ (2.0 * p * r) / (p + r)
37
+ end
38
+ end
39
+
40
+ # @!visibility private
41
+ def micro_average_precision(y_true, y_pred)
42
+ evaluated_values = y_true.sort.to_a.uniq.map do |label|
43
+ target_positions = y_pred.eq(label)
44
+ next [0.0, 0.0] if y_pred[target_positions].empty?
45
+ n_true_positives = Numo::Int32.cast(y_true[target_positions].eq(y_pred[target_positions])).sum.to_f
46
+ n_false_positives = Numo::Int32.cast(y_true[target_positions].ne(y_pred[target_positions])).sum.to_f
47
+ [n_true_positives, n_true_positives + n_false_positives]
48
+ end
49
+ res = evaluated_values.transpose.map { |v| v.inject(:+) }
50
+ res.first / res.last
51
+ end
52
+
53
+ # @!visibility private
54
+ def micro_average_recall(y_true, y_pred)
55
+ evaluated_values = y_true.sort.to_a.uniq.map do |label|
56
+ target_positions = y_true.eq(label)
57
+ next 0.0 if y_pred[target_positions].empty?
58
+ n_true_positives = Numo::Int32.cast(y_true[target_positions].eq(y_pred[target_positions])).sum.to_f
59
+ n_false_negatives = Numo::Int32.cast(y_true[target_positions].ne(y_pred[target_positions])).sum.to_f
60
+ [n_true_positives, n_true_positives + n_false_negatives]
61
+ end
62
+ res = evaluated_values.transpose.map { |v| v.inject(:+) }
63
+ res.first / res.last
64
+ end
65
+
66
+ # @!visibility private
67
+ def micro_average_f_score(y_true, y_pred)
68
+ p = micro_average_precision(y_true, y_pred)
69
+ r = micro_average_recall(y_true, y_pred)
70
+ (2.0 * p * r) / (p + r)
71
+ end
72
+
73
+ # @!visibility private
74
+ def macro_average_precision(y_true, y_pred)
75
+ precision_each_class(y_true, y_pred).inject(:+) / y_true.to_a.uniq.size
76
+ end
77
+
78
+ # @!visibility private
79
+ def macro_average_recall(y_true, y_pred)
80
+ recall_each_class(y_true, y_pred).inject(:+) / y_true.to_a.uniq.size
81
+ end
82
+
83
+ # @!visibility private
84
+ def macro_average_f_score(y_true, y_pred)
85
+ f_score_each_class(y_true, y_pred).inject(:+) / y_true.to_a.uniq.size
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,44 @@
1
+ require 'svmkit/base/evaluator'
2
+ require 'svmkit/evaluation_measure/precision_recall'
3
+
4
+ module SVMKit
5
+ # This module consists of the classes for model evaluation.
6
+ module EvaluationMeasure
7
+ # Recall is a class that calculates the recall of the predicted labels.
8
+ #
9
+ # @example
10
+ # evaluator = SVMKit::EvaluationMeasure::Recall.new
11
+ # puts evaluator.score(ground_truth, predicted)
12
+ class Recall
13
+ include Base::Evaluator
14
+ include EvaluationMeasure::PrecisionRecall
15
+
16
+ # Return the average type for calculation of recall.
17
+ # @return [String] ('binary', 'micro', 'macro')
18
+ attr_reader :average
19
+
20
+ # Create a new evaluation measure calculater for recall score.
21
+ #
22
+ # @param average [String] The average type ('binary', 'micro', 'macro')
23
+ def initialize(average: 'binary')
24
+ @average = average
25
+ end
26
+
27
+ # Claculate average recall
28
+ #
29
+ # @param y_true [Numo::Int32] (shape: [n_samples]) Ground truth labels.
30
+ # @param y_pred [Numo::Int32] (shape: [n_samples]) Predicted labels.
31
+ # @return [Float] Average recall
32
+ def score(y_true, y_pred)
33
+ case @average
34
+ when 'binary'
35
+ recall_each_class(y_true, y_pred).last
36
+ when 'micro'
37
+ micro_average_recall(y_true, y_pred)
38
+ when 'macro'
39
+ macro_average_recall(y_true, y_pred)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -127,9 +127,13 @@ module SVMKit
127
127
  # Predict probability for samples.
128
128
  #
129
129
  # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to predict the probailities.
130
- # @return [Numo::DFloat] (shape: [n_samples]) Predicted probability per sample.
130
+ # @return [Numo::DFloat] (shape: [n_samples, n_classes]) Predicted probability of each class per sample.
131
131
  def predict_proba(x)
132
- decision_function(x)
132
+ n_samples, = x.shape
133
+ proba = Numo::DFloat.zeros(n_samples, 2)
134
+ proba[true, 1] = decision_function(x)
135
+ proba[true, 0] = 1.0 - proba[true, 1]
136
+ proba
133
137
  end
134
138
 
135
139
  # Claculate the mean accuracy of the given testing data.
@@ -21,6 +21,10 @@ module SVMKit
21
21
  # @return [Splitter]
22
22
  attr_reader :splitter
23
23
 
24
+ # Return the evaluator that calculates score.
25
+ # @return [Evaluator]
26
+ attr_reader :evaluator
27
+
24
28
  # Return the flag indicating whether to caculate the score of training dataset.
25
29
  # @return [Boolean]
26
30
  attr_reader :return_train_score
@@ -29,10 +33,12 @@ module SVMKit
29
33
  #
30
34
  # @param estimator [Classifier] The classifier of which performance is evaluated.
31
35
  # @param splitter [Splitter] The splitter that divides dataset to training and testing dataset.
36
+ # @param evaluator [Evaluator] The evaluator that calculates score of estimator results.
32
37
  # @param return_train_score [Boolean] The flag indicating whether to calculate the score of training dataset.
33
- def initialize(estimator: nil, splitter: nil, return_train_score: false)
38
+ def initialize(estimator: nil, splitter: nil, evaluator: nil, return_train_score: false)
34
39
  @estimator = estimator
35
40
  @splitter = splitter
41
+ @evaluator = evaluator
36
42
  @return_train_score = return_train_score
37
43
  end
38
44
 
@@ -49,7 +55,7 @@ module SVMKit
49
55
  # the return_train_score is false.
50
56
  def perform(x, y)
51
57
  # Initialize the report of cross validation.
52
- report = {test_score: [], train_score: nil, fit_time: []}
58
+ report = { test_score: [], train_score: nil, fit_time: [] }
53
59
  report[:train_score] = [] if @return_train_score
54
60
  # Evaluate the estimator on each split.
55
61
  @splitter.split(x, y).each do |train_ids, test_ids|
@@ -64,8 +70,13 @@ module SVMKit
64
70
  @estimator.fit(train_x, train_y)
65
71
  # Calculate scores and prepare the report.
66
72
  report[:fit_time].push(Time.now.to_i - start_time)
67
- report[:test_score].push(@estimator.score(test_x, test_y))
68
- report[:train_score].push(@estimator.score(train_x, train_y)) if @return_train_score
73
+ if @evaluator.nil?
74
+ report[:test_score].push(@estimator.score(test_x, test_y))
75
+ report[:train_score].push(@estimator.score(train_x, train_y)) if @return_train_score
76
+ else
77
+ report[:test_score].push(@evaluator.score(test_y, @estimator.predict(test_x)))
78
+ report[:train_score].push(@estimator.score(train_x, @estimator.predict(train_x))) if @return_train_score
79
+ end
69
80
  end
70
81
  report
71
82
  end
@@ -0,0 +1,190 @@
1
+ require 'svmkit/base/base_estimator'
2
+ require 'svmkit/base/classifier'
3
+
4
+ module SVMKit
5
+ # This module consists of the classes that implemnt polynomial models.
6
+ module PolynomialModel
7
+ # FactorizationMachineClassifier is a class that
8
+ # implements Fatorization Machine for binary classification
9
+ # with (mini-batch) stochastic gradient descent optimization.
10
+ # Note that this implementation uses hinge loss for the loss function.
11
+ #
12
+ # @example
13
+ # estimator =
14
+ # SVMKit::PolynomialModel::FactorizationMachineClassifier.new(
15
+ # n_factors: 10, reg_param_bias: 0.001, reg_param_weight: 0.001, reg_param_factor: 0.001,
16
+ # max_iter: 5000, batch_size: 50, random_seed: 1)
17
+ # estimator.fit(training_samples, traininig_labels)
18
+ # results = estimator.predict(testing_samples)
19
+ #
20
+ # *Reference*
21
+ # - S. Rendle, "Factorization Machines with libFM," ACM Transactions on Intelligent Systems and Technology, vol. 3 (3), pp. 57:1--57:22, 2012.
22
+ # - S. Rendle, "Factorization Machines," Proceedings of the 10th IEEE International Conference on Data Mining (ICDM'10), pp. 995--1000, 2010.
23
+ class FactorizationMachineClassifier
24
+ include Base::BaseEstimator
25
+ include Base::Classifier
26
+
27
+ # Return the factor matrix for Factorization Machine.
28
+ # @return [Numo::DFloat] (shape: [n_factors, n_features])
29
+ attr_reader :factor_mat
30
+
31
+ # Return the weight vector for Factorization Machine.
32
+ # @return [Numo::DFloat] (shape: [n_features])
33
+ attr_reader :weight_vec
34
+
35
+ # Return the bias term for Factoriazation Machine.
36
+ # @return [Float]
37
+ attr_reader :bias_term
38
+
39
+ # Return the random generator for transformation.
40
+ # @return [Random]
41
+ attr_reader :rng
42
+
43
+ # Create a new classifier with Support Vector Machine by the Pegasos algorithm.
44
+ #
45
+ # @param n_factors [Integer] The maximum number of iterations.
46
+ # @param reg_param_bias [Float] The regularization parameter for bias term.
47
+ # @param reg_param_weight [Float] The regularization parameter for weight vector.
48
+ # @param reg_param_factor [Float] The regularization parameter for factor matrix.
49
+ # @param init_std [Float] The standard deviation of normal random number for initialization of factor matrix.
50
+ # @param max_iter [Integer] The maximum number of iterations.
51
+ # @param batch_size [Integer] The size of the mini batches.
52
+ # @param random_seed [Integer] The seed value using to initialize the random generator.
53
+ def initialize(n_factors: 2, reg_param_bias: 1.0, reg_param_weight: 1.0, reg_param_factor: 1.0,
54
+ init_std: 0.1, max_iter: 1000, batch_size: 10, random_seed: nil)
55
+ @params = {}
56
+ @params[:n_factors] = n_factors
57
+ @params[:reg_param_bias] = reg_param_bias
58
+ @params[:reg_param_weight] = reg_param_weight
59
+ @params[:reg_param_factor] = reg_param_factor
60
+ @params[:init_std] = init_std
61
+ @params[:max_iter] = max_iter
62
+ @params[:batch_size] = batch_size
63
+ @params[:random_seed] = random_seed
64
+ @params[:random_seed] ||= srand
65
+ @factor_mat = nil
66
+ @weight_vec = nil
67
+ @bias_term = 0.0
68
+ @rng = Random.new(@params[:random_seed])
69
+ end
70
+
71
+ # Fit the model with given training data.
72
+ #
73
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The training data to be used for fitting the model.
74
+ # @param y [Numo::Int32] (shape: [n_samples]) The labels to be used for fitting the model.
75
+ # @return [FactorizationMachineClassifier] The learned classifier itself.
76
+ def fit(x, y)
77
+ # Generate binary labels.
78
+ negative_label = y.to_a.uniq.sort.shift
79
+ bin_y = y.map { |l| l != negative_label ? 1.0 : -1.0 }
80
+ # Initialize some variables.
81
+ n_samples, n_features = x.shape
82
+ rand_ids = [*0...n_samples].shuffle(random: @rng)
83
+ @factor_mat = rand_normal([@params[:n_factors], n_features], 0, @params[:init_std])
84
+ @weight_vec = Numo::DFloat.zeros(n_features)
85
+ @bias_term = 0.0
86
+ # Start optimization.
87
+ @params[:max_iter].times do |t|
88
+ # Random sampling.
89
+ subset_ids = rand_ids.shift(@params[:batch_size])
90
+ rand_ids.concat(subset_ids)
91
+ data = x[subset_ids, true]
92
+ label = bin_y[subset_ids]
93
+ # Calculate gradients for loss function.
94
+ loss_grad = loss_gradient(data, label)
95
+ next if loss_grad.ne(0.0).count.zero?
96
+ # Update each parameter.
97
+ @bias_term -= learning_rate(@params[:reg_param_bias], t) * bias_gradient(loss_grad)
98
+ @weight_vec -= learning_rate(@params[:reg_param_weight], t) * weight_gradient(loss_grad, data)
99
+ @params[:n_factors].times do |n|
100
+ @factor_mat[n, true] -= learning_rate(@params[:reg_param_factor], t) *
101
+ factor_gradient(loss_grad, data, @factor_mat[n, true])
102
+ end
103
+ end
104
+ self
105
+ end
106
+
107
+ # Calculate confidence scores for samples.
108
+ #
109
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to compute the scores.
110
+ # @return [Numo::DFloat] (shape: [n_samples]) Confidence score per sample.
111
+ def decision_function(x)
112
+ linear_term = @bias_term + x.dot(@weight_vec)
113
+ factor_term = 0.5 * (@factor_mat.dot(x.transpose)**2 - (@factor_mat**2).dot(x.transpose**2)).sum
114
+ linear_term + factor_term
115
+ end
116
+
117
+ # Predict class labels for samples.
118
+ #
119
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to predict the labels.
120
+ # @return [Numo::Int32] (shape: [n_samples]) Predicted class label per sample.
121
+ def predict(x)
122
+ Numo::Int32.cast(decision_function(x).map { |v| v >= 0.0 ? 1 : -1 })
123
+ end
124
+
125
+ # Claculate the mean accuracy of the given testing data.
126
+ #
127
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) Testing data.
128
+ # @param y [Numo::Int32] (shape: [n_samples]) True labels for testing data.
129
+ # @return [Float] Mean accuracy
130
+ def score(x, y)
131
+ p = predict(x)
132
+ n_hits = (y.to_a.map.with_index { |l, n| l == p[n] ? 1 : 0 }).inject(:+)
133
+ n_hits / y.size.to_f
134
+ end
135
+
136
+ # Dump marshal data.
137
+ # @return [Hash] The marshal data about FactorizationMachineClassifier
138
+ def marshal_dump
139
+ { params: @params, factor_mat: @factor_mat, weight_vec: @weight_vec, bias_term: @bias_term, rng: @rng }
140
+ end
141
+
142
+ # Load marshal data.
143
+ # @return [nil]
144
+ def marshal_load(obj)
145
+ @params = obj[:params]
146
+ @factor_mat = obj[:factor_mat]
147
+ @weight_vec = obj[:weight_vec]
148
+ @bias_term = obj[:bias_term]
149
+ @rng = obj[:rng]
150
+ nil
151
+ end
152
+
153
+ private
154
+
155
+ def loss_gradient(x, y)
156
+ evaluated = y * decision_function(x)
157
+ gradient = Numo::DFloat.zeros(evaluated.size)
158
+ gradient[evaluated < 1.0] = -y[evaluated < 1.0]
159
+ gradient
160
+ end
161
+
162
+ def learning_rate(reg_param, iter)
163
+ 1.0 / (reg_param * (iter + 1))
164
+ end
165
+
166
+ def bias_gradient(loss_grad)
167
+ loss_grad.mean + @params[:reg_param_bias] * @bias_term
168
+ end
169
+
170
+ def weight_gradient(loss_grad, data)
171
+ (loss_grad.expand_dims(1) * data).mean(0) + @params[:reg_param_weight] * @weight_vec
172
+ end
173
+
174
+ def factor_gradient(loss_grad, data, factor)
175
+ reg_term = @params[:reg_param_factor] * factor
176
+ (loss_grad.expand_dims(1) * (data * data.dot(factor).expand_dims(1) - factor * (data**2))).mean(0) + reg_term
177
+ end
178
+
179
+ def rand_uniform(shape)
180
+ Numo::DFloat[*Array.new(shape.inject(&:*)) { @rng.rand }].reshape(*shape)
181
+ end
182
+
183
+ def rand_normal(shape, mu, sigma)
184
+ a = rand_uniform(shape)
185
+ b = rand_uniform(shape)
186
+ mu + sigma * (Numo::NMath.sqrt(-2.0 * Numo::NMath.log(a)) * Numo::NMath.sin(2.0 * Math::PI * b))
187
+ end
188
+ end
189
+ end
190
+ end
@@ -1,5 +1,5 @@
1
1
  # SVMKit is an experimental library of machine learning in Ruby.
2
2
  module SVMKit
3
3
  # @!visibility private
4
- VERSION = '0.2.3'.freeze
4
+ VERSION = '0.2.4'.freeze
5
5
  end
data/lib/svmkit.rb CHANGED
@@ -8,10 +8,12 @@ require 'svmkit/base/base_estimator'
8
8
  require 'svmkit/base/classifier'
9
9
  require 'svmkit/base/transformer'
10
10
  require 'svmkit/base/splitter'
11
+ require 'svmkit/base/evaluator'
11
12
  require 'svmkit/kernel_approximation/rbf'
12
13
  require 'svmkit/linear_model/svc'
13
14
  require 'svmkit/linear_model/logistic_regression'
14
15
  require 'svmkit/kernel_machine/kernel_svc'
16
+ require 'svmkit/polynomial_model/factorization_machine_classifier'
15
17
  require 'svmkit/multiclass/one_vs_rest_classifier'
16
18
  require 'svmkit/nearest_neighbors/k_neighbors_classifier'
17
19
  require 'svmkit/preprocessing/l2_normalizer'
@@ -20,3 +22,7 @@ require 'svmkit/preprocessing/standard_scaler'
20
22
  require 'svmkit/model_selection/k_fold'
21
23
  require 'svmkit/model_selection/stratified_k_fold'
22
24
  require 'svmkit/model_selection/cross_validation'
25
+ require 'svmkit/evaluation_measure/accuracy'
26
+ require 'svmkit/evaluation_measure/precision'
27
+ require 'svmkit/evaluation_measure/recall'
28
+ require 'svmkit/evaluation_measure/f_score'
data/svmkit.gemspec CHANGED
@@ -11,12 +11,15 @@ Gem::Specification.new do |spec|
11
11
  spec.email = ['yoshoku@outlook.com']
12
12
 
13
13
  spec.summary = <<MSG
14
- SVMKit is an experimental library of machine learning in Ruby.
14
+ SVMKit is a machine learninig library in Ruby.
15
+ SVMKit implements machine learning algorithms with interfaces similar to Scikit-Learn in Python.
15
16
  MSG
16
17
  spec.description = <<MSG
17
- SVMKit is a library for machine learninig in Ruby.
18
- SVMKit implements machine learning algorithms with an interface similar to Scikit-Learn in Python.
19
- However, since SVMKit is an experimental library, there are few machine learning algorithms implemented.
18
+ SVMKit is a machine learninig library in Ruby.
19
+ SVMKit implements machine learning algorithms with interfaces similar to Scikit-Learn in Python.
20
+ Since the development of SVMKit has just getting started,
21
+ the methods implemented in SVMKit are only Linear / Kernel SVC,
22
+ Logistic Regression, Factorization Machine, K-nearest neighbor method, and cross-validation.
20
23
  MSG
21
24
  spec.homepage = 'https://github.com/yoshoku/svmkit'
22
25
  spec.license = 'BSD-2-Clause'
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.2.3
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - yoshoku
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-01-15 00:00:00.000000000 Z
11
+ date: 2018-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: numo-narray
@@ -81,9 +81,11 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0.15'
83
83
  description: |
84
- SVMKit is a library for machine learninig in Ruby.
85
- SVMKit implements machine learning algorithms with an interface similar to Scikit-Learn in Python.
86
- However, since SVMKit is an experimental library, there are few machine learning algorithms implemented.
84
+ SVMKit is a machine learninig library in Ruby.
85
+ SVMKit implements machine learning algorithms with interfaces similar to Scikit-Learn in Python.
86
+ Since the development of SVMKit has just getting started,
87
+ the methods implemented in SVMKit are only Linear / Kernel SVC,
88
+ Logistic Regression, Factorization Machine, K-nearest neighbor method, and cross-validation.
87
89
  email:
88
90
  - yoshoku@outlook.com
89
91
  executables: []
@@ -105,9 +107,15 @@ files:
105
107
  - lib/svmkit.rb
106
108
  - lib/svmkit/base/base_estimator.rb
107
109
  - lib/svmkit/base/classifier.rb
110
+ - lib/svmkit/base/evaluator.rb
108
111
  - lib/svmkit/base/splitter.rb
109
112
  - lib/svmkit/base/transformer.rb
110
113
  - lib/svmkit/dataset.rb
114
+ - lib/svmkit/evaluation_measure/accuracy.rb
115
+ - lib/svmkit/evaluation_measure/f_score.rb
116
+ - lib/svmkit/evaluation_measure/precision.rb
117
+ - lib/svmkit/evaluation_measure/precision_recall.rb
118
+ - lib/svmkit/evaluation_measure/recall.rb
111
119
  - lib/svmkit/kernel_approximation/rbf.rb
112
120
  - lib/svmkit/kernel_machine/kernel_svc.rb
113
121
  - lib/svmkit/linear_model/logistic_regression.rb
@@ -118,6 +126,7 @@ files:
118
126
  - lib/svmkit/multiclass/one_vs_rest_classifier.rb
119
127
  - lib/svmkit/nearest_neighbors/k_neighbors_classifier.rb
120
128
  - lib/svmkit/pairwise_metric.rb
129
+ - lib/svmkit/polynomial_model/factorization_machine_classifier.rb
121
130
  - lib/svmkit/preprocessing/l2_normalizer.rb
122
131
  - lib/svmkit/preprocessing/min_max_scaler.rb
123
132
  - lib/svmkit/preprocessing/standard_scaler.rb
@@ -152,5 +161,6 @@ rubyforge_project:
152
161
  rubygems_version: 2.4.5.4
153
162
  signing_key:
154
163
  specification_version: 4
155
- summary: SVMKit is an experimental library of machine learning in Ruby.
164
+ summary: SVMKit is a machine learninig library in Ruby. SVMKit implements machine
165
+ learning algorithms with interfaces similar to Scikit-Learn in Python.
156
166
  test_files: []