我可以使用 MapReduce 计算文档字段的相似度吗?
Can I calculate the similarity of document fields using MapReduce?
我知道无法使用 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}]
但是当然在reduce中我只能计算总和,因为我不知道S('one')
和S('three')
的并集是什么。
我是否必须在 map-reduce 之后重新计算总和,或者我是否可以更改我的方法以便能够在 0 和 1 之间建立相似度(就像 Jaccard 所做的那样)?
免责声明:尽管它看起来像是大学作业,但实际上并非如此。这是一个个人项目。
我相信您可以使用聚合框架计算两个数组字段 X
和 Y
的 Jaccard 系数 - 您应该始终更喜欢使用 map/reduce。两组X
和Y
的Jaccard系数定义为
J(X, Y) = size(X & Y) / size(X | Y)
其中size(T)
为集合中的元素个数T
,&
为集合交集,|
为集合并集。要使用聚合框架进行计算,请使用以下(粗略)管道:
db.test.aggregate([
{ "$project" : { "intersection" : { "$setIntersection" : ["$X", "$Y"] }, "union" : { "$setUnion" : ["$X", "$Y"] } } },
{ "$project" : { "jaccard" : { "$divide" : [{ "$size" : "$intersection" }, {"$size" : "$union" }] } } }
])
我将计算分为两步以使其更清楚,但它可能是一个 $project
阶段。您可能需要添加额外的逻辑来处理 X
和 Y
都为空或其中之一不是数组或缺失的情况。前置 $match
阶段来计算文档子集的系数。
我知道无法使用 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}]
但是当然在reduce中我只能计算总和,因为我不知道S('one')
和S('three')
的并集是什么。
我是否必须在 map-reduce 之后重新计算总和,或者我是否可以更改我的方法以便能够在 0 和 1 之间建立相似度(就像 Jaccard 所做的那样)?
免责声明:尽管它看起来像是大学作业,但实际上并非如此。这是一个个人项目。
我相信您可以使用聚合框架计算两个数组字段 X
和 Y
的 Jaccard 系数 - 您应该始终更喜欢使用 map/reduce。两组X
和Y
的Jaccard系数定义为
J(X, Y) = size(X & Y) / size(X | Y)
其中size(T)
为集合中的元素个数T
,&
为集合交集,|
为集合并集。要使用聚合框架进行计算,请使用以下(粗略)管道:
db.test.aggregate([
{ "$project" : { "intersection" : { "$setIntersection" : ["$X", "$Y"] }, "union" : { "$setUnion" : ["$X", "$Y"] } } },
{ "$project" : { "jaccard" : { "$divide" : [{ "$size" : "$intersection" }, {"$size" : "$union" }] } } }
])
我将计算分为两步以使其更清楚,但它可能是一个 $project
阶段。您可能需要添加额外的逻辑来处理 X
和 Y
都为空或其中之一不是数组或缺失的情况。前置 $match
阶段来计算文档子集的系数。