cmfrec 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +27 -1
- data/lib/cmfrec.rb +3 -0
- data/lib/cmfrec/data.rb +100 -0
- data/lib/cmfrec/ffi.rb +7 -5
- data/lib/cmfrec/recommender.rb +47 -34
- data/lib/cmfrec/version.rb +1 -1
- data/vendor/libcmfrec.dylib +0 -0
- data/vendor/libcmfrec.so +0 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9c19c6069b22f666ab280851cdfcaab346c1c08599be2e97043bdc41da552b6f
|
4
|
+
data.tar.gz: 6f0ffb63861b47568119e7014ff1c9d1a71fcf5852c6b1df2a8ca9b16bd239d3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 15104fb705c8bf1ffe3959846ddacde37a8845ee667c6ab334df6b1aacc7da42af894e2f94f1bfc35739943f8293b3f70e22358f7fc030e814c5dadbce4bb75e
|
7
|
+
data.tar.gz: 8d7806b1500de927ecca3705ade074a2dc197a5e413a3a0e755f3d952aa8916b10a87f635e7958726e315a05376c216c6c5a79b6d33f4a61d723e4bbfbbcd382
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -16,7 +16,7 @@ Add this line to your application’s Gemfile:
|
|
16
16
|
gem 'cmfrec'
|
17
17
|
```
|
18
18
|
|
19
|
-
|
19
|
+
For Windows, also follow [these instructions](#windows-installation).
|
20
20
|
|
21
21
|
## Getting Started
|
22
22
|
|
@@ -107,6 +107,24 @@ Get recommendations with only side information
|
|
107
107
|
recommender.new_user_recs([], user_info: {cats: 0, dogs: 2})
|
108
108
|
```
|
109
109
|
|
110
|
+
## Examples
|
111
|
+
|
112
|
+
### MovieLens
|
113
|
+
|
114
|
+
Load the data
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
ratings, user_info, item_info = Cmfrec.load_movielens
|
118
|
+
```
|
119
|
+
|
120
|
+
Create a recommender and get predictions
|
121
|
+
|
122
|
+
```ruby
|
123
|
+
recommender = Cmfrec::Recommender.new(factors: 20)
|
124
|
+
recommender.fit(ratings.first(80000), user_info: user_info, item_info: item_info)
|
125
|
+
recommender.predict(ratings.last(20000))
|
126
|
+
```
|
127
|
+
|
110
128
|
## Options
|
111
129
|
|
112
130
|
Specify the number of factors and epochs
|
@@ -167,6 +185,14 @@ recommender.user_bias
|
|
167
185
|
recommender.item_bias
|
168
186
|
```
|
169
187
|
|
188
|
+
## Windows Installation
|
189
|
+
|
190
|
+
On Windows, build the [cmfrec C shared library](https://github.com/david-cortes/cmfrec#instalation) and set:
|
191
|
+
|
192
|
+
```ruby
|
193
|
+
Cmfrec.ffi_lib = "path/to/cmfrec.dll"
|
194
|
+
```
|
195
|
+
|
170
196
|
## History
|
171
197
|
|
172
198
|
View the [changelog](https://github.com/ankane/cmfrec/blob/master/CHANGELOG.md)
|
data/lib/cmfrec.rb
CHANGED
@@ -3,12 +3,15 @@ require "etc"
|
|
3
3
|
require "fiddle/import"
|
4
4
|
|
5
5
|
# modules
|
6
|
+
require "cmfrec/data"
|
6
7
|
require "cmfrec/recommender"
|
7
8
|
require "cmfrec/version"
|
8
9
|
|
9
10
|
module Cmfrec
|
10
11
|
class Error < StandardError; end
|
11
12
|
|
13
|
+
extend Data
|
14
|
+
|
12
15
|
class << self
|
13
16
|
attr_accessor :ffi_lib
|
14
17
|
end
|
data/lib/cmfrec/data.rb
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
module Cmfrec
|
2
|
+
module Data
|
3
|
+
def load_movielens
|
4
|
+
require "csv"
|
5
|
+
|
6
|
+
data_path = download_file("ml-100k/u.data", "http://files.grouplens.org/datasets/movielens/ml-100k/u.data",
|
7
|
+
file_hash: "06416e597f82b7342361e41163890c81036900f418ad91315590814211dca490")
|
8
|
+
user_path = download_file("ml-100k/u.user", "http://files.grouplens.org/datasets/movielens/ml-100k/u.user",
|
9
|
+
file_hash: "f120e114da2e8cf314fd28f99417c94ae9ddf1cb6db8ce0e4b5995d40e90e62c")
|
10
|
+
item_path = download_file("ml-100k/u.item", "http://files.grouplens.org/datasets/movielens/ml-100k/u.item",
|
11
|
+
file_hash: "553841ebc7de3a0fd0d6b62a204ea30c1e651aacfb2814c7a6584ac52f2c5701")
|
12
|
+
|
13
|
+
# convert u.item to utf-8
|
14
|
+
movies_str = File.read(item_path).encode("UTF-8", "binary", invalid: :replace, undef: :replace, replace: "")
|
15
|
+
|
16
|
+
user_info = []
|
17
|
+
CSV.foreach(user_path, col_sep: "|") do |row|
|
18
|
+
user = {user_id: row[0].to_i}
|
19
|
+
10.times do |i|
|
20
|
+
user[:"region#{i}"] = row[4][0] == i.to_s ? 1 : 0
|
21
|
+
end
|
22
|
+
user_info << user
|
23
|
+
end
|
24
|
+
|
25
|
+
item_info = []
|
26
|
+
movies = {}
|
27
|
+
genres = %w(unknown action adventure animation childrens comedy crime documentary drama fantasy filmnoir horror musical mystery romance scifi thriller war western)
|
28
|
+
CSV.parse(movies_str, col_sep: "|", converters: [:numeric]) do |row|
|
29
|
+
movies[row[0]] = row[1]
|
30
|
+
item = {item_id: row[1], year: row[2] ? Date.parse(row[2]).year : 1970}
|
31
|
+
genres.each_with_index do |genre, i|
|
32
|
+
item[:"genre_#{genre}"] = row[i + 5]
|
33
|
+
end
|
34
|
+
item_info << item
|
35
|
+
end
|
36
|
+
|
37
|
+
data = []
|
38
|
+
CSV.foreach(data_path, col_sep: "\t", converters: [:numeric]) do |row|
|
39
|
+
data << {
|
40
|
+
user_id: row[0],
|
41
|
+
item_id: movies[row[1]],
|
42
|
+
rating: row[2]
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
[data, user_info, item_info]
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def download_file(fname, origin, file_hash:)
|
52
|
+
require "fileutils"
|
53
|
+
|
54
|
+
# TODO handle this better
|
55
|
+
raise "No HOME" unless ENV["HOME"]
|
56
|
+
dest = "#{ENV["HOME"]}/.cmfrec/#{fname}"
|
57
|
+
FileUtils.mkdir_p(File.dirname(dest))
|
58
|
+
|
59
|
+
return dest if File.exist?(dest)
|
60
|
+
|
61
|
+
require "digest"
|
62
|
+
require "net/http"
|
63
|
+
require "tmpdir"
|
64
|
+
|
65
|
+
temp_path = "#{Dir.tmpdir}/cmfrec-#{Time.now.to_f}" # TODO better name
|
66
|
+
|
67
|
+
digest = Digest::SHA2.new
|
68
|
+
|
69
|
+
uri = URI(origin)
|
70
|
+
|
71
|
+
# Net::HTTP automatically adds Accept-Encoding for compression
|
72
|
+
# of response bodies and automatically decompresses gzip
|
73
|
+
# and deflateresponses unless a Range header was sent.
|
74
|
+
# https://ruby-doc.org/stdlib-2.6.4/libdoc/net/http/rdoc/Net/HTTP.html
|
75
|
+
Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https") do |http|
|
76
|
+
request = Net::HTTP::Get.new(uri)
|
77
|
+
|
78
|
+
puts "Downloading data from #{origin}"
|
79
|
+
File.open(temp_path, "wb") do |f|
|
80
|
+
http.request(request) do |response|
|
81
|
+
response.read_body do |chunk|
|
82
|
+
f.write(chunk)
|
83
|
+
digest.update(chunk)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
if digest.hexdigest != file_hash
|
90
|
+
raise Error, "Bad hash: #{digest.hexdigest}"
|
91
|
+
end
|
92
|
+
|
93
|
+
puts "Hash verified: #{file_hash}"
|
94
|
+
|
95
|
+
FileUtils.mv(temp_path, dest)
|
96
|
+
|
97
|
+
dest
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
data/lib/cmfrec/ffi.rb
CHANGED
@@ -10,17 +10,19 @@ module Cmfrec
|
|
10
10
|
raise e
|
11
11
|
end
|
12
12
|
|
13
|
+
# https://github.com/david-cortes/cmfrec/blob/master/src/cmfrec.h
|
14
|
+
|
13
15
|
typealias "bool", "char"
|
14
16
|
# determined by CMakeLists.txt
|
15
17
|
typealias "int_t", "int"
|
16
18
|
typealias "real_t", "double"
|
17
19
|
|
18
|
-
extern "int_t fit_collective_explicit_als(real_t *biasA, real_t *biasB, real_t *A, real_t *B, real_t *C, real_t *D, real_t *Ai, real_t *Bi, bool add_implicit_features, bool reset_values, int_t seed, real_t *glob_mean, real_t *U_colmeans, real_t *I_colmeans, int_t m, int_t n, int_t k, int_t
|
19
|
-
extern "int_t fit_collective_implicit_als(real_t *A, real_t *B, real_t *C, real_t *D, bool reset_values, int_t seed, real_t *U_colmeans, real_t *I_colmeans, int_t m, int_t n, int_t k, int_t
|
20
|
-
extern "int_t factors_collective_explicit_single(real_t *a_vec, real_t *a_bias,
|
21
|
-
extern "int_t factors_collective_implicit_single(real_t *a_vec,
|
22
|
-
extern "void predict_multiple(real_t *restrict A, int_t k_user, real_t *restrict B, int_t k_item, real_t *restrict biasA, real_t *restrict biasB, real_t glob_mean, int_t k, int_t k_main, int_t m, int_t n, int_t predA[], int_t predB[], size_t nnz, real_t *restrict outp, int_t nthreads)"
|
20
|
+
extern "int_t fit_collective_explicit_als(real_t *restrict biasA, real_t *restrict biasB, real_t *restrict A, real_t *restrict B, real_t *restrict C, real_t *restrict D, real_t *restrict Ai, real_t *restrict Bi, bool add_implicit_features, bool reset_values, int_t seed, real_t *restrict glob_mean, real_t *restrict U_colmeans, real_t *restrict I_colmeans, int_t m, int_t n, int_t k, int_t ixA[], int_t ixB[], real_t *restrict X, size_t nnz, real_t *restrict Xfull, real_t *restrict weight, bool user_bias, bool item_bias, bool center, real_t lam, real_t *restrict lam_unique, real_t l1_lam, real_t *restrict l1_lam_unique, bool scale_lam, bool scale_lam_sideinfo, real_t *restrict U, int_t m_u, int_t p, real_t *restrict II, int_t n_i, int_t q, int_t U_row[], int_t U_col[], real_t *restrict U_sp, size_t nnz_U, int_t I_row[], int_t I_col[], real_t *restrict I_sp, size_t nnz_I, bool NA_as_zero_X, bool NA_as_zero_U, bool NA_as_zero_I, int_t k_main, int_t k_user, int_t k_item, real_t w_main, real_t w_user, real_t w_item, real_t w_implicit, int_t niter, int_t nthreads, bool verbose, bool handle_interrupt, bool use_cg, int_t max_cg_steps, bool finalize_chol, bool nonneg, int_t max_cd_steps, bool nonneg_C, bool nonneg_D, bool precompute_for_predictions, bool include_all_X, real_t *restrict B_plus_bias, real_t *restrict precomputedBtB, real_t *restrict precomputedTransBtBinvBt, real_t *restrict precomputedBtXbias, real_t *restrict precomputedBeTBeChol, real_t *restrict precomputedBiTBi, real_t *restrict precomputedTransCtCinvCt, real_t *restrict precomputedCtCw)"
|
21
|
+
extern "int_t fit_collective_implicit_als(real_t *restrict A, real_t *restrict B, real_t *restrict C, real_t *restrict D, bool reset_values, int_t seed, real_t *restrict U_colmeans, real_t *restrict I_colmeans, int_t m, int_t n, int_t k, int_t ixA[], int_t ixB[], real_t *restrict X, size_t nnz, real_t lam, real_t *restrict lam_unique, real_t l1_lam, real_t *restrict l1_lam_unique, real_t *restrict U, int_t m_u, int_t p, real_t *restrict II, int_t n_i, int_t q, int_t U_row[], int_t U_col[], real_t *restrict U_sp, size_t nnz_U, int_t I_row[], int_t I_col[], real_t *restrict I_sp, size_t nnz_I, bool NA_as_zero_U, bool NA_as_zero_I, int_t k_main, int_t k_user, int_t k_item, real_t w_main, real_t w_user, real_t w_item, real_t *restrict w_main_multiplier, real_t alpha, bool adjust_weight, bool apply_log_transf, int_t niter, int_t nthreads, bool verbose, bool handle_interrupt, bool use_cg, int_t max_cg_steps, bool finalize_chol, bool nonneg, int_t max_cd_steps, bool nonneg_C, bool nonneg_D, bool precompute_for_predictions, real_t *restrict precomputedBtB, real_t *restrict precomputedBeTBe, real_t *restrict precomputedBeTBeChol)"
|
22
|
+
extern "int_t factors_collective_explicit_single(real_t *restrict a_vec, real_t *restrict a_bias,real_t *restrict u_vec, int_t p,real_t *restrict u_vec_sp, int_t u_vec_ixB[], size_t nnz_u_vec,real_t *restrict u_bin_vec, int_t pbin,bool NA_as_zero_U, bool NA_as_zero_X,bool nonneg,real_t *restrict C, real_t *restrict Cb,real_t glob_mean, real_t *restrict biasB,real_t *restrict U_colmeans,real_t *restrict Xa, int_t ixB[], size_t nnz,real_t *restrict Xa_dense, int_t n,real_t *restrict weight,real_t *restrict B,real_t *restrict Bi, bool add_implicit_features,int_t k, int_t k_user, int_t k_item, int_t k_main,real_t lam, real_t *restrict lam_unique,real_t l1_lam, real_t *restrict l1_lam_unique,bool scale_lam, bool scale_lam_sideinfo,real_t w_main, real_t w_user, real_t w_implicit,int_t n_max, bool include_all_X,real_t *restrict BtB,real_t *restrict TransBtBinvBt,real_t *restrict BtXbias,real_t *restrict BeTBeChol,real_t *restrict BiTBi,real_t *restrict CtCw,real_t *restrict TransCtCinvCt,real_t *restrict B_plus_bias)"
|
23
|
+
extern "int_t factors_collective_implicit_single(real_t *restrict a_vec,real_t *restrict u_vec, int_t p,real_t *restrict u_vec_sp, int_t u_vec_ixB[], size_t nnz_u_vec,bool NA_as_zero_U,bool nonneg,real_t *restrict U_colmeans,real_t *restrict B, int_t n, real_t *restrict C,real_t *restrict Xa, int_t ixB[], size_t nnz,int_t k, int_t k_user, int_t k_item, int_t k_main,real_t lam, real_t l1_lam, real_t alpha, real_t w_main, real_t w_user,real_t w_main_multiplier,bool apply_log_transf,real_t *restrict BeTBe,real_t *restrict BtB,real_t *restrict BeTBeChol)"
|
23
24
|
extern "int_t predict_X_old_collective_explicit(int_t row[], int_t col[], real_t *restrict predicted, size_t n_predict, real_t *restrict A, real_t *restrict biasA, real_t *restrict B, real_t *restrict biasB, real_t glob_mean, int_t k, int_t k_user, int_t k_item, int_t k_main, int_t m, int_t n_max, int_t nthreads)"
|
25
|
+
extern "int_t predict_X_old_collective_implicit(int_t row[], int_t col[], real_t *restrict predicted, size_t n_predict, real_t *restrict A, real_t *restrict B, int_t k, int_t k_user, int_t k_item, int_t k_main, int_t m, int_t n, int_t nthreads)"
|
24
26
|
extern "int_t topN(real_t *restrict a_vec, int_t k_user, real_t *restrict B, int_t k_item, real_t *restrict biasB, real_t glob_mean, real_t biasA, int_t k, int_t k_main, int_t *restrict include_ix, int_t n_include, int_t *restrict exclude_ix, int_t n_exclude, int_t *restrict outp_ix, real_t *restrict outp_score, int_t n_top, int_t n, int_t nthreads)"
|
25
27
|
end
|
26
28
|
end
|
data/lib/cmfrec/recommender.rb
CHANGED
@@ -46,6 +46,8 @@ module Cmfrec
|
|
46
46
|
x_full = nil
|
47
47
|
weight = nil
|
48
48
|
lam_unique = nil
|
49
|
+
l1_lambda = 0
|
50
|
+
l1_lam_unique = nil
|
49
51
|
|
50
52
|
uu = nil
|
51
53
|
ii = nil
|
@@ -92,6 +94,7 @@ module Cmfrec
|
|
92
94
|
@m, @n, @k,
|
93
95
|
x_row, x_col, x, nnz,
|
94
96
|
@lambda_, lam_unique,
|
97
|
+
l1_lambda, l1_lam_unique,
|
95
98
|
uu, @m_u, p_,
|
96
99
|
ii, @n_i, q,
|
97
100
|
u_row, u_col, u_sp, nnz_u,
|
@@ -125,6 +128,10 @@ module Cmfrec
|
|
125
128
|
|
126
129
|
glob_mean = Fiddle::Pointer.malloc(Fiddle::SIZEOF_DOUBLE)
|
127
130
|
|
131
|
+
center = true
|
132
|
+
scale_lam = false
|
133
|
+
scale_lam_sideinfo = false
|
134
|
+
|
128
135
|
args = [
|
129
136
|
@bias_a, @bias_b,
|
130
137
|
@a, @b,
|
@@ -138,8 +145,10 @@ module Cmfrec
|
|
138
145
|
x_row, x_col, x, nnz,
|
139
146
|
x_full,
|
140
147
|
weight,
|
141
|
-
@user_bias, @item_bias,
|
148
|
+
@user_bias, @item_bias, center,
|
142
149
|
@lambda_, lam_unique,
|
150
|
+
l1_lambda, l1_lam_unique,
|
151
|
+
scale_lam, scale_lam_sideinfo,
|
143
152
|
uu, @m_u, p_,
|
144
153
|
ii, @n_i, q,
|
145
154
|
u_row, u_col, u_sp, nnz_u,
|
@@ -155,6 +164,7 @@ module Cmfrec
|
|
155
164
|
nil, #B_plus_bias,
|
156
165
|
nil, #precomputedBtB,
|
157
166
|
nil, #precomputedTransBtBinvBt,
|
167
|
+
nil, #precomputedBtXbias
|
158
168
|
nil, #precomputedBeTBeChol,
|
159
169
|
nil, #precomputedBiTBi,
|
160
170
|
nil, #precomputedTransCtCinvCt,
|
@@ -177,41 +187,36 @@ module Cmfrec
|
|
177
187
|
|
178
188
|
data = to_dataset(data)
|
179
189
|
|
180
|
-
u = data.map { |v| @user_map[v[:user_id]] ||
|
181
|
-
i = data.map { |v| @item_map[v[:item_id]] ||
|
182
|
-
|
183
|
-
pred_a = int_ptr(u)
|
184
|
-
pred_b = int_ptr(i)
|
185
|
-
nnz = data.size
|
186
|
-
outp = Fiddle::Pointer.malloc(nnz * Fiddle::SIZEOF_DOUBLE)
|
190
|
+
u = data.map { |v| @user_map[v[:user_id]] || @user_map.size }
|
191
|
+
i = data.map { |v| @item_map[v[:item_id]] || @item_map.size }
|
187
192
|
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
@global_mean,
|
193
|
-
@k, @k_main,
|
194
|
-
@m, @n,
|
195
|
-
pred_a, pred_b, nnz,
|
196
|
-
outp,
|
197
|
-
@nthreads
|
198
|
-
)
|
193
|
+
row = int_ptr(u)
|
194
|
+
col = int_ptr(i)
|
195
|
+
n_predict = data.size
|
196
|
+
predicted = Fiddle::Pointer.malloc(n_predict * Fiddle::SIZEOF_DOUBLE)
|
199
197
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
198
|
+
if @implicit
|
199
|
+
check_status FFI.predict_X_old_collective_implicit(
|
200
|
+
row, col, predicted, n_predict,
|
201
|
+
@a, @b,
|
202
|
+
@k, @k_user, @k_item, @k_main,
|
203
|
+
@m, @n,
|
204
|
+
@nthreads
|
205
|
+
)
|
206
|
+
else
|
207
|
+
check_status FFI.predict_X_old_collective_explicit(
|
208
|
+
row, col, predicted, n_predict,
|
209
|
+
@a, @bias_a,
|
210
|
+
@b, @bias_b,
|
211
|
+
@global_mean,
|
212
|
+
@k, @k_user, @k_item, @k_main,
|
213
|
+
@m, @n,
|
214
|
+
@nthreads
|
215
|
+
)
|
213
216
|
end
|
214
217
|
|
218
|
+
predictions = real_array(predicted)
|
219
|
+
predictions.map! { |v| v.nan? ? @global_mean : v } if @implicit
|
215
220
|
predictions
|
216
221
|
end
|
217
222
|
|
@@ -448,6 +453,8 @@ module Cmfrec
|
|
448
453
|
|
449
454
|
weight = nil
|
450
455
|
lam_unique = nil
|
456
|
+
l1_lambda = 0
|
457
|
+
l1_lam_unique = nil
|
451
458
|
n_max = @n
|
452
459
|
|
453
460
|
if data.any?
|
@@ -476,7 +483,7 @@ module Cmfrec
|
|
476
483
|
@b, @n, @c,
|
477
484
|
xa, x_col, nnz,
|
478
485
|
@k, @k_user, @k_item, @k_main,
|
479
|
-
@lambda_, @alpha,
|
486
|
+
@lambda_, l1_lambda, @alpha,
|
480
487
|
@w_main, @w_user, @w_main_multiplier,
|
481
488
|
@apply_log_transf,
|
482
489
|
nil, #BeTBe,
|
@@ -487,6 +494,9 @@ module Cmfrec
|
|
487
494
|
else
|
488
495
|
cb = nil
|
489
496
|
|
497
|
+
scale_lam = false
|
498
|
+
scale_lam_sideinfo = false
|
499
|
+
|
490
500
|
args = [
|
491
501
|
a_vec, bias_a,
|
492
502
|
u_vec, p_,
|
@@ -501,11 +511,14 @@ module Cmfrec
|
|
501
511
|
@add_implicit_features,
|
502
512
|
@k, @k_user, @k_item, @k_main,
|
503
513
|
@lambda_, lam_unique,
|
514
|
+
l1_lambda, l1_lam_unique,
|
515
|
+
scale_lam, scale_lam_sideinfo,
|
504
516
|
@w_main, @w_user, @w_implicit,
|
505
517
|
n_max,
|
506
518
|
@include_all_x,
|
507
|
-
nil, #TransBtBinvBt,
|
508
519
|
nil, #BtB,
|
520
|
+
nil, #TransBtBinvBt,
|
521
|
+
nil, #BtXbias,
|
509
522
|
nil, #BeTBeChol,
|
510
523
|
nil, #BiTBi,
|
511
524
|
nil, #CtCw,
|
data/lib/cmfrec/version.rb
CHANGED
data/vendor/libcmfrec.dylib
CHANGED
Binary file
|
data/vendor/libcmfrec.so
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cmfrec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-12-10 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email: andrew@chartkick.com
|
@@ -20,6 +20,7 @@ files:
|
|
20
20
|
- LICENSE.txt
|
21
21
|
- README.md
|
22
22
|
- lib/cmfrec.rb
|
23
|
+
- lib/cmfrec/data.rb
|
23
24
|
- lib/cmfrec/ffi.rb
|
24
25
|
- lib/cmfrec/recommender.rb
|
25
26
|
- lib/cmfrec/version.rb
|