svmkit 0.2.0 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4a53bee5e11b90721544b873d144b149b38aafe1
4
- data.tar.gz: f1ded6552e6cbdd8af3c29c4d8d403d3c8a62128
3
+ metadata.gz: b3cb57cc46849d792fff7b6c6500b9498d56fc71
4
+ data.tar.gz: 65c909ee0efaafc42df12dd24aa6c62d5b816d6a
5
5
  SHA512:
6
- metadata.gz: c3e3073f1afd4470cc21e1241d1f3666bbfefcd871700f711cfe377bb04c490f2f3ff10bc4d8ef764e05e0015faf09aef114e45ad0affde35a18641b064ed389
7
- data.tar.gz: 90144eea5e5f848dffb1325cd4576f27dbf61e5032917493e4957f5acba96489cc2b556f88a2078f5f2d9b5d2842c32454e6e56c003bfd2e36f6d5263cefc4c6
6
+ metadata.gz: 25b52e63512393706f3f53ddf415a2e4ac07923f3d1bd909cca0ade9de66d5bbb63d32a932bce32f2fa2b6c4430bab73f483d94d620eb355540a91905320644a
7
+ data.tar.gz: a3b983cf6d75168cb6eda70ec5da113feb2bc52c7fc501af3a9328f569c6d793c19e4744a4a80f0c3c60b0ea4e5387db21451f2a004f8d4699605b8348c81bab
data/.rubocop.yml CHANGED
@@ -4,6 +4,9 @@
4
4
  Documentation:
5
5
  Enabled: false
6
6
 
7
+ Metrics/AbcSize:
8
+ Max: 30
9
+
7
10
  Metrics/LineLength:
8
11
  Max: 120
9
12
 
@@ -13,5 +16,15 @@ Metrics/ModuleLength:
13
16
  Metrics/ClassLength:
14
17
  Max: 200
15
18
 
19
+ Metrics/MethodLength:
20
+ Max: 40
21
+
22
+ Metrics/BlockLength:
23
+ Exclude:
24
+ - 'spec/**/*'
25
+
26
+ ParameterLists:
27
+ Max: 10
28
+
16
29
  Security/MarshalLoad:
17
30
  Enabled: false
data/HISTORY.md CHANGED
@@ -1,3 +1,6 @@
1
+ # 0.2.1
2
+ - Added class for K-nearest neighbors classifier.
3
+
1
4
  # 0.2.0
2
5
  - Migrated the linear algebra library to Numo::NArray.
3
6
  - Added module for loading and saving libsvm format file.
data/lib/svmkit.rb CHANGED
@@ -12,6 +12,7 @@ require 'svmkit/linear_model/svc'
12
12
  require 'svmkit/linear_model/logistic_regression'
13
13
  require 'svmkit/kernel_machine/kernel_svc'
14
14
  require 'svmkit/multiclass/one_vs_rest_classifier'
15
+ require 'svmkit/nearest_neighbors/k_neighbors_classifier'
15
16
  require 'svmkit/preprocessing/l2_normalizer'
16
17
  require 'svmkit/preprocessing/min_max_scaler'
17
18
  require 'svmkit/preprocessing/standard_scaler'
@@ -35,12 +35,12 @@ module SVMKit
35
35
  # @param n_components [Integer] The number of dimensions of the RBF kernel feature space.
36
36
  # @param random_seed [Integer] The seed value using to initialize the random generator.
37
37
  def initialize(gamma: 1.0, n_components: 128, random_seed: nil)
38
- self.params = {}
39
- self.params[:gamma] = gamma
40
- self.params[:n_components] = n_components
41
- self.params[:random_seed] = random_seed
42
- self.params[:random_seed] ||= srand
43
- @rng = Random.new(self.params[:random_seed])
38
+ @params = {}
39
+ @params[:gamma] = gamma
40
+ @params[:n_components] = n_components
41
+ @params[:random_seed] = random_seed
42
+ @params[:random_seed] ||= srand
43
+ @rng = Random.new(@params[:random_seed])
44
44
  @random_mat = nil
45
45
  @random_vec = nil
46
46
  end
@@ -54,10 +54,10 @@ module SVMKit
54
54
  # @return [RBF] The learned transformer itself.
55
55
  def fit(x, _y = nil)
56
56
  n_features = x.shape[1]
