이러한 LSTM Autoencoder 구현의 차이점은 무엇입니까?

Dec 08 2020

return_sequence특히이 질문을 촉발시킨 것은 TensorFlow 버전의 LSTM 레이어에 대한 주장입니다.

문서는 다음과 같이 말합니다.

부울. 마지막 출력을 반환할지 여부입니다. 출력 시퀀스 또는 전체 시퀀스에서. 기본값 : False.

일부 구현, 특히이 인수를 사용하여 출력 시퀀스의 마지막 요소를 제외한 모든 항목을 자동 인코더의 '인코더'절반의 출력으로 제거하는 자동 인코더를 보았습니다.

다음은 가지 구현입니다. 매우 큰 차이처럼 보이지만 모두 자신을 똑같은 것이라고 부르기 때문에 차이의 원인을 이해하고 싶습니다.

예 1 (TensorFlow) :

이 구현은 시퀀스의 마지막 요소를 제외한 LSTM의 모든 출력을 제거한 다음 해당 요소를 몇 번 반복하여 시퀀스를 재구성합니다.

model = Sequential()
model.add(LSTM(100, activation='relu', input_shape=(n_in,1)))
# Decoder below
model.add(RepeatVector(n_out))
model.add(LSTM(100, activation='relu', return_sequences=True))
model.add(TimeDistributed(Dense(1)))

PyTorch에서 오토 인코더 구현을 살펴보면 작성자가이 작업을 수행하는 것을 볼 수 없습니다. 대신 인코더에 LSTM의 전체 출력을 사용합니다 (때로는 고밀도 레이어가 뒤 따르고 때로는 그렇지 않음).

예 1 (PyTorch) :

이 구현은 LSTM 계층이 적용되기 전에 임베딩을 훈련합니다 ... LSTM 기반 자동 인코더의 아이디어를 거의 무효화하는 것 같습니다 ... 시퀀스는 LSTM 계층에 도달 할 때 이미 인코딩되어 있습니다.

class EncoderLSTM(nn.Module):
  def __init__(self, input_size, hidden_size, n_layers=1, drop_prob=0):
    super(EncoderLSTM, self).__init__()
    self.hidden_size = hidden_size
    self.n_layers = n_layers

    self.embedding = nn.Embedding(input_size, hidden_size)
    self.lstm = nn.LSTM(hidden_size, hidden_size, n_layers, dropout=drop_prob, batch_first=True)

  def forward(self, inputs, hidden):
    # Embed input words
    embedded = self.embedding(inputs)
    # Pass the embedded word vectors into LSTM and return all outputs
    output, hidden = self.lstm(embedded, hidden)
    return output, hidden

예제 2 (PyTorch) :

이 예제 인코더는 먼저 하나의 LSTM 레이어로 입력을 확장 한 다음 숨겨진 노드 수가 더 적은 두 번째 LSTM 레이어를 통해 압축을 수행합니다. 확장 외에도 이것은 내가 찾은이 문서와 일치하는 것 같습니다.https://arxiv.org/pdf/1607.00148.pdf

그러나이 구현의 디코더에는 최종 조밀 계층이 없습니다. 디코딩은 인코딩을 원래 입력과 동일한 차원으로 다시 확장하는 두 번째 lstm 레이어를 통해 발생합니다. 여기에서보십시오 . 이것은 논문과 일치하지 않습니다 (논문이 권위 있는지 아닌지는 모르겠지만).

class Encoder(nn.Module):
  def __init__(self, seq_len, n_features, embedding_dim=64):
    super(Encoder, self).__init__()
    self.seq_len, self.n_features = seq_len, n_features
    self.embedding_dim, self.hidden_dim = embedding_dim, 2 * embedding_dim
    self.rnn1 = nn.LSTM(
      input_size=n_features,
      hidden_size=self.hidden_dim,
      num_layers=1,
      batch_first=True
    )
    self.rnn2 = nn.LSTM(
      input_size=self.hidden_dim,
      hidden_size=embedding_dim,
      num_layers=1,
      batch_first=True
    )
  def forward(self, x):
    x = x.reshape((1, self.seq_len, self.n_features))
    x, (_, _) = self.rnn1(x)
    x, (hidden_n, _) = self.rnn2(x)
    return hidden_n.reshape((self.n_features, self.embedding_dim))

질문:

구현에서 이러한 불일치에 대해 궁금합니다. 그 차이는 상당히 큽니다. 이러한 모든 유효한 방법이 동일한 작업을 수행합니까? 아니면 "실제"LSTM 오토 인코더에서 이러한 잘못된 시도가 있습니까?

답변

2 LucaAngioloni Dec 08 2020 at 22:38

LSTM 기반 오토 인코더의 아키텍처를 설계하는 공식적이거나 올바른 방법은 없습니다 ... 이름이 제공하는 유일한 세부 사항은 모델이 오토 인코더 여야하고 어딘가에 LSTM 계층을 사용해야한다는 것입니다.

찾은 구현은 동일한 작업에 사용될 수 있지만 각각 다르고 고유합니다.

그것들을 설명해 봅시다 :

  • TF 구현 :

    • 입력에 채널 이 하나만 있다고 가정합니다. 이는 시퀀스의 각 요소 가 숫자 일 뿐이며 이미 전처리 되었음을 의미합니다 .
    • 의 기본 동작 LSTM layerKeras / TF는 출력에 LSTM의 마지막 출력, 당신은 출력에 모든 출력 단계를 설정할 수 return_sequences매개 변수를.
    • 이 경우 입력 데이터는 다음으로 축소되었습니다. (batch_size, LSTM_units)
    • LSTM의 마지막 출력은 물론 이전 출력의 함수라는 것을 고려하십시오 (특히 상태 저장 LSTM 인 경우).
    • Dense(1)입력과 동일한 모양을 얻기 위해 마지막 레이어에 a 를 적용합니다 .
  • PyTorch 1 :

    • LSTM에 공급되기 전에 입력에 임베딩을 적용합니다.
    • 이것은 표준 관행이며 예를 들어 각 입력 요소를 벡터 형식으로 변환하는 데 도움이됩니다 (예를 들어 텍스트 시퀀스에서 벡터가 아닌 각 단어가 벡터 공간에 매핑되는 경우 word2vec 참조 ). 데이터가보다 의미있는 형식을 갖도록하는 것은 전처리 단계 일뿐입니다.
    • 임베딩이 입력 시퀀스의 각 요소에 독립적 으로 적용 되기 때문에 LSTM 자동 인코더의 아이디어를 무너 뜨리지 않으므로 LSTM 레이어에 들어갈 때 인코딩되지 않습니다.
  • PyTorch 2 :

    • 이 경우 입력 모양은 (seq_len, 1)첫 번째 TF 예제와 같지 않으므로 디코더는 이후에 밀도가 필요하지 않습니다. 저자는 입력 모양과 동일한 LSTM 레이어의 여러 단위를 사용했습니다.

결국 학습하려는 데이터, 특히 성격 (텍스트, 오디오, 이미지), 입력 형태, 보유한 데이터 양 등에 따라 모델의 아키텍처를 선택합니다.