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 +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +2 -6
- data/lib/disco/model.rb +7 -10
- data/lib/disco/recommender.rb +9 -0
- data/lib/disco/version.rb +1 -1
- data/lib/disco.rb +6 -6
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0fb469aae804d8f6ed2fe398b3584e67d1ebf29cd0d0d394eda952d32c0756f9
|
4
|
+
data.tar.gz: 295bde072449c13e3da22975efa0bdbe9ea5a1fdbbb787f0b0d63411056e6799
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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://
|
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:
|
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
|
-
|
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
|
data/lib/disco/recommender.rb
CHANGED
@@ -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
data/lib/disco.rb
CHANGED
@@ -3,13 +3,13 @@ require "libmf"
|
|
3
3
|
require "numo/narray"
|
4
4
|
|
5
5
|
# modules
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
-
|
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
|
-
|
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.
|
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:
|
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
|
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
|
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.
|
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.
|
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
|