Perbedaan antara implementasi LSTM Autoencoder ini?
Secara khusus, yang memicu pertanyaan ini adalah return_sequence
argumen versi TensorFlow dari lapisan LSTM.
Dokumen mengatakan:
Boolean. Apakah akan mengembalikan keluaran terakhir. dalam urutan keluaran, atau urutan lengkap. Default: Salah.
Saya telah melihat beberapa implementasi, terutama autoencoder yang menggunakan argumen ini untuk menghapus semuanya kecuali elemen terakhir dalam urutan output sebagai output dari setengah 'encoder' dari autoencoder.
Di bawah ini adalah tiga implementasi yang berbeda. Saya ingin memahami alasan di balik perbedaan tersebut, karena perbedaannya tampak sangat besar tetapi semuanya menyebut diri mereka sama.
Contoh 1 (TensorFlow):
Implementasi ini menghapus semua output LSTM kecuali elemen terakhir dari urutan, dan kemudian mengulangi elemen tersebut beberapa kali untuk merekonstruksi urutan:
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)))
Saat melihat implementasi autoencoder di PyTorch, saya tidak melihat penulis melakukan ini. Sebaliknya mereka menggunakan seluruh keluaran LSTM untuk pembuat enkode (terkadang diikuti oleh lapisan padat dan terkadang tidak).
Contoh 1 (PyTorch):
Implementasi ini melatih penyematan SEBELUM lapisan LSTM diterapkan ... Tampaknya hampir mengalahkan gagasan pembuat enkode otomatis berbasis LSTM ... Urutannya sudah dikodekan pada saat menyentuh lapisan 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
Contoh 2 (PyTorch):
Contoh encoder ini pertama-tama memperluas input dengan satu lapisan LSTM, kemudian melakukan kompresinya melalui lapisan LSTM kedua dengan jumlah node tersembunyi yang lebih kecil. Selain pemekaran, hal ini sepertinya sejalan dengan tulisan yang saya temukan:https://arxiv.org/pdf/1607.00148.pdf
Namun, dalam dekoder implementasi ini, tidak ada lapisan padat akhir. Penguraian kode terjadi melalui lapisan lstm kedua yang memperluas pengkodean kembali ke dimensi yang sama seperti masukan asli. Lihat disini . Ini tidak sejalan dengan makalah (meskipun saya tidak tahu apakah makalah tersebut berwibawa atau tidak).
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))
Pertanyaan:
Saya bertanya-tanya tentang perbedaan ini dalam implementasi. Perbedaannya tampaknya cukup besar. Apakah semua cara yang valid ini untuk mencapai hal yang sama? Atau beberapa dari upaya yang salah kaprah pada pemoder otomatis LSTM "asli"?
Jawaban
Tidak ada cara resmi atau cara yang benar untuk mendesain arsitektur autoencoder berbasis LSTM ... Satu-satunya spesifikasi yang diberikan oleh nama tersebut adalah bahwa modelnya harus Autoencoder dan harus menggunakan lapisan LSTM di suatu tempat.
Implementasi yang Anda temukan masing-masing berbeda dan unik meskipun dapat digunakan untuk tugas yang sama.
Mari kita gambarkan:
Implementasi TF :
- Ini mengasumsikan input hanya memiliki satu saluran , yang berarti bahwa setiap elemen dalam urutan hanya berupa angka dan ini sudah diproses sebelumnya .
- Perilaku default
LSTM layer
dalam Keras / TF adalah untuk mengeluarkan hanya keluaran terakhir dari LSTM, Anda dapat mengaturnya untuk mengeluarkan semua langkah keluaran denganreturn_sequences
parameter. - Dalam hal ini data masukan telah menyusut
(batch_size, LSTM_units)
- Pertimbangkan bahwa keluaran terakhir dari LSTM tentu saja merupakan fungsi dari keluaran sebelumnya (khususnya jika itu adalah LSTM yang stateful)
- Ini menerapkan a
Dense(1)
di lapisan terakhir untuk mendapatkan bentuk yang sama sebagai masukan.
PyTorch 1 :
- Mereka menerapkan embedding ke input sebelum diumpankan ke LSTM.
- Ini adalah praktik standar dan ini membantu misalnya untuk mengubah setiap elemen masukan menjadi bentuk vektor (lihat word2vec misalnya di mana dalam urutan teks, setiap kata yang bukan vektor dipetakan ke dalam ruang vektor). Ini hanya tahap preprocessing agar data memiliki bentuk yang lebih bermakna.
- Ini tidak mengalahkan gagasan dari pembuat kode otomatis LSTM, karena penyematan diterapkan secara independen ke setiap elemen dari urutan masukan, sehingga tidak dikodekan saat memasuki lapisan LSTM.
PyTorch 2 :
- Dalam hal ini bentuk inputnya tidak
(seq_len, 1)
seperti pada contoh TF pertama, sehingga decoder tidak perlu padat setelahnya. Penulis menggunakan sejumlah unit di lapisan LSTM yang sama dengan bentuk masukan.
- Dalam hal ini bentuk inputnya tidak
Pada akhirnya Anda memilih arsitektur model Anda tergantung pada data yang ingin Anda latih, khususnya: sifat (teks, audio, gambar), bentuk masukan, jumlah data yang Anda miliki, dan sebagainya ...