disco 0.3.1 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a4af4d7df56f884618557fd98f97da2686cecbfaf3ce1f1f52b6ba1a3a9155f5
4
- data.tar.gz: ddbc7551c3534c41284e958042a94d988cdd5c52248f3ca7e4a8d8a72c6b168e
3
+ metadata.gz: 0fb469aae804d8f6ed2fe398b3584e67d1ebf29cd0d0d394eda952d32c0756f9
4
+ data.tar.gz: 295bde072449c13e3da22975efa0bdbe9ea5a1fdbbb787f0b0d63411056e6799
5
5
  SHA512:
6
- metadata.gz: 5f40f125fe4096dcf09eaf1d1295f23e68fef9bbe1e5651a1ecfa1ed06748df7a0f4c9ea048b767b429b67b4d0add1f32663388707616571a6936a55ffd1d6b7
7
- data.tar.gz: baf3caa4deec5422bd85e9372bc717f683d4cbb067f468eb7d4c964556885f7bb273fa0b6339201aef917c8f046346c20356358462fc73103243608a5245ebe6
6
+ metadata.gz: 287c44da295f55d2f95788fb7c0488738c1f70a409bb372461ad37d1786ade8fd0650abb8de62f023805a03bd667f74b509069bbaa9ca4f58a56aa1628d8b7c4
7
+ data.tar.gz: 81bceaa14ffc78918157b25c4cb4a21f0d08d625042867866032fe006a8cbfcd041914dfa19c720a0bc7211d00fe40d14f95fc2e1d769b7a9af59711641dcc78
data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## 0.4.0 (2023-01-30)
2
+
3
+ - Fixed issue with `has_recommended` and inheritance with Rails < 6.1
4
+ - Deprecated marshal serialization
5
+ - Dropped support for Ruby < 2.7 and Rails < 6
6
+
7
+ ## 0.3.2 (2022-09-26)
8
+
9
+ - Fixed issue when `fit` is called multiple times
10
+
1
11
  ## 0.3.1 (2022-07-10)
2
12
 
3
13
  - Added support for JSON serialization
data/README.md CHANGED
@@ -176,8 +176,6 @@ user.update_recommended_products_v2(recs)
176
176
  user.recommended_products_v2
177
177
  ```
178
178
 
179
- For Rails < 6, speed up inserts by adding [activerecord-import](https://github.com/zdennis/activerecord-import) to your app.
180
-
181
179
  ## Storing Recommenders
182
180
 
183
181
  If you’d prefer to perform recommendations on-the-fly, store the recommender
@@ -187,9 +185,7 @@ json = recommender.to_json
187
185
  File.write("recommender.json", json)
188
186
  ```
189
187
 
