估计阅读时长: 7 分钟

假若现在有两条Fasta序列放在你面前,现在需要你进行这两条Fasta序列的相似度计算分析。如果对于我而言,大学刚毕业刚入门生物信息学的时候,可能只能够想到通过blast比对的方式进行序列相似性计算分析。基于blast比对方式可以找到生物学意义上的序列相似性结果,但是计算的效率会比较低。假设现在让你使用这些序列进行机器学习建模分析,或者基于传统数学意义上的基于相似度的无监督聚类分析的时候,面对这些长度上长短不一的生物序列数据,可能会比较蒙圈,因为传统的数学分析方法都要求我们分析的目标至少应该是等长的向量数据。

使用图理论描述序列

在接触过图分析理论,对序列数据有一个比较深刻的认识之后,实现上面的分析目标,实际上我们可以将目标生物序列转换为图对象,然后基于图对象进行一维嵌入表示的方式将长度上长短不一的序列转换为等长的数值向量。最后基于得到的向量数据,就可以进行基于常规的数学方法做机器学习建模或者无监督的数据挖掘分析了。

生物序列图嵌入方法就是这样一种基于图论的方法将变长的序列数据转换为等长的向量的方法,其主要是通过图理论将不同长度的两条生物序列嵌入表示为两个等长的向量,当任意的生物序列都转换为等长的两个向量之后,我们就可以通过传统的聚类算法,机器学习算法来进行生物序列数据的分析,例如无监督聚类,机器学习分类。

那这个方法的实现原理是怎样的?

序列的图对象表示

其实这个序列图嵌入方法与自然语言处理分析之中的TextRank算法中对自然语言文本的图嵌入过程有一些类似,只不过TextRank处理的自然语言文本是没有太多重复单词的文本数据,而对于序列图嵌入方法而言,其所进行图嵌入的目标则是存在有大量重复单词出现的序列数据。序列图嵌入和TextRank自然语言文本处理方法,在最开始对所输入的目标文本的图对象表示,都可以基于下面的方法描述来进行:

  1. 对于任意一个给定的文本数据,我们会需要首先进行文本的分词处理,对于TextRank算法所处理的自然语言文本,如果是英文文本的话,会非常容易,直接按照空格做拆分。对于中文还需要一些额外的算法做分词。对于生物序列数据,则是非常简单的吧序列文本里面的每一个字符拿出来就是一个单词对象了
  2. 接着我们就可以在分词结果的基础上进行图对象的构建了:在图对象里面,都是存在有节点和节点之间的边连接关系这两种类型的数据组成的。在我们前面所分词处理后的文本数据中,所分出来的每一个单词实际上都相当于图对象之中的节点对象;那么,这个时候,源文本中的前一个单词和后一个单词二者之间就可以添加一条边连接。通过单词和单词之间的前后链接关系我们就可以将任意一个文本数据转换为基于单词节点的图对象了

在完成了上面所描述的图对象的构建之后,我们接下来就可以将这个图对象进行向量化表示就完成了将我们所获得的序列数据描述为等长的向量数据这一目标了。那么如何将我们的图对象进行向量化描述呢?

> example_sequence
ATGCCCGTCCCGTAAA
Adjacent Count Normalized
A-A 2 0.125
A-T 1 0.0625
T-A 1 0.0625
A-G 0 0
G-A 0 0
A-C 0 0
C-A 0 0
T-T 0 0
T-C 1 0.0625
C-T 0 0
T-G 1 0.0625
G-T 2 0.125
C-C 4 0.25
C-G 2 0.125
G-C 1 0.0625
G-G 0 0

通过序列中,残基元素之间的边连接关系得到上面的相邻碱基计数表格后,实际上就完成了对一条任意长度的Fasta序列嵌入为了等长元素向量;在完成对原始Count值进行序列长度归一化之后,就可以与其他的任意Fasta序列的嵌入向量结果之间进行比较计算

图对象嵌入表示

因为我们创建图对象的本意就是用来描述任意两个节点之间的关联关系的,所以对于任意图对象而言,我们使用两两组合排列的方式吧图对象里面所有节点的连接关系给列举出来实际上就可以将图对象转换为向量了。当组合出来的两个节点之间存在有边连接关系的时候,就把边连接关系的权重放入到向量中对应的位置;当组合出来两个节点之间没有边连接关系的时候,就放一个零,这样子,把图对象表示为向量是不是非常简单。

对于通过自然语言文本生成的图对象而言,上面的方法可能会有些行不通,因为自然语言分词出来的单词可能是无限数量类型的,所以假若描述为向量的话,向量理论上也是无限长的。但是对于生物序列数据所产生的图对象而言,则情况简单的多了。

其实我们观察生物序列的文本特点就可以了解到,任意一条生物序列数据,里面都是由有限的基础的若干元素所构成的:DNA序列ATGC,RNA序列AUGC,蛋白序列则是20种常见氨基酸的简写字母。那么我们通过上面所描述的方法进行生物序列图对象的向量化表示,得到的就是有限长度的向量结果。

那么现在既然有了可以用来描述对应生物序列的向量数据了,那现在我们就可以基于这些向量进行常规数学方法的机器学习建模和数据挖掘分析了。

使用SGT算法进行任意序列的图嵌入

使用GCModeller进行Fasta序列的图嵌入

基于上面的SGT算法,在GCModeller之中定义了一个帮助类:来进行任意Fasta序列的图嵌入操作。这个帮助类的代码如下:

