据我所知,使用map reduce计算两个文档的Jaccard相似度是不可能的,因为map只需要一个项目。
我想计算文档字段元素的相似性。这可能使用map reduce吗?我目前无法看到发出什么。
输入:
{'_id': 'foobar1',
'categories': ['one', 'two', 'three']}
{'_id': 'foobar2',
'categories': ['one']}
{'_id': 'foobar3',
'categories': ['one', 'two']}
我现在想要计算类别one
,two
和three
彼此之间的相似程度,考虑它们所属的文档。这也可以说是在下面的集合中找到文档之间的相似性(仅在理想世界中,我不必将数据重新计算到此集合)。
{'_id': 'one'
'documents': ['foobar1', 'foobar2', 'foobar3']}
{'_id': 'two',
'categories': ['foobar1', 'foobar3']}
{'_id': 'three',
'categories': ['foobar1']}
期望的输出:
{('one', 'two'): 2/3,
('one', 'three'): 1/3,
('two', 'three'): 1/2}
这是否可以使用map reduce以及如何使用?
到目前为止,我从地图中发出的内容如下:
[{('one', 'two'): 1},
{('one', 'three'): 1},
{('two', 'three'): 1},
{('one', 'two'): 1}]
但当然在减少中我只能计算总和,因为我不知道S('one')
和S('three')
的联合是什么。
我是否必须在map-reduce之后重新计算总和,或者我可以改变我的方法以便能够在0和1之间建立相似性(就像Jaccard那样)?
免责声明:即使它看起来像大学任务,但事实并非如此。这是个人项目。
答案 0 :(得分:3)
我相信你可以使用聚合框架计算两个数组字段X
和Y
的Jaccard系数 - 你应该总是喜欢使用map / reduce。两组X
和Y
的Jaccard系数定义为
J(X, Y) = size(X & Y) / size(X | Y)
其中size(T)
是集合T
中的元素数量,&
设置为交集,|
设置为union。要使用聚合框架计算此值,请使用以下(粗略)管道:
db.test.aggregate([
{ "$project" : { "intersection" : { "$setIntersection" : ["$X", "$Y"] }, "union" : { "$setUnion" : ["$X", "$Y"] } } },
{ "$project" : { "jaccard" : { "$divide" : [{ "$size" : "$intersection" }, {"$size" : "$union" }] } } }
])
我将计算分为两个步骤以使其更清晰,但它可能是一个$project
阶段。您可能需要添加额外的逻辑来处理X
和Y
都为空或其中一个不是数组或缺失的情况。预先设置$match
阶段来计算文档子集的系数。