BLESS全称:Bloom-filter-based Error Correction Solution for High-throughput Sequencing Reads,即基于布隆过滤器的高通量测序修正方法。

原文链接:https://academic.oup.com/bioinformatics/article-lookup/doi/10.1093/bioinformatics/btu030

1.首先对布隆过滤器的原理进行简单解释。

布隆过滤器[1](Bloom Filter)是由布隆(Burton Howard Bloom)在1970年提出的。它实际上是由一个很长的二进制向量和一系列随机映射函数组成,布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率(假正例False positives,即Bloom Filter报告某一元素存在于某集合中,但是实际上该元素并不在集合中)和删除困难,但是没有识别错误的情形(即假反例False negatives,如果某个元素确实没有在该集合中,那么Bloom Filter 是不会报告该元素存在于集合中的,所以不会漏报)。相关内容链接:

http://blog.csdn.net/lifuxiangcaohui/article/details/42025629?locationNum=15&fps=1

http://www.dataguru.cn/thread-509369-1-1.html

http://www.cnblogs.com/liyulong1982/p/6013002.html

基本思想

如果想判断一个元素是不是在一个集合里,一般想到的是将所有元素保存起来,然后通过比较确定。链表,树等等数据结构都是这种思路. 但是随着集合中元素的增加,我们需要的存储空间越来越大,检索速度也越来越慢。不过世界上还有一种叫作散列表(又叫哈希表,Hash table)的数据结构。它可以通过一个Hash函数将一个元素映射成一个位阵列(Bit Array)中的一个点。这样一来,我们只要看看这个点是不是 1 就知道可以集合中有没有它了。这就是布隆过滤器的基本思想。

Hash面临的问题就是冲突。假设 Hash 函数是良好的,如果我们的位阵列长度为 m 个点,那么如果我们想将冲突率降低到例如 1%, 这个散列表就只能容纳 m/100 个元素。显然这就不叫空间有效了(Space-efficient)。解决方法也简单,就是使用多个 Hash,如果它们有一个说元素不在集合中,那肯定就不在。如果它们都说在,虽然也有一定可能性它们在说谎,不过直觉上判断这种事情的概率是比较低的。

再结合图像解释一下,布隆过滤器由一个m位的向量BV表示,BV(Bit Vector)初始时是一个全0的向量,采用了p个hash函数映射的方式,输入集合Sin 中含有n个元素,p次hash映射产生p个映射得到的index值,即位置下标值,然后将这些位置的下标置为1

优点

相比于其它的数据结构,布隆过滤器在空间和时间方面都有巨大的优势。布隆过滤器存储空间和插入/查询时间都是常数。另外, Hash 函数相互之间没有关系,方便由硬件并行实现。布隆过滤器不需要存储元素本身,在某些对保密要求非常严格的场合有优势。

布隆过滤器可以表示全集,其它任何数据结构都不能;

k 和 m 相同,使用同一组 Hash 函数的两个布隆过滤器的交并差运算可以使用位操作进行。

缺点

但是布隆过滤器的缺点和优点一样明显。误算率(False Positive)是其中之一。随着存入的元素数量增加,误算率随之增加。但是如果元素数量太少,则使用散列表足矣。

另外,一般情况下不能从布隆过滤器中删除元素. 我们很容易想到把位列阵变成整数数组,每插入一个元素相应的计数器加1, 这样删除元素时将计数器减掉就可以了。然而要保证安全的删除元素并非如此简单。首先我们必须保证删除的元素的确在布隆过滤器里面. 这一点单凭这个过滤器是无法保证的。另外计数器回绕也会造成问题。

赵主任问题:为什么说布隆过滤器存储比其他的数据结构所需内存小?

核心回答内容:布隆过滤器采用的一个n位的向量,可以表示2的n次方个k-mers,所以能节省很多空间。

False positives 概率推导

假设 Hash 函数以等概率条件选择并设置 Bit Array 中的某一位,m 是该位数组的大小,k 是 Hash 函数的个数,那么位数组中某一特定的位在进行元素插入时的 Hash 操作中没有被置位的概率是:

那么在所有 k 次 Hash 操作后该位都没有被置 "1" 的概率是:

如果我们插入了 n 个元素,那么某一位仍然为 "0" 的概率是:

因而该位为 "1"的概率是:

现在检测某一元素是否在该集合中。标明某个元素是否在集合中所需的 k 个位置都按照如上的方法设置为 "1",但是该方法可能会使算法错误的认为某一原本不在集合中的元素却被检测为在该集合中(False Positives),该概率由以下公式确定:

为了让错误率最小,如何确定m,n,k呢?

其实上述结果是在假定由每个 Hash 计算出需要设置的位(bit) 的位置是相互独立为前提计算出来的,不难看出,随着 m (位数组大小)的增加,假正例(False Positives)的概率会下降,同时随着插入元素个数 n 的增加,False Positives的概率又会上升,对于给定的m,n,如何选择Hash函数个数 k 由以下公式确定:

此时False Positives的概率为:

而对于给定的False Positives概率 p,如何选择最优的位数组大小 m 呢,

上式表明,位数组的大小最好与插入元素的个数成线性关系,对于给定的 m,n,k,假正例概率最大为:

2.基因纠错相关方法介绍

纠错方法主要可以分为四类:1)k-mer spectrum based,2)suffix tree/array based,3)multiple sequence alignment based,and 4)hidden Markov model based

