【问题标题】:Can I calculate the similarity of document fields using MapReduce?我可以使用 MapReduce 计算文档字段的相似度吗?
【发布时间】:2015-01-13 03:52:36
【问题描述】:

我知道使用 map reduce 无法计算两个文档的 Jaccard 相似度,因为 map 只取一项。

我想计算文档字段元素的相似度。这可以使用map reduce吗?我看不到从当前点发射什么。

输入:

{'_id': 'foobar1',
 'categories': ['one', 'two', 'three']}
{'_id': 'foobar2',
 'categories': ['one']}
{'_id': 'foobar3',
 'categories': ['one', 'two']}

我现在想计算类别onetwothree 彼此之间的相似程度,考虑到它们所属的文档。这也可能是在以下集合中找到文档之间的相似性的状态(只是在理想情况下,我不必重新计算我的数据到这个集合)。

{'_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 那样)?

免责声明:尽管它可能看起来像大学任务,但事实并非如此。这是一个个人项目。

【问题讨论】:

    标签: mongodb mapreduce


    【解决方案1】:

    我相信您可以使用聚合框架计算两个数组字段 XY 的 Jaccard 系数 - 您应该始终更喜欢使用 map/reduce。两组XY的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 阶段。您可能需要添加额外的逻辑来处理XY 都为空或其中一个不是数组或丢失的情况。预先添加一个 $match 阶段来计算文档子集的系数。

    【讨论】:

    • 是否有交叉产品的聚合管道关键字?对于$project$X$Y 一起使用,关键字必须在同一个文档中(或者我误读了文档)。因此,即使我有文件 {"cat1" : [element1, element2], "cat2": [element1, element3]},我也需要进行交叉乘积以获得所有交叉乘积可能性的 X = [element1, element2], Y = [element1, element3]
    • 我想这可以归结为描述你究竟在追求什么。我的回答含糊地针对这个问题,但没有完全解决它,因为不清楚你想要什么——你能给出你期望的确切输出吗?在我所知道的任何意义上,您提供的所需输出都不是 Jaccard 相似度计算——它更像是计算字段值中子集的频率。另外,如果我对 Jaccard 相似性的定义与您的不一致,您能否将我引向您的定义来源?
    • 您对 Jaccard 相似性的定义是正确的,但我认为您误解了我确实想要文档的相似性(我认为这根本不可能),但是元素项的 Jaccard 相似度。因此,您可以考虑将我的文档“反转”为 '{one: [foobar1, foobar2, foobar3], two: [foobar1, foobar3], three: [foobar1]}',然后在此处获取文档的 jaccard 相似度。但是文档之间的 Jaccard 相似度的解决方案也很好。根据您的回答,我只是猜测,我只能对 一个文档中的两个字段进行 Jaccard 相似性。
    • 感谢您的澄清。对于给定的文档结构,我认为计算该信息的最佳方法是大多数客户端,通过检索一组包含 onetwo 的文档 ID,然后计算这些集合的 Jaccard 相似度。 Map/reduce 和聚合将无法操纵文档以“反转”它们 w.r.t。字段值,正如您所说的那样。
    猜你喜欢
    • 1970-01-01
    • 2012-09-01
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-12
    • 2019-10-23
    • 1970-01-01
    相关资源
    最近更新 更多