190
- > You can save it to a file, database, or any other storage system. Also, user and item IDs should be integers or strings for this.
191
-
192
- The serialized recommender includes user activity from the training data (to avoid recommending previously rated items), so be sure to protect it.
188
+ The serialized recommender includes user activity from the training data (to avoid recommending previously rated items), so be sure to protect it. You can save it to a file, database, or any other storage system, or use a tool like [Trove](https://github.com/ankane/trove). Also, user and item IDs should be integers or strings for this.
193
189
 
194
190
  Load a recommender
195
191
 
@@ -225,7 +221,7 @@ recommender.fit(data, validation_set: validation_set)
225
221
 
226
222
  ## Cold Start
227
223
 
228
- Collaborative filtering suffers from the [cold start problem](https://www.yuspify.com/blog/cold-start-problem-recommender-systems/). It’s unable to make good recommendations without data on a user or item, which is problematic for new users and items.
224
+ Collaborative filtering suffers from the [cold start problem](https://en.wikipedia.org/wiki/Cold_start_(recommender_systems)). It’s unable to make good recommendations without data on a user or item, which is problematic for new users and items.
229
225
 
230
226
  ```ruby
231
227
  recommender.user_recs(new_user_id) # returns empty array
data/lib/disco/model.rb CHANGED
@@ -1,7 +1,12 @@
1
1
  module Disco
2
2
  module Model
3
3
  def has_recommended(name, class_name: nil)
4
+ if ActiveRecord::VERSION::MAJOR < 6
5
+ raise Disco::Error, "Requires Active Record 6+"
6
+ end
7
+
4
8
  class_name ||= name.to_s.singularize.camelize
9
+ subject_type = model_name.name
5
10
 
6
11
  class_eval do
7
12
  unless reflect_on_association(:recommendations)
@@ -12,21 +17,13 @@ module Disco
12
17
 
13
18
  define_method("update_recommended_#{name}") do |items|
14
19
  now = Time.now
15
- items = items.map { |item| {subject_type: model_name.name, subject_id: id, item_type: class_name, item_id: item.fetch(:item_id), context: name, score: item.fetch(:score), created_at: now, updated_at: now} }
20
+ items = items.map { |item| {subject_type: subject_type, subject_id: id, item_type: class_name, item_id: item.fetch(:item_id), context: name, score: item.fetch(:score), created_at: now, updated_at: now} }
16
21
 
17
22
  self.class.transaction do
18
23
  recommendations.where(context: name).delete_all
19
24
 
20
25
  if items.any?
21
- if recommendations.respond_to?(:insert_all!)
22
- # Rails 6
23
- recommendations.insert_all!(items)
24
- elsif recommendations.respond_to?(:bulk_import!)
25
- # activerecord-import
26
- recommendations.bulk_import!(items, validate: false)
27
- else
28
- recommendations.create!([items])
29
- end
26
+ recommendations.insert_all!(items)
30
27
  end
31
28
  end
32
29
  end
@@ -36,6 +36,8 @@ module Disco
36
36
  end
37
37
  end
38
38
 
39
+ @user_map = {}
40
+ @item_map = {}
39
41
  @rated = Hash.new { |hash, key| hash[key] = {} }
40
42
  input = []
41
43
  train_set.each do |v|
@@ -56,6 +58,9 @@ module Disco
56
58
  # TODO improve performance
57
59
  unless @implicit
58
60
  @min_rating, @max_rating = train_set.minmax_by { |o| o[:rating] }.map { |o| o[:rating] }
61
+ else
62
+ @min_rating = nil
63
+ @max_rating = nil
59
64
  end
60
65
 
61
66
  if @top_items
@@ -425,6 +430,8 @@ module Disco
425
430
  end
426
431
 
427
432
  def marshal_dump
433
+ warn "[disco] Marshal serialization is deprecated - use JSON instead"
434
+
428
435
  obj = {
429
436
  implicit: @implicit,
430
437
  user_map: @user_map,
@@ -452,6 +459,8 @@ module Disco
452
459
  end
453
460
 
454
461
  def marshal_load(obj)
462
+ warn "[disco] Marshal serialization is deprecated - use JSON instead"
463
+
455
464
  @implicit = obj[:implicit]
456
465
  @user_map = obj[:user_map]
457
466
  @item_map = obj[:item_map]
data/lib/disco/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Disco
2
- VERSION = "0.3.1"
2
+ VERSION = "0.4.0"
3
3
  end
data/lib/disco.rb CHANGED
@@ -3,13 +3,13 @@ require "libmf"
3
3
  require "numo/narray"
4
4
 
5
5
  # modules
6
- require "disco/data"
7
- require "disco/metrics"
8
- require "disco/recommender"
9
- require "disco/version"
6
+ require_relative "disco/data"
7
+ require_relative "disco/metrics"
8
+ require_relative "disco/recommender"
9
+ require_relative "disco/version"
10
10
 
11
11
  # integrations
12
- require "disco/engine" if defined?(Rails)
12
+ require_relative "disco/engine" if defined?(Rails)
13
13
 
14
14
  module Disco
15
15
  class Error < StandardError; end
@@ -19,7 +19,7 @@ end
19
19
 
20
20
  if defined?(ActiveSupport.on_load)
21
21
  ActiveSupport.on_load(:active_record) do
22
- require "disco/model"
22
+ require_relative "disco/model"
23
23
  extend Disco::Model
24
24
  end
25
25
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: disco
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.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: 2022-07-10 00:00:00.000000000 Z
11
+ date: 2023-01-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: libmf
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 0.2.0
19
+ version: '0.2'
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
- version: 0.2.0
26
+ version: '0.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: numo-narray
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -69,14 +69,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
69
69
  requirements:
70
70
  - - ">="
71
71
  - !ruby/object:Gem::Version
72
- version: '2.6'
72
+ version: '2.7'
73
73
  required_rubygems_version: !ruby/object:Gem::Requirement
74
74
  requirements:
75
75
  - - ">="
76
76
  - !ruby/object:Gem::Version
77
77
  version: '0'
78
78
  requirements: []
79
- rubygems_version: 3.3.7
79
+ rubygems_version: 3.4.1
80
80
  signing_key:
81
81
  specification_version: 4
82
82
  summary: Recommendations for Ruby and Rails using collaborative filtering