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
         |