【问题标题】:Using Deep Learning to Predict Subsequence from Sequence使用深度学习从序列中预测子序列
【发布时间】:2016-09-07 20:59:39
【问题描述】:

我的数据如下所示:

可以查看here,并已包含在下面的代码中。 实际上,我有大约 7000 个样本(行),downloadable too

任务给定抗原,预测相应的表位。 所以表位总是抗原的精确子串。这相当于 Sequence to Sequence Learning。这是我在 Keras 下的循环神经网络上运行的代码。它是根据example建模的。

我的问题是:

  1. RNN、LSTM 或 GRU 能否用于预测上述子序列?
  2. 如何提高代码的准确性?
  3. 如何修改我的代码以使其运行得更快?

这是我的运行代码,准确度得分非常差。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function
import sys
import json
import pandas as pd
from keras.models import Sequential
from keras.engine.training import slice_X
from keras.layers.core import Activation,  RepeatVector, Dense
from keras.layers import recurrent, TimeDistributed
import numpy as np
from six.moves import range

class CharacterTable(object):
    '''
    Given a set of characters:
    + Encode them to a one hot integer representation
    + Decode the one hot integer representation to their character output
    + Decode a vector of probabilties to their character output
    '''
    def __init__(self, chars, maxlen):
        self.chars = sorted(set(chars))
        self.char_indices = dict((c, i) for i, c in enumerate(self.chars))
        self.indices_char = dict((i, c) for i, c in enumerate(self.chars))
        self.maxlen = maxlen

    def encode(self, C, maxlen=None):
        maxlen = maxlen if maxlen else self.maxlen
        X = np.zeros((maxlen, len(self.chars)))
        for i, c in enumerate(C):
            X[i, self.char_indices[c]] = 1
        return X

    def decode(self, X, calc_argmax=True):
        if calc_argmax:
            X = X.argmax(axis=-1)
        return ''.join(self.indices_char[x] for x in X)

class colors:
    ok = '\033[92m'
    fail = '\033[91m'
    close = '\033[0m'

INVERT = True
HIDDEN_SIZE = 128
BATCH_SIZE = 64
LAYERS = 3
# Try replacing GRU, or SimpleRNN
RNN = recurrent.LSTM


def main():
    """
    Epitope_core = answers
    Antigen      = questions
    """

    epi_antigen_df = pd.io.parsers.read_table("http://dpaste.com/2PZ9WH6.txt")
    antigens = epi_antigen_df["Antigen"].tolist()
    epitopes = epi_antigen_df["Epitope Core"].tolist()

    if INVERT:
        antigens = [ x[::-1] for x in antigens]

    allchars = "".join(antigens+epitopes)
    allchars = list(set(allchars))
    aa_chars =  "".join(allchars)
    sys.stderr.write(aa_chars + "\n")

    max_antigen_len = len(max(antigens, key=len))
    max_epitope_len = len(max(epitopes, key=len))

    X = np.zeros((len(antigens),max_antigen_len, len(aa_chars)),dtype=np.bool)
    y = np.zeros((len(epitopes),max_epitope_len, len(aa_chars)),dtype=np.bool)

    ctable = CharacterTable(aa_chars, max_antigen_len)

    sys.stderr.write("Begin vectorization\n")
    for i, antigen in enumerate(antigens):
        X[i] = ctable.encode(antigen, maxlen=max_antigen_len)
    for i, epitope in enumerate(epitopes):
        y[i] = ctable.encode(epitope, maxlen=max_epitope_len)


    # Shuffle (X, y) in unison as the later parts of X will almost all be larger digits
    indices = np.arange(len(y))
    np.random.shuffle(indices)
    X = X[indices]
    y = y[indices]

    # Explicitly set apart 10% for validation data that we never train over
    split_at = len(X) - len(X) / 10
    (X_train, X_val) = (slice_X(X, 0, split_at), slice_X(X, split_at))
    (y_train, y_val) = (y[:split_at], y[split_at:])

    sys.stderr.write("Build model\n")
    model = Sequential()
    # "Encode" the input sequence using an RNN, producing an output of HIDDEN_SIZE
    # note: in a situation where your input sequences have a variable length,
    # use input_shape=(None, nb_feature).
    model.add(RNN(HIDDEN_SIZE, input_shape=(max_antigen_len, len(aa_chars))))
    # For the decoder's input, we repeat the encoded input for each time step
    model.add(RepeatVector(max_epitope_len))
    # The decoder RNN could be multiple layers stacked or a single layer
    for _ in range(LAYERS):
        model.add(RNN(HIDDEN_SIZE, return_sequences=True))

    # For each of step of the output sequence, decide which character should be chosen
    model.add(TimeDistributed(Dense(len(aa_chars))))
    model.add(Activation('softmax'))

    model.compile(loss='categorical_crossentropy',
                optimizer='adam',
                metrics=['accuracy'])

    # Train the model each generation and show predictions against the validation dataset
    for iteration in range(1, 200):
        print()
        print('-' * 50)
        print('Iteration', iteration)
        model.fit(X_train, y_train, batch_size=BATCH_SIZE, nb_epoch=5,
                validation_data=(X_val, y_val))
        ###
        # Select 10 samples from the validation set at random so we can visualize errors
        for i in range(10):
            ind = np.random.randint(0, len(X_val))
            rowX, rowy = X_val[np.array([ind])], y_val[np.array([ind])]
            preds = model.predict_classes(rowX, verbose=0)
            q = ctable.decode(rowX[0])
            correct = ctable.decode(rowy[0])
            guess = ctable.decode(preds[0], calc_argmax=False)
            # print('Q', q[::-1] if INVERT else q)
            print('T', correct)
            print(colors.ok + '☑' + colors.close if correct == guess else colors.fail + '☒' + colors.close, guess)
            print('---')

