網頁

2019年7月7日 星期日

Working with DNA sequence data for machine learning - an introduction

在生物計算中,使用DNA序列數據是常見的。Python package的Biopython可以幫助我們在處理Python中的生物序列數據。 DNA序列數據通常包含在稱為“fasta”格式的文件格式中。 Fasta格式是一行前綴與另一行序列:

>有關序列的信息
ATGTTTCGCATCACCAACATTGAGTTTCTTCCCGAATACCGACAAAAGGAGTCCAGGGAA

該文件可包含一個或多個DNA序列。還有很多其他格式,但fasta是最常見的。

以下是使用Biopython以fasta格式處理DNA序列的簡單示範。序列對象將包含您可以直接使用的屬性,例如id和sequence。

文件“example.fa”是包含2個DNA序列的fasta文件。這裡使用內置的解析類別加載它們並創建序列對象,然後顯示id和sequence屬性。

from Bio import SeqIO
for seq_record in SeqIO.parse('../input/example.fa', "fasta"):
    print(seq_record.id)
    print(seq_record.seq)

ENST00000435737.5
ATGTTTCGCATCACCAACATTGAGTTTCTTCCCGAATACCGACAAAAGGAGTCCAGGGAATTTCTTTCAGTGTCACGGACTGTGCAGCAAGTGATAAACCTGGTTTATACAACATCTGCCTTCTCCAAATTTTATGAGCAGTCTGTTGTTGCAGATGTCAGCAACAACAAAGGCGGCCTCCTTGTCCACTTTTGGATTGTTTTTGTCATGCCACGTGCCAAAGGCCACATCTTCTGTGAAGACTGTGTTGCCGCCATCTTGAAGGACTCCATCCAGACAAGCATCATAAACCGGACCTCTGTGGGGAGCTTGCAGGGACTGGCTGTGGACATGGACTCTGTGGTACTAAATGAAGTCCTGGGGCTGACTCTCATTGTCTGGATTGACTGA
ENST00000419127.5
ATGTTTCGCATCACCAACATTGAGTTTCTTCCCGAATACCGACAAAAGGAGTCCAGGGAATTTCTTTCAGTGTCACGGACTGTGCAGCAAGTGATAAACCTGGTTTATACAACATCTGCCTTCTCCAAATTTTATGAGCAGTCTGTTGTTGCAGATGTCAGCAACAACAAAGGCGGCCTCCTTGTCCACTTTTGGATTGTTTTTGTCATGCCACGTGCCAAAGGCCACATCTTCTGTGAAGACTGTGTTGCCGCCATCTTGAAGGACTCCATCCAGACAAGCATCATAAACCGGACCTCTGTGGGGAGCTTGCAGGGACTGGCTGTGGACATGGACTCTGTGGTACTAAATGACAAAGGCTGCTCTCAGTACTTCTATGCAGAGCATCTGTCTCTCCACTACCCGCTGGAGATTTCTGCAGCCTCAGGGAGGCTGATGTGTCACTTCAAGCTGGTGGCCATAGTGGGCTACCTGATTCGTCTCTCAATCAAGTCCATCCAAATCGAAGCCGACAACTGTGTCACTGACTCCCTGACCATTTACGACTCCCTTTTGCCCATCCGGAGCAGCATCTTGTACAGAATTTGTGAACCCACAAGAACATTAATGTCATTTGTTTCTACAAATAATCTCATGTTGGTGACATTTAAGTCTCCTCATATACGGAGGCTCTCAGGAATCCGGGCATATTTTGAGGTCATTCCAGAACAAAAGTGTGAAAACACAGTGTTGGTCAAAGACATCACTGGCTTTGAAGGGAAAATTTCAAGCCCATATTACCCGAGCTACTATCCTCCAAAATGCAAGTGTACCTGGAAATTTCAGACTTCTCTATCAACTCTTGGCATAGCACTGAAATTCTATAACTATTCAATAACCAAGAAGAGTATGAAAGGCTGTGAGCATGGATGGTGGGAAATTAATGAGCACATGTACTGTGGCTCCTACATGGATCATCAGACAATTTTTCGAGTGCCCAGCCCTCTGGTTCACATTCAGCTCCAGTGCAGTTCAAGGCTTTCAGACAAGCCACTTTTGGCAGAATATGGCAGTTACAACATCAGTCAACCCTGCCCTGTTGGATCTTTTAGATGCTCCTCCGGTTTATGTGTCCCTCAGGCCCAGCGTTGTGATGGAGTAAATGACTGCTTTGATGAAAGTGATGAACTGTTTTGCGTGAGCCCTCAACCTGCCTGCAATACCAGCTCCTTCAGGCAGCATGGCCCTCTCATCTGTGATGGCTTCAGGGACTGTGAGAATGGCCGGGATGAGCAAAACTGCACTCAAAGTATTCCATGCAACAACAGAACTTTTAAGTGTGGCAATGATATTTGCTTTAGGAAACAAAATGCAAAATGTGATGGGACAGTGGATTGTCCAGATGGAAGTGATGAAGAAGGCTGCACCTGCAGCAGGAGTTCCTCCGCCCTTCACCGCATCATCGGAGGCACAGACACCCTGGAGGGGGGTTGGCCGTGGCAGGTCAGCCTCCACTTTGTTGGATCTGCCTACTGTGGTGCCTCAGTCATCTCCAGGGAGTGGCTTCTTTCTGCAGCCCACTGTTTTCATGGAAACAGGCTGTCAGATCCCACACCATGGACTGCACACCTCGGGATGTATGTTCAGGGGAATGCCAAGTTTGTCTCCCCGGTGAGAAGAATTGTGGTCCACGAGTACTATAACAGTCAGACTTTTGATTATGATATTGCTTTGCTACAGCTCAGTATTGCCTGGCCTGAGACCCTGAAACAGCTCATTCAGCCAATATGCATTCCTCCCACTGGTCAGAGAGTTCGCAGTGGGGAGAAGTGCTGGGTAACTGGCTGGGGGCGAAGACACGAAGCAGATAATAAAGGCTCCCTCGTTCTGCAGCAAGCGGAGGTAGAGCTCATTGATCAAACGCTCTGTGTTTCCACCTACGGGATCATCACTTCTCGGATGCTCTGTGCAGGCATAATGTCAGGCAAGAGAGATGCCTGCAAAGGAGATTCGGGTGGACCTTTATCTTGTCGAAGAAAAAGTGATGGAAAATGGATTTTGACTGGCATTGTTAGCTGGGGACATGGAAGTGGACGACCAAACTTTCCTGGTGTTTACACAAGGGTGTCAAACTTTGTTCCCTGGATTCATAAATATGTCCCTTCTCTTTTGTAA
用DNA序列數據進行機器學習
現在我們可以輕鬆地加載和操作生物序列數據,我們如何將它用於機器學習或深度學習?有三種一般方法。 1)將序列資訊編碼為序數向量並直接使用,2)對序列字母進行one-hot編碼並使用和3)將DNA序列作為語言(文本)處理並使用各種“語言”處理方法。

