disco 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|