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

17

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

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

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

Мой вопрос:

  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 = '3[92m'
    fail = '3[91m'
    close = '3[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()
    
задан neversaint 12.05.2016 в 09:20
источник
  • Должен ли эпитоп быть точной подстрокой антигена или допускать нечеткие совпадения? –  wildplasser 14.05.2016 в 13:11
  • Аккуратная проблема! 1. Похоже, что эпитоп никогда не является точной подстрокой антигена? 2. Совершенно нормально использовать последовательное обучение для этой задачи, но моя интуиция заключается в том, что 7000 примеров слишком мало. 3. Как вы имеете дело с переменной длиной эпитопа? Исходный пример дополнен пробелами. 4. Вы пробовали поиск по гиперпараметру? 5. Является ли модель переоснащением или недофинансированием (т. Е. Хорошая ошибка обучения и ошибка проверки плохой, или они оба плохи)? 6. Каково узкое место в вашем коде с точки зрения времени выполнения? 7. Ссылка на ваш набор данных нарушена. –  1'' 14.05.2016 в 23:20
  • @wildplasser: точное –  neversaint 15.05.2016 в 01:21
  • @ 1 '': 1. Всегда точно. 3. Рассматривайте переменную длину как есть. 5. Оба плохие. 6. Когда ~ 7000 образцов, ~ 20 мин / эпоха. 7. Ссылка обновлена. Я также включаю ссылку на скачивание версии 7000 строк. –  neversaint 15.05.2016 в 01:28
  • , если совпадение точно, поиска словаря будет достаточно. Это именно то, что делает fgrep: постройте DFA, узнавая коллекцию игл, которые нужно искать в любой стоге сена. ожидаемая сложность - это O log (M) * NK, с M * типичный размер рисунка (около 15 в примере), N - размер стога сена, а K: = количество стогов сена. –  wildplasser 15.05.2016 в 02:11
Показать остальные комментарии

1 ответ

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

Да, вы можете использовать любой из них. LSTM и GRU являются типами RNN; если под RNN вы имеете в виду полностью подключенный RNN , они потеряли популярность из-за проблемы исчезающих градиентов (< a href="http://www.dsi.unifi.it/~paolo/ps/tnn-94-gradient.pdf"> 1 , 2 ). Из-за относительно небольшого числа примеров в вашем наборе данных GRU может быть предпочтительнее LSTM из-за его более простой архитектуры.

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

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

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

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

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

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

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

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

    
ответ дан 1'' 15.05.2016 в 23:40
  • Я согласен, что вы должны попытаться смоделировать две точки резания (начало и конец эпитопа). Селективность, которую вы наблюдаете, - это селективность протеолитических ферментов (и способ их контроля) –  wildplasser 18.05.2016 в 12:34
  • @ "1: Можете ли вы быть конкретными с последней частью 2. Проблема классификации с двумя задачами? Пример кода? –  neversaint 19.05.2016 в 02:32
  • @neversaint См. мое редактирование. –  1'' 19.05.2016 в 04:55
  • @ "1: Спасибо. Но как выглядят X_train, y_train и X_test, y_test? –  neversaint 19.05.2016 в 04:59
  • @neversaint X тот же, что и раньше, но y - матрица 7000 x 2. Например, y_train [0] может быть [0,3, 0,7]. –  1'' 19.05.2016 в 05:01