序數編碼DNA序列數據(Ordinal encoding DNA sequence data)
一種方法是將每個核苷酸字符編碼為序數值。例如,“ATGC”變為[0.25,0.5,0.75,1.0]。任何其他基礎,如“N”可以是0. Allen Chieng,Hoon Choong和Nung Kion Lee在他們的論文“Evaluation of Convolutionary Neural Networks Modeling of DNA Sequences using Ordinal versus one-hot Encoding Method”中表明,這種方法效果非常好。

讓我們首先創建一些實用程序函數,例如從序列字符串創建numpy陣列物件,以及帶有DNA序列字母“a”,“c”,“g”和“t”的標籤編碼器,還可以創建任何字元,“n”。

# function to convert a DNA sequence string to a numpy array
# converts to lower case, changes any non 'acgt' characters to 'n'
import numpy as np
import re
def string_to_array(my_string):
    my_string = my_string.lower()
    my_string = re.sub('[^acgt]', 'z', my_string)
    my_array = np.array(list(my_string))
    return my_array

# create a label encoder with 'acgtn' alphabet
from sklearn.preprocessing import LabelEncoder
label_encoder = LabelEncoder()
label_encoder.fit(np.array(['a','c','g','t','z']))

ps. re.sub('[^acgt]', 'z', my_string)是用來匹配出非acgt的字母n變成z,[]是用來指定一個字符類別,^將匹配除 "acgt" 之外的任意字符。

參考
https://note.artchiu.org/2015/01/23/%E6%AF%94%E8%BC%83%E8%A9%B3%E7%B4%B0-python-%E6%AD%A3%E5%89%87%E8%A1%A8%E9%81%94%E5%BC%8F%E6%93%8D%E4%BD%9C%E6%8C%87%E5%8D%97-re%E4%BD%BF%E7%94%A8/

這是一個將DNA序列編碼為序數向量的函數。 它返回一個n = 0,n = 0.25,c = 0.50,g = 0.75,t = 1.00,n = 0.00的numpy陣列。

# function to encode a DNA sequence string as an ordinal vector
# returns a numpy vector with a=0.25, c=0.50, g=0.75, t=1.00, n=0.00
def ordinal_encoder(my_array):
    integer_encoded = label_encoder.transform(my_array)
    float_encoded = integer_encoded.astype(float)
    float_encoded[float_encoded == 0] = 0.25 # A
    float_encoded[float_encoded == 1] = 0.50 # C
    float_encoded[float_encoded == 2] = 0.75 # G
    float_encoded[float_encoded == 3] = 1.00 # T
    float_encoded[float_encoded == 4] = 0.00 # anything else, z
    return float_encoded

所以讓我們用一個簡單的短序列來試試吧:

test_sequence = 'AACGCGCTTNN'
ordinal_encoder(string_to_array(test_sequence))


