# Praktikum 1

### Setup

Impor matplotlib dan buat fungsi pembantu untuk memplot grafik:

{% code overflow="wrap" lineNumbers="true" %}

```python
import numpy as np
import tensorflow_datasets as tfds
import tensorflow as tf

tfds.disable_progress_bar()
```

{% endcode %}

{% code overflow="wrap" lineNumbers="true" %}

```python
import matplotlib.pyplot as plt

def plot_graphs(history, metric):
  plt.plot(history.history[metric])
  plt.plot(history.history['val_'+metric], '')
  plt.xlabel("Epochs")
  plt.ylabel(metric)
  plt.legend([metric, 'val_'+metric])
```

{% endcode %}

### Setup input pipeline

Dataset ulasan film IMDB adalah kumpulan data klasifikasi biner—semua ulasan memiliki sentimen positif atau negatif.

Download dataset menggunakan [TFDS](https://www.tensorflow.org/datasets). Lihat [loading text tutorial](https://www.tensorflow.org/tutorials/load_data/text) jika ingin me load data secara manual

{% code overflow="wrap" lineNumbers="true" %}

```python
dataset, info = tfds.load('imdb_reviews', with_info=True,
                          as_supervised=True)
train_dataset, test_dataset = dataset['train'], dataset['test']

train_dataset.element_spec
```

{% endcode %}

Awalnya ini mengembalikan dataset (teks, pasangan label):

{% code overflow="wrap" lineNumbers="true" %}

```python
for example, label in train_dataset.take(1):
  print('text: ', example.numpy())
  print('label: ', label.numpy())
```

{% endcode %}

Berikutnya acak data untuk pelatihan dan membuat kumpulan pasangan (teks, label) ini:

***

{% code overflow="wrap" lineNumbers="true" %}

```python
BUFFER_SIZE = 10000
BATCH_SIZE = 64

train_dataset = train_dataset.shuffle(BUFFER_SIZE).batch(BATCH_SIZE).prefetch(tf.data.AUTOTUNE)
test_dataset = test_dataset.batch(BATCH_SIZE).prefetch(tf.data.AUTOTUNE)

for example, label in train_dataset.take(1):
  print('texts: ', example.numpy()[:3])
  print()
  print('labels: ', label.numpy()[:3])

```

{% endcode %}

### Buat Teks Encoder

***

Teks mentah yang dimuat oleh tfds perlu diproses sebelum dapat digunakan dalam model. Cara termudah memproses teks untuk pelatihan adalah menggunakan lapisan TextVectorization. Lapisan ini memiliki banyak kemampuan, namun pada tutorial ini menggunakan perilaku default. Buat lapisan tersebut, dan teruskan teks kumpulan data ke metode .adapt lapisan:

{% code overflow="wrap" lineNumbers="true" %}

```python
VOCAB_SIZE = 1000
encoder = tf.keras.layers.TextVectorization(
    max_tokens=VOCAB_SIZE)
encoder.adapt(train_dataset.map(lambda text, label: text))
```

{% endcode %}

Metode .adapt mengatur kosakata lapisan. 20 token pertama dapat dilihat dengan kode berikut. Setelah padding dan token yang tidak diketahui, mereka diurutkan berdasarkan frekuensi:

{% code overflow="wrap" lineNumbers="true" %}

```python
vocab = np.array(encoder.get_vocabulary())
vocab[:20]
```

{% endcode %}

Setelah kosakata diatur, lapisan dapat mengkodekan teks ke dalam indeks. Tensor indeks diberi bantalan 0 ke urutan terpanjang dalam batch (kecuali jika Anda menetapkan output\_sequence\_length tetap):

{% code overflow="wrap" lineNumbers="true" %}

```python
encoded_example = encoder(example)[:3].numpy()
encoded_example
```

{% endcode %}

Dengan pengaturan default, prosesnya tidak dapat dibalik sepenuhnya. Ada dua alasan utama untuk itu:&#x20;

-Nilai default untuk argumen standarisasi preprocessing.TextVectorization adalah "lower\_and\_strip\_punctuation".&#x20;

-Ukuran kosa kata yang terbatas dan kurangnya fallback berbasis karakter menghasilkan beberapa token yang tidak diketahui.

{% code overflow="wrap" lineNumbers="true" %}

```python
for n in range(3):
  print("Original: ", example[n].numpy())
  print("Round-trip: ", " ".join(vocab[encoded_example[n]]))
  print()
```

{% endcode %}

### Buat Model

***

![A drawing of the information flow in the model](https://github.com/tensorflow/text/blob/master/docs/tutorials/images/bidirectional.png?raw=1)

***

diagram model dapat dilihat pada gambar diatas

1. Model ini dapat dibuat sebagai tf.keras.Sequential.
2. &#x20;Lapisan pertama adalah encoder, yang mengubah teks menjadi urutan indeks token.&#x20;
3. Setelah encoder adalah lapisan penyematan (embedding layer). Lapisan penyematan menyimpan satu vektor per kata. Saat dipanggil, ini mengubah rangkaian indeks kata menjadi rangkaian vektor. Vektor-vektor ini dapat dilatih. Setelah pelatihan (dengan data yang cukup), kata-kata dengan arti yang mirip sering kali memiliki vektor yang serupa. Pencarian indeks ini jauh lebih efisien daripada operasi setara dengan meneruskan vektor yang disandikan one-hot melalui lapisan tf.keras.layers.Dense.&#x20;
4. Jaringan saraf berulang (RNN) memproses masukan urutan dengan melakukan iterasi melalui elemen. RNN meneruskan keluaran dari satu langkah waktu ke masukannya pada langkah waktu berikutnya.&#x20;

   Pembungkus tf.keras.layers.Bidirection juga dapat digunakan dengan lapisan RNN. Ini menyebarkan masukan maju dan mundur melalui lapisan RNN dan kemudian menggabungkan keluaran akhir.&#x20;

   -Keuntungan utama RNN dua arah adalah sinyal dari awal masukan tidak perlu diproses sepanjang waktu untuk memengaruhi keluaran.&#x20;

   -Kerugian utama dari RNN dua arah adalah Anda tidak dapat melakukan streaming prediksi secara efisien saat kata-kata ditambahkan di akhir.&#x20;
5. Setelah RNN mengonversi urutan menjadi satu vektor, kedua lapisan tersebut.Dense melakukan beberapa pemrosesan akhir, dan mengonversi representasi vektor ini menjadi logit tunggal sebagai keluaran klasifikasi.

Kode nya adalah sebagai berikut :

{% code overflow="wrap" lineNumbers="true" %}

```python
model = tf.keras.Sequential([
    encoder,
    tf.keras.layers.Embedding(
        input_dim=len(encoder.get_vocabulary()),
        output_dim=64,
        # Use masking to handle the variable sequence lengths
        mask_zero=True),
    tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(64)),
    tf.keras.layers.Dense(64, activation='relu'),
    tf.keras.layers.Dense(1)
])
```

{% endcode %}

Harap dicatat bahwa model sekuensial Keras digunakan di sini karena semua lapisan dalam model hanya memiliki masukan tunggal dan menghasilkan keluaran tunggal. Jika Anda ingin menggunakan lapisan RNN stateful, Anda mungkin ingin membangun model Anda dengan API fungsional Keras atau subkelas model sehingga Anda dapat mengambil dan menggunakan kembali status lapisan RNN. Untuk detailnya bisa dilihat pada [Keras RNN guide](https://www.tensorflow.org/guide/keras/rnn#rnn_state_reuse)&#x20;

Lapisan penyematan menggunakan masking ([uses masking](https://www.tensorflow.org/guide/keras/masking_and_padding) ) untuk menangani panjang urutan yang bervariasi. Semua lapisan setelah penyematan dukungan penyematan&#x20;

{% code overflow="wrap" lineNumbers="true" %}

```python
print([layer.supports_masking for layer in model.layers])
```

{% endcode %}

Untuk memastikan bahwa ini berfungsi seperti yang diharapkan, evaluasi sebuah kalimat dua kali. Pertama, satu kalimat sehingga tidak ada bantalan (padding) untuk disamarkan:

{% code overflow="wrap" lineNumbers="true" %}

```python
# predict on a sample text without padding.

sample_text = ('The movie was cool. The animation and the graphics '
               'were out of this world. I would recommend this movie.')
predictions = model.predict(np.array([sample_text]))
print(predictions[0])
```

{% endcode %}

Sekarang, evaluasi lagi dalam batch dengan kalimat yang lebih panjang. Hasilnya harus sama:

{% code overflow="wrap" lineNumbers="true" %}

```python
# predict on a sample text with padding

padding = "the " * 2000
predictions = model.predict(np.array([sample_text, padding]))
print(predictions[0])
```

{% endcode %}

compile model Keras untuk mengonfigurasi proses pelatihan:

{% code overflow="wrap" lineNumbers="true" %}

```python
model.compile(loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
              optimizer=tf.keras.optimizers.Adam(1e-4),
              metrics=['accuracy'])
```

{% endcode %}

### Train Model

{% code overflow="wrap" lineNumbers="true" %}

```python
history = model.fit(train_dataset, epochs=10,
                    validation_data=test_dataset,
                    validation_steps=30)
```

{% endcode %}

{% code overflow="wrap" lineNumbers="true" %}

```python
test_loss, test_acc = model.evaluate(test_dataset)

print('Test Loss:', test_loss)
print('Test Accuracy:', test_acc)
```

{% endcode %}

{% code overflow="wrap" lineNumbers="true" %}

```python
plt.figure(figsize=(16, 8))
plt.subplot(1, 2, 1)
plot_graphs(history, 'accuracy')
plt.ylim(None, 1)
plt.subplot(1, 2, 2)
plot_graphs(history, 'loss')
plt.ylim(0, None)
```

{% endcode %}

Jalankan prediksi pada kalimat baru:

Jika prediksi >= 0,0 berarti positif, jika tidak maka negatif.

{% code overflow="wrap" lineNumbers="true" %}

```python
sample_text = ('The movie was cool. The animation and the graphics '
               'were out of this world. I would recommend this movie.')
predictions = model.predict(np.array([sample_text]))
```

{% endcode %}

### Stack two or more LSTM layers <a href="#stack_two_or_more_lstm_layers" id="stack_two_or_more_lstm_layers"></a>

Lapisan berulang Keras memiliki dua mode yang tersedia yang dikontrol oleh argumen konstruktor return\_sequences :

* Jika False, ia hanya mengembalikan keluaran terakhir untuk setiap urutan masukan (bentuk tensor 2D (batch\_size, output\_features)). Ini adalah default yang digunakan pada model sebelumnya.&#x20;
* Jika True, Sequence lengkap output berturut-turut untuk setiap langkah waktu dikembalikan (bentuk tensor 3D (ukuran\_batch, langkah waktu, fitur\_output)).

Berikut adalah alur informasi dengan return\_sequences=True:

![layered\_bidirectional](https://www.tensorflow.org/static/text/tutorials/images/layered_bidirectional.png)

Hal yang menarik dari penggunaan RNN dengan return\_sequences=True adalah outputnya masih memiliki 3 axis, sama seperti inputnya, sehingga bisa diteruskan ke layer RNN lain, seperti ini:

{% code overflow="wrap" lineNumbers="true" %}

```python
model = tf.keras.Sequential([
    encoder,
    tf.keras.layers.Embedding(len(encoder.get_vocabulary()), 64, mask_zero=True),
    tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(64,  return_sequences=True)),
    tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(32)),
    tf.keras.layers.Dense(64, activation='relu'),
    tf.keras.layers.Dropout(0.5),
    tf.keras.layers.Dense(1)
])
```

{% endcode %}

{% code overflow="wrap" lineNumbers="true" %}

```python
model.compile(loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
              optimizer=tf.keras.optimizers.Adam(1e-4),
              metrics=['accuracy'])
```

{% endcode %}

{% code overflow="wrap" lineNumbers="true" %}

```python
history = model.fit(train_dataset, epochs=10,
                    validation_data=test_dataset,
                    validation_steps=30)
```

{% endcode %}

{% code overflow="wrap" lineNumbers="true" %}

```python
test_loss, test_acc = model.evaluate(test_dataset)

print('Test Loss:', test_loss)
print('Test Accuracy:', test_acc)
```

{% endcode %}

{% code overflow="wrap" lineNumbers="true" %}

```python
# predict on a sample text without padding.

sample_text = ('The movie was not good. The animation and the graphics '
               'were terrible. I would not recommend this movie.')
predictions = model.predict(np.array([sample_text]))
print(predictions)
```

{% endcode %}

{% code overflow="wrap" lineNumbers="true" %}

```python
plt.figure(figsize=(16, 6))
plt.subplot(1, 2, 1)
plot_graphs(history, 'accuracy')
plt.subplot(1, 2, 2)
plot_graphs(history, 'loss')
```

{% endcode %}

## Catatan

Informasi menarik lain terkait dengan [GRU layers](https://www.tensorflow.org/api_docs/python/tf/keras/layers/GRU).

Informasi membuat custom RNN --> [Keras RNN Guide](https://www.tensorflow.org/guide/keras/rnn).

***
