使用Map / Reduce计算自举算法

时间:2011-03-22 14:19:57

标签: algorithm mapreduce

这个问题最初是我的作业,但我的回答是错误的,我很好奇这个问题的最佳解决方案是什么。

目标是使用4个map reduce步骤计算“Recommender System bootstrapping algorithm”的关键方面。我的问题是第3步,所以我只带来它的细节。

  


输入:表单记录:   
1。 (人口数量,项目,数量   评级用户,评级总和,总和   评级平方)
2。 (人口   id,splitter item,likers / dislikers,   项目,评级用户数,总和   评级,平均等级总和)

第二种形式非常类似于第一种形式,但每种形式的记录(分裂者,喜欢者/不喜欢者) - 喜欢/不喜欢的人是布尔值。

这意味着(我认为)有2 ^ |项目|来自第一种形式的每条记录的秒形式的记录......(许多同学做错了(我认为......)假设有相同数量的第一和第二形式记录)

任务说明:

  

此步骤将根据分割器电影计算每部电影引起的平方误差(SE)。

  • 输出:表格的记录(人口ID,拆分项目,项目,在拆分器上给出拆分的项目的平方误差)。

提示:

  

假设存在一个字符串   先于(在系统的排序顺序中)   任何分配者电影id。

这必须在一个mapreduce步骤中完成!

其他背景:
这是在“The Netflix Challange”的背景下学到的。

SE定义: SE definition

编辑:有关问题的其他材料[关于netflix挑战的一些说明和有关问题的数学信息]可以在this link [特别是幻灯片12-24]中找到

EDIT2:请注意,由于我们正在使用map / reduce,因此我们无法假设任何有关ORDER记录的信息都将被处理[在map和reduce中]。

1 个答案:

答案 0 :(得分:3)

我不确定我理解你的问题。

你最终想要的是SE(U)。在幻灯片23和24的一些数学细节之后,使用\ sum_ {i} SE(U)_i

计算“平凡”。

你自己明白,第4个和最后一个是地图缩小以得到这个总和。

第三步是地图缩小到(LaTeX风格)

SE(U)_i = \sum_{u in U_i} (r_{u,i} - r_i)^2

enter image description here

  • reduce函数在U_i
  • 中求和
  • 地图功能拆分要求和的术语

在Python中,这可能如下所示:

def map(Ui):
    ''' Ui is the list of user who have rated the film i'''
    for user in Ui:
        results.append((user,(r_{u,i} - r_i)^2))

def reduce(results):
    ''' Returns a final pair (item, SE(U)_i ) '''
    return (item, sum([value for user,value in results]))

修改:我的原始答案不完整。让我再次表达。

你最终想要的是每个分配器的SE(U)。

步骤准备一些有关商品的有用数据。发出的条目定义为:

key = (population_id, item)
value =
    number: |U_i|,
    sum_of_ratings: \sum_{u \ in U_i} r_{u,i} 
    sum_of_squared_ratings: \sum_{u \in U_i} r_{u,i} ^2
  • 地图功能会展开项目的统计信息。
  • reduce函数计算总和。

现在,对于任何给定的分割片M:

U_M = U_{+M} + U_{-M} + U_{M?}

步骤b 为每个分割器M明确计算小子群M +和M-的统计量。

NB赞成者/不喜欢者不是布尔本身,它是子群体识别者'+'或' - '

每个拆分项有2个新条目:

key = (population_id, item, M, '+') 
value = 
    number: |U_i(+)|
    sum_of_ratings: \sum_{u \ in U_i(+)} r_{u,i}
    sum_of_squared_ratings: \sum_{u \in U_i(+)} r_{u,i} ^2

Same thing for '-'

或者如果你更喜欢dis / likers符号

key = (population_id, item, M, dis/likers) 
value = 
    number: |U_i(dis/likers)|
    sum_of_ratings: \sum_{u \ in U_i(dis/likers)} r_{u,i}
    sum_of_squared_ratings: \sum_{u \in U_i(dis/likers)} r_{u,i} ^2

cf中间幻灯片24

NB如果你认为每部电影可能是一个分割器,那么第二种形式有2x | item | ^ 2项;那是因为项目 - > (boolean,item,splitter) - 远远小于你的2 ^ | item |评价,你还没有解释。

步骤c 为每个分割器M计算每部电影的估计SE,即SE(U_M)_i

因为总和可以在不同的成员之间分配:

U_M = U_{+M} + U_{-M} + U_{M?}

SE(U_M)_i = SE(U_M?)_i + SE(U_+M) + SE(U_-M)

使用此地图函数显式计算SE(U_{+M})

def map(key, value):
    '''     
    key = (population_id, item, M, dis/likers) 
    '''
    value = 
        count: 1
        dist: (r_u,i - r_i)^2

    emit key, value

def reduce(key, values):
    ''' 
    This function explicitly computes the SE for dis/likers
    key = (population_id, item, M, dis/likers)
    value= count, dist
    '''
    emit key, sum(count, sum(dist))

现在我们需要SE(U_{M?})_i,这是幻灯片24中给出的“琐碎”计算:

SE(?)_i = \sum_{u \in U_i(?)}{r_{u,i}^2} - (\sum r)^2 / |U_i(?)|

当然,我们不会做这么大的事情,但是在讲座中使用上面的评论,并且已经在步骤a中计算了数据(这是我从最后3个方程式中从幻灯片24中得出的结论)< / p>

SE(?)_i = \sum_{u \in U_i}{r_{u,i}^2} - \sum_{u \in U_i('+'/'-')}{r_{u,i}^2} - (...)/ (|U_i| - |U_i('+'/'-'))

所以这个甚至不是Map / Reduce,它只是一个最终的步骤:

def finalize(key, values):
    for [k in keys if k match key]:
        ''' From all entries get
        # from step a
        key = (population_id, item) value=(nb_ratings, sum_ratings, sum_ratings_squared)
        # from step b
        key = (population_id, item, M, '+') value=(nb_ratings_likers, sum_ratings_likers, sum_ratings_squared_likers)
        key = (population_id, item, M, '-') value=(nb_ratings_dislikers, sum_ratings_dislikers, sum_ratings_squared_dislikers)
        # from step c
        key = (population_id, item, M, '+') value=(se_likers)
        key = (population_id, item, M, '-') value=(se_dislikers)
        '''
        se_other = sum_rating_squared - sum_ratings_squared_likers  - sum_ratins_squared_dislikers - sum_ratings_likers / (nb_ratings -  (nb_ratings_likers)) - sum_ratins_squared_dislikers  - sum_ratings_likers / (nb_ratings -  (nb_ratings_likers))
        emit
            key: (population_id, splitter, item)
            value : se_likers + se_dislikers + se_other

步骤d 最后,最后的步骤计算U_M的SE。它只是先前条目的总和,以及一个简单的Map / Reduce:

对于分割器M:

SE(U_M) = \sum_i SE(U_M)_i = \sum_i SE(U_M?)_i + \sum_i SE(U_+M) + \sum_i SE(U_-M)