One-hot encoding DNA sequence data
另一種方法是使用one-hot編碼來表示DNA序列。 這廣泛被使用在深度學習方法中,並且很適合卷積神經網絡等算法。 在這個例子中,“ATGC”將變為[0,0,0,1],[0,0,1,0],[0,1,0,0],[1,0,0,0]。 並且這些單熱編碼矢量可以連接或轉換為二維陣列。 我們來試試吧。 這裡執行一個one-hot編碼的函式:

# function to one-hot encode a DNA sequence string
# non 'acgt' bases (n) are 0000
# returns a L x 4 numpy array
from sklearn.preprocessing import OneHotEncoder
def one_hot_encoder(my_array):
    integer_encoded = label_encoder.transform(my_array)
    onehot_encoder = OneHotEncoder(sparse=False,handle_unknown='ignore')
    integer_encoded = integer_encoded.reshape(len(integer_encoded), 1)
    onehot_encoded = onehot_encoder.fit_transform(integer_encoded)
    onehot_encoded = np.delete(onehot_encoded, -1, 1)
    return onehot_encoded

ps. my_array是一個密集矩陣(dense matrix)不是稀疏矩陣(sparse matrix),所以OneHotEncoder的引數sparse設定為False。

所以讓我們用一個簡單的短序列來試試吧:

test_sequence = 'AACGCGGTTNN'
one_hot_encoder(string_to_array(test_sequence))


Treating DNA sequence as a "language", otherwise known as k-mer counting
上述方法中仍然存在一種挑戰,就是沒有一個產生均勻長度的向量,並且這是將數據饋送到分類或回歸算法的要求。因此,使用上述方法,您必須求助於截斷序列或使用“n”或“0”填充以獲得均勻長度的向量。

DNA和蛋白質序列可以被隱喻地視為生命的語言。該語言編碼指令以及分子的功能在所有生命形式中被發現。基因序列語言類比為書,子序列(基因和基因家族)是句子和章節,k-mers和肽(motifs)是單字,核苷酸鹼基和氨基酸是字母表。由於類比似乎很合適,因此在自然語言處理領域所做的出色工作也應該適用於DNA和蛋白質序列的自然語言。

這裡使用的方法簡單易行。首先採用長生物序列並將其分解為重疊“單字”的k-mer長度。例如,如果我使用長度為6(六進制)的“單字”,則“ATGCATGCA”變為:“ATGCAT”,“TGCATG”,“GCATGC”,“CATGCA”。因此,我們的範例序列被分解為4個六進制的單字。

這裡使用六進制的“單字”是任意選擇的,字長可以調整,以適應特定的情況。對於任何給定的應用,需要根據經驗確定字長和重疊量。

在基因組學中,我們將這些類型的操作稱為“k-mer計數” (k-mer counting),或計算每個可能的k-mer序列的出現。有專門的工具,但Python自然語言處理工具使它變得簡單。

以下函數是一個可用於將任何序列(字符串)轉換為重疊的k-mer字:

def getKmers(sequence, size):
    return [sequence[x:x+size].lower() for x in range(len(sequence) - size + 1)]

讓我們看看它的實際效果:

mySeq = 'CATGGCCATCCCCCCCCGAGCGGGGGGGGGG'
getKmers(mySeq, size=6)


它返回一個k-mer“單字”列表。 然後,您可以將“單字”加入“句子”,然後像往常一樣在“句子”上應用您喜歡的自然語言處理方法。

words = getKmers(mySeq, size=6)
sentence = ' '.join(words)
sentence


您可以調整單字長度和重疊量。 這允許您確定序列訊息和詞彙量大小在應用程序中的重要性。 例如,如果您使用長度為6的單字,並且有4個字母,則您的詞彙大小為4096個可能的單字。 然後,您可以繼續創建一個像NLP一樣的bag-of-words模型。

讓我們做幾個“句子”,讓它更有趣。

mySeq2 = 'GATGGCCATCCCCGCCCGAGCGGGGGGGG'
mySeq3 = 'CATGGCCATCCCCGCCCGAGCGGGCGGGG'
sentence2 = ' '.join(getKmers(mySeq2, size=6))
sentence3 = ' '.join(getKmers(mySeq3, size=6))

# Creating the Bag of Words model
from sklearn.feature_extraction.text import CountVectorizer
cv = CountVectorizer()
X = cv.fit_transform([sentence, sentence2, sentence3]).toarray()

據推測,您將擁有許多可編碼的序列,並且具有較大的詞彙量。 在這個例子中,我只使用3個短序列,所以我們的詞彙表中只有幾個單字。 最後,您將擁有統一長度的數值向量,可以將其輸入到各種機器學習或深度學習算法中。 在這裡,您可以看到詞彙表中的bag-of-words返回六進制數。

X




參考
https://www.kaggle.com/thomasnelson/working-with-dna-sequence-data-for-ml

沒有留言:

張貼留言