我有一个stores
和categories
型号。商店可以有很多类别。
我正在尝试为每个商店创建相关商店列表。
我想根据商店与另一家商店分享的常见类别数来计算得分。
我有计划,但不知道如何在Ruby on Rails中开始编码。
有什么建议吗?
PS。我认为最好有一个单独的表来存储每个商店的计算数据 - 因为在数据库中实时执行会非常紧张。
更新我刚刚在我的逻辑中发现了一个主要缺陷 - 像亚马逊这样的几家百货商店将主导所有商家的相关商店(因为它们几乎属于所有类别,因此会匹配利基商店的每个类别)。 有关此问题的任何方法吗?
答案 0 :(得分:2)
你的“主要缺陷”并不少见。正如你所说,亚马逊将与所有事情“相关”。对于尝试使用此类关系的任何类型的推荐系统,这是一个非常常见的问题。我没有用商店类别做到这一点,但问题与我建立的视频选择/排名系统非常相似。
帮助防止热门内容占主导地位的常用方法是,不是使用匹配类别的计数,而是为每个商店的分数赋予权重。常见的加权因子为1/category_count
或1/sqrt(category_count)
。
想象一下三家商店:
Jim's Books - 2 categories: ["Books", "Music"]
Amazon - 10 categories: ["Books", "Music", "Movies", "Housewares", etc.]
Ralph's Remainders - 3 categories: ["Books", "Music", "Movies"]
现在,如果您正在寻找与Jim的书籍类似的商店,那么您可以匹配类别。显然,亚马逊和拉尔夫都包括“书籍”和“音乐”类别,如果你只使用匹配类别的数量,两者都会有相同的分数。
但是如果你使用加权因子,那么他们的得分就大不相同了。加权因子为1/category_count
:
Amazon - 10 categories, weighting factor = 1/10.
Ralph's - 3 categories, weighting factor = 1/3.
所以亚马逊的相似度得分为0.20,拉尔夫的相似度得分为0.66。
如果加权系数为1/sqrt(category_count)
,则:
Amazon - weighting factor = 1/sqrt(10) = 0.316
Ralph's - weighting factor = 1/sqrt(3) = 0.562
在这种情况下,亚马逊的得分约为0.632,而拉尔夫的得分为1.124。
我发现1/sqrt(category_count)
通常更好,因为它会抑制极受欢迎的商店(即那些有很多类别的商店)的压倒性影响,但并不是说那些商店不会进入结果。使用1/category_count
过分强调只有一个或两个类别的商店。
答案 1 :(得分:1)
如果假设你有模特:
class Store < ActiveRecord:Base
has_many :categories_stores
has_many :categories, :throught => :categories_stores
end
class CategoriesStore < ActiveRecord::Base
belongs_to :category
belongs_to :store
end
class Category < ActiveRecord::Base
has_many :categories_stores
has_many :categories, :throught => :categories_stores
end
单词中的主要算法是: 1.查找具有所选商店的类别(ID)。 2.找到具有步骤1中任何类别的商店。 3.计算来自类别列表1的每个找到的商店的类别。
这一切都可以通过SQL中的几种方式完成。例如:
SELECT s3.store_id, COUNT(s3.category_id) FROM categories_stores s1, categories_stores s2, categories_stores s3 WHERE s1.store_id = :id and s2.category_id = s1.category_id and s3.store_id = s2.store_id and s3.category_id = s1.category_id GROUP BY s3.store_id
其中:id - 是查询的参数。查询的某些部分可以由纯ruby完成,有些则不能。