''' <summary>
''' Create sgt embedding matrix
''' </summary>
Public Class CreateMatrix

    ReadOnly sgt As SequenceGraphTransform

    ''' <summary>
    ''' get the dimension size of the generated biological sequence 
    ''' matrix via the function <see cref="ToMatrix(FastaSeq)"/>
    ''' </summary>
    ''' <returns>The CNN input size</returns>
    Public ReadOnly Property dimension As Size
        <MethodImpl(MethodImplOptions.AggressiveInlining)>
        Get
            Return New Size(sgt.alphabets.Length, sgt.alphabets.Length)
        End Get
    End Property

    Sub New(Optional mol As SeqTypes = SeqTypes.Protein)
        Dim allChars As String() = GetChars(mol)

        sgt = New SequenceGraphTransform
        sgt.set_alphabets(allChars)
    End Sub

    Private Shared Function GetChars(mol As SeqTypes) As String()
        Select Case mol
            Case SeqTypes.Protein
                Return AminoAcidObjUtility _
                    .AminoAcidLetters _
                    .JoinIterates("-") _
                    .AsCharacter _
                    .ToArray
            Case Else
                Return mol.GetVector _
                    .JoinIterates({"-"c, "N"c}) _
                    .AsCharacter _
                    .ToArray
        End Select
    End Function

    Public Function ToMatrix(seq As FastaSeq) As Double()()
        Dim v = sgt.fit(seq.SequenceData)
        Dim m = sgt.TranslateMatrix(v)

        Return m
    End Function

    ''' <summary>
    ''' make the given fasta sequence embedding as vector
    ''' </summary>
    ''' <param name="seq"></param>
    ''' <returns></returns>
    <MethodImpl(MethodImplOptions.AggressiveInlining)>
    Public Function ToVector(seq As FastaSeq) As Double()
        Return sgt.fitVector(seq.SequenceData)
    End Function

End Class

可以看得到,这个帮助类的构造函数接受一个序列类型的参数,然后在构造函数中根据序列类别加载不同的序列字母集合到SGT算法模块之中。在创建了这个帮助类对象实例之后,我们就可以通过ToVector函数将fasta序列进行嵌入为向量了。基于这个得到的向量数据,因为其是等长的,所以就可以非常容易的应用到下游的数据建模分析之中:例如聚类,机器学习训练之类的要求结构化数据输入的工作场景。

在此帮助类的基础之上,GCModeller的序列工具包中定义了针对生物序列进行图嵌入操作的工具函数,可以在R#语言之中进行使用。

''' <summary>
''' Create algorithm for make sequence embedding
''' </summary>
''' <param name="moltype"></param>
''' <returns></returns>
<ExportAPI("seq_sgt")>
Public Function seq_sgt(Optional moltype As SeqTypes = SeqTypes.Protein) As CreateMatrix
    Return New CreateMatrix(moltype)
End Function

''' <summary>
''' embedding the given fasta sequence as vector
''' </summary>
''' <param name="sgt"></param>
''' <param name="seqs"></param>
''' <param name="env"></param>
''' <returns></returns>
<ExportAPI("seq_vector")>
Public Function seq_vector(sgt As CreateMatrix, 
                           <RRawVectorArgument> 
                           seqs As Object, 
                           Optional env As Environment = Nothing) As Object

    Dim seq_pool = GetFastaSeq(seqs, env).ToArray

    If seq_pool.Length = 1 Then
        Return sgt.ToVector(seq_pool(0))
    Else
        Dim vec As list = list.empty

        For Each seq As FastaSeq In seq_pool
            Call vec.add(seq.Title, sgt.ToVector(seq))
        Next

        Return vec
    End If
End Function

可以了解到,在GCModeller中对外导出了两个函数,一个函数seq_sgt是用于创建针对特定的序列类型的图嵌入算法对象。第二个函数就可以基于前面所创建的图嵌入算法模块,针对输入的fasta序列进行向量嵌入操作。下面是一个R#脚本的小小的示例:

require(GCModeller);

imports "bioseq.fasta" from "seqtoolkit";

# get fasta sequence data
let seqs = read.fasta("./proteins.fa");
let sgt  = seq_sgt(moltype = "prot");
let vec  = sgt |> seq_vector(seqs);

# run data analysis on the generated embedding vectors
谢桂纲
Latest posts by 谢桂纲 (see all)

Attachments

  • Fasta-A • 544 kB • 170 click
    2023年6月29日

  • visualize • 45 kB • 172 click
    2023年7月1日

One response

  1. 针对图对象进行向量化表示嵌入:

    首先,通过node2vec方法,将node表示为向量
    第二步,针对node向量矩阵,进行umap降维计算,对node进行排序,生成node排序序列
    第三步,针对node排序序列进行SGT序列图嵌入,实现将网络图对象嵌入为一维向量

    来自江苏

Leave a Reply

Your email address will not be published. Required fields are marked *

博客文章
May 2025
S M T W T F S
 123
45678910
11121314151617
18192021222324
25262728293031
  1. […] 在上面的工具调用消息数据结构中,我们可以清楚的看见有需要进行调用的工具名称,以及参数列表。当我们拿到这样子的调用信息后,就可以基于一定的规则找到需要执行的运行时中的函数来完成功能的实现。对于.NET平台上,我们一般是使用自定义属性加反射操作来解析相关的名称绑定结果。在.NET平台上对于这样子的一个根据调用信息来进行运行时解析和调用的方法,可以稍微参考《【Darwinism】Linux平台上的VisualBasic高性能并行计算应用的开发》的反射代码方法。 […]