2016-05-12 13 views
17

Ho un dato che assomiglia a questo:Utilizzando Deep Learning per predire Subsequence dalla sequenza

enter image description here

Esso può essere visualizzato here ed è stato incluso nel seguente codice. In realtà ho ~ 7000 campioni (riga), downloadable too.

Il compito è dato antigene, prevedere l'epitopo corrispondente. Quindi l'epitopo è sempre una sottostringa esatta dell'antigene. Questo è equivalente a il Sequence to Sequence Learning. Ecco il mio codice in esecuzione su Recurrent Neural Network sotto Keras. È stato modellato secondo lo example.

La mia domanda è:

  1. può RNN, LSTM o GRU usato per predire sottosequenza come poste sopra?
  2. Come posso migliorare la precisione del mio codice?
  3. Come posso modificare il mio codice in modo che possa funzionare più velocemente?

Ecco il mio codice di esecuzione che ha dato un punteggio di precisione molto cattivo.

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

L'epithope * deve essere una sottostringa ** esatta ** dell'antigene o sono consentite anche le corrispondenze fuzzy? – wildplasser

+0

Neat problem! 1. Sembra che l'epitopo non sia mai una sottostringa esatta dell'antigene? 2. È perfetto usare l'apprendimento sequenza-sequenza per questo compito, ma la mia intuizione è che 7000 esempi sono troppo pochi. 3. Come hai a che fare con la lunghezza variabile dell'epitopo? L'esempio originale riempito di spazi. 4. Hai provato la ricerca iperparametrica? 5. Il modello è sovradimensionato o underfitting (vale a dire l'errore di allenamento è buono e l'errore di convalida è negativo o entrambi sono negativi)? 6. Qual è il collo di bottiglia nel codice in termini di runtime? 7. Il collegamento al set di dati è rotto. –

+0

@wildplasser: esatto – neversaint

risposta

13
  1. può RNN, LSTM o GRU usato per predire sottosequenza come poste sopra?

Sì, è possibile utilizzare uno di questi. LSTM e GRU sono tipi di RNN; se per RNN intendi uno fully-connected RNN, questi sono caduti in disgrazia a causa del problema dei gradienti di fuga (, 2). A causa del numero relativamente piccolo di esempi nel set di dati, un GRU potrebbe essere preferibile a un LSTM a causa della sua architettura più semplice.

  1. Come posso migliorare la precisione del mio codice?

Hai detto che l'allenamento e l'errore di convalida sono entrambi negativi. In generale, questo potrebbe essere dovuto a uno dei vari fattori:

  • Il tasso di apprendimento è troppo bassa (non è un problema dal momento che si sta utilizzando Adam, un algoritmo di tasso di apprendimento per-parametro adattativo)
  • Il modello è troppo semplice per i dati (non è affatto il problema, dal momento che hai un modello molto complesso e un piccolo set di dati)
  • Hai sfumature sfumate (probabilmente il problema dato che hai un RNN a 3 strati). Prova a ridurre il numero di livelli a 1 (in generale, è bene iniziare facendo funzionare un modello semplice e aumentare la complessità), e considera anche la ricerca iperparametrica (ad esempio uno stato nascosto a 128 dimensioni potrebbe essere troppo grande - prova 30?).

Un'altra opzione, poiché la vostra epitopo è una stringa dell'input, vale a prevedere gli indici di inizio e fine della epitopo all'interno della sequenza dell'antigene (potenzialmente normalizzato dalla lunghezza della sequenza dell'antigene) invece di prevedere la sottostringa un carattere alla volta. Questo sarebbe un problema di regressione con due compiti. Ad esempio, se l'antigene è FSKIAGLTVT (lungo 10 lettere) e il suo epitopo è KIAGL (posizioni da 3 a 7, a base uno), l'input sarà FSKIAGLTVT e gli output saranno 0.3 (primo compito) e 0.7 (secondo compito) .

In alternativa, se è possibile effettuare tutti gli antigeni siano della stessa lunghezza (rimuovendo parti di set di dati con brevi antigeni e/o tagliando le estremità di lunghe antigeni patto di saper a priori che l'epitopo non è vicino le estremità), puoi inquadrarlo come un problema di classificazione con due compiti (inizio e fine) e classi di lunghezza della sequenza, dove stai cercando di assegnare una probabilità all'antigene che inizia e termina in ciascuna delle posizioni.

  1. Come posso modificare il mio codice in modo che possa essere eseguito più velocemente?

La riduzione del numero di livelli velocizza significativamente il codice. Inoltre, i GRU saranno più veloci degli LSTM grazie alla loro architettura più semplice. Tuttavia, entrambi i tipi di reti ricorrenti saranno più lenti di, ad es. reti convoluzionali.

Sentitevi liberi di inviarmi una e-mail (indirizzo nel mio profilo) se siete interessati a una collaborazione.

+0

Concordo sul fatto che dovresti provare a modellare i due punti di taglio (inizio e fine dell'epitopo). La selettività che osservate è la selettività degli enzimi proteolitici (e il modo in cui sono controllati) – wildplasser

+0

@ "1: Potete essere specifici con la seconda parte 2. Problema di classificazione con due attività? Esempio di codice? – neversaint

+1

@neversaint Vedere il mio modifica –