目录

moon-minhash 🚀

MoonBit 近似集合相似度与文本去重工具

基于 100% 原生 MoonBit 构建的高性能近似集合相似度计算、MinHash 签名生成、LSH (Locality-Sensitive Hashing) 分桶检索、b-bit 签名压缩、流式去重与图聚类引擎。

MoonBit Version License CI Status


📖 项目简介

在海量网页抓取、新闻聚合、日志分析与文档数据库中,判断海量文档之间的海姆/Jaccard 相似度是一项计算密集型任务。传统 O(N2)O(N^2) 两两比对算法在大规模数据集下不可行。

moon-minhash 为 MoonBit 生态提供了一套完整的文本近似相似度计算与海量数据去重解决方案。通过将高维集合降维映射为低维 MinHash 签名,结合 LSH (局部敏感哈希) 的 b×rb \times r 分桶策略,实现亚线性 O(1)O(1) 或 O(K)O(K) 级候选检索与重复文档过滤。

🌟 核心特性

  1. **分词与 Chunking (src/tokenizer)**:

    • 支持 Character N-gram、Word N-gram 与 CJK 字符分词。
    • 提供文本标准化(大小写转换、空白字符折叠、标点与数字过滤)。
    • 实现基于 Rabin 指纹的变长内容确定性分块(Rabin Content-Defined Chunking / CDC)。
    • 内置 Porter Stemmer 英文词干提取器(五阶段后缀剥离算法)。
    • 内置 Stop Words Filter 英文停用词过滤器(120+ 常用停用词表)。
  2. **高性能非密码学哈希族 (src/hash)**:

    • 纯 MoonBit 实现的 32-bit & 128-bit MurmurHash3。
    • 高吞吐 xxHash32 与 SipHash-2-4。
    • FNV-1a 32-bit 与 64-bit 非密码学哈希函数。
    • 基于线性同余与大素数算术的通用哈希函数族 (h(x)=(a⋅x+b)(modp)h(x) = (a \cdot x + b) \pmod p),支持任意 KK 维随机置换。
  3. **MinHash 签名计算与相似度估计 (src/minhash)**:

    • 经典单趟 MinHash 签名生成器与 Jaccard 相似度无偏估计。
    • 单趟流式 SuperMinHash 密集签名生成算法。
    • 基于一致性加权采样 (Consistent Weighted Sampling / CWS) 的 Weighted MinHash。
  4. **局部敏感哈希索引 (src/lsh)**:

    • 自动化 Banding 策略 (k=b×rk = b \times r) 与概率 S 曲线 (P(s)=1−(1−sr)bP(s) = 1 - (1 - s^r)^b) 参数自动调优。
    • LSH 桶索引,支持快速 O(1)O(1) 候选集召回与阈值匹配。
    • Multi-probe LSH 扰动探测,提升高噪边界下的召回率。
    • **SimHash (Cosine LSH)**:基于 Charikar 随机超平面投影的余弦相似度指纹 + Hamming 距离桶索引。
  5. **签名压缩与基数估计 (src/compress)**:

    • b-bit MinHash 签名量化 (1-bit, 2-bit, 4-bit),相比 32-bit 签名降低内存占用达 16x~32x。
    • 基于 Hamming 距离修正公式的 b-bit Jaccard 相似度快速估算。
    • HyperLogLog 基数估计器,支持集合基数估计与交并集推算。
  6. **分片索引与合并引擎 (src/shard)**:

    • 支持多 Shard 分区索引管理 (ShardManager) 与动态路由。
    • 提供 merge_shards 分片合并算法,适合分布式与大内存场景。
  7. **流式去重与图聚类引擎 (src/dedup)**:

    • StreamingDeduplicator:实时单条文档流式去重,毫秒级返回重复匹配文档 ID。
    • DeduplicationEngine:批量文档去重引擎,生成包含去重率、唯一文档数与重复群组的统计报告。
    • DisjointSetCluster:基于带路径压缩与按秩合并的 Union-Find(并查集)算法,支持分治归并(Hierarchical Reduction Merge)策略,自动将相似文档连通图合并为同义聚类。
  8. **文本相似度度量矩阵 (src/similarity)**:

    • Levenshtein Distance 与 Damerau-Levenshtein Distance(编辑距离族)。
    • Jaro-Winkler Similarity(拼写纠错相似度)。
    • Sørensen-Dice Coefficient、Overlap Coefficient、Tversky Index(集合度量族)。
    • Cosine Similarity(词频向量空间度量)。
    • String Jaccard Similarity 与 Hamming Distance。
  9. **CLI 交互工具与 Benchmark (src/cli, src/bench)**:

    • 命令行交互工具与全功能 Performance Benchmark 压力测试集。