if __name__ == '__main__':
    main()

【问题讨论】:

  • epithope 必须是抗原的exact 子字符串,还是也允许模糊匹配?
  • 好问题! 1. 看起来表位从来都不是抗原的精确子串? 2. 对这个任务使用序列到序列学习完全没问题,但我的直觉是 7000 个例子太少了。 3. 您如何处理可变长度的表位?原始示例用空格填充。 4. 你试过超参数搜索吗? 5. 模型是过拟合还是欠拟合(即训练误差是好的,验证误差是坏的,还是两者都不好)? 6. 你的代码在运行时的瓶颈是什么? 7. 指向您的数据集的链接已损坏。
  • @1'': 1. 始终准确。 3. 按原样对待可变长度。 5. 两者都不好。 6. 当~7000 个样本时,~20min/epoch。 7.链接更新。我还包括~7000 lines version download link
  • 如果匹配准确,字典搜索就足够了。这正是 fgrep 所做的:构建一个 DFA,识别要在任何大海捞针中搜索的针集合。预期复杂度约为 O log(M) * NK,其中 M 是模式的 *典型 大小(在示例中约为 15),N 是干草堆的大小,K := number干草堆。
  • @neversaint 您可以尝试使用 GRU 而不是 LSTM 来加快速度,也许这会减少您遇到的欠拟合。您能否澄清“按原样处理可变长度”?

标签: python theano deep-learning keras


【解决方案1】:
  1. RNN、LSTM 或 GRU 能否用于预测上述子序列?

是的,您可以使用其中任何一种。 LSTM 和 GRU 是 RNN 的类型;如果 RNN 的意思是 fully-connected RNN,那么由于梯度消失问题(12),这些已经失宠。由于数据集中的示例数量相对较少,因此 GRU 可能比 LSTM 更可取,因为它的架构更简单。

  1. 如何提高代码的准确性?

您提到训练和验证错误都很糟糕。一般来说,这可能是由于以下几个因素之一:

  • 学习率太低(这不是问题,因为您使用的是 Adam,一种按参数自适应学习率算法)
  • 模型对于数据来说过于简单(根本不是问题,因为您有一个非常复杂的模型和一个小数据集)
  • 您的梯度消失(可能是因为您有一个 3 层 RNN)。尝试将层数减少到 1(通常,最好先让一个简单的模型工作,然后增加复杂性),并考虑超参数搜索(例如,128 维隐藏状态可能太大 - 尝试 30? )。

另一个选项,因为您的表位是您输入的子字符串,所以 预测抗原序列中表位的开始和结束索引(可能由抗原序列的长度标准化)一次预测一个字符的子字符串。这将是两个任务的回归问题。例如,如果抗原是 FSKIAGLTVT(10 个字母长)并且它的表位是 KIAGL(位置 3 到 7,从一个开始),那么输入将是 FSKIAGLTVT,输出将是 0.3(第一个任务)和 0.7(第二个任务) .

或者,如果您可以使所有抗原的长度相同(假设您知道 先验表位不在末端),您可以将其构建为具有两个任务(开始和结束)和序列长度类的分类问题,您试图在每个位置为抗原分配一个开始和结束的概率.

  1. 如何修改我的代码以使其运行得更快?

减少层数将显着加快您的代码速度。此外,由于其更简单的架构,GRU 将比 LSTM 更快。然而,这两种类型的循环网络都将比例如慢。卷积网络。

如果您对合作感兴趣,请随时给我发送电子邮件(我的个人资料中的地址)。

【讨论】:

  • 我同意您应该尝试对两个切割点(表位的起点和终点)进行建模。您观察到的选择性是蛋白水解酶的选择性(以及它们的控制方式)
  • @"1: 后面的2号能不能具体点。两个任务的分类问题?示例代码?
  • @"1:谢谢。但是X_train , y_trainX_test , y_test 看起来怎么样?
  • @neversaint X 与之前相同,但 y 是一个 7000 x 2 矩阵。例如,y_train[0] 可以是 [0.3, 0.7]
  • @neversaint 这能回答你的问题吗?还有什么我可以澄清的吗?
猜你喜欢
  • 2018-11-03
  • 1970-01-01
  • 1970-01-01
  • 2014-06-25
  • 1970-01-01
  • 2018-09-16
  • 1970-01-01
  • 2020-04-22
  • 1970-01-01
相关资源
最近更新 更多