cmfrec 0.1.5 → 0.2.0
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 +4 -4
- data/CHANGELOG.md +22 -0
- data/README.md +21 -16
- data/lib/cmfrec/data.rb +12 -7
- data/lib/cmfrec/ffi.rb +8 -7
- data/lib/cmfrec/recommender.rb +254 -192
- data/lib/cmfrec/version.rb +1 -1
- data/lib/cmfrec.rb +7 -7
- data/vendor/arm64-darwin/COPYRIGHTS +57 -0
- data/vendor/arm64-darwin/LICENSE +23 -0
- data/vendor/arm64-darwin/libcmfrec.dylib +0 -0
- data/vendor/x86_64-darwin/COPYRIGHTS +57 -0
- data/vendor/x86_64-darwin/LICENSE +23 -0
- data/vendor/x86_64-darwin/libcmfrec.dylib +0 -0
- data/vendor/x86_64-linux/COPYRIGHTS +57 -0
- data/vendor/x86_64-linux/LICENSE +23 -0
- data/vendor/x86_64-linux/libcmfrec.so +0 -0
- metadata +14 -9
- data/vendor/LICENSE.txt +0 -74
- data/vendor/libcmfrec.arm64.dylib +0 -0
- data/vendor/libcmfrec.dylib +0 -0
- data/vendor/libcmfrec.so +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e6dbbc801e415a4f505ffc436be23ccf066d144da072669e782b88c02e14b0f8
|
|
4
|
+
data.tar.gz: 3851230f0a4dc4be9fbc24fe81681de0758bdbb583803780f8e07b10741f4bd1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 103c09a7c0e13fca3cb81dc68c667e776fc965a485cf358e0fc8f350a97474b54bdfc0910f4472051020dbe34b8c097908c1024d5fc036ad77d0444372885109
|
|
7
|
+
data.tar.gz: b107b36333f714106d981168f24fda48a2a211f288a2dbe01f570adb607b7d6a5215c18df4c67d159bb367d652f3d10faeb4dbc66688eaf117c5b7a1432ee951
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
## 0.2.0 (2022-06-14)
|
|
2
|
+
|
|
3
|
+
- Updated cmfrec to 3.4.2
|
|
4
|
+
- Fixed missing item ids with `load_movielens`
|
|
5
|
+
- Dropped support for Ruby < 2.7
|
|
6
|
+
|
|
7
|
+
## 0.1.7 (2022-03-22)
|
|
8
|
+
|
|
9
|
+
- Improved ARM detection
|
|
10
|
+
- Fixed error with `load_movielens`
|
|
11
|
+
- Fixed duplicates in `item_info` with `load_movielens`
|
|
12
|
+
|
|
13
|
+
## 0.1.6 (2021-08-12)
|
|
14
|
+
|
|
15
|
+
- Added `user_ids` and `item_ids` methods
|
|
16
|
+
- Added `user_id` argument to `user_factors`
|
|
17
|
+
- Added `item_id` argument to `item_factors`
|
|
18
|
+
- Added `user_id` argument to `user_bias`
|
|
19
|
+
- Added `item_id` argument to `item_bias`
|
|
20
|
+
- Added `item_ids` argument to `new_user_recs`
|
|
21
|
+
- Fixed order for `user_recs`
|
|
22
|
+
|
|
1
23
|
## 0.1.5 (2021-08-10)
|
|
2
24
|
|
|
3
25
|
- Fixed issue with `user_recs` and `new_user_recs` returning rated items
|
data/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# cmfrec
|
|
1
|
+
# cmfrec Ruby
|
|
2
2
|
|
|
3
3
|
:fire: Recommendations for Ruby, powered by [cmfrec](https://github.com/david-cortes/cmfrec)
|
|
4
4
|
|
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
- Works with explicit and implicit feedback
|
|
7
7
|
- Uses high-performance matrix factorization
|
|
8
8
|
|
|
9
|
-
[](https://github.com/ankane/cmfrec/actions)
|
|
9
|
+
[](https://github.com/ankane/cmfrec-ruby/actions)
|
|
10
10
|
|
|
11
11
|
## Installation
|
|
12
12
|
|
|
13
13
|
Add this line to your application’s Gemfile:
|
|
14
14
|
|
|
15
15
|
```ruby
|
|
16
|
-
gem
|
|
16
|
+
gem "cmfrec"
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
For Windows, also follow [these instructions](#windows-installation).
|
|
@@ -58,8 +58,8 @@ Get recommendations for a new user
|
|
|
58
58
|
|
|
59
59
|
```ruby
|
|
60
60
|
recommender.new_user_recs([
|
|
61
|
-
{item_id: 1,
|
|
62
|
-
{item_id: 2,
|
|
61
|
+
{item_id: 1, rating: 5},
|
|
62
|
+
{item_id: 2, rating: 3}
|
|
63
63
|
])
|
|
64
64
|
```
|
|
65
65
|
|
|
@@ -112,7 +112,7 @@ recommender.new_user_recs([], user_info: {cats: 0, dogs: 2})
|
|
|
112
112
|
Add this line to your application’s Gemfile:
|
|
113
113
|
|
|
114
114
|
```ruby
|
|
115
|
-
gem
|
|
115
|
+
gem "ngt"
|
|
116
116
|
```
|
|
117
117
|
|
|
118
118
|
Get similar users
|
|
@@ -150,11 +150,7 @@ recommender.predict(ratings.last(20000))
|
|
|
150
150
|
[Ahoy](https://github.com/ankane/ahoy) is a great source for implicit feedback
|
|
151
151
|
|
|
152
152
|
```ruby
|
|
153
|
-
views = Ahoy::Event.
|
|
154
|
-
where(name: "Viewed post").
|
|
155
|
-
group(:user_id).
|
|
156
|
-
group("properties->>'post_id'"). # postgres syntax
|
|
157
|
-
count
|
|
153
|
+
views = Ahoy::Event.where(name: "Viewed post").group(:user_id).group_prop(:post_id).count
|
|
158
154
|
|
|
159
155
|
data =
|
|
160
156
|
views.map do |(user_id, post_id), count|
|
|
@@ -230,8 +226,17 @@ bin = File.binread("recommender.bin")
|
|
|
230
226
|
recommender = Marshal.load(bin)
|
|
231
227
|
```
|
|
232
228
|
|
|
229
|
+
Alternatively, you can store only the factors and use a library like [Neighbor](https://github.com/ankane/neighbor). See the [examples](https://github.com/ankane/neighbor/tree/master/examples) for Disco, which has a similar API. For explicit feedback, you should [disable the bias](#explicit-feedback) with this approach.
|
|
230
|
+
|
|
233
231
|
## Reference
|
|
234
232
|
|
|
233
|
+
Get ids
|
|
234
|
+
|
|
235
|
+
```ruby
|
|
236
|
+
recommender.user_ids
|
|
237
|
+
recommender.item_ids
|
|
238
|
+
```
|
|
239
|
+
|
|
235
240
|
Get the global mean
|
|
236
241
|
|
|
237
242
|
```ruby
|
|
@@ -262,22 +267,22 @@ Cmfrec.ffi_lib = "path/to/cmfrec.dll"
|
|
|
262
267
|
|
|
263
268
|
## History
|
|
264
269
|
|
|
265
|
-
View the [changelog](https://github.com/ankane/cmfrec/blob/master/CHANGELOG.md)
|
|
270
|
+
View the [changelog](https://github.com/ankane/cmfrec-ruby/blob/master/CHANGELOG.md)
|
|
266
271
|
|
|
267
272
|
## Contributing
|
|
268
273
|
|
|
269
274
|
Everyone is encouraged to help improve this project. Here are a few ways you can help:
|
|
270
275
|
|
|
271
|
-
- [Report bugs](https://github.com/ankane/cmfrec/issues)
|
|
272
|
-
- Fix bugs and [submit pull requests](https://github.com/ankane/cmfrec/pulls)
|
|
276
|
+
- [Report bugs](https://github.com/ankane/cmfrec-ruby/issues)
|
|
277
|
+
- Fix bugs and [submit pull requests](https://github.com/ankane/cmfrec-ruby/pulls)
|
|
273
278
|
- Write, clarify, or fix documentation
|
|
274
279
|
- Suggest or add new features
|
|
275
280
|
|
|
276
281
|
To get started with development:
|
|
277
282
|
|
|
278
283
|
```sh
|
|
279
|
-
git clone https://github.com/ankane/cmfrec.git
|
|
280
|
-
cd cmfrec
|
|
284
|
+
git clone https://github.com/ankane/cmfrec-ruby.git
|
|
285
|
+
cd cmfrec-ruby
|
|
281
286
|
bundle install
|
|
282
287
|
bundle exec rake vendor:all
|
|
283
288
|
bundle exec rake test
|
data/lib/cmfrec/data.rb
CHANGED
|
@@ -3,11 +3,11 @@ module Cmfrec
|
|
|
3
3
|
def load_movielens
|
|
4
4
|
require "csv"
|
|
5
5
|
|
|
6
|
-
data_path = download_file("ml-100k/u.data", "
|
|
6
|
+
data_path = download_file("ml-100k/u.data", "https://files.grouplens.org/datasets/movielens/ml-100k/u.data",
|
|
7
7
|
file_hash: "06416e597f82b7342361e41163890c81036900f418ad91315590814211dca490")
|
|
8
|
-
user_path = download_file("ml-100k/u.user", "
|
|
8
|
+
user_path = download_file("ml-100k/u.user", "https://files.grouplens.org/datasets/movielens/ml-100k/u.user",
|
|
9
9
|
file_hash: "f120e114da2e8cf314fd28f99417c94ae9ddf1cb6db8ce0e4b5995d40e90e62c")
|
|
10
|
-
item_path = download_file("ml-100k/u.item", "
|
|
10
|
+
item_path = download_file("ml-100k/u.item", "https://files.grouplens.org/datasets/movielens/ml-100k/u.item",
|
|
11
11
|
file_hash: "553841ebc7de3a0fd0d6b62a204ea30c1e651aacfb2814c7a6584ac52f2c5701")
|
|
12
12
|
|
|
13
13
|
# convert u.item to utf-8
|
|
@@ -24,9 +24,15 @@ module Cmfrec
|
|
|
24
24
|
|
|
25
25
|
item_info = []
|
|
26
26
|
movies = {}
|
|
27
|
+
movie_names = {}
|
|
27
28
|
genres = %w(unknown action adventure animation childrens comedy crime documentary drama fantasy filmnoir horror musical mystery romance scifi thriller war western)
|
|
28
29
|
CSV.parse(movies_str, col_sep: "|", converters: [:numeric]) do |row|
|
|
29
30
|
movies[row[0]] = row[1]
|
|
31
|
+
|
|
32
|
+
# filter duplicates
|
|
33
|
+
next if movie_names[row[1]]
|
|
34
|
+
movie_names[row[1]] = true
|
|
35
|
+
|
|
30
36
|
item = {item_id: row[1], year: row[2] ? Date.parse(row[2]).year : 1970}
|
|
31
37
|
genres.each_with_index do |genre, i|
|
|
32
38
|
item[:"genre_#{genre}"] = row[i + 5]
|
|
@@ -49,7 +55,10 @@ module Cmfrec
|
|
|
49
55
|
private
|
|
50
56
|
|
|
51
57
|
def download_file(fname, origin, file_hash:)
|
|
58
|
+
require "digest"
|
|
52
59
|
require "fileutils"
|
|
60
|
+
require "net/http"
|
|
61
|
+
require "tmpdir"
|
|
53
62
|
|
|
54
63
|
# TODO handle this better
|
|
55
64
|
raise "No HOME" unless ENV["HOME"]
|
|
@@ -58,10 +67,6 @@ module Cmfrec
|
|
|
58
67
|
|
|
59
68
|
return dest if File.exist?(dest)
|
|
60
69
|
|
|
61
|
-
require "digest"
|
|
62
|
-
require "net/http"
|
|
63
|
-
require "tmpdir"
|
|
64
|
-
|
|
65
70
|
temp_path = "#{Dir.tmpdir}/cmfrec-#{Time.now.to_f}" # TODO better name
|
|
66
71
|
|
|
67
72
|
digest = Digest::SHA2.new
|
data/lib/cmfrec/ffi.rb
CHANGED
|
@@ -17,12 +17,13 @@ module Cmfrec
|
|
|
17
17
|
typealias "int_t", "int"
|
|
18
18
|
typealias "real_t", "double"
|
|
19
19
|
|
|
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,
|
|
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,
|
|
22
|
-
extern "int_t
|
|
23
|
-
extern "int_t
|
|
24
|
-
extern "int_t
|
|
25
|
-
extern "int_t
|
|
26
|
-
extern "int_t
|
|
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, bool scale_bias_const, real_t *scaling_biasA, real_t *scaling_biasB, 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 nthreads, bool verbose, bool handle_interrupt, bool use_cg, int_t max_cg_steps, bool precondition_cg, 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, real_t *precomputedCtUbias)"
|
|
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 nthreads, bool verbose, bool handle_interrupt, bool use_cg, int_t max_cg_steps, bool precondition_cg, 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, real_t *precomputedCtUbias)"
|
|
22
|
+
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 nthreads)"
|
|
23
|
+
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 nthreads)"
|
|
24
|
+
extern "int_t topN_old_collective_explicit(real_t *a_vec, real_t a_bias, real_t *A, real_t *biasA, int_t row_index, real_t *B, real_t *biasB, real_t glob_mean, int_t k, int_t k_user, int_t k_item, int_t k_main, int_t *include_ix, int_t n_include, int_t *exclude_ix, int_t n_exclude, int_t *outp_ix, real_t *outp_score, int_t n_top, int_t n, int_t n_max, bool include_all_X, int nthreads)"
|
|
25
|
+
extern "int_t topN_old_collective_implicit(real_t *a_vec, real_t *A, int_t row_index, real_t *B, int_t k, int_t k_user, int_t k_item, int_t k_main, int_t *include_ix, int_t n_include, int_t *exclude_ix, int_t n_exclude, int_t *outp_ix, real_t *outp_score, int_t n_top, int_t n, int nthreads)"
|
|
26
|
+
extern "int_t topN_new_collective_explicit(bool user_bias, real_t *u_vec, int_t p, real_t *u_vec_sp, int_t u_vec_X_col[], size_t nnz_u_vec, real_t *u_bin_vec, int_t pbin, bool NA_as_zero_U, bool NA_as_zero_X, bool nonneg, real_t *C, real_t *Cb, real_t glob_mean, real_t *biasB, real_t *U_colmeans, real_t *Xa, int_t X_col[], size_t nnz, real_t *Xa_dense, int_t n, real_t *weight, real_t *B, real_t *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 *lam_unique, real_t l1_lam, real_t *l1_lam_unique, bool scale_lam, bool scale_lam_sideinfo, bool scale_bias_const, real_t scaling_biasA, real_t w_main, real_t w_user, real_t w_implicit, int_t n_max, bool include_all_X, real_t *BtB, real_t *TransBtBinvBt, real_t *BtXbias, real_t *BeTBeChol, real_t *BiTBi, real_t *CtCw, real_t *TransCtCinvCt, real_t *CtUbias, real_t *B_plus_bias, int_t *include_ix, int_t n_include, int_t *exclude_ix, int_t n_exclude, int_t *outp_ix, real_t *outp_score, int_t n_top, int nthreads)"
|
|
27
|
+
extern "int_t topN_new_collective_implicit(int_t n, real_t *u_vec, int_t p, real_t *u_vec_sp, int_t u_vec_X_col[], size_t nnz_u_vec, bool NA_as_zero_U, bool nonneg, real_t *U_colmeans, real_t *B, real_t *C, real_t *Xa, int_t X_col[], 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 *BeTBe, real_t *BtB, real_t *BeTBeChol, real_t *CtUbias, int_t *include_ix, int_t n_include, int_t *exclude_ix, int_t n_exclude, int_t *outp_ix, real_t *outp_score, int_t n_top, int nthreads)"
|
|
27
28
|
end
|
|
28
29
|
end
|
data/lib/cmfrec/recommender.rb
CHANGED
|
@@ -67,23 +67,10 @@ module Cmfrec
|
|
|
67
67
|
user = @user_map[user_id]
|
|
68
68
|
|
|
69
69
|
if user
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
data = item_ids.map { |v| {user_id: user_id, item_id: v} }
|
|
76
|
-
scores = predict(data)
|
|
77
|
-
|
|
78
|
-
item_ids.zip(scores).map do |item_id, score|
|
|
79
|
-
{item_id: item_id, score: score}
|
|
80
|
-
end
|
|
81
|
-
else
|
|
82
|
-
a_vec = @a[user * @k * Fiddle::SIZEOF_DOUBLE, @k * Fiddle::SIZEOF_DOUBLE]
|
|
83
|
-
a_bias = @bias_a ? @bias_a[user * Fiddle::SIZEOF_DOUBLE, Fiddle::SIZEOF_DOUBLE].unpack1("d") : 0
|
|
84
|
-
# @rated[user] will be nil for recommenders saved before 0.1.5
|
|
85
|
-
top_n(a_vec: a_vec, a_bias: a_bias, count: count, rated: (@rated[user] || {}).keys)
|
|
86
|
-
end
|
|
70
|
+
a_vec = @a[user * @k * Fiddle::SIZEOF_DOUBLE, @k * Fiddle::SIZEOF_DOUBLE]
|
|
71
|
+
a_bias = @bias_a ? @bias_a[user * Fiddle::SIZEOF_DOUBLE, Fiddle::SIZEOF_DOUBLE].unpack1("d") : 0
|
|
72
|
+
# @rated[user] will be nil for recommenders saved before 0.1.5
|
|
73
|
+
top_n(a_vec: a_vec, a_bias: a_bias, count: count, rated: (@rated[user] || {}).keys, item_ids: item_ids, row_index: user)
|
|
87
74
|
else
|
|
88
75
|
# no items if user is unknown
|
|
89
76
|
# TODO maybe most popular items
|
|
@@ -91,28 +78,164 @@ module Cmfrec
|
|
|
91
78
|
end
|
|
92
79
|
end
|
|
93
80
|
|
|
94
|
-
|
|
95
|
-
def new_user_recs(data, count: 5, user_info: nil)
|
|
81
|
+
def new_user_recs(data, count: 5, user_info: nil, item_ids: nil)
|
|
96
82
|
check_fit
|
|
97
83
|
|
|
98
|
-
|
|
99
|
-
|
|
84
|
+
data = to_dataset(data)
|
|
85
|
+
user_info = to_dataset(user_info) if user_info
|
|
86
|
+
|
|
87
|
+
# remove unknown items
|
|
88
|
+
data, unknown_data = data.partition { |d| @item_map[d[:item_id]] }
|
|
89
|
+
|
|
90
|
+
if unknown_data.any?
|
|
91
|
+
# TODO warn for unknown items?
|
|
92
|
+
# warn "[cmfrec] Unknown items: #{unknown_data.map { |d| d[:item_id] }.join(", ")}"
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
rated_ids = data.map { |d| @item_map[d[:item_id]] }
|
|
96
|
+
|
|
97
|
+
nnz = data.size
|
|
98
|
+
|
|
99
|
+
u_vec_sp = []
|
|
100
|
+
u_vec_x_col = []
|
|
101
|
+
if user_info
|
|
102
|
+
user_info.each do |k, v|
|
|
103
|
+
next if k == :user_id
|
|
104
|
+
|
|
105
|
+
uc = @user_info_map[k]
|
|
106
|
+
raise "Bad key: #{k}" unless uc
|
|
107
|
+
|
|
108
|
+
u_vec_x_col << uc
|
|
109
|
+
u_vec_sp << v
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
p_ = @user_info_map.size
|
|
113
|
+
nnz_u_vec = u_vec_sp.size
|
|
114
|
+
u_vec_x_col = int_ptr(u_vec_x_col)
|
|
115
|
+
u_vec_sp = real_ptr(u_vec_sp)
|
|
116
|
+
|
|
117
|
+
u_vec = nil
|
|
118
|
+
u_bin_vec = nil
|
|
119
|
+
pbin = 0
|
|
120
|
+
|
|
121
|
+
weight = nil
|
|
122
|
+
lam_unique = nil
|
|
123
|
+
l1_lam_unique = nil
|
|
124
|
+
n_max = @n
|
|
125
|
+
|
|
126
|
+
if data.any?
|
|
127
|
+
if @implicit
|
|
128
|
+
ratings = data.map { |d| d[:value] || 1 }
|
|
129
|
+
else
|
|
130
|
+
ratings = data.map { |d| d[:rating] }
|
|
131
|
+
check_ratings(ratings)
|
|
132
|
+
end
|
|
133
|
+
xa = real_ptr(ratings)
|
|
134
|
+
x_col = int_ptr(rated_ids)
|
|
135
|
+
else
|
|
136
|
+
xa = nil
|
|
137
|
+
x_col = nil
|
|
138
|
+
end
|
|
139
|
+
xa_dense = nil
|
|
140
|
+
|
|
141
|
+
rated = rated_ids.uniq
|
|
142
|
+
|
|
143
|
+
prep = prepare_top_n(count: count, rated: rated, item_ids: item_ids)
|
|
144
|
+
return [] if prep.empty?
|
|
145
|
+
include_ix, n_include, exclude_ix, n_exclude, outp_ix, outp_score, count = prep
|
|
146
|
+
|
|
147
|
+
if @implicit
|
|
148
|
+
args = [
|
|
149
|
+
@n,
|
|
150
|
+
u_vec, p_,
|
|
151
|
+
u_vec_sp, u_vec_x_col, nnz_u_vec,
|
|
152
|
+
@na_as_zero_user,
|
|
153
|
+
@nonneg,
|
|
154
|
+
@u_colmeans,
|
|
155
|
+
@b, @c,
|
|
156
|
+
xa, x_col, nnz,
|
|
157
|
+
@k, @k_user, @k_item, @k_main,
|
|
158
|
+
@lambda_, @l1_lambda, @alpha, @w_main, @w_user,
|
|
159
|
+
@w_main_multiplier,
|
|
160
|
+
@apply_log_transf,
|
|
161
|
+
nil, #BeTBe,
|
|
162
|
+
nil, #BtB,
|
|
163
|
+
nil, #BeTBeChol,
|
|
164
|
+
nil, #CtUbias,
|
|
165
|
+
include_ix, n_include,
|
|
166
|
+
exclude_ix, n_exclude,
|
|
167
|
+
outp_ix, outp_score,
|
|
168
|
+
count, @nthreads
|
|
169
|
+
]
|
|
170
|
+
check_status FFI.topN_new_collective_implicit(*fiddle_args(args))
|
|
171
|
+
else
|
|
172
|
+
cb = nil
|
|
173
|
+
scaling_bias_a = 0
|
|
174
|
+
|
|
175
|
+
args = [
|
|
176
|
+
@user_bias,
|
|
177
|
+
u_vec, p_,
|
|
178
|
+
u_vec_sp, u_vec_x_col, nnz_u_vec,
|
|
179
|
+
u_bin_vec, pbin,
|
|
180
|
+
@na_as_zero_user, @na_as_zero,
|
|
181
|
+
@nonneg,
|
|
182
|
+
@c, cb,
|
|
183
|
+
@global_mean, @bias_b,
|
|
184
|
+
@u_colmeans,
|
|
185
|
+
xa, x_col, nnz,
|
|
186
|
+
xa_dense, @n,
|
|
187
|
+
weight,
|
|
188
|
+
@b,
|
|
189
|
+
@bi, @add_implicit_features,
|
|
190
|
+
@k, @k_user, @k_item, @k_main,
|
|
191
|
+
@lambda_, lam_unique,
|
|
192
|
+
@l1_lambda, l1_lam_unique,
|
|
193
|
+
@scale_lam, @scale_lam_sideinfo,
|
|
194
|
+
@scale_bias_const, scaling_bias_a,
|
|
195
|
+
@w_main, @w_user, @w_implicit,
|
|
196
|
+
n_max, @include_all_x,
|
|
197
|
+
nil, #BtB,
|
|
198
|
+
nil, #TransBtBinvBt,
|
|
199
|
+
nil, #BtXbias,
|
|
200
|
+
nil, #BeTBeChol,
|
|
201
|
+
nil, #BiTBi,
|
|
202
|
+
nil, #CtCw,
|
|
203
|
+
nil, #TransCtCinvCt,
|
|
204
|
+
nil, #CtUbias,
|
|
205
|
+
nil, #B_plus_bias,
|
|
206
|
+
include_ix, n_include,
|
|
207
|
+
exclude_ix, n_exclude,
|
|
208
|
+
outp_ix, outp_score,
|
|
209
|
+
count, @nthreads
|
|
210
|
+
]
|
|
211
|
+
check_status FFI.topN_new_collective_explicit(*fiddle_args(args))
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
top_n_output(outp_ix, outp_score)
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def user_ids
|
|
218
|
+
@user_map.keys
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def item_ids
|
|
222
|
+
@item_map.keys
|
|
100
223
|
end
|
|
101
224
|
|
|
102
|
-
def user_factors
|
|
103
|
-
read_factors(@a, [@m, @m_u].max, @k_user + @k + @k_main)
|
|
225
|
+
def user_factors(user_id = nil)
|
|
226
|
+
read_factors(@a, [@m, @m_u].max, @k_user + @k + @k_main, user_id, @user_map)
|
|
104
227
|
end
|
|
105
228
|
|
|
106
|
-
def item_factors
|
|
107
|
-
read_factors(@b, [@n, @n_i].max, @k_item + @k + @k_main)
|
|
229
|
+
def item_factors(item_id = nil)
|
|
230
|
+
read_factors(@b, [@n, @n_i].max, @k_item + @k + @k_main, item_id, @item_map)
|
|
108
231
|
end
|
|
109
232
|
|
|
110
|
-
def user_bias
|
|
111
|
-
read_bias(@bias_a) if @bias_a
|
|
233
|
+
def user_bias(user_id = nil)
|
|
234
|
+
read_bias(@bias_a, user_id, @user_map) if @bias_a
|
|
112
235
|
end
|
|
113
236
|
|
|
114
|
-
def item_bias
|
|
115
|
-
read_bias(@bias_b) if @bias_b
|
|
237
|
+
def item_bias(item_id = nil)
|
|
238
|
+
read_bias(@bias_b, item_id, @item_map) if @bias_b
|
|
116
239
|
end
|
|
117
240
|
|
|
118
241
|
def similar_items(item_id, count: 5)
|
|
@@ -216,7 +339,6 @@ module Cmfrec
|
|
|
216
339
|
x_full = nil
|
|
217
340
|
weight = nil
|
|
218
341
|
lam_unique = nil
|
|
219
|
-
l1_lambda = 0
|
|
220
342
|
l1_lam_unique = nil
|
|
221
343
|
|
|
222
344
|
uu = nil
|
|
@@ -253,7 +375,7 @@ module Cmfrec
|
|
|
253
375
|
@m, @n, @k,
|
|
254
376
|
x_row, x_col, x, nnz,
|
|
255
377
|
@lambda_, lam_unique,
|
|
256
|
-
l1_lambda, l1_lam_unique,
|
|
378
|
+
@l1_lambda, l1_lam_unique,
|
|
257
379
|
uu, @m_u, p_,
|
|
258
380
|
ii, @n_i, q,
|
|
259
381
|
u_row, u_col, u_sp, nnz_u,
|
|
@@ -263,12 +385,13 @@ module Cmfrec
|
|
|
263
385
|
@w_main, @w_user, @w_item, real_ptr([@w_main_multiplier]),
|
|
264
386
|
@alpha, @adjust_weight, @apply_log_transf,
|
|
265
387
|
@niter, @nthreads, @verbose, @handle_interrupt,
|
|
266
|
-
@use_cg, @max_cg_steps, @finalize_chol,
|
|
388
|
+
@use_cg, @max_cg_steps, @precondition_cg, @finalize_chol,
|
|
267
389
|
@nonneg, @max_cd_steps, @nonneg_c, @nonneg_d,
|
|
268
390
|
@precompute_for_predictions,
|
|
269
391
|
nil, #precomputedBtB,
|
|
270
392
|
nil, #precomputedBeTBe,
|
|
271
|
-
nil
|
|
393
|
+
nil, #precomputedBeTBeChol
|
|
394
|
+
nil #precomputedCtUbias
|
|
272
395
|
]
|
|
273
396
|
check_status FFI.fit_collective_implicit_als(*fiddle_args(args))
|
|
274
397
|
|
|
@@ -287,9 +410,9 @@ module Cmfrec
|
|
|
287
410
|
|
|
288
411
|
glob_mean = Fiddle::Pointer.malloc(Fiddle::SIZEOF_DOUBLE)
|
|
289
412
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
413
|
+
# TODO add
|
|
414
|
+
scaling_bias_a = nil
|
|
415
|
+
scaling_bias_b = nil
|
|
293
416
|
|
|
294
417
|
args = [
|
|
295
418
|
@bias_a, @bias_b,
|
|
@@ -304,10 +427,11 @@ module Cmfrec
|
|
|
304
427
|
x_row, x_col, x, nnz,
|
|
305
428
|
x_full,
|
|
306
429
|
weight,
|
|
307
|
-
@user_bias, @item_bias, center,
|
|
430
|
+
@user_bias, @item_bias, @center,
|
|
308
431
|
@lambda_, lam_unique,
|
|
309
|
-
l1_lambda, l1_lam_unique,
|
|
310
|
-
scale_lam, scale_lam_sideinfo,
|
|
432
|
+
@l1_lambda, l1_lam_unique,
|
|
433
|
+
@scale_lam, @scale_lam_sideinfo,
|
|
434
|
+
@scale_bias_const, scaling_bias_a, scaling_bias_b,
|
|
311
435
|
uu, @m_u, p_,
|
|
312
436
|
ii, @n_i, q,
|
|
313
437
|
u_row, u_col, u_sp, nnz_u,
|
|
@@ -316,7 +440,7 @@ module Cmfrec
|
|
|
316
440
|
@k_main, @k_user, @k_item,
|
|
317
441
|
@w_main, @w_user, @w_item, @w_implicit,
|
|
318
442
|
@niter, @nthreads, @verbose, @handle_interrupt,
|
|
319
|
-
@use_cg, @max_cg_steps, @finalize_chol,
|
|
443
|
+
@use_cg, @max_cg_steps, @precondition_cg, @finalize_chol,
|
|
320
444
|
@nonneg, @max_cd_steps, @nonneg_c, @nonneg_d,
|
|
321
445
|
@precompute_for_predictions,
|
|
322
446
|
@include_all_x,
|
|
@@ -327,7 +451,8 @@ module Cmfrec
|
|
|
327
451
|
nil, #precomputedBeTBeChol,
|
|
328
452
|
nil, #precomputedBiTBi,
|
|
329
453
|
nil, #precomputedTransCtCinvCt,
|
|
330
|
-
nil
|
|
454
|
+
nil, #precomputedCtCw
|
|
455
|
+
nil, #precomputedCtUbias
|
|
331
456
|
]
|
|
332
457
|
check_status FFI.fit_collective_explicit_als(*fiddle_args(args))
|
|
333
458
|
|
|
@@ -342,21 +467,20 @@ module Cmfrec
|
|
|
342
467
|
end
|
|
343
468
|
|
|
344
469
|
def set_params(
|
|
345
|
-
k: 40, lambda_:
|
|
346
|
-
item_bias: true, add_implicit_features: false,
|
|
470
|
+
k: 40, lambda_: 10.0, method: "als", use_cg: true,
|
|
471
|
+
user_bias: true, item_bias: true, center: true, add_implicit_features: false,
|
|
472
|
+
scale_lam: false, scale_lam_sideinfo: false, scale_bias_const: false,
|
|
347
473
|
k_user: 0, k_item: 0, k_main: 0,
|
|
348
474
|
w_main: 1.0, w_user: 1.0, w_item: 1.0, w_implicit: 0.5,
|
|
475
|
+
l1_lambda: 0.0, center_u: true, center_i: true,
|
|
349
476
|
maxiter: 800, niter: 10, parallelize: "separate", corr_pairs: 4,
|
|
350
|
-
max_cg_steps: 3, finalize_chol: true,
|
|
477
|
+
max_cg_steps: 3, precondition_cg: false, finalize_chol: true,
|
|
351
478
|
na_as_zero: false, na_as_zero_user: false, na_as_zero_item: false,
|
|
352
479
|
nonneg: false, nonneg_c: false, nonneg_d: false, max_cd_steps: 100,
|
|
353
480
|
precompute_for_predictions: true, include_all_x: true,
|
|
354
|
-
use_float:
|
|
355
|
-
|
|
356
|
-
handle_interrupt: true, produce_dicts: false,
|
|
357
|
-
copy_data: true, nthreads: -1
|
|
481
|
+
use_float: true, random_state: 1, verbose: true, print_every: 10,
|
|
482
|
+
handle_interrupt: true, produce_dicts: false, nthreads: -1
|
|
358
483
|
)
|
|
359
|
-
|
|
360
484
|
@k = k
|
|
361
485
|
@k_user = k_user
|
|
362
486
|
@k_item = k_item
|
|
@@ -392,9 +516,17 @@ module Cmfrec
|
|
|
392
516
|
@random_state = random_state.to_i
|
|
393
517
|
@produce_dicts = !!produce_dicts
|
|
394
518
|
@handle_interrupt = !!handle_interrupt
|
|
395
|
-
@copy_data = !!copy_data
|
|
396
519
|
nthreads = Etc.nprocessors if nthreads < 0
|
|
397
520
|
@nthreads = nthreads
|
|
521
|
+
|
|
522
|
+
@center = center
|
|
523
|
+
@scale_lam = scale_lam
|
|
524
|
+
@scale_lam_sideinfo = scale_lam_sideinfo
|
|
525
|
+
@scale_bias_const = scale_bias_const
|
|
526
|
+
@l1_lambda = l1_lambda
|
|
527
|
+
@precondition_cg = precondition_cg
|
|
528
|
+
|
|
529
|
+
# TODO center_u, center_i
|
|
398
530
|
end
|
|
399
531
|
|
|
400
532
|
def update_maps(train_set)
|
|
@@ -443,26 +575,47 @@ module Cmfrec
|
|
|
443
575
|
end
|
|
444
576
|
end
|
|
445
577
|
|
|
446
|
-
def read_factors(ptr, d1, d2)
|
|
447
|
-
arr = []
|
|
448
|
-
offset = 0
|
|
578
|
+
def read_factors(ptr, d1, d2, id, map)
|
|
449
579
|
width = d2 * Fiddle::SIZEOF_DOUBLE
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
580
|
+
if id
|
|
581
|
+
i = map[id]
|
|
582
|
+
ptr[i * width, width].unpack("d*") if i
|
|
583
|
+
else
|
|
584
|
+
arr = []
|
|
585
|
+
offset = 0
|
|
586
|
+
d1.times do |i|
|
|
587
|
+
arr << ptr[offset, width].unpack("d*")
|
|
588
|
+
offset += width
|
|
589
|
+
end
|
|
590
|
+
arr
|
|
453
591
|
end
|
|
454
|
-
arr
|
|
455
592
|
end
|
|
456
593
|
|
|
457
|
-
def read_bias(ptr)
|
|
458
|
-
|
|
594
|
+
def read_bias(ptr, id, map)
|
|
595
|
+
if id
|
|
596
|
+
i = map[id]
|
|
597
|
+
ptr[i * Fiddle::SIZEOF_DOUBLE, Fiddle::SIZEOF_DOUBLE].unpack1("d") if i
|
|
598
|
+
else
|
|
599
|
+
real_array(ptr)
|
|
600
|
+
end
|
|
459
601
|
end
|
|
460
602
|
|
|
461
|
-
def
|
|
462
|
-
|
|
463
|
-
|
|
603
|
+
def prepare_top_n(count: nil, rated: nil, item_ids: nil)
|
|
604
|
+
if item_ids
|
|
605
|
+
# remove missing ids
|
|
606
|
+
item_ids = item_ids.map { |v| @item_map[v] }.compact
|
|
607
|
+
return [] if item_ids.empty?
|
|
608
|
+
|
|
609
|
+
include_ix = int_ptr(item_ids)
|
|
610
|
+
n_include = item_ids.size
|
|
464
611
|
|
|
465
|
-
|
|
612
|
+
count = n_include if n_include < count
|
|
613
|
+
else
|
|
614
|
+
include_ix = nil
|
|
615
|
+
n_include = 0
|
|
616
|
+
end
|
|
617
|
+
|
|
618
|
+
if rated && !item_ids
|
|
466
619
|
# assumes rated is unique and all items are known
|
|
467
620
|
# calling code is responsible for this
|
|
468
621
|
exclude_ix = int_ptr(rated)
|
|
@@ -478,145 +631,54 @@ module Cmfrec
|
|
|
478
631
|
outp_ix = Fiddle::Pointer.malloc(count * Fiddle::SIZEOF_INT)
|
|
479
632
|
outp_score = Fiddle::Pointer.malloc(count * Fiddle::SIZEOF_DOUBLE)
|
|
480
633
|
|
|
481
|
-
|
|
482
|
-
a_vec, @k_user,
|
|
483
|
-
@b, @k_item,
|
|
484
|
-
@bias_b, @global_mean, a_bias,
|
|
485
|
-
@k, @k_main,
|
|
486
|
-
include_ix, n_include,
|
|
487
|
-
exclude_ix, n_exclude,
|
|
488
|
-
outp_ix, outp_score,
|
|
489
|
-
count, @n,
|
|
490
|
-
@nthreads
|
|
491
|
-
)
|
|
492
|
-
|
|
493
|
-
imap = @item_map.map(&:reverse).to_h
|
|
494
|
-
item_ids = int_array(outp_ix).map { |v| imap[v] }
|
|
495
|
-
scores = real_array(outp_score)
|
|
496
|
-
|
|
497
|
-
item_ids.zip(scores).map do |item_id, score|
|
|
498
|
-
{item_id: item_id, score: score}
|
|
499
|
-
end
|
|
634
|
+
[include_ix, n_include, exclude_ix, n_exclude, outp_ix, outp_score, count]
|
|
500
635
|
end
|
|
501
636
|
|
|
502
|
-
def
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
# remove unknown items
|
|
507
|
-
data, unknown_data = data.partition { |d| @item_map[d[:item_id]] }
|
|
508
|
-
|
|
509
|
-
if unknown_data.any?
|
|
510
|
-
# TODO warn for unknown items?
|
|
511
|
-
# warn "[cmfrec] Unknown items: #{unknown_data.map { |d| d[:item_id] }.join(", ")}"
|
|
512
|
-
end
|
|
513
|
-
|
|
514
|
-
item_ids = data.map { |d| @item_map[d[:item_id]] }
|
|
515
|
-
|
|
516
|
-
nnz = data.size
|
|
517
|
-
a_vec = Fiddle::Pointer.malloc((@k_user + @k + @k_main) * Fiddle::SIZEOF_DOUBLE)
|
|
518
|
-
bias_a = Fiddle::Pointer.malloc(Fiddle::SIZEOF_DOUBLE)
|
|
519
|
-
|
|
520
|
-
u_vec_sp = []
|
|
521
|
-
u_vec_x_col = []
|
|
522
|
-
if user_info
|
|
523
|
-
user_info.each do |k, v|
|
|
524
|
-
next if k == :user_id
|
|
525
|
-
|
|
526
|
-
uc = @user_info_map[k]
|
|
527
|
-
raise "Bad key: #{k}" unless uc
|
|
528
|
-
|
|
529
|
-
u_vec_x_col << uc
|
|
530
|
-
u_vec_sp << v
|
|
531
|
-
end
|
|
532
|
-
end
|
|
533
|
-
p_ = @user_info_map.size
|
|
534
|
-
nnz_u_vec = u_vec_sp.size
|
|
535
|
-
u_vec_x_col = int_ptr(u_vec_x_col)
|
|
536
|
-
u_vec_sp = real_ptr(u_vec_sp)
|
|
537
|
-
|
|
538
|
-
u_vec = nil
|
|
539
|
-
u_bin_vec = nil
|
|
540
|
-
pbin = 0
|
|
541
|
-
|
|
542
|
-
weight = nil
|
|
543
|
-
lam_unique = nil
|
|
544
|
-
l1_lambda = 0
|
|
545
|
-
l1_lam_unique = nil
|
|
546
|
-
n_max = @n
|
|
547
|
-
|
|
548
|
-
if data.any?
|
|
549
|
-
if @implicit
|
|
550
|
-
ratings = data.map { |d| d[:value] || 1 }
|
|
551
|
-
else
|
|
552
|
-
ratings = data.map { |d| d[:rating] }
|
|
553
|
-
check_ratings(ratings)
|
|
554
|
-
end
|
|
555
|
-
xa = real_ptr(ratings)
|
|
556
|
-
x_col = int_ptr(item_ids)
|
|
557
|
-
else
|
|
558
|
-
xa = nil
|
|
559
|
-
x_col = nil
|
|
560
|
-
end
|
|
561
|
-
xa_dense = nil
|
|
637
|
+
def top_n(a_vec:, a_bias:, count:, rated: nil, item_ids: nil, row_index:)
|
|
638
|
+
prep = prepare_top_n(count: count, rated: rated, item_ids: item_ids)
|
|
639
|
+
return [] if prep.empty?
|
|
640
|
+
include_ix, n_include, exclude_ix, n_exclude, outp_ix, outp_score, count = prep
|
|
562
641
|
|
|
563
642
|
if @implicit
|
|
564
|
-
|
|
643
|
+
check_status FFI.topN_old_collective_implicit(
|
|
565
644
|
a_vec,
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
@na_as_zero_user,
|
|
569
|
-
@nonneg,
|
|
570
|
-
@u_colmeans,
|
|
571
|
-
@b, @n, @c,
|
|
572
|
-
xa, x_col, nnz,
|
|
645
|
+
@a, row_index,
|
|
646
|
+
@b,
|
|
573
647
|
@k, @k_user, @k_item, @k_main,
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
nil #BeTBeChol
|
|
580
|
-
]
|
|
581
|
-
check_status FFI.factors_collective_implicit_single(*fiddle_args(args))
|
|
648
|
+
include_ix, n_include,
|
|
649
|
+
exclude_ix, n_exclude,
|
|
650
|
+
outp_ix, outp_score,
|
|
651
|
+
count, @n, @nthreads
|
|
652
|
+
)
|
|
582
653
|
else
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
u_bin_vec, pbin,
|
|
593
|
-
@na_as_zero_user, @na_as_zero,
|
|
594
|
-
@nonneg,
|
|
595
|
-
@c, cb,
|
|
596
|
-
@global_mean, @bias_b, @u_colmeans,
|
|
597
|
-
xa, x_col, nnz, xa_dense,
|
|
598
|
-
@n, weight, @b, @bi,
|
|
599
|
-
@add_implicit_features,
|
|
654
|
+
# TODO add param
|
|
655
|
+
n_max = @n
|
|
656
|
+
|
|
657
|
+
check_status FFI.topN_old_collective_explicit(
|
|
658
|
+
a_vec, a_bias,
|
|
659
|
+
@a, @bias_a, row_index,
|
|
660
|
+
@b,
|
|
661
|
+
@bias_b,
|
|
662
|
+
@global_mean,
|
|
600
663
|
@k, @k_user, @k_item, @k_main,
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
@
|
|
605
|
-
|
|
606
|
-
@include_all_x,
|
|
607
|
-
nil, #BtB,
|
|
608
|
-
nil, #TransBtBinvBt,
|
|
609
|
-
nil, #BtXbias,
|
|
610
|
-
nil, #BeTBeChol,
|
|
611
|
-
nil, #BiTBi,
|
|
612
|
-
nil, #CtCw,
|
|
613
|
-
nil, #TransCtCinvCt,
|
|
614
|
-
nil #B_plus_bias
|
|
615
|
-
]
|
|
616
|
-
check_status FFI.factors_collective_explicit_single(*fiddle_args(args))
|
|
664
|
+
include_ix, n_include,
|
|
665
|
+
exclude_ix, n_exclude,
|
|
666
|
+
outp_ix, outp_score,
|
|
667
|
+
count, @n, n_max, @include_all_x ? 1 : 0, @nthreads
|
|
668
|
+
)
|
|
617
669
|
end
|
|
618
670
|
|
|
619
|
-
|
|
671
|
+
top_n_output(outp_ix, outp_score)
|
|
672
|
+
end
|
|
673
|
+
|
|
674
|
+
def top_n_output(outp_ix, outp_score)
|
|
675
|
+
imap = @item_map.map(&:reverse).to_h
|
|
676
|
+
item_ids = int_array(outp_ix).map { |v| imap[v] }
|
|
677
|
+
scores = real_array(outp_score)
|
|
678
|
+
|
|
679
|
+
item_ids.zip(scores).map do |item_id, score|
|
|
680
|
+
{item_id: item_id, score: score}
|
|
681
|
+
end
|
|
620
682
|
end
|
|
621
683
|
|
|
622
684
|
# convert boolean to int
|
data/lib/cmfrec/version.rb
CHANGED
data/lib/cmfrec.rb
CHANGED
|
@@ -15,19 +15,19 @@ module Cmfrec
|
|
|
15
15
|
class << self
|
|
16
16
|
attr_accessor :ffi_lib
|
|
17
17
|
end
|
|
18
|
-
|
|
18
|
+
lib_path =
|
|
19
19
|
if Gem.win_platform?
|
|
20
|
-
"cmfrec.dll"
|
|
20
|
+
"x64-mingw/cmfrec.dll"
|
|
21
21
|
elsif RbConfig::CONFIG["host_os"] =~ /darwin/i
|
|
22
|
-
if RbConfig::CONFIG["host_cpu"] =~ /arm/i
|
|
23
|
-
"libcmfrec.
|
|
22
|
+
if RbConfig::CONFIG["host_cpu"] =~ /arm|aarch64/i
|
|
23
|
+
"arm64-darwin/libcmfrec.dylib"
|
|
24
24
|
else
|
|
25
|
-
"libcmfrec.dylib"
|
|
25
|
+
"x86_64-darwin/libcmfrec.dylib"
|
|
26
26
|
end
|
|
27
27
|
else
|
|
28
|
-
"libcmfrec.so"
|
|
28
|
+
"x86_64-linux/libcmfrec.so"
|
|
29
29
|
end
|
|
30
|
-
vendor_lib = File.expand_path("../vendor/#{
|
|
30
|
+
vendor_lib = File.expand_path("../vendor/#{lib_path}", __dir__)
|
|
31
31
|
self.ffi_lib = [vendor_lib]
|
|
32
32
|
|
|
33
33
|
# friendlier error message
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
For the included LFBGS library (files "lbfgs.h", "lbfgs.c", "arithmetic_ansi.h"):
|
|
2
|
+
|
|
3
|
+
The MIT License
|
|
4
|
+
|
|
5
|
+
Copyright (c) 1990 Jorge Nocedal
|
|
6
|
+
Copyright (c) 2007-2010 Naoaki Okazaki
|
|
7
|
+
|
|
8
|
+
Permission is hereby granted, free of charge, to any person obtaining a
|
|
9
|
+
copy of this software and associated documentation files (the "Software"),
|
|
10
|
+
to deal in the Software without restriction, including without limitation
|
|
11
|
+
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
12
|
+
and/or sell copies of the Software, and to permit persons to whom the
|
|
13
|
+
Software is furnished to do so, subject to the following conditions:
|
|
14
|
+
|
|
15
|
+
The above copyright notice and this permission notice shall be included in
|
|
16
|
+
all copies or substantial portions of the Software.
|
|
17
|
+
|
|
18
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
19
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
20
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
21
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
22
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
23
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
24
|
+
THE SOFTWARE.
|
|
25
|
+
|
|
26
|
+
For the included ziggurat tables (file "ziggurat.h"):
|
|
27
|
+
|
|
28
|
+
Copyright (c) 2005-2022, NumPy Developers.
|
|
29
|
+
All rights reserved.
|
|
30
|
+
|
|
31
|
+
Redistribution and use in source and binary forms, with or without
|
|
32
|
+
modification, are permitted provided that the following conditions are
|
|
33
|
+
met:
|
|
34
|
+
|
|
35
|
+
* Redistributions of source code must retain the above copyright
|
|
36
|
+
notice, this list of conditions and the following disclaimer.
|
|
37
|
+
|
|
38
|
+
* Redistributions in binary form must reproduce the above
|
|
39
|
+
copyright notice, this list of conditions and the following
|
|
40
|
+
disclaimer in the documentation and/or other materials provided
|
|
41
|
+
with the distribution.
|
|
42
|
+
|
|
43
|
+
* Neither the name of the NumPy Developers nor the names of any
|
|
44
|
+
contributors may be used to endorse or promote products derived
|
|
45
|
+
from this software without specific prior written permission.
|
|
46
|
+
|
|
47
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
48
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
49
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
50
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
51
|
+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
52
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
53
|
+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
54
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
55
|
+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
56
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
57
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020-2022 David Cortes
|
|
4
|
+
|
|
5
|
+
All rights reserved.
|
|
6
|
+
|
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
of this software and associated documentation files (the "Software"), to
|
|
9
|
+
deal in the Software without restriction, including without limitation the
|
|
10
|
+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
11
|
+
sell copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
furnished to do so, subject to the following conditions:
|
|
13
|
+
|
|
14
|
+
The above copyright notice and this permission notice shall be included in
|
|
15
|
+
all copies or substantial portions of the Software.
|
|
16
|
+
|
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
22
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
23
|
+
IN THE SOFTWARE.
|
|
Binary file
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
For the included LFBGS library (files "lbfgs.h", "lbfgs.c", "arithmetic_ansi.h"):
|
|
2
|
+
|
|
3
|
+
The MIT License
|
|
4
|
+
|
|
5
|
+
Copyright (c) 1990 Jorge Nocedal
|
|
6
|
+
Copyright (c) 2007-2010 Naoaki Okazaki
|
|
7
|
+
|
|
8
|
+
Permission is hereby granted, free of charge, to any person obtaining a
|
|
9
|
+
copy of this software and associated documentation files (the "Software"),
|
|
10
|
+
to deal in the Software without restriction, including without limitation
|
|
11
|
+
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
12
|
+
and/or sell copies of the Software, and to permit persons to whom the
|
|
13
|
+
Software is furnished to do so, subject to the following conditions:
|
|
14
|
+
|
|
15
|
+
The above copyright notice and this permission notice shall be included in
|
|
16
|
+
all copies or substantial portions of the Software.
|
|
17
|
+
|
|
18
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
19
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
20
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
21
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
22
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
23
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
24
|
+
THE SOFTWARE.
|
|
25
|
+
|
|
26
|
+
For the included ziggurat tables (file "ziggurat.h"):
|
|
27
|
+
|
|
28
|
+
Copyright (c) 2005-2022, NumPy Developers.
|
|
29
|
+
All rights reserved.
|
|
30
|
+
|
|
31
|
+
Redistribution and use in source and binary forms, with or without
|
|
32
|
+
modification, are permitted provided that the following conditions are
|
|
33
|
+
met:
|
|
34
|
+
|
|
35
|
+
* Redistributions of source code must retain the above copyright
|
|
36
|
+
notice, this list of conditions and the following disclaimer.
|
|
37
|
+
|
|
38
|
+
* Redistributions in binary form must reproduce the above
|
|
39
|
+
copyright notice, this list of conditions and the following
|
|
40
|
+
disclaimer in the documentation and/or other materials provided
|
|
41
|
+
with the distribution.
|
|
42
|
+
|
|
43
|
+
* Neither the name of the NumPy Developers nor the names of any
|
|
44
|
+
contributors may be used to endorse or promote products derived
|
|
45
|
+
from this software without specific prior written permission.
|
|
46
|
+
|
|
47
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
48
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
49
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
50
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
51
|
+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
52
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
53
|
+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
54
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
55
|
+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
56
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
57
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020-2022 David Cortes
|
|
4
|
+
|
|
5
|
+
All rights reserved.
|
|
6
|
+
|
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
of this software and associated documentation files (the "Software"), to
|
|
9
|
+
deal in the Software without restriction, including without limitation the
|
|
10
|
+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
11
|
+
sell copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
furnished to do so, subject to the following conditions:
|
|
13
|
+
|
|
14
|
+
The above copyright notice and this permission notice shall be included in
|
|
15
|
+
all copies or substantial portions of the Software.
|
|
16
|
+
|
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
22
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
23
|
+
IN THE SOFTWARE.
|
|
Binary file
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
For the included LFBGS library (files "lbfgs.h", "lbfgs.c", "arithmetic_ansi.h"):
|
|
2
|
+
|
|
3
|
+
The MIT License
|
|
4
|
+
|
|
5
|
+
Copyright (c) 1990 Jorge Nocedal
|
|
6
|
+
Copyright (c) 2007-2010 Naoaki Okazaki
|
|
7
|
+
|
|
8
|
+
Permission is hereby granted, free of charge, to any person obtaining a
|
|
9
|
+
copy of this software and associated documentation files (the "Software"),
|
|
10
|
+
to deal in the Software without restriction, including without limitation
|
|
11
|
+
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
12
|
+
and/or sell copies of the Software, and to permit persons to whom the
|
|
13
|
+
Software is furnished to do so, subject to the following conditions:
|
|
14
|
+
|
|
15
|
+
The above copyright notice and this permission notice shall be included in
|
|
16
|
+
all copies or substantial portions of the Software.
|
|
17
|
+
|
|
18
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
19
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
20
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
21
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
22
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
23
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
24
|
+
THE SOFTWARE.
|
|
25
|
+
|
|
26
|
+
For the included ziggurat tables (file "ziggurat.h"):
|
|
27
|
+
|
|
28
|
+
Copyright (c) 2005-2022, NumPy Developers.
|
|
29
|
+
All rights reserved.
|
|
30
|
+
|
|
31
|
+
Redistribution and use in source and binary forms, with or without
|
|
32
|
+
modification, are permitted provided that the following conditions are
|
|
33
|
+
met:
|
|
34
|
+
|
|
35
|
+
* Redistributions of source code must retain the above copyright
|
|
36
|
+
notice, this list of conditions and the following disclaimer.
|
|
37
|
+
|
|
38
|
+
* Redistributions in binary form must reproduce the above
|
|
39
|
+
copyright notice, this list of conditions and the following
|
|
40
|
+
disclaimer in the documentation and/or other materials provided
|
|
41
|
+
with the distribution.
|
|
42
|
+
|
|
43
|
+
* Neither the name of the NumPy Developers nor the names of any
|
|
44
|
+
contributors may be used to endorse or promote products derived
|
|
45
|
+
from this software without specific prior written permission.
|
|
46
|
+
|
|
47
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
48
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
49
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
50
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
51
|
+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
52
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
53
|
+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
54
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
55
|
+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
56
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
57
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020-2022 David Cortes
|
|
4
|
+
|
|
5
|
+
All rights reserved.
|
|
6
|
+
|
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
of this software and associated documentation files (the "Software"), to
|
|
9
|
+
deal in the Software without restriction, including without limitation the
|
|
10
|
+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
11
|
+
sell copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
furnished to do so, subject to the following conditions:
|
|
13
|
+
|
|
14
|
+
The above copyright notice and this permission notice shall be included in
|
|
15
|
+
all copies or substantial portions of the Software.
|
|
16
|
+
|
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
22
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
23
|
+
IN THE SOFTWARE.
|
|
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.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrew Kane
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2022-06-15 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description:
|
|
14
14
|
email: andrew@ankane.org
|
|
@@ -24,11 +24,16 @@ files:
|
|
|
24
24
|
- lib/cmfrec/ffi.rb
|
|
25
25
|
- lib/cmfrec/recommender.rb
|
|
26
26
|
- lib/cmfrec/version.rb
|
|
27
|
-
- vendor/
|
|
28
|
-
- vendor/
|
|
29
|
-
- vendor/libcmfrec.dylib
|
|
30
|
-
- vendor/
|
|
31
|
-
|
|
27
|
+
- vendor/arm64-darwin/COPYRIGHTS
|
|
28
|
+
- vendor/arm64-darwin/LICENSE
|
|
29
|
+
- vendor/arm64-darwin/libcmfrec.dylib
|
|
30
|
+
- vendor/x86_64-darwin/COPYRIGHTS
|
|
31
|
+
- vendor/x86_64-darwin/LICENSE
|
|
32
|
+
- vendor/x86_64-darwin/libcmfrec.dylib
|
|
33
|
+
- vendor/x86_64-linux/COPYRIGHTS
|
|
34
|
+
- vendor/x86_64-linux/LICENSE
|
|
35
|
+
- vendor/x86_64-linux/libcmfrec.so
|
|
36
|
+
homepage: https://github.com/ankane/cmfrec-ruby
|
|
32
37
|
licenses:
|
|
33
38
|
- MIT
|
|
34
39
|
metadata: {}
|
|
@@ -40,14 +45,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
40
45
|
requirements:
|
|
41
46
|
- - ">="
|
|
42
47
|
- !ruby/object:Gem::Version
|
|
43
|
-
version: '2.
|
|
48
|
+
version: '2.7'
|
|
44
49
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
45
50
|
requirements:
|
|
46
51
|
- - ">="
|
|
47
52
|
- !ruby/object:Gem::Version
|
|
48
53
|
version: '0'
|
|
49
54
|
requirements: []
|
|
50
|
-
rubygems_version: 3.
|
|
55
|
+
rubygems_version: 3.3.7
|
|
51
56
|
signing_key:
|
|
52
57
|
specification_version: 4
|
|
53
58
|
summary: Recommendations for Ruby using collective matrix factorization
|
data/vendor/LICENSE.txt
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2020 David Cortes
|
|
4
|
-
|
|
5
|
-
All rights reserved.
|
|
6
|
-
|
|
7
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
-
of this software and associated documentation files (the "Software"), to
|
|
9
|
-
deal in the Software without restriction, including without limitation the
|
|
10
|
-
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
11
|
-
sell copies of the Software, and to permit persons to whom the Software is
|
|
12
|
-
furnished to do so, subject to the following conditions:
|
|
13
|
-
|
|
14
|
-
The above copyright notice and this permission notice shall be included in
|
|
15
|
-
all copies or substantial portions of the Software.
|
|
16
|
-
|
|
17
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
22
|
-
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
23
|
-
IN THE SOFTWARE.
|
|
24
|
-
|
|
25
|
-
---
|
|
26
|
-
|
|
27
|
-
ANSI C implementation of vector operations.
|
|
28
|
-
|
|
29
|
-
Copyright (c) 2007-2010 Naoaki Okazaki
|
|
30
|
-
All rights reserved.
|
|
31
|
-
|
|
32
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
33
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
34
|
-
in the Software without restriction, including without limitation the rights
|
|
35
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
36
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
37
|
-
furnished to do so, subject to the following conditions:
|
|
38
|
-
|
|
39
|
-
The above copyright notice and this permission notice shall be included in
|
|
40
|
-
all copies or substantial portions of the Software.
|
|
41
|
-
|
|
42
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
43
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
44
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
45
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
46
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
47
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
48
|
-
THE SOFTWARE.
|
|
49
|
-
|
|
50
|
-
---
|
|
51
|
-
|
|
52
|
-
C library of Limited memory BFGS (L-BFGS).
|
|
53
|
-
|
|
54
|
-
Copyright (c) 1990, Jorge Nocedal
|
|
55
|
-
Copyright (c) 2007-2010 Naoaki Okazaki
|
|
56
|
-
All rights reserved.
|
|
57
|
-
|
|
58
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
59
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
60
|
-
in the Software without restriction, including without limitation the rights
|
|
61
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
62
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
63
|
-
furnished to do so, subject to the following conditions:
|
|
64
|
-
|
|
65
|
-
The above copyright notice and this permission notice shall be included in
|
|
66
|
-
all copies or substantial portions of the Software.
|
|
67
|
-
|
|
68
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
69
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
70
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
71
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
72
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
73
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
74
|
-
THE SOFTWARE.
|
|
Binary file
|
data/vendor/libcmfrec.dylib
DELETED
|
Binary file
|
data/vendor/libcmfrec.so
DELETED
|
Binary file
|