57
- params[:n_components] = 2 * n_features if params[:n_components] <= 0
58
- @random_mat = rand_normal([n_features, params[:n_components]]) * (2.0 * params[:gamma])**0.5
59
- n_half_components = params[:n_components] / 2
60
- @random_vec = Numo::DFloat.zeros(params[:n_components] - n_half_components).concatenate(
57
+ @params[:n_components] = 2 * n_features if @params[:n_components] <= 0
58
+ @random_mat = rand_normal([n_features, @params[:n_components]]) * (2.0 * @params[:gamma])**0.5
59
+ n_half_components = @params[:n_components] / 2
60
+ @random_vec = Numo::DFloat.zeros(@params[:n_components] - n_half_components).concatenate(
61
61
  Numo::DFloat.ones(n_half_components) * (0.5 * Math::PI)
62
62
  )
63
63
  self
@@ -82,13 +82,13 @@ module SVMKit
82
82
  def transform(x)
83
83
  n_samples, = x.shape
84
84
  projection = x.dot(@random_mat) + @random_vec.tile(n_samples, 1)
85
- Numo::NMath.sin(projection) * ((2.0 / params[:n_components])**0.5)
85
+ Numo::NMath.sin(projection) * ((2.0 / @params[:n_components])**0.5)
86
86
  end
87
87
 
88
88
  # Dump marshal data.
89
89
  # @return [Hash] The marshal data about RBF.
90
90
  def marshal_dump
91
- { params: params,
91
+ { params: @params,
92
92
  random_mat: @random_mat,
93
93
  random_vec: @random_vec,
94
94
  rng: @rng }
@@ -97,7 +97,7 @@ module SVMKit
97
97
  # Load marshal data.
98
98
  # @return [nil]
99
99
  def marshal_load(obj)
100
- self.params = obj[:params]
100
+ @params = obj[:params]
101
101
  @random_mat = obj[:random_mat]
102
102
  @random_vec = obj[:random_vec]
103
103
  @rng = obj[:rng]
@@ -34,13 +34,13 @@ module SVMKit
34
34
  # @param max_iter [Integer] The maximum number of iterations.
35
35
  # @param random_seed [Integer] The seed value using to initialize the random generator.
36
36
  def initialize(reg_param: 1.0, max_iter: 1000, random_seed: nil)
37
- self.params = {}
38
- self.params[:reg_param] = reg_param
39
- self.params[:max_iter] = max_iter
40
- self.params[:random_seed] = random_seed
41
- self.params[:random_seed] ||= srand
37
+ @params = {}
38
+ @params[:reg_param] = reg_param
39
+ @params[:max_iter] = max_iter
40
+ @params[:random_seed] = random_seed
41
+ @params[:random_seed] ||= srand
42
42
  @weight_vec = nil
43
- @rng = Random.new(self.params[:random_seed])
43
+ @rng = Random.new(@params[:random_seed])
44
44
  end
45
45
 
46
46
  # Fit the model with given training data.
@@ -58,13 +58,13 @@ module SVMKit
58
58
  rand_ids = []
59
59
  weight_vec = Numo::DFloat.zeros(n_training_samples)
60
60
  # Start optimization.
61
- params[:max_iter].times do |t|
61
+ @params[:max_iter].times do |t|
62
62
  # random sampling
63
63
  rand_ids = [*0...n_training_samples].shuffle(random: @rng) if rand_ids.empty?
64
64
  target_id = rand_ids.shift
65
65
  # update the weight vector
66
66
  func = (weight_vec * bin_y[target_id]).dot(x[target_id, true].transpose).to_f
67
- func *= bin_y[target_id] / (params[:reg_param] * (t + 1))
67
+ func *= bin_y[target_id] / (@params[:reg_param] * (t + 1))
68
68
  weight_vec[target_id] += 1.0 if func < 1.0
69
69
  end
70
70
  # Store the learned model.
@@ -105,13 +105,13 @@ module SVMKit
105
105
  # Dump marshal data.
106
106
  # @return [Hash] The marshal data about KernelSVC.
107
107
  def marshal_dump
108
- { params: params, weight_vec: @weight_vec, rng: @rng }
108
+ { params: @params, weight_vec: @weight_vec, rng: @rng }
109
109
  end
110
110
 
111
111
  # Load marshal data.
112
112
  # @return [nil]
113
113
  def marshal_load(obj)
114
- self.params = obj[:params]
114
+ @params = obj[:params]
115
115
  @weight_vec = obj[:weight_vec]
116
116
  @rng = obj[:rng]
117
117
  nil
@@ -20,16 +20,6 @@ module SVMKit
20
20
  include Base::BaseEstimator
21
21
  include Base::Classifier
22
22
 
23
- # @!visibility private
24
- DEFAULT_PARAMS = {
25
- reg_param: 1.0,
26
- fit_bias: false,
27
- bias_scale: 1.0,
28
- max_iter: 100,
29
- batch_size: 50,
30
- random_seed: nil
31
- }.freeze
32
-
33
23
  # Return the weight vector for Logistic Regression.
34
24
  # @return [Numo::DFloat] (shape: [n_features])
35
25
  attr_reader :weight_vec
@@ -52,17 +42,17 @@ module SVMKit
52
42
  # @param batch_size [Integer] The size of the mini batches.
53
43
  # @param random_seed [Integer] The seed value using to initialize the random generator.
54
44
  def initialize(reg_param: 1.0, fit_bias: false, bias_scale: 1.0, max_iter: 100, batch_size: 50, random_seed: nil)
55
- self.params = {}
56
- self.params[:reg_param] = reg_param
57
- self.params[:fit_bias] = fit_bias
58
- self.params[:bias_scale] = bias_scale
59
- self.params[:max_iter] = max_iter
60
- self.params[:batch_size] = batch_size
61
- self.params[:random_seed] = random_seed
62
- self.params[:random_seed] ||= srand
45
+ @params = {}
46
+ @params[:reg_param] = reg_param
47
+ @params[:fit_bias] = fit_bias
48
+ @params[:bias_scale] = bias_scale
49
+ @params[:max_iter] = max_iter
50
+ @params[:batch_size] = batch_size
51
+ @params[:random_seed] = random_seed
52
+ @params[:random_seed] ||= srand
63
53
  @weight_vec = nil
64
54
  @bias_term = 0.0
65
- @rng = Random.new(self.params[:random_seed])
55
+ @rng = Random.new(@params[:random_seed])
66
56
  end
67
57
 
68
58
  # Fit the model with given training data.
@@ -77,9 +67,9 @@ module SVMKit
77
67
  bin_y = y.to_a.map { |l| l != negative_label ? 1 : 0 }
78
68
  # Expand feature vectors for bias term.
79
69
  samples = x
80
- if params[:fit_bias]
70
+ if @params[:fit_bias]
81
71
  samples = Numo::NArray.hstack(
82
- [samples, Numo::DFloat.ones([x.shape[0], 1]) * params[:bias_scale]]
72
+ [samples, Numo::DFloat.ones([x.shape[0], 1]) * @params[:bias_scale]]
83
73
  )
84
74
  end
85
75
  # Initialize some variables.
@@ -87,27 +77,27 @@ module SVMKit
87
77
  rand_ids = [*0..n_samples - 1].shuffle(random: @rng)
88
78
  weight_vec = Numo::DFloat.zeros(n_features)
89
79
  # Start optimization.
90
- params[:max_iter].times do |t|
80
+ @params[:max_iter].times do |t|
91
81
  # random sampling
92
- subset_ids = rand_ids.shift(params[:batch_size])
82
+ subset_ids = rand_ids.shift(@params[:batch_size])
93
83
  rand_ids.concat(subset_ids)
94
84
  # update the weight vector.
95
- eta = 1.0 / (params[:reg_param] * (t + 1))
85
+ eta = 1.0 / (@params[:reg_param] * (t + 1))
96
86
  mean_vec = Numo::DFloat.zeros(n_features)
97
87
  subset_ids.each do |n|
98
88
  z = weight_vec.dot(samples[n, true])
99
89
  coef = bin_y[n] / (1.0 + Math.exp(bin_y[n] * z))
100
90
  mean_vec += samples[n, true] * coef
101
91
  end
102
- mean_vec *= eta / params[:batch_size]
103
- weight_vec = weight_vec * (1.0 - eta * params[:reg_param]) + mean_vec
92
+ mean_vec *= eta / @params[:batch_size]
93
+ weight_vec = weight_vec * (1.0 - eta * @params[:reg_param]) + mean_vec
104
94
  # scale the weight vector.
105
95
  norm = Math.sqrt(weight_vec.dot(weight_vec))
106
- scaler = (1.0 / params[:reg_param]**0.5) / (norm + 1.0e-12)
96
+ scaler = (1.0 / @params[:reg_param]**0.5) / (norm + 1.0e-12)
107
97
  weight_vec *= [1.0, scaler].min
108
98
  end
109
99
  # Store the learned model.
110
- if params[:fit_bias]
100
+ if @params[:fit_bias]
111
101
  @weight_vec = weight_vec[0...n_features - 1]
112
102
  @bias_term = weight_vec[n_features - 1]
113
103
  else
@@ -156,13 +146,13 @@ module SVMKit
156
146
  # Dump marshal data.
157
147
  # @return [Hash] The marshal data about LogisticRegression.
158
148
  def marshal_dump
159
- { params: params, weight_vec: @weight_vec, bias_term: @bias_term, rng: @rng }
149
+ { params: @params, weight_vec: @weight_vec, bias_term: @bias_term, rng: @rng }
160
150
  end
161
151
 
162
152
  # Load marshal data.
163
153
  # @return [nil]
164
154
  def marshal_load(obj)
165
- self.params = obj[:params]
155
+ @params = obj[:params]
166
156
  @weight_vec = obj[:weight_vec]
167
157
  @bias_term = obj[:bias_term]
168
158
  @rng = obj[:rng]
@@ -18,16 +18,6 @@ module SVMKit
18
18
  include Base::BaseEstimator
19
19
  include Base::Classifier
20
20
 
21
- # @!visibility private
22
- DEFAULT_PARAMS = {
23
- reg_param: 1.0,
24
- fit_bias: false,
25
- bias_scale: 1.0,
26
- max_iter: 100,
27
- batch_size: 50,
28
- random_seed: nil
29
- }.freeze
30
-
31
21
  # Return the weight vector for SVC.
32
22
  # @return [Numo::DFloat] (shape: [n_features])
33
23
  attr_reader :weight_vec
@@ -49,17 +39,17 @@ module SVMKit
49
39
  # @param batch_size [Integer] The size of the mini batches.
50
40
  # @param random_seed [Integer] The seed value using to initialize the random generator.
51
41
  def initialize(reg_param: 1.0, fit_bias: false, bias_scale: 1.0, max_iter: 100, batch_size: 50, random_seed: nil)
52
- self.params = {}
53
- self.params[:reg_param] = reg_param
54
- self.params[:fit_bias] = fit_bias
55
- self.params[:bias_scale] = bias_scale
56
- self.params[:max_iter] = max_iter
57
- self.params[:batch_size] = batch_size
58
- self.params[:random_seed] = random_seed
59
- self.params[:random_seed] ||= srand
42
+ @params = {}
43
+ @params[:reg_param] = reg_param
44
+ @params[:fit_bias] = fit_bias
45
+ @params[:bias_scale] = bias_scale
46
+ @params[:max_iter] = max_iter
47
+ @params[:batch_size] = batch_size
48
+ @params[:random_seed] = random_seed
49
+ @params[:random_seed] ||= srand
60
50
  @weight_vec = nil
61
51
  @bias_term = 0.0
62
- @rng = Random.new(self.params[:random_seed])
52
+ @rng = Random.new(@params[:random_seed])
63
53
  end
64
54
 
65
55
  # Fit the model with given training data.
@@ -73,9 +63,9 @@ module SVMKit
73
63
  bin_y = y.to_a.map { |l| l != negative_label ? 1 : -1 }
74
64
  # Expand feature vectors for bias term.
75
65
  samples = x
76
- if params[:fit_bias]
66
+ if @params[:fit_bias]
77
67
  samples = Numo::NArray.hstack(
78
- [samples, Numo::DFloat.ones([x.shape[0], 1]) * params[:bias_scale]]
68
+ [samples, Numo::DFloat.ones([x.shape[0], 1]) * @params[:bias_scale]]
79
69
  )
80
70
  end
81
71
  # Initialize some variables.
@@ -83,26 +73,26 @@ module SVMKit
83
73
  rand_ids = [*0..n_samples - 1].shuffle(random: @rng)
84
74
  weight_vec = Numo::DFloat.zeros(n_features)
85
75
  # Start optimization.
86
- params[:max_iter].times do |t|
76
+ @params[:max_iter].times do |t|
87
77
  # random sampling
88
- subset_ids = rand_ids.shift(params[:batch_size])
78
+ subset_ids = rand_ids.shift(@params[:batch_size])
89
79
  rand_ids.concat(subset_ids)
90
80
  target_ids = subset_ids.map { |n| n if weight_vec.dot(samples[n, true]) * bin_y[n] < 1 }.compact
91
81
  n_subsamples = target_ids.size
92
82
  next if n_subsamples.zero?
93
83
  # update the weight vector.
94
- eta = 1.0 / (params[:reg_param] * (t + 1))
84
+ eta = 1.0 / (@params[:reg_param] * (t + 1))
95
85
  mean_vec = Numo::DFloat.zeros(n_features)
96
86
  target_ids.each { |n| mean_vec += samples[n, true] * bin_y[n] }
97
87
  mean_vec *= eta / n_subsamples
98
- weight_vec = weight_vec * (1.0 - eta * params[:reg_param]) + mean_vec
88
+ weight_vec = weight_vec * (1.0 - eta * @params[:reg_param]) + mean_vec
99
89
  # scale the weight vector.
100
90
  norm = Math.sqrt(weight_vec.dot(weight_vec))
101
- scaler = (1.0 / params[:reg_param]**0.5) / (norm + 1.0e-12)
91
+ scaler = (1.0 / @params[:reg_param]**0.5) / (norm + 1.0e-12)
102
92
  weight_vec *= [1.0, scaler].min
103
93
  end
104
94
  # Store the learned model.
105
- if params[:fit_bias]
95
+ if @params[:fit_bias]
106
96
  @weight_vec = weight_vec[0...n_features - 1]
107
97
  @bias_term = weight_vec[n_features - 1]
108
98
  else
@@ -142,13 +132,13 @@ module SVMKit
142
132
  # Dump marshal data.
143
133
  # @return [Hash] The marshal data about SVC.
144
134
  def marshal_dump
145
- { params: params, weight_vec: @weight_vec, bias_term: @bias_term, rng: @rng }
135
+ { params: @params, weight_vec: @weight_vec, bias_term: @bias_term, rng: @rng }
146
136
  end
147
137
 
148
138
  # Load marshal data.
149
139
  # @return [nil]
150
140
  def marshal_load(obj)
151
- self.params = obj[:params]
141
+ @params = obj[:params]
152
142
  @weight_vec = obj[:weight_vec]
153
143
  @bias_term = obj[:bias_term]
154
144
  @rng = obj[:rng]
@@ -28,8 +28,8 @@ module SVMKit
28
28
  #
29
29
  # @param estimator [Classifier] The (binary) classifier for construction a multi-label classifier.
30
30
  def initialize(estimator: nil)
31
- self.params = {}
32
- self.params[:estimator] = estimator
31
+ @params = {}
32
+ @params[:estimator] = estimator
33
33
  @estimators = nil
34
34
  @classes = nil
35
35
  end
@@ -44,7 +44,7 @@ module SVMKit
44
44
  @classes = Numo::Int32.asarray(y_arr.uniq.sort)
45
45
  @estimators = @classes.to_a.map do |label|
46
46
  bin_y = Numo::Int32.asarray(y_arr.map { |l| l == label ? 1 : -1 })
47
- params[:estimator].dup.fit(x, bin_y)
47
+ @params[:estimator].dup.fit(x, bin_y)
48
48
  end
49
49
  self
50
50
  end
@@ -82,7 +82,7 @@ module SVMKit
82
82
  # Dump marshal data.
83
83
  # @return [Hash] The marshal data about OneVsRestClassifier.
84
84
  def marshal_dump
85
- { params: params,
85
+ { params: @params,
86
86
  classes: @classes,
87
87
  estimators: @estimators.map { |e| Marshal.dump(e) } }
88
88
  end
@@ -90,7 +90,7 @@ module SVMKit
90
90
  # Load marshal data.
91
91
  # @return [nil]
92
92
  def marshal_load(obj)
93
- self.params = obj[:params]
93
+ @params = obj[:params]
94
94
  @classes = obj[:classes]
95
95
  @estimators = obj[:estimators].map { |e| Marshal.load(e) }
96
96
  nil
@@ -0,0 +1,113 @@
1
+ require 'svmkit/base/base_estimator'
2
+ require 'svmkit/base/classifier'
3
+
4
+ module SVMKit
5
+ # This module consists of the classes that implement estimators based on nearest neighbors rule.
6
+ module NearestNeighbors
7
+ # KNeighborsClassifier is a class that implements the classifier with the k-nearest neighbors rule.
8
+ # The current implementation uses the Euclidean distance for finding the neighbors.
9
+ #
10
+ # @example
11
+ # estimator =
12
+ # SVMKit::NearestNeighbor::KNeighborsClassifier.new(n_neighbors = 5)
13
+ # estimator.fit(training_samples, traininig_labels)
14
+ # results = estimator.predict(testing_samples)
15
+ #
16
+ class KNeighborsClassifier
17
+ include Base::BaseEstimator
18
+ include Base::Classifier
19
+
20
+ # Return the prototypes for the nearest neighbor classifier.
21
+ # @return [Numo::DFloat] (shape: [n_samples, n_features])
22
+ attr_reader :prototypes
23
+
24
+ # Return the labels of the prototypes
25
+ # @return [Numo::Int32] (size: n_samples)
26
+ attr_reader :labels
27
+
28
+ # Return the class labels.
29
+ # @return [Numo::Int32] (size: n_classes)
30
+ attr_reader :classes
31
+
32
+ # Create a new classifier with the nearest neighbor rule.
33
+ #
34
+ # @param n_neighbors [Integer] The number of neighbors.
35
+ def initialize(n_neighbors: 5)
36
+ @params = {}
37
+ @params[:n_neighbors] = n_neighbors
38
+ @prototypes = nil
39
+ @labels = nil
40
+ @classes = nil
41
+ end
42
+
43
+ # Fit the model with given training data.
44
+ #
45
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The training data to be used for fitting the model.
46
+ # @param y [Numo::Int32] (shape: [n_samples]) The labels to be used for fitting the model.
47
+ # @return [KNeighborsClassifier] The learned classifier itself.
48
+ def fit(x, y)
49
+ @prototypes = Numo::DFloat.asarray(x.to_a)
50
+ @labels = Numo::Int32.asarray(y.to_a)
51
+ @classes = Numo::Int32.asarray(y.to_a.uniq.sort)
52
+ self
53
+ end
54
+
55
+ # Calculate confidence scores for samples.
56
+ #
57
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to compute the scores.
58
+ # @return [Numo::DFloat] (shape: [n_samples, n_classes]) Confidence scores per sample for each class.
59
+ def decision_function(x)
60
+ distance_matrix = PairwiseMetric.euclidean_distance(x, @prototypes)
61
+ n_samples, n_prototypes = distance_matrix.shape
62
+ n_classes = @classes.size
63
+ n_neighbors = [@params[:n_neighbors], n_prototypes].min
64
+ scores = Numo::DFloat.zeros(n_samples, n_classes)
65
+ n_samples.times do |m|
66
+ neighbor_ids = distance_matrix[m, true].to_a.each_with_index.sort.map(&:last)[0...n_neighbors]
67
+ neighbor_ids.each { |n| scores[m, @classes.to_a.index(@labels[n])] += 1.0 }
68
+ end
69
+ scores
70
+ end
71
+
72
+ # Predict class labels for samples.
73
+ #
74
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to predict the labels.
75
+ # @return [Numo::Int32] (shape: [n_samples]) Predicted class label per sample.
76
+ def predict(x)
77
+ n_samples = x.shape.first
78
+ decision_values = decision_function(x)
79
+ Numo::Int32.asarray(Array.new(n_samples) { |n| @classes[decision_values[n, true].max_index] })
80
+ end
81
+
82
+ # Claculate the mean accuracy of the given testing data.
83
+ #
84
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) Testing data.
85
+ # @param y [Numo::Int32] (shape: [n_samples]) True labels for testing data.
86
+ # @return [Float] Mean accuracy
87
+ def score(x, y)
88
+ p = predict(x)
89
+ n_hits = (y.to_a.map.with_index { |l, n| l == p[n] ? 1 : 0 }).inject(:+)
90
+ n_hits / y.size.to_f
91
+ end
92
+
93
+ # Dump marshal data.
94
+ # @return [Hash] The marshal data about KNeighborsClassifier.
95
+ def marshal_dump
96
+ { params: params,
97
+ prototypes: @prototypes,
98
+ labels: @labels,
99
+ classes: @classes }
100
+ end
101
+
102
+ # Load marshal data.
103
+ # @return [nil]
104
+ def marshal_load(obj)
105
+ @params = obj[:params]
106
+ @prototypes = obj[:prototypes]
107
+ @labels = obj[:labels]
108
+ @classes = obj[:classes]
109
+ nil
110
+ end
111
+ end
112
+ end
113
+ end
@@ -18,8 +18,8 @@ module SVMKit
18
18
  attr_reader :norm_vec # :nodoc:
19
19
 
20
20
  # Create a new normalizer for normaliing to unit L2-norm.
21
- def initialize()
22
- self.params = {}
21
+ def initialize
22
+ @params = {}
23
23
  @norm_vec = nil
24
24
  end
25
25
 
@@ -26,8 +26,8 @@ module SVMKit
26
26
  #
27
27
  # @param feature_range [Array<Float>] The desired range of samples.
28
28
  def initialize(feature_range: [0.0, 1.0])
29
- self.params = {}
30
- self.params[:feature_range] = feature_range
29
+ @params = {}
30
+ @params[:feature_range] = feature_range
31
31
  @min_vec = nil
32
32
  @max_vec = nil
33
33
  end
@@ -23,8 +23,8 @@ module SVMKit
23
23
  attr_reader :std_vec
24
24
 
25
25
  # Create a new normalizer for centering and scaling to unit variance.
26
- def initialize()
27
- self.params = {}
26
+ def initialize
27
+ @params = {}
28
28
  @mean_vec = nil
29
29
  @std_vec = nil
30
30
  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.0'.freeze
4
+ VERSION = '0.2.1'.freeze
5
5
  end
data/svmkit.gemspec CHANGED
@@ -29,21 +29,20 @@ Gem::Specification.new do |spec|
29
29
 
30
30
  spec.required_ruby_version = '>= 2.1'
31
31
 
32
- spec.add_runtime_dependency 'numo-narray', '>= 0.9.0.5'
32
+ spec.add_runtime_dependency 'numo-narray', '~> 0.9.0.5'
33
33
 
34
34
  spec.add_development_dependency 'bundler', '~> 1.15'
35
35
  spec.add_development_dependency 'rake', '~> 10.0'
36
36
  spec.add_development_dependency 'rspec', '~> 3.0'
37
37
  spec.add_development_dependency 'simplecov', '~> 0.15.1'
38
- spec.add_development_dependency 'numo-narray', '~> 0.9.0.9'
39
38
 
40
- spec.post_install_message = <<-EOF
39
+ spec.post_install_message = <<MSG
41
40
  *************************************************************************
42
41
  Thank you for installing SVMKit!!
43
42
 
44
43
  Note that the SVMKit has been changed to use Numo::NArray for
45
44
  linear algebra library from version 0.2.0.
46
45
  *************************************************************************
47
- EOF
46
+ MSG
48
47
 
49
48
  end
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: svmkit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - yoshoku
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-11-05 00:00:00.000000000 Z
11
+ date: 2017-12-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: numo-narray
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: 0.9.0.5
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.9.0.5
27
27
  - !ruby/object:Gem::Dependency
@@ -80,20 +80,6 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: 0.15.1
83
- - !ruby/object:Gem::Dependency
84
- name: numo-narray
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: 0.9.0.9
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: 0.9.0.9
97
83
  description: |
98
84
  SVMKit is a library for machine learninig in Ruby.
99
85
  SVMKit implements machine learning algorithms with an interface similar to Scikit-Learn in Python.
@@ -126,6 +112,7 @@ files:
126
112
  - lib/svmkit/linear_model/logistic_regression.rb
127
113
  - lib/svmkit/linear_model/svc.rb
128
114
  - lib/svmkit/multiclass/one_vs_rest_classifier.rb
115
+ - lib/svmkit/nearest_neighbors/k_neighbors_classifier.rb
129
116
  - lib/svmkit/pairwise_metric.rb
130
117
  - lib/svmkit/preprocessing/l2_normalizer.rb
131
118
  - lib/svmkit/preprocessing/min_max_scaler.rb
@@ -158,7 +145,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
158
145
  version: '0'
159
146
  requirements: []
160
147
  rubyforge_project:
161
- rubygems_version: 2.6.13
148
+ rubygems_version: 2.2.5
162
149
  signing_key:
163
150
  specification_version: 4
164
151
  summary: SVMKit is an experimental library of machine learning in Ruby.