🧮 数学原理

1. Jaccard 相似度与 MinHash 理论

对于两个集合 A,BA, B,其 Jaccard 相似度定义为:

J(A,B)=∣A∩B∣∣A∪B∣J(A, B) = \frac{|A \cap B|}{|A \cup B|}

使用 kk 个独立的哈希函数 h1,h2,…,hkh_1, h_2, \dots, h_k,定义 MinHash 签名 hmin(A)=x∈Ah(x)h_{min}(A) = \min_{x \in A} h(x)。对于任意独立哈希函数 hh:

P[hmin(A)=hmin(B)]=J(A,B)\mathbb{P}[h_{min}(A) = h_{min}(B)] = J(A, B)

通过 kk 维签名槽位相同比例 ∑i=1kI(hi,min(A)=hi,min(B))k\frac{\sum_{i=1}^k \mathbb{I}(h_{i,min}(A) = h_{i,min}(B))}{k},可以作为 J(A,B)J(A, B) 的无偏估计。

2. LSH 概率 S 曲线

将长度为 kk 的 MinHash 签名划分为 bb 个 Band,每个 Band 包含 rr 个哈希值 (k=b×rk = b \times r)。对于 Jaccard 相似度为 ss 的两份文档,它们在至少一个 Band 内完全匹配的概率为:

P(s)=1−(1−sr)bP(s) = 1 - (1 - s^r)^b

S 曲线在 s∗=(1/b)1/rs^* = (1/b)^{1/r} 处呈现极陡峭的 S 形跃迁,使得相似度大于 s∗s^* 的文档对以极高概率召回,而不相似文档对被高效过滤。


📁 目录结构

moon-minhash/
├── moon.mod                      # MoonBit 模块定义
├── README.md                     # 项目完整说明文档
├── LICENSE                       # Apache-2.0 开源许可协议
├── .gitignore                    # Git 忽略配置
├── .github/
│   └── workflows/
│       └── ci.yml                # CI 自动化构建与测试工作流
├── src/
│   ├── hash/                     # 非密码学哈希函数与 Universal Hash 族
│   │   ├── murmur3.mbt
│   │   ├── xxhash.mbt
│   │   ├── siphash.mbt
│   │   ├── fnv.mbt
│   │   ├── universal.mbt
│   │   ├── hash_test.mbt
│   │   └── fnv_test.mbt
│   ├── tokenizer/                # N-gram 分词、文本标准化、Rabin CDC、Porter Stemmer
│   │   ├── normalizer.mbt
│   │   ├── tokenizer.mbt
│   │   ├── shingle.mbt
│   │   ├── rabin_cdc.mbt
│   │   ├── porter.mbt
│   │   ├── stopwords.mbt
│   │   └── tokenizer_test.mbt
│   ├── minhash/                  # MinHash 签名计算、SuperMinHash 与 Weighted MinHash
│   │   ├── minhash.mbt
│   │   ├── super_minhash.mbt
│   │   ├── weighted.mbt
│   │   ├── minhash_test.mbt
│   │   └── weighted_test.mbt
│   ├── lsh/                      # LSH 索引、Banding 自动调优、Multi-probe、SimHash
│   │   ├── banding.mbt
│   │   ├── index.mbt
│   │   ├── multiprobe.mbt
│   │   ├── simhash.mbt
│   │   └── lsh_test.mbt
│   ├── compress/                 # b-bit 签名量化压缩与 HyperLogLog
│   │   ├── bbit.mbt
│   │   ├── hyperloglog.mbt
│   │   └── compress_test.mbt
│   ├── similarity/               # 文本编辑距离与向量空间相似度度量
│   │   ├── distance.mbt
│   │   └── distance_test.mbt
│   ├── shard/                    # 分区 Shard 管理与分片合并
│   │   ├── shard.mbt
│   │   ├── storage.mbt
│   │   └── shard_test.mbt
│   ├── dedup/                    # 流式去重引擎、Union-Find 图聚类
│   │   ├── cluster.mbt
│   │   ├── streaming.mbt
│   │   ├── engine.mbt
│   │   └── dedup_test.mbt
│   ├── cli/                      # 命令行可执行工具
│   │   └── main.mbt
│   └── bench/                    # 基准性能测试套件
│       ├── bench.mbt
│       └── bench_test.mbt

