cmfrec 0.1.5 → 0.1.6

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
  SHA256:
3
- metadata.gz: 7a200b99780aeee83c5a0190e593c3806c4140aa4c096b0ef2c112fd21a858b7
4
- data.tar.gz: 27b354dd491ca1d7a728d4ef2318c72c56d76c691286bc267c74d3b8dafd7c5b
3
+ metadata.gz: 34e8dc08914cbc418470cd7eb3adf3d33013b786319f4510212c80bf3629f3ca
4
+ data.tar.gz: c1b91a1f77b4b51a5ca4491376f8a02230ea54873f8c1b2b06f4761d6ddd0686
5
5
  SHA512:
6
- metadata.gz: 0c1ceefeac9131a804d94b6da78c7a6614f50c15d144841277829e5279ce2583872a681e972e336e21cb82d49466dee9f5f1de6a482fe8a99ab7aa5176ab0e5c
7
- data.tar.gz: 930b20b017b92555071699b38d903230da3ca1fc7b8b91b9e2f96ae3ae4dda9c8c289a47117beaa1e2539e5c9d622fe958d431f5106e8ab7c4809ea17e9fb6e8
6
+ metadata.gz: a3c57734379199196a4e3f51d9ec02b19ef1abac13d57a10ca3c20e9b76c9ee5db4b17d790330d41a9576c2ba28a9eeccafeb5760b54cfdf80a7431368895068
7
+ data.tar.gz: 5a24a77a6665854abb38916a22e8141a6cae637a51f98e3df3762566f2e73cb60b9bd9a25303df0411ea53dec3211bf7534711dc55c510311620341cbe4e4ac3
data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## 0.1.6 (2021-08-12)
2
+
3
+ - Added `user_ids` and `item_ids` methods
4
+ - Added `user_id` argument to `user_factors`
5
+ - Added `item_id` argument to `item_factors`
6
+ - Added `user_id` argument to `user_bias`
7
+ - Added `item_id` argument to `item_bias`
8
+ - Added `item_ids` argument to `new_user_recs`
9
+ - Fixed order for `user_recs`
10
+
1
11
  ## 0.1.5 (2021-08-10)
2
12
 
3
13
  - Fixed issue with `user_recs` and `new_user_recs` returning rated items
data/README.md CHANGED
@@ -232,6 +232,13 @@ recommender = Marshal.load(bin)
232
232
 
233
233
  ## Reference
234
234
 
235
+ Get ids
236
+
237
+ ```ruby
238
+ recommender.user_ids
239
+ recommender.item_ids
240
+ ```
241
+
235
242
  Get the global mean
236
243
 
237
244
  ```ruby
@@ -67,23 +67,10 @@ module Cmfrec
67
67
  user = @user_map[user_id]
68
68
 
69
69
  if user
70
- # TODO use top_n for item_ids as well
71
- if item_ids
72
- # remove missing ids
73
- item_ids = item_ids.select { |v| @item_map[v] }
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)
87
74
  else
88
75
  # no items if user is unknown
89
76
  # TODO maybe most popular items
@@ -91,28 +78,35 @@ module Cmfrec
91
78
  end
92
79
  end
93
80
 
94
- # TODO add item_ids
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
84
  a_vec, a_bias, rated = factors_warm(data, user_info: user_info)
99
- top_n(a_vec: a_vec, a_bias: a_bias, count: count, rated: rated)
85
+ top_n(a_vec: a_vec, a_bias: a_bias, count: count, rated: rated, item_ids: item_ids)
86
+ end
87
+
88
+ def user_ids
89
+ @user_map.keys
90
+ end
91
+
92
+ def item_ids
93
+ @item_map.keys
100
94
  end
101
95
 
102
- def user_factors
103
- read_factors(@a, [@m, @m_u].max, @k_user + @k + @k_main)
96
+ def user_factors(user_id = nil)
97
+ read_factors(@a, [@m, @m_u].max, @k_user + @k + @k_main, user_id, @user_map)
104
98
  end
105
99
 
106
- def item_factors
107
- read_factors(@b, [@n, @n_i].max, @k_item + @k + @k_main)
100
+ def item_factors(item_id = nil)
101
+ read_factors(@b, [@n, @n_i].max, @k_item + @k + @k_main, item_id, @item_map)
108
102
  end
109
103
 
110
- def user_bias
111
- read_bias(@bias_a) if @bias_a
104
+ def user_bias(user_id = nil)
105
+ read_bias(@bias_a, user_id, @user_map) if @bias_a
112
106
  end
113
107
 
114
- def item_bias
115
- read_bias(@bias_b) if @bias_b
108
+ def item_bias(item_id = nil)
109
+ read_bias(@bias_b, item_id, @item_map) if @bias_b
116
110
  end
117
111
 
118
112
  def similar_items(item_id, count: 5)
@@ -443,26 +437,48 @@ module Cmfrec
443
437
  end
444
438
  end
445
439
 
446
- def read_factors(ptr, d1, d2)
447
- arr = []
448
- offset = 0
440
+ def read_factors(ptr, d1, d2, id, map)
449
441
  width = d2 * Fiddle::SIZEOF_DOUBLE
450
- d1.times do |i|
451
- arr << ptr[offset, width].unpack("d*")
452
- offset += width
442
+ if id
443
+ i = map[id]
444
+ ptr[i * width, width].unpack("d*") if i
445
+ else
446
+ arr = []
447
+ offset = 0
448
+ d1.times do |i|
449
+ arr << ptr[offset, width].unpack("d*")
450
+ offset += width
451
+ end
452
+ arr
453
453
  end
454
- arr
455
454
  end
456
455
 
457
- def read_bias(ptr)
458
- real_array(ptr)
456
+ def read_bias(ptr, id, map)
457
+ if id
458
+ i = map[id]
459
+ ptr[i * Fiddle::SIZEOF_DOUBLE, Fiddle::SIZEOF_DOUBLE].unpack1("d") if i
460
+ else
461
+ real_array(ptr)
462
+ end
459
463
  end
460
464
 
461
- def top_n(a_vec:, a_bias:, count:, rated: nil)
462
- include_ix = nil
463
- n_include = 0
465
+ def top_n(a_vec:, a_bias:, count:, rated: nil, item_ids: nil)
466
+ if item_ids
467
+ # remove missing ids
468
+ item_ids = item_ids.map { |v| @item_map[v] }.compact
469
+ return [] if item_ids.empty?
470
+
471
+ include_ix = int_ptr(item_ids)
472
+ n_include = item_ids.size
473
+
474
+ # TODO uncomment in 0.2.0
475
+ count = n_include # if n_include < count
476
+ else
477
+ include_ix = nil
478
+ n_include = 0
479
+ end
464
480
 
465
- if rated
481
+ if rated && !item_ids
466
482
  # assumes rated is unique and all items are known
467
483
  # calling code is responsible for this
468
484
  exclude_ix = int_ptr(rated)
@@ -1,3 +1,3 @@
1
1
  module Cmfrec
2
- VERSION = "0.1.5"
2
+ VERSION = "0.1.6"
3
3
  end
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.5
4
+ version: 0.1.6
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-11 00:00:00.000000000 Z
11
+ date: 2021-08-12 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email: andrew@ankane.org