MinHash 标记过滤器编辑

使用 MinHash 技术为标记流生成签名。您可以使用 MinHash 签名来估计文档的相似度。请参阅 使用 min_hash 标记过滤器进行相似度搜索

min_hash 过滤器按顺序对标记流执行以下操作

  1. 对流中的每个标记进行哈希运算。
  2. 将哈希值分配到桶中,只保留每个桶中最小的哈希值。
  3. 将每个桶中最小的哈希值作为标记流输出。

此过滤器使用 Lucene 的 MinHashFilter

可配置参数编辑

bucket_count
(可选,整数)哈希值分配到的桶数。默认为 512
hash_count
(可选,整数)对流中每个标记进行哈希运算的方式数。默认为 1
hash_set_size

(可选,整数)从每个桶中保留的哈希值数量。默认为 1

哈希值按升序大小保留,首先是桶中最小的哈希值。

with_rotation
(可选,布尔值)如果为 true,并且 hash_set_size1,则过滤器会用其循环右侧第一个非空桶的值填充空桶。如果 bucket_count 参数大于 1,则此参数默认为 true。否则,此参数默认为 false

配置 min_hash 过滤器的技巧编辑

  • min_hash 过滤器输入标记通常应该是由 shingle 标记过滤器 生成的 k 词 shingles。您应该选择足够大的 k,以便任何给定 shingle 出现在文档中的概率都很低。同时,由于在内部每个 shingle 都被哈希成 128 位哈希值,因此您应该选择足够小的 k,以便所有可能的不同 k 词 shingles 都可以哈希成 128 位哈希值,并且冲突最小。
  • 我们建议您测试 hash_countbucket_counthash_set_size 参数的不同参数

    • 要提高精度,请增加 bucket_counthash_set_size 参数。较高的 bucket_counthash_set_size 值会增加不同标记被索引到不同桶的可能性。
    • 要提高召回率,请增加 hash_count 参数的值。例如,将 hash_count 设置为 2 会以两种不同的方式对每个标记进行哈希运算,从而增加搜索的潜在候选数量。
  • 默认情况下,min_hash 过滤器为每个文档生成 512 个标记。每个标记的大小为 16 字节。这意味着每个文档的大小将增加大约 8Kb。
  • min_hash 过滤器用于 Jaccard 相似度。这意味着文档包含某个标记的次数无关紧要,只有包含或不包含才重要。

使用 min_hash 标记过滤器进行相似度搜索编辑

min_hash 标记过滤器允许您对文档进行哈希运算以进行相似度搜索。相似度搜索或最近邻搜索是一个复杂的问题。一种简单的解决方案需要在查询文档和索引中的每个文档之间进行详尽的成对比较。如果索引很大,这将是一个非常耗时的操作。为了使相似度搜索更加实用和计算上可行,已经开发了许多近似最近邻搜索解决方案。其中一种解决方案涉及文档的哈希运算。

对文档进行哈希运算的方式是,相似的文档更有可能生成相同的哈希码并被放入同一个哈希桶中,而不同的文档更有可能被哈希到不同的哈希桶中。这种类型的哈希运算称为局部敏感哈希 (LSH)。

根据构成文档之间相似性的因素,已经提出了 各种 LSH 函数。对于 Jaccard 相似度,一种流行的 LSH 函数是 MinHash。MinHash 为文档生成签名的总体思路是,对整个索引词汇表应用随机排列(为词汇表随机编号),并记录文档中该排列的最小值(文档中存在的词汇表单词的最小编号)。排列运行多次;组合所有排列的最小值将构成文档的签名。

在实践中,不是使用随机排列,而是选择多个哈希函数。哈希函数为文档的每个标记计算一个哈希码,并选择其中最小的哈希码。来自所有哈希函数的最小哈希码组合在一起,形成文档的签名。

自定义并添加到分析器编辑

要自定义 min_hash 过滤器,请复制它以创建新的自定义标记过滤器的基础。您可以使用其可配置参数修改过滤器。

例如,以下 创建索引 API 请求使用以下自定义标记过滤器来配置新的 自定义分析器

  • my_shingle_filter,一个自定义的 shingle 过滤器my_shingle_filter 只输出五词 shingles。
  • my_minhash_filter,一个自定义的 min_hash 过滤器。my_minhash_filter 对每个五词 shingle 进行一次哈希运算。然后,它将哈希值分配到 512 个桶中,只保留每个桶中最小的哈希值。

该请求还将自定义分析器分配给 fingerprint 字段映射。

response = client.indices.create(
  index: 'my-index-000001',
  body: {
    settings: {
      analysis: {
        filter: {
          my_shingle_filter: {
            type: 'shingle',
            min_shingle_size: 5,
            max_shingle_size: 5,
            output_unigrams: false
          },
          my_minhash_filter: {
            type: 'min_hash',
            hash_count: 1,
            bucket_count: 512,
            hash_set_size: 1,
            with_rotation: true
          }
        },
        analyzer: {
          my_analyzer: {
            tokenizer: 'standard',
            filter: [
              'my_shingle_filter',
              'my_minhash_filter'
            ]
          }
        }
      }
    },
    mappings: {
      properties: {
        fingerprint: {
          type: 'text',
          analyzer: 'my_analyzer'
        }
      }
    }
  }
)
puts response
PUT /my-index-000001
{
  "settings": {
    "analysis": {
      "filter": {
        "my_shingle_filter": {      
          "type": "shingle",
          "min_shingle_size": 5,
          "max_shingle_size": 5,
          "output_unigrams": false
        },
        "my_minhash_filter": {
          "type": "min_hash",
          "hash_count": 1,          
          "bucket_count": 512,      
          "hash_set_size": 1,       
          "with_rotation": true     
        }
      },
      "analyzer": {
        "my_analyzer": {
          "tokenizer": "standard",
          "filter": [
            "my_shingle_filter",
            "my_minhash_filter"
          ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "fingerprint": {
        "type": "text",
        "analyzer": "my_analyzer"
      }
    }
  }
}

配置自定义 shingle 过滤器以仅输出五词 shingles。

流中的每个五词 shingle 都进行一次哈希运算。

哈希值被分配到 512 个桶中。

只保留每个桶中最小的哈希值。

过滤器用相邻桶的值填充空桶。