1)k-mers片段组成集合T,包含基因组中所有的k长度的光谱(连续片段)。如果读入的k-mer不在集合T中,则认为该片段很可能是有错误的。然后用最小的修正代价将该片段改为T中存在的k-mer片段。在没有基因组数据时,我们可以设定一个阈值M,将重复数(计数)大于M的k-mer片段放入集合T,我们将集合中的k-mer片段元素称为可靠的(solid)k-mer段,将不在其中的成为不可靠的(weak)k-mer段。T需要放在内存,这样就能迅速找到weak k-mers的修改方法。T集合的大小随着k的增加会变大。因此,存储T集合的内存使用就受到k的限制。对于一个大数据量的基因组,如果选择的k太小,我们就修改的过程中就会发现,一个weak k-mers可能可以修改成好几个solid k-mers。这样的不确定性,会导致输出的精度问题,因为修改正确性值得怀疑。

2)后缀树和后缀矩阵是处理字符串匹配的主要数据结构。后缀树不是一个存储很高效的数据结构在处理NGS读入时,因为每个基本结构在树中是一个结点的形式出现的。即使很多线性序列处理工具能成功的用后缀矩阵去保存涉及到的序列,维持用后缀矩阵完成NGS读入需要大量的内存空间。所以基于这一结构的纠错方法只能应用与小规模的基因组,即使这样也需要大量的存储空间。HiTEC是最流行的基于后缀矩阵的纠错方法。

?3)基于MSA的方法是用k-mers去创建一个hash表,与读入的k-mer发生关联。对于读入的数据是有着相同的k-mers,序列校准是找到读入中数据中有大量重叠的部分的。这样错误可以得到修正基于共识的序列。但是,基于MSA的方法是不可扩展的,因为读入的数据会导致hash表过大,使得这种方法的计算密集。

4)基于HMM的方法是,读取错误可以通过查找具有最高概率生成读取的状态转换来进行纠正。对于大的基因组很难使用这种方法,因为保存状态和寻找最高概率的转换需要大量的内存使用和较高的计算复杂度。另一种方法使用只有三个状态(插入、删除和匹配)的隐马尔可夫模型对RNA读入错误进行修正。使用MSA对RNA读入数据进行聚类,并为每个簇构建单独的HMM。然而,很难将这种方法应用于大基因组的DNA读取,因为使用MSA进行大量读取的群集读取将非常昂贵。

3.BLESS纠错算法

对于读入长度为L的序列r包含A,C,G,T符号,第i个符号用r[i]表示,0<=i<=L-1.   r[i,j]表示r中从第i位到第j位.算法示意图如下:

2017.10.16 因研究方向需要,这周转到深度学习与ngs结合相关内容,这部分内容暂时先这样。

BLESS学习笔记的更多相关文章

  1. 尚学堂JAVA基础学习笔记

    目录 尚学堂JAVA基础学习笔记 写在前面 第1章 JAVA入门 第2章 数据类型和运算符 第3章 控制语句 第4章 Java面向对象基础 1. 面向对象基础 2. 面向对象的内存分析 3. 构造方法 ...

  2. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  3. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  4. PHP-会员登录与注册例子解析-学习笔记

    1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...

  5. 2014年暑假c#学习笔记目录

    2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...

  6. JAVA GUI编程学习笔记目录

    2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...

  7. seaJs学习笔记2 – seaJs组建库的使用

    原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ...

  8. CSS学习笔记

    CSS学习笔记 2016年12月15日整理 CSS基础 Chapter1 在console输入escape("宋体") ENTER 就会出现unicode编码 显示"%u ...

  9. HTML学习笔记

    HTML学习笔记 2016年12月15日整理 Chapter1 URL(scheme://host.domain:port/path/filename) scheme: 定义因特网服务的类型,常见的为 ...

随机推荐

  1. C# md5加密方法

    public static string md5(string str, int code) { if (code == 16) //16位MD5加密(取32位加密的9~25字符) { return ...

  2. Django学习-11-请求相关信息

    requests对象是由类创建的 from django.core.handlers.wsgi import WSGIRequest    --> 类 request.environ中封装了请求 ...

  3. json 的循环输出

    json不能用for-of循环,会报错 可以用for-in循环: var json = {'a':'apple','b':'banana','c':'orange','d':'pear'}; for( ...

  4. 极重要基础命令三剑客加find

    find  -type:以文件类型查找 -name:以文件名查找 ! 取反 sed命令实战: sed -n “2p” oldboy.txt 打印第二行 sed -n "1,2p" ...

  5. 2018第一波iOS经典笔试题(现场实拍)

    序言 作为一个开发者,眼里不仅仅只存在于那一行又一行的代码,更还有那诗和远方. 注明:面试是对自我审视的一种过程,面试题和iOS程序员本身技术水平没任何关联,无论你能否全部答出,都不要对自己产生任何正 ...

  6. C#多线程之异步编程

    c#中异步编程,主要有两种方法: 1.委托的异步调用: 2.Task的await,async (c# 4.5) 我们来看例子: /// <summary> /// 异步保存网页,url:网 ...

  7. Kafka最佳实践

    一.硬件考量 1.1.内存 不建议为kafka分配超过5g的heap,因为会消耗28-30g的文件系统缓存,而是考虑为kafka的读写预留充足的buffer.Buffer大小的快速计算方法是平均磁盘写 ...

  8. 从AngularJS2谈到前台开发工程化

    才刚刚对AngularJS有些了解,又听闻AngularJS2早就铺天盖地了,AngularJS3刚刚夭折,AngularJS4今年已经发布了,还是学习先下AngularJS2吧,据说更加适合以移动为 ...

  9. Django用户登录与注册系统

    一.创建项目 1.1.创建项目和app python manage.py startproject mysite_login python manage.py startapp login 1.2.设 ...

  10. Java中String字符串常量池总结

    最近到广州某建站互联网公司面试,当时面试官问假设有两个字符串String a="abc",String b = "abc";问输出a==b是true还是fals ...