libmf 0.2.4 → 0.2.5

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
  SHA256:
3
- metadata.gz: ca5a2bbda585f7e2f57630d20dfb6cf6091ab33e90227edd277c457af7f8dac7
4
- data.tar.gz: 3f8a1612c831223e552cf5af4172f31080d297f2e3f059624d66790613333890
3
+ metadata.gz: 499cc67221be5e767caa7257e69c23a2b17c537c5950e2eeebb7de21d5bec1f0
4
+ data.tar.gz: 9345dc3804dfc928bbdb03b588e64f20fbb3ddb5a3674b65972c122842bef60e
5
5
  SHA512:
6
- metadata.gz: 6d8cf1bf142c4e365c2b01a10c5e407d331d24d8410f8ee2b262c6ca6c94dfe129c5ac0a3dc6ae97e0739884aaeec9483c39546714975a8e9929c8a63799f15c
7
- data.tar.gz: 80356261c846d506160df89424b9f67d070908e1cc1f9c583e83cbbec5b7ebce272acb5146e447dd1394bb7c5d3268bf00837dc0814eb5ccb23d8c23c53efae3
6
+ metadata.gz: 6cd517a3e7eb418390012352a62de72aa9e3a4077b08c5d8602e89a9a8af0dcdc654a51359641e374d263804189a814afffa8e2f55db52ef7506e222e2143e5f
7
+ data.tar.gz: 5dad62dd22cd82499d4f0c2b2c06792945c50065a2517d89baeec8d00c62e2628d62d3702cc3964344c3e437f4281afd1f79f58291efca12f3c788e5ed07d0e1
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 0.2.5 (2021-10-18)
2
+
3
+ - Added named loss functions
4
+ - Added `Matrix` class
5
+ - Improved error checking for `fit`, `cv`, `save_model`, and `load_model`
6
+
1
7
  ## 0.2.4 (2021-08-05)
2
8
 
3
9
  - Fixed memory leak
data/README.md CHANGED
@@ -90,7 +90,7 @@ Pass parameters - default values below
90
90
 
91
91
  ```ruby
92
92
  Libmf::Model.new(
93
- loss: 0, # loss function
93
+ loss: :real_l2, # loss function
94
94
  factors: 8, # number of latent factors
95
95
  threads: 12, # number of threads used
96
96
  bins: 25, # number of bins
@@ -111,21 +111,21 @@ Libmf::Model.new(
111
111
 
112
112
  For real-valued matrix factorization
113
113
 
114
- - 0 - squared error (L2-norm)
115
- - 1 - absolute error (L1-norm)
116
- - 2 - generalized KL-divergence
114
+ - `:real_l2` - squared error (L2-norm)
115
+ - `:real_l1` - absolute error (L1-norm)
116
+ - `:real_kl` - generalized KL-divergence
117
117
 
118
118
  For binary matrix factorization
119
119
 
120
- - 5 - logarithmic error
121
- - 6 - squared hinge loss
122
- - 7 - hinge loss
120
+ - `:binary_log` - logarithmic error
121
+ - `:binary_l2` - squared hinge loss
122
+ - `:binary_l1` - hinge loss
123
123
 
124
124
  For one-class matrix factorization
125
125
 
126
- - 10 - row-oriented pair-wise logarithmic loss
127
- - 11 - column-oriented pair-wise logarithmic loss
128
- - 12 - squared error (L2-norm)
126
+ - `:one_class_row` - row-oriented pair-wise logarithmic loss
127
+ - `:one_class_col` - column-oriented pair-wise logarithmic loss
128
+ - `:one_class_l2` - squared error (L2-norm)
129
129
 
130
130
  ## Performance
131
131
 
@@ -0,0 +1,13 @@
1
+ module Libmf
2
+ class Matrix
3
+ attr_reader :data
4
+
5
+ def initialize
6
+ @data = []
7
+ end
8
+
9
+ def push(row_index, column_index, value)
10
+ @data << [row_index, column_index, value]
11
+ end
12
+ end
13
+ end
data/lib/libmf/model.rb CHANGED
@@ -14,6 +14,7 @@ module Libmf
14
14
  else
15
15
  FFI.mf_train(train_set, param)
16
16
  end
17
+ raise Error, "fit failed" if @model.null?
17
18
 
18
19
  nil
19
20
  end
@@ -24,15 +25,20 @@ module Libmf
24
25
 
25
26
  def cv(data, folds: 5)
26
27
  problem = create_problem(data)
27
- FFI.mf_cross_validation(problem, folds, param)
28
+ # TODO update fork to differentiate between bad parameters and zero error
29
+ res = FFI.mf_cross_validation(problem, folds, param)
30
+ raise Error, "cv failed" if res == 0
31
+ res
28
32
  end
29
33
 
30
34
  def save_model(path)
31
- FFI.mf_save_model(model, path)
35
+ status = FFI.mf_save_model(model, path)
36
+ raise Error, "Cannot save model" if status != 0
32
37
  end
33
38
 
34
39
  def load_model(path)
35
40
  @model = FFI.mf_load_model(path)
41
+ raise Error, "Cannot open model" if @model.null?
36
42
  end
37
43
 
38
44
  def rows
@@ -80,6 +86,22 @@ module Libmf
80
86
  def param
81
87
  param = FFI.mf_get_default_param
82
88
  options = @options.dup
89
+
90
+ if options[:loss].is_a?(Symbol)
91
+ loss_map = {
92
+ real_l2: 0,
93
+ real_l1: 1,
94
+ real_kl: 2,
95
+ binary_log: 5,
96
+ binary_l2: 6,
97
+ binary_l1: 7,
98
+ one_class_row: 10,
99
+ one_class_col: 11,
100
+ one_class_l2: 12
101
+ }
102
+ options[:loss] = loss_map[options[:loss]] || (raise ArgumentError, "Unknown loss")
103
+ end
104
+
83
105
  # silence insufficient blocks warning with default params
84
106
  options[:bins] ||= 25 unless options[:nr_bins]
85
107
  options[:copy_data] = false unless options.key?(:copy_data)
@@ -107,6 +129,10 @@ module Libmf
107
129
  return FFI.mf_read_problem(File.expand_path(data))
108
130
  end
109
131
 
132
+ if data.is_a?(Matrix)
133
+ data = data.data
134
+ end
135
+
110
136
  raise Error, "No data" if data.empty?
111
137
 
112
138
  # TODO do in C for better performance
data/lib/libmf/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Libmf
2
- VERSION = "0.2.4"
2
+ VERSION = "0.2.5"
3
3
  end
data/lib/libmf.rb CHANGED
@@ -2,6 +2,7 @@
2
2
  require "ffi"
3
3
 
4
4
  # modules
5
+ require "libmf/matrix"
5
6
  require "libmf/model"
6
7
  require "libmf/version"
7
8
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: libmf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-06 00:00:00.000000000 Z
11
+ date: 2021-10-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -35,6 +35,7 @@ files:
35
35
  - README.md
36
36
  - lib/libmf.rb
37
37
  - lib/libmf/ffi.rb
38
+ - lib/libmf/matrix.rb
38
39
  - lib/libmf/model.rb
39
40
  - lib/libmf/version.rb
40
41
  - vendor/COPYRIGHT