Kraken2原理:基于k-mer的快速分类算法
Kraken2这东西,说白了就是用DNA短串来给序列贴标签。我自己在做项目时,常被新同学问:“它怎么就那么快?” 今天我来拆开讲讲。
k-mer是什么
把一条序列切成固定长度的小片段。比如 ATCGATCG,切成4-mer就是:ATCG、TCGA、CGAT、GATC。Kraken2默认k=31,也就是每31个碱基为一个单元。
你想想看,一条Illumina读长150bp,能切出120个31-mer。每个小段都有机会匹配到参考基因组。这就是Kraken2分类的基础——投票机制。
建库过程:从基因组到哈希表
Kraken2建库分三步走:
- 提取参考基因组所有k-mer
- 给每个k-mer分配LCA(最低共同祖先)
- 构建哈希表
第二步最关键。如果一个31-mer只在单一种里出现,那就直接标为这个种。如果它出现在多个物种里,算法会回溯到它们的共同祖先。我配图说明一下:
哈希表里存的是(k-mer,LCA分类ID)对。查找时复杂度是O(1)——这就是 Kraken2 快的原因之一。我印象最深的是,有次跑一个1000万条reads的样本,它只用了不到8分钟就出结果。
分类过程:一次快速投票
当一条序列进来:
- 拆成31-mer:滑动窗口,每步移动1个碱基
- 哈希查找:每个k-mer查表,快速得到物种或LCA
- 投票决策:把所有k-mer的结果汇总,出现最多的分类胜出
举个实际例子。假设一条序列有120个31-mer命中,其中80个指向大肠杆菌,40个指向沙门氏菌。Kraken2会投票给大肠杆菌。我曾在项目里看到,有些序列表面看起来像某菌,但内部k-mer分布根本不是那么回事,投票结果一下子就暴露出来了。
为什么它能这么快
传统的方法(比如BLAST)要逐个比对,慢在搜索上。Kraken2干脆把匹配过程前置到建库阶段:
| 项目 | 传统比对(BLAST) | Kraken2 |
|---|---|---|
| 查库方式 | 逐个序列比对,耗时 | 哈希表O(1)查找 |
| 数据库大小 | 动辄几十GB | 压缩后~8GB(标准库) |
| 10万条reads用时 | 数小时 | 数十秒 |
| 内存需求 | 通常大于50GB | 约11GB(MiniKraken) |
k-mer长度与数据库的平衡
你把k调大,特异性上去了,但匹配概率下降了。我在实践中通常会检查一下数据库的构建参数。比如建库命令中其实可以设置k-mer长度:
kraken2-build --kmer-len 31 --db my_db --build
我个人习惯用默认31,除非是特殊项目。Kraken2还做了个优化——最小化k-mer存储。它把重复或冗余的k-mer去重,只保留代表性片段。这解释了为什么标准库能压缩到5GB大小。
核心优势总结:O(1)查找 + 最小化存储 + 投票决策 = 极速分类
跑起来什么样
命令行很简单,但背后是几百万个的哈希查找:
kraken2 --db /path/to/standard_db --threads 8 \
--report my_report.tsv \
--output my_output.txt \
sample.fastq
输出的文件一般有两列:分类等级(U:未分类、R:根、D:域...到S:种)和reads数量。我在取结果的时候,一般会先看“U”那一行——未分类比例高的话,说明样本里有数据库未收录的新东西。
小结一下
Kraken2的原理就是把复杂的序列比对问题,转换成了简单的哈希表查找。做生物信息这么多年,我觉得在速度和资源受限的场景下,它依然是首选。当然,也有它搞不定的情况——下次讲MetaPhlAn时,你会发现两者恰好互补。