TensorFlow ile NLP — Giriş 3
Uyarı:
Eğer TensorFlow ile NLP — Giriş 2 yazısını okumadıysanız ilk önce onu okumanızı tavsiye ediyorum.
Model 3: GRU
Bir başka popüler ve etkili RNN bileşeni, GRU veya kapılı tekrarlayan birimdir. GRU hücresi, bir LSTM hücresine benzer özelliklere sahiptir ancak daha az parametreye sahiptir.
GRU hücresini TensorFlow’da kullanmak için tensorflow.keras.layers.GRU()
sınıfını çağırabiliriz.
GRU destekli modelin mimarisi, kullandığımız yapıyla aynı olacak:
Input (metin) -> Tokenization -> Embedding -> Layers -> Output (etiket olasılığı)
Yine tek fark, embed ve output arasında kullandığımız katman(lar) olacaktır.
TensorFlow, modellerimizde GRU hücresi gibi güçlü bileşenleri kullanmayı kolaylaştırır. Ve şimdi üçüncü modelimiz yapıldı, eskisi gibi derleyelim.
Model: "model_3_GRU"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_3 (InputLayer) [(None, 1)] 0
_________________________________________________________________
text_vectorization_1 (TextVe (None, 15) 0
_________________________________________________________________
embedding (Embedding) (None, 15, 128) 1280000
_________________________________________________________________
gru (GRU) (None, 64) 37248
_________________________________________________________________
dense_2 (Dense) (None, 1) 65
=================================================================
Total params: 1,317,313
Trainable params: 1,317,313
Non-trainable params: 0
_________________________________________________________________
model_2
(LSTM) ve model_3
(GRU) arasındaki eğitilebilir parametre sayısındaki farka dikkat edin. Fark, GRU hücresinden daha fazla eğitilebilir parametreye sahip LSTM hücresinden gelir.
Modelimize daha önce yaptığımız gibi fit edeceğiz. Ayrıca, create_tensorboard_callback()
fonksiyonumuzu kullanarak model sonuçlarımızı takip edeceğiz.
Saving TensorBoard log files to: model_logs/GRU/20210822-070958
Epoch 1/5
215/215 [==============================] - 5s 14ms/step - loss: 0.1533 - accuracy: 0.9399 - val_loss: 0.7544 - val_accuracy: 0.7690
Epoch 2/5
215/215 [==============================] - 2s 9ms/step - loss: 0.0892 - accuracy: 0.9677 - val_loss: 0.6545 - val_accuracy: 0.7808
Epoch 3/5
215/215 [==============================] - 2s 9ms/step - loss: 0.0744 - accuracy: 0.9720 - val_loss: 0.8501 - val_accuracy: 0.7743
Epoch 4/5
215/215 [==============================] - 2s 9ms/step - loss: 0.0622 - accuracy: 0.9740 - val_loss: 0.9582 - val_accuracy: 0.7743
Epoch 5/5
215/215 [==============================] - 2s 10ms/step - loss: 0.0565 - accuracy: 0.9768 - val_loss: 1.2119 - val_accuracy: 0.7717
TensorFlow’daki GRU hücresinin optimize edilmiş varsayılan ayarları nedeniyle, eğitim hiç uzun sürmez. Doğrulama örnekleri üzerinde bazı tahminlerde bulunma zamanı.
((762, 1), array([[1.6326897e-02],
[8.8803720e-01],
[9.9982280e-01],
[4.5834299e-02],
[1.4948420e-04],
[9.9980944e-01],
[9.7764552e-01],
[9.9996221e-01],
[9.9989629e-01],
[9.8516256e-01]], dtype=float32))
Yine, onları yuvarlayarak tahmin sınıflarına dönüştürebileceğimiz bir dizi tahmin olasılığı elde ederiz.
<tf.Tensor: shape=(10,), dtype=float32, numpy=array([0., 1., 1., 0., 0., 1., 1., 1., 1., 1.], dtype=float32)>
Şimdi tahmini sınıflarımız var, bunları temel doğruluk etiketlerine göre değerlendirelim.
{'accuracy': 77.16535433070865,
'f1': 0.7712815503325242,
'precision': 0.7712950933950157,
'recall': 0.7716535433070866}
Son olarak, GRU modelimizin sonuçlarını taban çizgimizle karşılaştırabiliriz.
Baseline accuracy: 79.27, New accuracy: 77.17, Difference: -2.10
Baseline precision: 0.81, New precision: 0.77, Difference: -0.04
Baseline recall: 0.79, New recall: 0.77, Difference: -0.02
Baseline f1: 0.79, New f1: 0.77, Difference: -0.01
GRU ile LSTM arasında ki farkı, StackExchange’de bulunan yorumda çok güzel özetlemiş:
- GRU, LSTM birimi gibi bilgi akışını kontrol eder, ancak bir bellek birimi kullanmak zorunda kalmadan. Herhangi bir kontrol olmaksızın tam gizli içeriği ortaya çıkarır.
- GRU nispeten yeni ve benim açımdan performans LSTM ile eşit, ancak hesaplama açısından daha verimli (belirtildiği gibi daha az karmaşık yapı). Bu yüzden giderek daha fazla kullanıldığını görüyoruz.
- Deneyimlerime göre, dil modelleme yapıyorsanız (diğer görevlerden emin değilsiniz) GRU’lar daha hızlı eğitim alır ve daha az eğitim verisi üzerinde LSTM’lerden daha iyi performans gösterir.
- GRU’lar daha basittir ve bu nedenle değiştirilmesi daha kolaydır.
Model 4: Çift Yönlü RNN modeli
Halihazırda GRU ve LSTM hücreli iki RNN oluşturduk. Şimdi başka bir tür RNN’yi, çift yönlü RNN’yi inceleyeceğiz.
Standart bir RNN, bir diziyi soldan sağa işleyecektir, burada çift yönlü bir RNN, diziyi soldan sağa ve ardından tekrar sağdan sola işleyecektir.
Sezgisel olarak, bu, bir cümleyi ilk kez normal şekilde (soldan sağa) okuyormuşsunuz gibi düşünülebilir, ancak bir nedenden dolayı bu mantıklı gelmedi, bu yüzden kelimeler arasında geri dönüp tekrar üzerinden geçtiniz. (sağdan sola).
Pratikte, birçok dizi modeli, çift yönlü RNN’leri kullanırken performansta sıklıkla görülür ve gelişme gösterir.
Bununla birlikte, performanstaki bu gelişme genellikle daha uzun eğitim süreleri ve artan model parametreleri pahasına gelir (model soldan sağa ve sağdan sola gittiğinden, eğitilebilir parametrelerin sayısı iki katına çıkar).
Yeterince konuştuk, hadi çift yönlü bir RNN oluşturalım.
TensorFlow bir kez daha [tensorflow.keras.layers.Bi Directional
](https://www.tensorflow.org/api_docs/python/tf/keras/layers/Bi Direction) sınıfını sağlayarak bize yardımcı oluyor. Mevcut RNN'lerimizi sarmak için Bi Directional
sınıfını kullanabilir ve onları anında çift yönlü hale getirebiliriz.
🔑 Not: TensorFlow’daki herhangi bir RNN hücresinde “Çift Yönlü” sarmalayıcıyı kullanabilirsiniz. Örneğin,
layers.Bidirectional(layers.GRU(64))
çift yönlü bir GRU hücresi oluşturur.
Çift yönlü modelimiz oluşturuldu, derleyelim.
Model: "model_4_Bidirectional"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_4 (InputLayer) [(None, 1)] 0
_________________________________________________________________
text_vectorization_1 (TextVe (None, 15) 0
_________________________________________________________________
embedding (Embedding) (None, 15, 128) 1280000
_________________________________________________________________
bidirectional (Bidirectional (None, 128) 98816
_________________________________________________________________
dense_3 (Dense) (None, 1) 129
=================================================================
Total params: 1,378,945
Trainable params: 1,378,945
Non-trainable params: 0
_________________________________________________________________
model_2'ye (normal LSTM) kıyasla model_4'te (çift yönlü LSTM) artan eğitilebilir parametre sayısına dikkat edin. Bunun nedeni, RNN’mize eklediğimiz çift yönlülüktür.
Çift yönlü modelimize fit etme ve performansını takip etme zamanı.
Saving TensorBoard log files to: model_logs/bidirectional_RNN/20210822-071022
Epoch 1/5
215/215 [==============================] - 8s 21ms/step - loss: 0.1078 - accuracy: 0.9653 - val_loss: 0.9425 - val_accuracy: 0.7664
Epoch 2/5
215/215 [==============================] - 3s 14ms/step - loss: 0.0544 - accuracy: 0.9774 - val_loss: 1.2819 - val_accuracy: 0.7585
Epoch 3/5
215/215 [==============================] - 3s 14ms/step - loss: 0.0462 - accuracy: 0.9791 - val_loss: 1.1894 - val_accuracy: 0.7664
Epoch 4/5
215/215 [==============================] - 3s 14ms/step - loss: 0.0469 - accuracy: 0.9784 - val_loss: 1.3589 - val_accuracy: 0.7782
Epoch 5/5
215/215 [==============================] - 3s 14ms/step - loss: 0.0401 - accuracy: 0.9806 - val_loss: 1.4919 - val_accuracy: 0.7612
Modelimizin çift yönlü olması nedeniyle eğitim süresinde hafif bir artış görüyoruz. Endişelenme, çok dramatik bir artış değil. Onunla bazı tahminler yapalım.
array([[1.2317987e-01],
[7.2211808e-01],
[9.9997759e-01],
[9.2619851e-02],
[5.5663345e-06],
[9.9944931e-01],
[9.8846996e-01],
[9.9999142e-01],
[9.9998176e-01],
[9.5131034e-01]], dtype=float32)
Ve onları tahmin sınıflarına dönüştüreceğiz ve onları temel doğruluk etiketlerine ve temel modele göre değerlendireceğiz.
<tf.Tensor: shape=(10,), dtype=float32, numpy=array([0., 1., 1., 0., 0., 1., 1., 1., 1., 1.], dtype=float32)>
{'accuracy': 76.11548556430446,
'f1': 0.7593763358258425,
'precision': 0.7618883943071393,
'recall': 0.7611548556430446}
Baseline accuracy: 79.27, New accuracy: 76.12, Difference: -3.15
Baseline precision: 0.81, New precision: 0.76, Difference: -0.05
Baseline recall: 0.79, New recall: 0.76, Difference: -0.03
Baseline f1: 0.79, New f1: 0.76, Difference: -0.03
Metin için Evrişimli Sinir Ağları
Daha önce görüntüler için evrişimli sinir ağlarını (CNN’ler) kullanmış olabilirsiniz, ancak bunlar diziler için de kullanılabilir.
Görüntüler ve diziler için CNN’leri kullanma arasındaki temel fark, verilerin şeklidir. Görüntüler 2 boyutlu (yükseklik x genişlik) gelirken, diziler genellikle 1 boyutludur (bir metin dizisi).
CNN’leri dizilerle kullanmak için 2 boyutlu evrişim yerine 1 boyutlu evrişim kullanırız.
Diziler için tipik bir CNN mimarisi aşağıdaki gibi görünecektir:
Input (metin) -> Tokenization -> Embedding -> Layers -> Output (sınıf olasılıkları)
“Bu, diğer modeller için kullandığımız mimari düzene benziyor…” diye düşünüyor olabilirsiniz. Haklısınız da. Fark yine katmanlar bileşenindedir. Bir LSTM veya GRU hücresi kullanmak yerine, bir tensorflow.keras.layers.Conv1D()
katmanı ve ardından bir tensorflow.keras.layers.GlobablMaxPool1D()
katmanı kullanacağız.
Model 5: Conv1D
Tam 1 boyutlu bir CNN modeli oluşturmadan önce, 1 boyutlu evrişim katmanını çalışırken görelim. Önce bir metin örneğinin gömülmesini oluşturacağız ve onu bir Conv1D()
katmanı ve GlobalMaxPool1D()
katmanından geçirmeyi deneyeceğiz.
(TensorShape([1, 15, 128]), TensorShape([1, 11, 32]), TensorShape([1, 32]))
Her katmanın çıktı şekillerine dikkat edin.
Gömme, ayarladığımız parametrelerin çıktı şekli boyutuna sahiptir (input_length=15
veoutput_dim=128
).
1 boyutlu evrişim katmanı, parametreleriyle aynı hizada sıkıştırılmış bir çıktıya sahiptir. Aynı şey, maksimum havuzlama katmanı çıktısı için de geçerlidir.
Metnimiz bir dize olarak başlar, ancak çeşitli dönüştürme adımlarıyla 64 uzunluğunda bir özellik vektörüne dönüştürülür. Bu dönüşümlerin her birinin neye benzediğine bir bakalım.
(<tf.Tensor: shape=(1, 15, 128), dtype=float32, numpy=
array([[[ 0.00319095, -0.01416333, -0.03029248, ..., -0.03457287,
-0.04297013, -0.04403625]...]]], dtype=float32)>..)
Pekala, diziler için bir CNN’nin çeşitli bileşenlerinin çıktılarını gördük, onları bir araya getirelim ve tam bir model oluşturalım, onu derleyelim (tıpkı diğer modellerimizde yaptığımız gibi) ve bir özet alalım.
Model: "model_5_Conv1D"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_5 (InputLayer) [(None, 1)] 0
_________________________________________________________________
text_vectorization_1 (TextVe (None, 15) 0
_________________________________________________________________
embedding (Embedding) (None, 15, 128) 1280000
_________________________________________________________________
conv1d_1 (Conv1D) (None, 11, 32) 20512
_________________________________________________________________
global_max_pooling1d_1 (Glob (None, 32) 0
_________________________________________________________________
dense_4 (Dense) (None, 1) 33
=================================================================
Total params: 1,300,545
Trainable params: 1,300,545
Non-trainable params: 0
_________________________________________________________________
Süperr! Harika görünüyor! 1-boyutlu evrişimli katman için eğitilebilir parametre sayısının model_2
'deki LSTM katmanınınkine nasıl benzer olduğuna dikkat edin.
1D CNN modelimizi metin verilerimizle fit edelim. Önceki deneylere uygun olarak, create_tensorboard_callback()
fonksiyonumuzu kullanarak sonuçlarını kaydedeceğiz.
Saving TensorBoard log files to: model_logs/Conv1D/20210822-071110
Epoch 1/5
215/215 [==============================] - 4s 10ms/step - loss: 0.1339 - accuracy: 0.9584 - val_loss: 0.8689 - val_accuracy: 0.7664
Epoch 2/5
215/215 [==============================] - 2s 7ms/step - loss: 0.0763 - accuracy: 0.9727 - val_loss: 0.9643 - val_accuracy: 0.7651
Epoch 3/5
215/215 [==============================] - 2s 7ms/step - loss: 0.0600 - accuracy: 0.9761 - val_loss: 1.0885 - val_accuracy: 0.7546
Epoch 4/5
215/215 [==============================] - 2s 7ms/step - loss: 0.0542 - accuracy: 0.9783 - val_loss: 1.1663 - val_accuracy: 0.7559
Epoch 5/5
215/215 [==============================] - 2s 7ms/step - loss: 0.0512 - accuracy: 0.9790 - val_loss: 1.2285 - val_accuracy: 0.7572
Güzel! GPU hızlandırma sayesinde 1D evrişimli modelimiz güzel ve hızlı bir şekilde eğitiyor. Onunla bazı tahminler yapalım ve eskisi gibi değerlendirelim.
array([[1.3275287e-01],
[3.1561503e-01],
[9.9978405e-01],
[5.4979675e-02],
[2.5409597e-07],
[9.8810232e-01],
[9.4828182e-01],
[9.9995220e-01],
[9.9999881e-01],
[9.4418395e-01]], dtype=float32)
<tf.Tensor: shape=(10,), dtype=float32, numpy=array([0., 0., 1., 0., 0., 1., 1., 1., 1., 1.], dtype=float32)>
{'accuracy': 75.7217847769029,
'f1': 0.7549472494674683,
'precision': 0.7585989210360964,
'recall': 0.7572178477690289}
Baseline accuracy: 79.27, New accuracy: 75.72, Difference: -3.54
Baseline precision: 0.81, New precision: 0.76, Difference: -0.05
Baseline recall: 0.79, New recall: 0.76, Difference: -0.04
Baseline f1: 0.79, New f1: 0.75, Difference: -0.03
… devamı TensorFlow ile NLP — Giriş 4 yazımda.