1.1.2 Sequence-to-Graph Seed: Minimizer Option
选哈希值最小(或最大)的那个 k-mer 作为 minimizer,核心目的是:用随机哈希把“选择”变成一种确定性的、与序列内容无关的随机采样。
这样既能保证不同 read、不同样本在相同区域选出一致的 minimizer,又能让 minimizer 分布均匀、变化不频繁,从而降低索引和查询成本。
具体原因可以分成几层:
1. 避免序列组成偏倚
如果不用哈希,而是用某种固定规则选代表,比如“字典序最小的 k-mer”,会出问题:
- 某些碱基组成的 k-mer 会总是被选中;
- 富含 A/T 或 G/C 的区域可能产生过多或过少的 minimizer;
- 选择结果与序列内容强相关,导致分布不均匀。
哈希函数把每个 k-mer 映射成一个看起来随机的数值。
这样每个 k-mer 被选为窗口最小值的概率大致相等,与它具体是什么序列无关。
于是 minimizer 在基因组上的分布近似均匀,不会偏向某些碱基模式。
2. 保证不同样本间的一致性
Minimizer 最重要的用途之一是:
不同 read 覆盖同一区域时,应该能选出相同的 minimizer,这样索引才能匹配上。
哈希是确定性的:
同一个 k-mer,无论出现在哪条 read 里,哈希值都一样。
所以在相同窗口内,只要窗口内容相同,选出的最小哈希 k-mer 也相同。
这样:
- 建索引时,参考序列选出的 minimizer;
- 查询时,read 选出的 minimizer;
只要它们覆盖同一段保守序列,就能共享相同的键,从而命中。
如果选择规则依赖上下文或随机种子,不同样本可能选出不同代表,索引就无法复用。
3. 窗口滑动时变化少,minimizer 稳定
在一个大小为 的滑动窗口里,选哈希值最小的 k-mer。
当窗口向右滑动一格:
- 一个新 k-mer 进入;
- 一个旧 k-mer 离开。
只有两种情况会改变当前 minimizer:
- 新进入的 k-mer 哈希值比当前最小值还小;
- 当前最小值恰好是离开窗口的那个 k-mer。
因此,minimizer 不会每滑动一格就变一次,而是成段稳定。
这样:
- 索引中 minimizer 数量远少于全部 k-mer;
- 查询时命中的 minimizer 也更集中;
- 后续 chaining 的种子数量可控。
如果选“字典序最小”,在序列局部波动时可能频繁切换,导致 minimizer 集合不稳定。
4. 对变异有一定鲁棒性
假设一个窗口内发生了单碱基变异:
- 如果变异没有改变哈希值最小的那个 k-mer,minimizer 不变;
- 如果改变了,也只是局部窗口的 minimizer 变化,相邻窗口仍可能保留原来的 minimizer。
这种随机采样性质使得相似序列之间能共享相当比例的 minimizer。
理论上的期望是:两个相似度较高的序列,共享 minimizer 的比例也较高,从而保证 seeding 的灵敏度。
5. 为什么选“最小”或“最大”都可以?
选最小还是最大只是约定。
只要索引构建和查询使用同一个哈希函数、同一个窗口大小、同一个方向,结果就一致。
通常选最小哈希值,因为实现简单:
维护一个滑动窗口最小值,可以用双端队列在 均摊时间完成。
选最大只是把比较方向反过来,本质一样。
6. 和“随机采样”的关系
Minimizer 本质上是一种局部随机采样:
- 每个窗口至少选一个代表;
- 代表由哈希值决定,而不是由序列本身决定;
- 采样概率均匀,且确定可复现。
这类似于:
把每个 k-mer 随机分配一个“优先级”,每个窗口选优先级最高的那个。
这样得到的样本既稀疏,又能在不同数据集之间对齐。
总结
选哈希值最小/最大的 k-mer,是为了:
- 消除序列组成偏倚,让选择近似随机均匀;
- 保证确定性,相同序列在不同 read 中选出相同 minimizer;
- 保持稳定性,窗口滑动时 minimizer 变化不频繁;
- 控制数量,用少量代表覆盖整个 read;
- 支持跨样本匹配,让索引和查询能共享 minimizer。
所以它不是随便定的规则,而是 minimizer 方法能同时兼顾灵敏度、效率和可复用性的关键设计。