Practical-pytorch: Funciones de entrada múltiple de Seq2seq

Creado en 23 jul. 2017  ·  3Comentarios  ·  Fuente: spro/practical-pytorch

¿Hay alguna manera de pasar una característica adicional junto con los tokens de palabras existentes como entrada y enviarla al codificador RNN?

Consideremos el problema de NMT, digamos que tengo 2 columnas de características más para el vocabulario de origen correspondiente (Característica1 aquí). Por ejemplo, considere esto a continuación:

Característica1 Característica2 Característica3
palabra1 xa
palabra2 yb
palabra3 yc
.
.

Sería genial que alguien dijera cómo implementar / hacer esto de manera práctica en pytorch. Gracias por adelantado.

Comentario más útil

Para el inicializador, necesitaría agregar argumentos para los tamaños de sus características y crear una nueva capa de incrustación para cada característica discreta. En el método forward (), agregaría argumentos para las características adicionales, las enviaría a través de las capas de incrustación relevantes y las concatenaría todas en un vector para el RNN. El RNN también tendría un tamaño de entrada de 3 * hidden_size debido a las tres incrustaciones sumadas (o podría crear diferentes tamaños de incrustación para cada función).

En general, debería verse así:

class EncoderRNN(nn.Module):
    def __init__(..., word_size, feature2_size, feature3_size, hidden_size, ...):

        ...

        self.word_embedding = nn.Embedding(word_size, hidden_size)
        self.feature2_embedding = nn.Embedding(feature2_size, hidden_size)
        self.feature3_embedding = nn.Embedding(feature3_size, hidden_size)
        # Note: * 3 because the above 3 embeddings will be concatenated
        self.gru = nn.GRU(hidden_size * 3, hidden_size, n_layers, dropout=self.dropout, bidirectional=True)

    def forward(self, word_seqs, feature2_seqs, feature3_seqs, input_lengths, hidden=None):
        # Note: we run this all at once (over multiple batches of multiple sequences)
        word_embedded = self.word_embedding(word_seqs)
        feature2_embedded = self.feature2_embedding(feature2_seqs)
        feature3_embedded = self.feature3_embedding(feature3_seqs)
        combined = torch.cat((word_embedded, feature2_embedded, feature3_embedded), 2)
        packed = torch.nn.utils.rnn.pack_padded_sequence(combined, input_lengths)
        ...

Todos 3 comentarios

La forma más sencilla es concatenar entidades en un solo vector de entrada. Sin embargo, esto solo funciona si su RNN toma entrada vectorial, no entradas discretas (LongTensor) a través de una capa de incrustación. En ese caso, querrá concatenar sus características adicionales después de que la entrada esté incrustada. Esto se puede lograr más fácilmente usando un argumento de entrada adicional en su codificador y usando torch.cat (vea la entrada de categoría en https://github.com/spro/practical-pytorch/blob/master/conditional-char -rnn / conditional-char-rnn.ipynb para un ejemplo simple, aunque eso no usa una capa de incrustación).

Si sus características también son discretas, querrá varias capas de incrustación, una para cada una, y concatenar todos los resultados.

La sección citada trata más sobre la entrada y la longitud de la secuencia de destino, no sobre el tamaño de la característica.

Para el inicializador, necesitaría agregar argumentos para los tamaños de sus características y crear una nueva capa de incrustación para cada característica discreta. En el método forward (), agregaría argumentos para las características adicionales, las enviaría a través de las capas de incrustación relevantes y las concatenaría todas en un vector para el RNN. El RNN también tendría un tamaño de entrada de 3 * hidden_size debido a las tres incrustaciones sumadas (o podría crear diferentes tamaños de incrustación para cada función).

En general, debería verse así:

class EncoderRNN(nn.Module):
    def __init__(..., word_size, feature2_size, feature3_size, hidden_size, ...):

        ...

        self.word_embedding = nn.Embedding(word_size, hidden_size)
        self.feature2_embedding = nn.Embedding(feature2_size, hidden_size)
        self.feature3_embedding = nn.Embedding(feature3_size, hidden_size)
        # Note: * 3 because the above 3 embeddings will be concatenated
        self.gru = nn.GRU(hidden_size * 3, hidden_size, n_layers, dropout=self.dropout, bidirectional=True)

    def forward(self, word_seqs, feature2_seqs, feature3_seqs, input_lengths, hidden=None):
        # Note: we run this all at once (over multiple batches of multiple sequences)
        word_embedded = self.word_embedding(word_seqs)
        feature2_embedded = self.feature2_embedding(feature2_seqs)
        feature3_embedded = self.feature3_embedding(feature3_seqs)
        combined = torch.cat((word_embedded, feature2_embedded, feature3_embedded), 2)
        packed = torch.nn.utils.rnn.pack_padded_sequence(combined, input_lengths)
        ...

@spro Muchas gracias por sus aportes. He escrito una publicación de blog sobre el mismo:
https://iamsiva11.github.io/extra-features-seq2seq/. Espero que sea útil para muchos otros.

¿Fue útil esta página
0 / 5 - 0 calificaciones