1

私のコレクションには以下が含まれます:

{ user_id : 1, product_id : 1 },
{ user_id : 1, product_id : 2 },
{ user_id : 1, product_id : 3 },
{ user_id : 2, product_id : 2 },
{ user_id : 2, product_id : 3 },
{ user_id : 3, product_id : 2 },

user_idがユーザーの ID で、product_idが製品の ID である、ユーザーが表示した私のコレクション トラック製品。
2 人のユーザー間の類似性 (両方が閲覧した製品の数など) を計算したいと考えています。
たとえば、上記のコレクションから、ユーザー間の類似性は次のようになります。

{ user_id1 : 1, user_id2 : 2, similarity : 2 },
{ user_id1 : 1, user_id2 : 3, similarity : 1 },
{ user_id1 : 2, user_id2 : 3, similarity : 1 },

編集済み

私はmap-reduceなしでそれをやった

def self.build_similarity_weight
  users_id = ProductView.all.distinct(:user_id).to_a
  users_id.each do |user_id|
    this_user_products = ProductView.all.where(user_id: user_id).distinct(:product_id).to_a

    other_users = users_id.map { |e| e } 
    other_users.delete_if { |x| x == user_id }

    other_users.each do |other_uid|
      other_user_products = ProductView.all.where(user_id: other_uid).distinct(:product_id).to_a
      user_sim = (other_user_products & this_user_products).length
      usw = UserSimilarityWeight.new(user_id1: user_id, user_id2: other_uid, weight: user_sim)
      usw.save
    end
  end
end

問題は、私のコードが効率的でないことです。O(n 2 )です。ここで、nはユーザー数です。
map-reduce を使用してコードをより効率的にするにはどうすればよいですか?

よろしく、

4

1 に答える 1

2

まず、2 つの mapreduce を実行します。

    • map: product_id をキーとして省略し、user_id を値として省略
    • reduce: ループ内で値リスト (各製品のユーザー ID のリスト) を繰り返し、ユーザー ID のキー ペア (最小のユーザー ID が最初のもの) と値 1 を省略します。
  1. (最初の map reduce の結果に取り組んでいます)

    • マップ: ユーザーのペアをキーとして、値 1 を値として渡すだけです
    • reduce: 各ペアの値を合計します。

第二に、結果は O(n2) のオーダーであるため、O(n2) よりも効率的になることはできません。つまり、魔法のような方法でペアと類似性が得られたとしても、n^2 のペアを記述する必要があります。

于 2012-05-18T15:35:54.400 に答える