Использование глубокого обучения для прогнозирования подпоследовательности из последовательности

У меня есть данные, которые выглядят так:

введите описание изображения здесь

Здесь можно просмотреть и был включен в код ниже. На самом деле у меня есть ~ 7000 выборок (строка), загружаемый тоже.

Задача получает антиген, предсказывает соответствующий эпитоп. Таким образом, эпитоп всегда является точной подстрокой антигена. Это эквивалентно Последовательность для обучения последовательностям. Вот мой код, который работает в Recurrent Neural Network под Keras. Он был смоделирован в соответствии с example.

Мой вопрос:

  • Можно ли использовать RNN, LSTM или GRU для прогнозирования подпоследовательности, как указано выше?
  • Как повысить точность кода?
  • Как мне изменить свой код, чтобы он мог работать быстрее?

Вот мой код запуска, который дал очень плохую оценку точности.

#!/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 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()

Ответы

Ответ 1

  • Можно ли использовать RNN, LSTM или GRU для прогнозирования подпоследовательности, как указано выше?

Да, вы можете использовать любой из них. LSTM и ГРУ являются типами RNN; если по RNN вы имеете в виду полностью связанный RNN, они оказались в немилости из-за проблемы исчезающих градиентов (1, 2). Из-за относительно небольшого числа примеров в вашем наборе данных GRU может быть предпочтительнее LSTM из-за его более простой архитектуры.

  1. Как повысить точность кода?

Вы упомянули, что ошибка обучения и проверки достоверна. В общем, это может быть связано с одним из нескольких факторов:

  • Уровень обучения слишком низок (не проблема, поскольку вы используете Адам, алгоритм адаптивной скорости обучения для каждого параметра)
  • Модель слишком проста для данных (совсем не проблема, поскольку у вас очень сложная модель и небольшой набор данных)
  • У вас исчезают градиенты (возможно, проблема с трехслойной RNN). Попробуйте уменьшить количество слоев до 1 (в общем, хорошо начать с создания простой модели, а затем увеличить сложность), а также рассмотреть поиск гиперпараметра (например, 128-мерное скрытое состояние может быть слишком большим - попробуйте 30?).

Другой вариант, так как ваш эпитоп является подстрокой вашего ввода, должен предсказать начальные и конечные индексы эпитопа внутри последовательности антигена (потенциально нормированные длиной антигенной последовательности) вместо предсказания подстроки по одному символу за раз. Это будет проблемой регрессии с двумя задачами. Например, если антиген FSKIAGLTVT (длиной 10 букв), а его эпитоп - KIAGL (позиции от 3 до 7, один на основе), то вход будет FSKIAGLTVT, а выходы будут 0,3 (первая задача) и 0,7 (вторая задача).

Альтернативно, если вы можете сделать все антигены одинаковой длины (путем удаления частей вашего набора данных с короткими антигенами и/или измельчения концов длинных антигенов, предполагая, что вы знаете априори, что эпитоп не близок к концам), вы можете создать его как проблему классификации с двумя задачами (начало и конец) и классы длины последовательности, где вы пытаетесь назначить вероятность запуска и окончания антигена в каждой из позиций.

  1. Как мне изменить свой код, чтобы он мог работать быстрее?

Уменьшение количества слоев значительно ускорит ваш код. Кроме того, GRU будут быстрее, чем LSTM из-за их более простой архитектуры. Однако оба типа повторяющихся сетей будут медленнее, чем, например, сверточных сетей.

Не стесняйтесь присылать мне адрес электронной почты (адрес в моем профиле), если вы заинтересованы в сотрудничестве.