⚡ 快速开始与使用示例

1. 签名计算与相似度估计

let text1 = "MoonBit is an end-to-end build tool and programming language system for WebAssembly"
let text2 = "MoonBit is an end-to-end build tool and programming language system for WebAssembly targets"

let hasher = @minhash.MinHasher::new(64, 42UL)
let sig1 = hasher.compute_text(text1)
let sig2 = hasher.compute_text(text2)

let sim = @minhash.jaccard_similarity(sig1, sig2)
println("Estimated Jaccard Similarity: " + sim.to_string())

2. LSH 索引构建与候选查询

// 自动调优得到 (b=16, r=4) 分桶配置
let lsh = @lsh.LSHIndex::new(16, 4)

lsh.insert("doc_1", sig1)
lsh.insert("doc_2", sig2)

let matches = lsh.query_similar(sig1, 0.5)
for i = 0; i < matches.length(); i = i + 1 {
  let item = matches[i]
  println("Found match: " + item.0 + ", sim: " + item.1.to_string())
}

3. 流式与批量文档去重

let engine = @dedup.DeduplicationEngine::new(0.6, 64, 42UL)
let docs = [
  @dedup.DocumentItem::new("d1", text1),
  @dedup.DocumentItem::new("d2", text2),
  @dedup.DocumentItem::new("d3", "Unrelated outdoors document content"),
]

let report = engine.deduplicate_batch(docs)
println("Total Documents: " + report.total_documents.to_string())
println("Unique Documents: " + report.unique_documents.to_string())
println("Duplicates Found: " + report.duplicate_documents.to_string())

🛠️ 构建与测试说明

本项目要求最新版 MoonBit 工具链 (0.10.4 / 2026 版本):

# 检查类型与编译
moon check

# 运行全套单元测试与 Benchmark
moon test

# 运行代码格式化
moon fmt

# 重新生成包接口描述文件 (.mbti)
moon info

# 运行 CLI 交互示例
moon run src/cli

📊 代码规模与来源说明

  • 来源说明:本项目代码(包含 hash, tokenizer, minhash, lsh, compress, similarity, shard, dedup, cli, bench)为 100% 原生原创 MoonBit 实现,未依赖任何第三方 C/Rust 动态库或外部生成代码。
  • 源码规模统计(仅统计 src/ 下手写 .mbt 文件):
    • .mbt 源文件总数:40 个
    • .mbt 源码行数:4,100 行(含测试)
    • 测试用例覆盖:全模块覆盖(共 54 个单元测试与 Benchmark 全部 Pass)

📄 开源许可证

本项目采用 Apache-2.0 License 协议开源。

关于

实现 MinHash 签名、LSH 分桶、Jaccard 相似度近似和批量候选检索,适合网页、新闻、日志和文档集合去重。项目可进一步支持流式插入、签名压缩、分片合并和大规模相似文档检索。

112.0 KB
邀请码
    Gitlink(确实开源)
  • 加入我们
  • 官网邮箱:gitlink@ccf.org.cn
  • QQ群
  • QQ群
  • 公众号
  • 公众号

版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9 京公网安备 11010802047560号