Upload 11 files
Browse files- .gitattributes +6 -0
- Transformer Mechanism/Transformer_Implementation/home/jovyan/work/W4A1/.ipynb_checkpoints/C5_W4_A1_Transformer_Subclass_v1-checkpoint.ipynb +1303 -0
- Transformer Mechanism/Transformer_Implementation/home/jovyan/work/W4A1/C5_W4_A1_Transformer_Subclass_v1.ipynb +0 -0
- Transformer Mechanism/Transformer_Implementation/home/jovyan/work/W4A1/__pycache__/public_tests.cpython-37.pyc +0 -0
- Transformer Mechanism/Transformer_Implementation/home/jovyan/work/W4A1/decoder.png +3 -0
- Transformer Mechanism/Transformer_Implementation/home/jovyan/work/W4A1/decoder_layer.png +3 -0
- Transformer Mechanism/Transformer_Implementation/home/jovyan/work/W4A1/encoder.png +3 -0
- Transformer Mechanism/Transformer_Implementation/home/jovyan/work/W4A1/encoder_layer.png +3 -0
- Transformer Mechanism/Transformer_Implementation/home/jovyan/work/W4A1/ner.json +0 -0
- Transformer Mechanism/Transformer_Implementation/home/jovyan/work/W4A1/public_tests.py +315 -0
- Transformer Mechanism/Transformer_Implementation/home/jovyan/work/W4A1/self-attention.png +3 -0
- Transformer Mechanism/Transformer_Implementation/home/jovyan/work/W4A1/transformer.png +3 -0
.gitattributes
CHANGED
|
@@ -103,3 +103,9 @@ Seq2Seq/Trigger_detection/home/jovyan/work/W3A2/raw_data/negatives/5_1.wav filte
|
|
| 103 |
Seq2Seq/Trigger_detection/home/jovyan/work/W3A2/tmp.wav filter=lfs diff=lfs merge=lfs -text
|
| 104 |
Seq2Seq/Trigger_detection/home/jovyan/work/W3A2/train.wav filter=lfs diff=lfs merge=lfs -text
|
| 105 |
Seq2Seq/Trigger_detection/home/jovyan/work/W3A2/Trigger_word_detection_v2a.ipynb filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 103 |
Seq2Seq/Trigger_detection/home/jovyan/work/W3A2/tmp.wav filter=lfs diff=lfs merge=lfs -text
|
| 104 |
Seq2Seq/Trigger_detection/home/jovyan/work/W3A2/train.wav filter=lfs diff=lfs merge=lfs -text
|
| 105 |
Seq2Seq/Trigger_detection/home/jovyan/work/W3A2/Trigger_word_detection_v2a.ipynb filter=lfs diff=lfs merge=lfs -text
|
| 106 |
+
Transformer[[:space:]]Mechanism/Transformer_Implementation/home/jovyan/work/W4A1/decoder_layer.png filter=lfs diff=lfs merge=lfs -text
|
| 107 |
+
Transformer[[:space:]]Mechanism/Transformer_Implementation/home/jovyan/work/W4A1/decoder.png filter=lfs diff=lfs merge=lfs -text
|
| 108 |
+
Transformer[[:space:]]Mechanism/Transformer_Implementation/home/jovyan/work/W4A1/encoder_layer.png filter=lfs diff=lfs merge=lfs -text
|
| 109 |
+
Transformer[[:space:]]Mechanism/Transformer_Implementation/home/jovyan/work/W4A1/encoder.png filter=lfs diff=lfs merge=lfs -text
|
| 110 |
+
Transformer[[:space:]]Mechanism/Transformer_Implementation/home/jovyan/work/W4A1/self-attention.png filter=lfs diff=lfs merge=lfs -text
|
| 111 |
+
Transformer[[:space:]]Mechanism/Transformer_Implementation/home/jovyan/work/W4A1/transformer.png filter=lfs diff=lfs merge=lfs -text
|
Transformer Mechanism/Transformer_Implementation/home/jovyan/work/W4A1/.ipynb_checkpoints/C5_W4_A1_Transformer_Subclass_v1-checkpoint.ipynb
ADDED
|
@@ -0,0 +1,1303 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cells": [
|
| 3 |
+
{
|
| 4 |
+
"cell_type": "markdown",
|
| 5 |
+
"metadata": {
|
| 6 |
+
"colab": {
|
| 7 |
+
"base_uri": "https://localhost:8080/"
|
| 8 |
+
},
|
| 9 |
+
"id": "AbzZLqIPv6b7",
|
| 10 |
+
"outputId": "19f2fc2b-6f1d-4b43-fd50-4c513e3936fd"
|
| 11 |
+
},
|
| 12 |
+
"source": [
|
| 13 |
+
"# Transformer Network\n",
|
| 14 |
+
"\n",
|
| 15 |
+
"Welcome to Week 4's assignment, the last assignment of Course 5 of the Deep Learning Specialization! And congratulations on making it to the last assignment of the entire Deep Learning Specialization - you're almost done!\n",
|
| 16 |
+
"\n",
|
| 17 |
+
"Earlier in the course, you've implemented sequential neural networks such as RNNs, GRUs, and LSTMs. In this notebook you'll explore the Transformer architecture, a neural network that takes advantage of parallel processing and allows you to substantially speed up the training process. \n",
|
| 18 |
+
"\n",
|
| 19 |
+
"**After this assignment you'll be able to**:\n",
|
| 20 |
+
"\n",
|
| 21 |
+
"* Create positional encodings to capture sequential relationships in data\n",
|
| 22 |
+
"* Calculate scaled dot-product self-attention with word embeddings\n",
|
| 23 |
+
"* Implement masked multi-head attention\n",
|
| 24 |
+
"* Build and train a Transformer model\n",
|
| 25 |
+
"\n",
|
| 26 |
+
"For the last time, let's get started!\n",
|
| 27 |
+
"\n",
|
| 28 |
+
"## Important Note on Submission to the AutoGrader\n",
|
| 29 |
+
"\n",
|
| 30 |
+
"Before submitting your assignment to the AutoGrader, please make sure you are not doing the following:\n",
|
| 31 |
+
"\n",
|
| 32 |
+
"1. You have not added any _extra_ `print` statement(s) in the assignment.\n",
|
| 33 |
+
"2. You have not added any _extra_ code cell(s) in the assignment.\n",
|
| 34 |
+
"3. You have not changed any of the function parameters.\n",
|
| 35 |
+
"4. You are not using any global variables inside your graded exercises. Unless specifically instructed to do so, please refrain from it and use the local variables instead.\n",
|
| 36 |
+
"5. You are not changing the assignment code where it is not required, like creating _extra_ variables.\n",
|
| 37 |
+
"\n",
|
| 38 |
+
"If you do any of the following, you will get something like, `Grader Error: Grader feedback not found` (or similarly unexpected) error upon submitting your assignment. Before asking for help/debugging the errors in your assignment, check for these first. If this is the case, and you don't remember the changes you have made, you can get a fresh copy of the assignment by following these [instructions](https://www.coursera.org/learn/nlp-sequence-models/supplement/X39s5/optional-downloading-your-notebook-downloading-your-workspace-and-refreshing)."
|
| 39 |
+
]
|
| 40 |
+
},
|
| 41 |
+
{
|
| 42 |
+
"cell_type": "markdown",
|
| 43 |
+
"metadata": {},
|
| 44 |
+
"source": [
|
| 45 |
+
"## Table of Contents\n",
|
| 46 |
+
"\n",
|
| 47 |
+
"- [Packages](#0)\n",
|
| 48 |
+
"- [1 - Positional Encoding](#1)\n",
|
| 49 |
+
" - [1.1 - Sine and Cosine Angles](#1-1)\n",
|
| 50 |
+
" - [Exercise 1 - get_angles](#ex-1)\n",
|
| 51 |
+
" - [1.2 - Sine and Cosine Positional Encodings](#1-2)\n",
|
| 52 |
+
" - [Exercise 2 - positional_encoding](#ex-2)\n",
|
| 53 |
+
"- [2 - Masking](#2)\n",
|
| 54 |
+
" - [2.1 - Padding Mask](#2-1)\n",
|
| 55 |
+
" - [2.2 - Look-ahead Mask](#2-2)\n",
|
| 56 |
+
"- [3 - Self-Attention](#3)\n",
|
| 57 |
+
" - [Exercise 3 - scaled_dot_product_attention](#ex-3)\n",
|
| 58 |
+
"- [4 - Encoder](#4)\n",
|
| 59 |
+
" - [4.1 Encoder Layer](#4-1)\n",
|
| 60 |
+
" - [Exercise 4 - EncoderLayer](#ex-4)\n",
|
| 61 |
+
" - [4.2 - Full Encoder](#4-2)\n",
|
| 62 |
+
" - [Exercise 5 - Encoder](#ex-5)\n",
|
| 63 |
+
"- [5 - Decoder](#5)\n",
|
| 64 |
+
" - [5.1 - Decoder Layer](#5-1)\n",
|
| 65 |
+
" - [Exercise 6 - DecoderLayer](#ex-6)\n",
|
| 66 |
+
" - [5.2 - Full Decoder](#5-2)\n",
|
| 67 |
+
" - [Exercise 7 - Decoder](#ex-7)\n",
|
| 68 |
+
"- [6 - Transformer](#6)\n",
|
| 69 |
+
" - [Exercise 8 - Transformer](#ex-8)\n",
|
| 70 |
+
"- [7 - References](#7)"
|
| 71 |
+
]
|
| 72 |
+
},
|
| 73 |
+
{
|
| 74 |
+
"cell_type": "markdown",
|
| 75 |
+
"metadata": {},
|
| 76 |
+
"source": [
|
| 77 |
+
"<a name='0'></a>\n",
|
| 78 |
+
"## Packages\n",
|
| 79 |
+
"\n",
|
| 80 |
+
"Run the following cell to load the packages you'll need."
|
| 81 |
+
]
|
| 82 |
+
},
|
| 83 |
+
{
|
| 84 |
+
"cell_type": "code",
|
| 85 |
+
"execution_count": null,
|
| 86 |
+
"metadata": {
|
| 87 |
+
"deletable": false,
|
| 88 |
+
"editable": false
|
| 89 |
+
},
|
| 90 |
+
"outputs": [],
|
| 91 |
+
"source": [
|
| 92 |
+
"### v1.6"
|
| 93 |
+
]
|
| 94 |
+
},
|
| 95 |
+
{
|
| 96 |
+
"cell_type": "code",
|
| 97 |
+
"execution_count": null,
|
| 98 |
+
"metadata": {
|
| 99 |
+
"id": "_OpwqWL2QH5G"
|
| 100 |
+
},
|
| 101 |
+
"outputs": [],
|
| 102 |
+
"source": [
|
| 103 |
+
"import tensorflow as tf\n",
|
| 104 |
+
"import time\n",
|
| 105 |
+
"import numpy as np\n",
|
| 106 |
+
"import matplotlib.pyplot as plt\n",
|
| 107 |
+
"\n",
|
| 108 |
+
"from tensorflow.keras.layers import Embedding, MultiHeadAttention, Dense, Input, Dropout, LayerNormalization"
|
| 109 |
+
]
|
| 110 |
+
},
|
| 111 |
+
{
|
| 112 |
+
"cell_type": "markdown",
|
| 113 |
+
"metadata": {},
|
| 114 |
+
"source": [
|
| 115 |
+
"<a name='1'></a>\n",
|
| 116 |
+
"## 1 - Positional Encoding\n",
|
| 117 |
+
"\n",
|
| 118 |
+
"In sequence to sequence tasks, the relative order of your data is extremely important to its meaning. When you were training sequential neural networks such as RNNs, you fed your inputs into the network in order. Information about the order of your data was automatically fed into your model. However, when you train a Transformer network using multi-head attention, you feed your data into the model all at once. While this dramatically reduces training time, there is no information about the order of your data. This is where positional encoding is useful - you can specifically encode the positions of your inputs and pass them into the network using these sine and cosine formulas:\n",
|
| 119 |
+
" \n",
|
| 120 |
+
"$$\n",
|
| 121 |
+
"PE_{(pos, 2i)}= sin\\left(\\frac{pos}{{10000}^{\\frac{2i}{d}}}\\right)\n",
|
| 122 |
+
"\\tag{1}$$\n",
|
| 123 |
+
"<br>\n",
|
| 124 |
+
"$$\n",
|
| 125 |
+
"PE_{(pos, 2i+1)}= cos\\left(\\frac{pos}{{10000}^{\\frac{2i}{d}}}\\right)\n",
|
| 126 |
+
"\\tag{2}$$\n",
|
| 127 |
+
"\n",
|
| 128 |
+
"* $d$ is the dimension of the word embedding and positional encoding\n",
|
| 129 |
+
"* $pos$ is the position of the word.\n",
|
| 130 |
+
"* $k$ refers to each of the different dimensions in the positional encodings, with $i$ equal to $k$ $//$ $2$.\n",
|
| 131 |
+
"\n",
|
| 132 |
+
"To develop some intuition about positional encodings, you can think of them broadly as a feature that contains the information about the relative positions of words. The sum of the positional encoding and word embedding is ultimately what is fed into the model. If you just hard code the positions in, say by adding a matrix of 1's or whole numbers to the word embedding, the semantic meaning is distorted. Conversely, the values of the sine and cosine equations are small enough (between -1 and 1) that when you add the positional encoding to a word embedding, the word embedding is not significantly distorted, and is instead enriched with positional information. Using a combination of these two equations helps your Transformer network attend to the relative positions of your input data. This was a short discussion on positional encodings, but to develop further intuition, check out the *Positional Encoding Ungraded Lab*. \n",
|
| 133 |
+
"\n",
|
| 134 |
+
"**Note:** In the lectures Andrew uses vertical vectors, but in this assignment all vectors are horizontal. All matrix multiplications should be adjusted accordingly.\n",
|
| 135 |
+
"\n",
|
| 136 |
+
"<a name='1-1'></a>\n",
|
| 137 |
+
"### 1.1 - Sine and Cosine Angles\n",
|
| 138 |
+
"\n",
|
| 139 |
+
"Notice that even though the sine and cosine positional encoding equations take in different arguments (`2i` versus `2i+1`, or even versus odd numbers) the inner terms for both equations are the same: $$\\theta(pos, i, d) = \\frac{pos}{10000^{\\frac{2i}{d}}} \\tag{3}$$\n",
|
| 140 |
+
"\n",
|
| 141 |
+
"Consider the inner term as you calculate the positional encoding for a word in a sequence.<br> \n",
|
| 142 |
+
"$PE_{(pos, 0)}= sin\\left(\\frac{pos}{{10000}^{\\frac{0}{d}}}\\right)$, since solving `2i = 0` gives `i = 0` <br>\n",
|
| 143 |
+
"$PE_{(pos, 1)}= cos\\left(\\frac{pos}{{10000}^{\\frac{0}{d}}}\\right)$, since solving `2i + 1 = 1` gives `i = 0`\n",
|
| 144 |
+
"\n",
|
| 145 |
+
"The angle is the same for both! The angles for $PE_{(pos, 2)}$ and $PE_{(pos, 3)}$ are the same as well, since for both, `i = 1` and therefore the inner term is $\\left(\\frac{pos}{{10000}^{\\frac{2}{d}}}\\right)$. This relationship holds true for all paired sine and cosine curves:\n",
|
| 146 |
+
"\n",
|
| 147 |
+
"| k | <code> 0 </code>|<code> 1 </code>|<code> 2 </code>|<code> 3 </code>| <code> ... </code> |<code> d - 2 </code>|<code> d - 1 </code>| \n",
|
| 148 |
+
"| ---------------- | :------: | ----------------- | ----------------- | ----------------- | ----- | ----------------- | ----------------- |\n",
|
| 149 |
+
"| encoding(0) = |[$sin(\\theta(0, 0, d))$| $cos(\\theta(0, 0, d))$| $sin(\\theta(0, 1, d))$| $cos(\\theta(0, 1, d))$|... |$sin(\\theta(0, d//2, d))$| $cos(\\theta(0, d//2, d))$]|\n",
|
| 150 |
+
"| encoding(1) = | [$sin(\\theta(1, 0, d))$| $cos(\\theta(1, 0, d))$| $sin(\\theta(1, 1, d))$| $cos(\\theta(1, 1, d))$|... |$sin(\\theta(1, d//2, d))$| $cos(\\theta(1, d//2, d))$]|\n",
|
| 151 |
+
"...\n",
|
| 152 |
+
"| encoding(pos) = | [$sin(\\theta(pos, 0, d))$| $cos(\\theta(pos, 0, d))$| $sin(\\theta(pos, 1, d))$| $cos(\\theta(pos, 1, d))$|... |$sin(\\theta(pos, d//2, d))$| $cos(\\theta(pos, d//2, d))]$|\n",
|
| 153 |
+
"\n",
|
| 154 |
+
"\n",
|
| 155 |
+
"<a name='ex-1'></a>\n",
|
| 156 |
+
"### Exercise 1 - get_angles\n",
|
| 157 |
+
"\n",
|
| 158 |
+
"Implement the function `get_angles()` to calculate the possible angles for the sine and cosine positional encodings\n",
|
| 159 |
+
"\n",
|
| 160 |
+
"**Hints**\n",
|
| 161 |
+
"\n",
|
| 162 |
+
"- If `k = [0, 1, 2, 3, 4, 5]`, then, `i` must be `i = [0, 0, 1, 1, 2, 2]`\n",
|
| 163 |
+
"- `i = k//2`"
|
| 164 |
+
]
|
| 165 |
+
},
|
| 166 |
+
{
|
| 167 |
+
"cell_type": "code",
|
| 168 |
+
"execution_count": null,
|
| 169 |
+
"metadata": {
|
| 170 |
+
"id": "bPzwMVfcQpT-"
|
| 171 |
+
},
|
| 172 |
+
"outputs": [],
|
| 173 |
+
"source": [
|
| 174 |
+
"# UNQ_C1 (UNIQUE CELL IDENTIFIER, DO NOT EDIT)\n",
|
| 175 |
+
"# GRADED FUNCTION get_angles\n",
|
| 176 |
+
"def get_angles(pos, k, d):\n",
|
| 177 |
+
" \"\"\"\n",
|
| 178 |
+
" Get the angles for the positional encoding\n",
|
| 179 |
+
" \n",
|
| 180 |
+
" Arguments:\n",
|
| 181 |
+
" pos -- Column vector containing the positions [[0], [1], ...,[N-1]]\n",
|
| 182 |
+
" k -- Row vector containing the dimension span [[0, 1, 2, ..., d-1]]\n",
|
| 183 |
+
" d(integer) -- Encoding size\n",
|
| 184 |
+
" \n",
|
| 185 |
+
" Returns:\n",
|
| 186 |
+
" angles -- (pos, d) numpy array \n",
|
| 187 |
+
" \"\"\"\n",
|
| 188 |
+
" \n",
|
| 189 |
+
" # START CODE HERE\n",
|
| 190 |
+
" # Get i from dimension span k\n",
|
| 191 |
+
" i = None\n",
|
| 192 |
+
" # Calculate the angles using pos, i and d\n",
|
| 193 |
+
" angles = None\n",
|
| 194 |
+
" # END CODE HERE\n",
|
| 195 |
+
" \n",
|
| 196 |
+
" return angles"
|
| 197 |
+
]
|
| 198 |
+
},
|
| 199 |
+
{
|
| 200 |
+
"cell_type": "code",
|
| 201 |
+
"execution_count": null,
|
| 202 |
+
"metadata": {},
|
| 203 |
+
"outputs": [],
|
| 204 |
+
"source": [
|
| 205 |
+
"from public_tests import *\n",
|
| 206 |
+
"\n",
|
| 207 |
+
"get_angles_test(get_angles)\n",
|
| 208 |
+
"\n",
|
| 209 |
+
"# Example\n",
|
| 210 |
+
"position = 4\n",
|
| 211 |
+
"d_model = 8\n",
|
| 212 |
+
"pos_m = np.arange(position)[:, np.newaxis]\n",
|
| 213 |
+
"dims = np.arange(d_model)[np.newaxis, :]\n",
|
| 214 |
+
"get_angles(pos_m, dims, d_model)"
|
| 215 |
+
]
|
| 216 |
+
},
|
| 217 |
+
{
|
| 218 |
+
"cell_type": "markdown",
|
| 219 |
+
"metadata": {},
|
| 220 |
+
"source": [
|
| 221 |
+
"<a name='1-2'></a>\n",
|
| 222 |
+
"### 1.2 - Sine and Cosine Positional Encodings\n",
|
| 223 |
+
"\n",
|
| 224 |
+
"Now you can use the angles you computed to calculate the sine and cosine positional encodings.\n",
|
| 225 |
+
"\n",
|
| 226 |
+
"$$\n",
|
| 227 |
+
"PE_{(pos, 2i)}= sin\\left(\\frac{pos}{{10000}^{\\frac{2i}{d}}}\\right)\n",
|
| 228 |
+
"$$\n",
|
| 229 |
+
"<br>\n",
|
| 230 |
+
"$$\n",
|
| 231 |
+
"PE_{(pos, 2i+1)}= cos\\left(\\frac{pos}{{10000}^{\\frac{2i}{d}}}\\right)\n",
|
| 232 |
+
"$$\n",
|
| 233 |
+
"\n",
|
| 234 |
+
"<a name='ex-2'></a>\n",
|
| 235 |
+
"### Exercise 2 - positional_encoding\n",
|
| 236 |
+
"\n",
|
| 237 |
+
"Implement the function `positional_encoding()` to calculate the sine and cosine positional encodings\n",
|
| 238 |
+
"\n",
|
| 239 |
+
"**Reminder:** Use the sine equation when $i$ is an even number and the cosine equation when $i$ is an odd number.\n",
|
| 240 |
+
"\n",
|
| 241 |
+
"#### Additional Hints\n",
|
| 242 |
+
"* You may find \n",
|
| 243 |
+
"[np.newaxis](https://numpy.org/doc/stable/user/basics.indexing.html#dimensional-indexing-tools) useful depending on the implementation you choose. "
|
| 244 |
+
]
|
| 245 |
+
},
|
| 246 |
+
{
|
| 247 |
+
"cell_type": "code",
|
| 248 |
+
"execution_count": null,
|
| 249 |
+
"metadata": {
|
| 250 |
+
"id": "y78txxoHQtwG"
|
| 251 |
+
},
|
| 252 |
+
"outputs": [],
|
| 253 |
+
"source": [
|
| 254 |
+
"# UNQ_C2 (UNIQUE CELL IDENTIFIER, DO NOT EDIT)\n",
|
| 255 |
+
"# GRADED FUNCTION positional_encoding\n",
|
| 256 |
+
"def positional_encoding(positions, d):\n",
|
| 257 |
+
" \"\"\"\n",
|
| 258 |
+
" Precomputes a matrix with all the positional encodings \n",
|
| 259 |
+
" \n",
|
| 260 |
+
" Arguments:\n",
|
| 261 |
+
" positions (int) -- Maximum number of positions to be encoded \n",
|
| 262 |
+
" d (int) -- Encoding size \n",
|
| 263 |
+
" \n",
|
| 264 |
+
" Returns:\n",
|
| 265 |
+
" pos_encoding -- (1, position, d_model) A matrix with the positional encodings\n",
|
| 266 |
+
" \"\"\"\n",
|
| 267 |
+
" # START CODE HERE\n",
|
| 268 |
+
" # initialize a matrix angle_rads of all the angles \n",
|
| 269 |
+
" angle_rads = get_angles(None,\n",
|
| 270 |
+
" None,\n",
|
| 271 |
+
" None)\n",
|
| 272 |
+
" \n",
|
| 273 |
+
" # apply sin to even indices in the array; 2i\n",
|
| 274 |
+
" angle_rads[:, 0::2] = None\n",
|
| 275 |
+
" \n",
|
| 276 |
+
" # apply cos to odd indices in the array; 2i+1\n",
|
| 277 |
+
" angle_rads[:, 1::2] = None\n",
|
| 278 |
+
" # END CODE HERE\n",
|
| 279 |
+
" \n",
|
| 280 |
+
" pos_encoding = angle_rads[np.newaxis, ...]\n",
|
| 281 |
+
" \n",
|
| 282 |
+
" return tf.cast(pos_encoding, dtype=tf.float32)"
|
| 283 |
+
]
|
| 284 |
+
},
|
| 285 |
+
{
|
| 286 |
+
"cell_type": "code",
|
| 287 |
+
"execution_count": null,
|
| 288 |
+
"metadata": {
|
| 289 |
+
"colab": {
|
| 290 |
+
"base_uri": "https://localhost:8080/",
|
| 291 |
+
"height": 300
|
| 292 |
+
},
|
| 293 |
+
"id": "jYiWrawRQvuv",
|
| 294 |
+
"outputId": "cfccc7c9-428e-4b08-d969-e3090fafc1ad"
|
| 295 |
+
},
|
| 296 |
+
"outputs": [],
|
| 297 |
+
"source": [
|
| 298 |
+
"# UNIT TEST \n",
|
| 299 |
+
"positional_encoding_test(positional_encoding, get_angles)"
|
| 300 |
+
]
|
| 301 |
+
},
|
| 302 |
+
{
|
| 303 |
+
"cell_type": "markdown",
|
| 304 |
+
"metadata": {},
|
| 305 |
+
"source": [
|
| 306 |
+
"Nice work calculating the positional encodings! Now you can visualize them."
|
| 307 |
+
]
|
| 308 |
+
},
|
| 309 |
+
{
|
| 310 |
+
"cell_type": "code",
|
| 311 |
+
"execution_count": null,
|
| 312 |
+
"metadata": {},
|
| 313 |
+
"outputs": [],
|
| 314 |
+
"source": [
|
| 315 |
+
"pos_encoding = positional_encoding(50, 512)\n",
|
| 316 |
+
"\n",
|
| 317 |
+
"print (pos_encoding.shape)\n",
|
| 318 |
+
"\n",
|
| 319 |
+
"plt.pcolormesh(pos_encoding[0], cmap='RdBu')\n",
|
| 320 |
+
"plt.xlabel('d')\n",
|
| 321 |
+
"plt.xlim((0, 512))\n",
|
| 322 |
+
"plt.ylabel('Position')\n",
|
| 323 |
+
"plt.colorbar()\n",
|
| 324 |
+
"plt.show()"
|
| 325 |
+
]
|
| 326 |
+
},
|
| 327 |
+
{
|
| 328 |
+
"cell_type": "markdown",
|
| 329 |
+
"metadata": {},
|
| 330 |
+
"source": [
|
| 331 |
+
"Each row represents a positional encoding - notice how none of the rows are identical! You have created a unique positional encoding for each of the words."
|
| 332 |
+
]
|
| 333 |
+
},
|
| 334 |
+
{
|
| 335 |
+
"cell_type": "markdown",
|
| 336 |
+
"metadata": {},
|
| 337 |
+
"source": [
|
| 338 |
+
"<a name='2'></a>\n",
|
| 339 |
+
"## 2 - Masking\n",
|
| 340 |
+
"\n",
|
| 341 |
+
"There are two types of masks that are useful when building your Transformer network: the *padding mask* and the *look-ahead mask*. Both help the softmax computation give the appropriate weights to the words in your input sentence. \n",
|
| 342 |
+
"\n",
|
| 343 |
+
"<a name='2-1'></a>\n",
|
| 344 |
+
"### 2.1 - Padding Mask\n",
|
| 345 |
+
"\n",
|
| 346 |
+
"Oftentimes your input sequence will exceed the maximum length of a sequence your network can process. Let's say the maximum length of your model is five, it is fed the following sequences:\n",
|
| 347 |
+
"\n",
|
| 348 |
+
" [[\"Do\", \"you\", \"know\", \"when\", \"Jane\", \"is\", \"going\", \"to\", \"visit\", \"Africa\"], \n",
|
| 349 |
+
" [\"Jane\", \"visits\", \"Africa\", \"in\", \"September\" ],\n",
|
| 350 |
+
" [\"Exciting\", \"!\"]\n",
|
| 351 |
+
" ]\n",
|
| 352 |
+
"\n",
|
| 353 |
+
"which might get vectorized as:\n",
|
| 354 |
+
"\n",
|
| 355 |
+
" [[ 71, 121, 4, 56, 99, 2344, 345, 1284, 15],\n",
|
| 356 |
+
" [ 56, 1285, 15, 181, 545],\n",
|
| 357 |
+
" [ 87, 600]\n",
|
| 358 |
+
" ]\n",
|
| 359 |
+
" \n",
|
| 360 |
+
"When passing sequences into a transformer model, it is important that they are of uniform length. You can achieve this by padding the sequence with zeros, and truncating sentences that exceed the maximum length of your model:\n",
|
| 361 |
+
"\n",
|
| 362 |
+
" [[ 71, 121, 4, 56, 99],\n",
|
| 363 |
+
" [ 2344, 345, 1284, 15, 0],\n",
|
| 364 |
+
" [ 56, 1285, 15, 181, 545],\n",
|
| 365 |
+
" [ 87, 600, 0, 0, 0],\n",
|
| 366 |
+
" ]\n",
|
| 367 |
+
" \n",
|
| 368 |
+
"Sequences longer than the maximum length of five will be truncated, and zeros will be added to the truncated sequence to achieve uniform length. Similarly, for sequences shorter than the maximum length, zeros will also be added for padding. However, these zeros will affect the softmax calculation - this is when a padding mask comes in handy! You will need to define a boolean mask that specifies to which elements you must attend(1) and which elements you must ignore(0). Later you will use that mask to set all the zeros in the sequence to a value close to negative infinity (-1e9). We'll implement this for you so you can get to the fun of building the Transformer network! 😇 Just make sure you go through the code so you can correctly implement padding when building your model. \n",
|
| 369 |
+
"\n",
|
| 370 |
+
"After masking, your input should go from `[87, 600, 0, 0, 0]` to `[87, 600, -1e9, -1e9, -1e9]`, so that when you take the softmax, the zeros don't affect the score.\n",
|
| 371 |
+
"\n",
|
| 372 |
+
"The [MultiheadAttention](https://keras.io/api/layers/attention_layers/multi_head_attention/) layer implemented in Keras, uses this masking logic.\n",
|
| 373 |
+
"\n",
|
| 374 |
+
"**Note:** The below function only creates the mask of an _already padded sequence_. Later in this week, you’ll go through some Labs on Transformer applications, where you’ll be introduced to [TensorFlow Tokenizer](https://www.tensorflow.org/api_docs/python/tf/keras/preprocessing/text/Tokenizer) and [Hugging Face Tokenizer](https://huggingface.co/docs/tokenizers/api/tokenizer), which internally handle padding (and truncating) the input sequence."
|
| 375 |
+
]
|
| 376 |
+
},
|
| 377 |
+
{
|
| 378 |
+
"cell_type": "code",
|
| 379 |
+
"execution_count": null,
|
| 380 |
+
"metadata": {
|
| 381 |
+
"id": "JOL9XWsFQxxo"
|
| 382 |
+
},
|
| 383 |
+
"outputs": [],
|
| 384 |
+
"source": [
|
| 385 |
+
"def create_padding_mask(decoder_token_ids):\n",
|
| 386 |
+
" \"\"\"\n",
|
| 387 |
+
" Creates a matrix mask for the padding cells\n",
|
| 388 |
+
" \n",
|
| 389 |
+
" Arguments:\n",
|
| 390 |
+
" decoder_token_ids -- (n, m) matrix\n",
|
| 391 |
+
" \n",
|
| 392 |
+
" Returns:\n",
|
| 393 |
+
" mask -- (n, 1, m) binary tensor\n",
|
| 394 |
+
" \"\"\" \n",
|
| 395 |
+
" seq = 1 - tf.cast(tf.math.equal(decoder_token_ids, 0), tf.float32)\n",
|
| 396 |
+
" \n",
|
| 397 |
+
" # add extra dimensions to add the padding\n",
|
| 398 |
+
" # to the attention logits. \n",
|
| 399 |
+
" # this will allow for broadcasting later when comparing sequences\n",
|
| 400 |
+
" return seq[:, tf.newaxis, :] "
|
| 401 |
+
]
|
| 402 |
+
},
|
| 403 |
+
{
|
| 404 |
+
"cell_type": "code",
|
| 405 |
+
"execution_count": null,
|
| 406 |
+
"metadata": {
|
| 407 |
+
"colab": {
|
| 408 |
+
"base_uri": "https://localhost:8080/"
|
| 409 |
+
},
|
| 410 |
+
"id": "5J5FFjklQ1Fz",
|
| 411 |
+
"outputId": "8319446f-3ed4-406a-cf38-ca2b08142ff4"
|
| 412 |
+
},
|
| 413 |
+
"outputs": [],
|
| 414 |
+
"source": [
|
| 415 |
+
"x = tf.constant([[7., 6., 0., 0., 1.], [1., 2., 3., 0., 0.], [0., 0., 0., 4., 5.]])\n",
|
| 416 |
+
"print(create_padding_mask(x))"
|
| 417 |
+
]
|
| 418 |
+
},
|
| 419 |
+
{
|
| 420 |
+
"cell_type": "markdown",
|
| 421 |
+
"metadata": {},
|
| 422 |
+
"source": [
|
| 423 |
+
"If we multiply (1 - mask) by -1e9 and add it to the sample input sequences, the zeros are essentially set to negative infinity. Notice the difference when taking the softmax of the original sequence and the masked sequence:"
|
| 424 |
+
]
|
| 425 |
+
},
|
| 426 |
+
{
|
| 427 |
+
"cell_type": "code",
|
| 428 |
+
"execution_count": null,
|
| 429 |
+
"metadata": {},
|
| 430 |
+
"outputs": [],
|
| 431 |
+
"source": [
|
| 432 |
+
"print(tf.keras.activations.softmax(x))\n",
|
| 433 |
+
"print(tf.keras.activations.softmax(x + (1 - create_padding_mask(x)) * -1.0e9))"
|
| 434 |
+
]
|
| 435 |
+
},
|
| 436 |
+
{
|
| 437 |
+
"cell_type": "markdown",
|
| 438 |
+
"metadata": {},
|
| 439 |
+
"source": [
|
| 440 |
+
"<a name='2-2'></a>\n",
|
| 441 |
+
"### 2.2 - Look-ahead Mask\n",
|
| 442 |
+
"\n",
|
| 443 |
+
"The look-ahead mask follows similar intuition. In training, you will have access to the complete correct output of your training example. The look-ahead mask helps your model pretend that it correctly predicted a part of the output and see if, *without looking ahead*, it can correctly predict the next output. \n",
|
| 444 |
+
"\n",
|
| 445 |
+
"For example, if the expected correct output is `[1, 2, 3]` and you wanted to see if given that the model correctly predicted the first value it could predict the second value, you would mask out the second and third values. So you would input the masked sequence `[1, -1e9, -1e9]` and see if it could generate `[1, 2, -1e9]`.\n",
|
| 446 |
+
"\n",
|
| 447 |
+
"Just because you've worked so hard, we'll also implement this mask for you 😇😇. Again, take a close look at the code so you can effectively implement it later."
|
| 448 |
+
]
|
| 449 |
+
},
|
| 450 |
+
{
|
| 451 |
+
"cell_type": "code",
|
| 452 |
+
"execution_count": null,
|
| 453 |
+
"metadata": {
|
| 454 |
+
"id": "9O9UbM31Q3hK"
|
| 455 |
+
},
|
| 456 |
+
"outputs": [],
|
| 457 |
+
"source": [
|
| 458 |
+
"def create_look_ahead_mask(sequence_length):\n",
|
| 459 |
+
" \"\"\"\n",
|
| 460 |
+
" Returns a lower triangular matrix filled with ones\n",
|
| 461 |
+
" \n",
|
| 462 |
+
" Arguments:\n",
|
| 463 |
+
" sequence_length -- matrix size\n",
|
| 464 |
+
" \n",
|
| 465 |
+
" Returns:\n",
|
| 466 |
+
" mask -- (size, size) tensor\n",
|
| 467 |
+
" \"\"\"\n",
|
| 468 |
+
" mask = tf.linalg.band_part(tf.ones((1, sequence_length, sequence_length)), -1, 0)\n",
|
| 469 |
+
" return mask "
|
| 470 |
+
]
|
| 471 |
+
},
|
| 472 |
+
{
|
| 473 |
+
"cell_type": "code",
|
| 474 |
+
"execution_count": null,
|
| 475 |
+
"metadata": {
|
| 476 |
+
"colab": {
|
| 477 |
+
"base_uri": "https://localhost:8080/"
|
| 478 |
+
},
|
| 479 |
+
"id": "nfzHoVj9Q5nG",
|
| 480 |
+
"outputId": "300e76ec-77d0-460a-b6df-71e40de86606"
|
| 481 |
+
},
|
| 482 |
+
"outputs": [],
|
| 483 |
+
"source": [
|
| 484 |
+
"x = tf.random.uniform((1, 3))\n",
|
| 485 |
+
"temp = create_look_ahead_mask(x.shape[1])\n",
|
| 486 |
+
"temp"
|
| 487 |
+
]
|
| 488 |
+
},
|
| 489 |
+
{
|
| 490 |
+
"cell_type": "markdown",
|
| 491 |
+
"metadata": {
|
| 492 |
+
"id": "VG0gPyv0oDBi"
|
| 493 |
+
},
|
| 494 |
+
"source": [
|
| 495 |
+
"<a name='3'></a>\n",
|
| 496 |
+
"## 3 - Self-Attention\n",
|
| 497 |
+
"\n",
|
| 498 |
+
"As the authors of the Transformers paper state, \"Attention is All You Need\". \n",
|
| 499 |
+
"\n",
|
| 500 |
+
"<img src=\"self-attention.png\" alt=\"Encoder\" width=\"600\"/>\n",
|
| 501 |
+
"<caption><center><font color='purple'><b>Figure 1: Self-Attention calculation visualization</font></center></caption>\n",
|
| 502 |
+
" \n",
|
| 503 |
+
"The use of self-attention paired with traditional convolutional networks allows for parallelization which speeds up training. You will implement **scaled dot product attention** which takes in a query, key, value, and a mask as inputs to return rich, attention-based vector representations of the words in your sequence. This type of self-attention can be mathematically expressed as:\n",
|
| 504 |
+
"$$\n",
|
| 505 |
+
"\\text { Attention }(Q, K, V)=\\operatorname{softmax}\\left(\\frac{Q K^{T}}{\\sqrt{d_{k}}}+{M}\\right) V\\tag{4}\\\n",
|
| 506 |
+
"$$\n",
|
| 507 |
+
"\n",
|
| 508 |
+
"* $Q$ is the matrix of queries \n",
|
| 509 |
+
"* $K$ is the matrix of keys\n",
|
| 510 |
+
"* $V$ is the matrix of values\n",
|
| 511 |
+
"* $M$ is the optional mask you choose to apply \n",
|
| 512 |
+
"* ${d_k}$ is the dimension of the keys, which is used to scale everything down so the softmax doesn't explode\n",
|
| 513 |
+
"\n",
|
| 514 |
+
"<a name='ex-3'></a>\n",
|
| 515 |
+
"### Exercise 3 - scaled_dot_product_attention \n",
|
| 516 |
+
"\n",
|
| 517 |
+
"Implement the function `scaled_dot_product_attention()` to create attention-based representations.\n",
|
| 518 |
+
"\n",
|
| 519 |
+
"**Reminder**: The boolean mask parameter can be passed in as `none` or as either padding or look-ahead. \n",
|
| 520 |
+
" \n",
|
| 521 |
+
" Multiply (1. - mask) by -1e9 before applying the softmax. \n",
|
| 522 |
+
"\n",
|
| 523 |
+
"**Additional Hints**\n",
|
| 524 |
+
"* You may find [tf.matmul](https://www.tensorflow.org/api_docs/python/tf/linalg/matmul) useful for matrix multiplication."
|
| 525 |
+
]
|
| 526 |
+
},
|
| 527 |
+
{
|
| 528 |
+
"cell_type": "code",
|
| 529 |
+
"execution_count": null,
|
| 530 |
+
"metadata": {
|
| 531 |
+
"id": "CSysk_rjQ7lp"
|
| 532 |
+
},
|
| 533 |
+
"outputs": [],
|
| 534 |
+
"source": [
|
| 535 |
+
"# UNQ_C3 (UNIQUE CELL IDENTIFIER, DO NOT EDIT)\n",
|
| 536 |
+
"# GRADED FUNCTION scaled_dot_product_attention\n",
|
| 537 |
+
"def scaled_dot_product_attention(q, k, v, mask):\n",
|
| 538 |
+
" \"\"\"\n",
|
| 539 |
+
" Calculate the attention weights.\n",
|
| 540 |
+
" q, k, v must have matching leading dimensions.\n",
|
| 541 |
+
" k, v must have matching penultimate dimension, i.e.: seq_len_k = seq_len_v.\n",
|
| 542 |
+
" The mask has different shapes depending on its type(padding or look ahead) \n",
|
| 543 |
+
" but it must be broadcastable for addition.\n",
|
| 544 |
+
"\n",
|
| 545 |
+
" Arguments:\n",
|
| 546 |
+
" q -- query shape == (..., seq_len_q, depth)\n",
|
| 547 |
+
" k -- key shape == (..., seq_len_k, depth)\n",
|
| 548 |
+
" v -- value shape == (..., seq_len_v, depth_v)\n",
|
| 549 |
+
" mask: Float tensor with shape broadcastable \n",
|
| 550 |
+
" to (..., seq_len_q, seq_len_k). Defaults to None.\n",
|
| 551 |
+
"\n",
|
| 552 |
+
" Returns:\n",
|
| 553 |
+
" output -- attention_weights\n",
|
| 554 |
+
" \"\"\"\n",
|
| 555 |
+
" # START CODE HERE\n",
|
| 556 |
+
" \n",
|
| 557 |
+
" matmul_qk = None # (..., seq_len_q, seq_len_k)\n",
|
| 558 |
+
"\n",
|
| 559 |
+
" # scale matmul_qk\n",
|
| 560 |
+
" dk = None\n",
|
| 561 |
+
" scaled_attention_logits = None\n",
|
| 562 |
+
"\n",
|
| 563 |
+
" # add the mask to the scaled tensor.\n",
|
| 564 |
+
" if mask is not None: # Don't replace this None\n",
|
| 565 |
+
" scaled_attention_logits += None \n",
|
| 566 |
+
"\n",
|
| 567 |
+
" # softmax is normalized on the last axis (seq_len_k) so that the scores\n",
|
| 568 |
+
" # add up to 1.\n",
|
| 569 |
+
" attention_weights = None # (..., seq_len_q, seq_len_k)\n",
|
| 570 |
+
"\n",
|
| 571 |
+
" output = None # (..., seq_len_q, depth_v)\n",
|
| 572 |
+
" \n",
|
| 573 |
+
" # END CODE HERE\n",
|
| 574 |
+
"\n",
|
| 575 |
+
" return output, attention_weights"
|
| 576 |
+
]
|
| 577 |
+
},
|
| 578 |
+
{
|
| 579 |
+
"cell_type": "code",
|
| 580 |
+
"execution_count": null,
|
| 581 |
+
"metadata": {},
|
| 582 |
+
"outputs": [],
|
| 583 |
+
"source": [
|
| 584 |
+
"# UNIT TEST\n",
|
| 585 |
+
"scaled_dot_product_attention_test(scaled_dot_product_attention)"
|
| 586 |
+
]
|
| 587 |
+
},
|
| 588 |
+
{
|
| 589 |
+
"cell_type": "markdown",
|
| 590 |
+
"metadata": {},
|
| 591 |
+
"source": [
|
| 592 |
+
"Excellent work! You can now implement self-attention. With that, you can start building the encoder block! "
|
| 593 |
+
]
|
| 594 |
+
},
|
| 595 |
+
{
|
| 596 |
+
"cell_type": "markdown",
|
| 597 |
+
"metadata": {
|
| 598 |
+
"id": "blS0pEpTqRVI"
|
| 599 |
+
},
|
| 600 |
+
"source": [
|
| 601 |
+
"<a name='4'></a>\n",
|
| 602 |
+
"## 4 - Encoder\n",
|
| 603 |
+
"\n",
|
| 604 |
+
"The Transformer Encoder layer pairs self-attention and convolutional neural network style of processing to improve the speed of training and passes K and V matrices to the Decoder, which you'll build later in the assignment. In this section of the assignment, you will implement the Encoder by pairing multi-head attention and a feed forward neural network (Figure 2a). \n",
|
| 605 |
+
"<img src=\"encoder_layer.png\" alt=\"Encoder\" width=\"400\"/>\n",
|
| 606 |
+
"<caption><center><font color='purple'><b>Figure 2a: Transformer encoder layer</font></center></caption>\n",
|
| 607 |
+
"\n",
|
| 608 |
+
"* `MultiHeadAttention` you can think of as computing the self-attention several times to detect different features. \n",
|
| 609 |
+
"* Feed forward neural network contains two Dense layers which we'll implement as the function `FullyConnected`\n",
|
| 610 |
+
"\n",
|
| 611 |
+
"Your input sentence first passes through a *multi-head attention layer*, where the encoder looks at other words in the input sentence as it encodes a specific word. The outputs of the multi-head attention layer are then fed to a *feed forward neural network*. The exact same feed forward network is independently applied to each position.\n",
|
| 612 |
+
" \n",
|
| 613 |
+
"* For the `MultiHeadAttention` layer, you will use the [Keras implementation](https://www.tensorflow.org/api_docs/python/tf/keras/layers/MultiHeadAttention). If you're curious about how to split the query matrix Q, key matrix K, and value matrix V into different heads, you can look through the implementation. \n",
|
| 614 |
+
"* You will also use the [Sequential API](https://keras.io/api/models/sequential/) with two dense layers to built the feed forward neural network layers.\n",
|
| 615 |
+
" \n",
|
| 616 |
+
"**Note:** In Python, the `__call__` method allows you to call an object like a function. TensorFlow leverages this by providing a `call` function within Keras layers. This means you can use a layer like `a_Layer(arg)` and TensorFlow will internally execute `a_Layer.call(arg)` to process your data. This design makes it intuitive to apply layers within your TensorFlow models. "
|
| 617 |
+
]
|
| 618 |
+
},
|
| 619 |
+
{
|
| 620 |
+
"cell_type": "code",
|
| 621 |
+
"execution_count": null,
|
| 622 |
+
"metadata": {
|
| 623 |
+
"id": "sC5vJhz29vZR"
|
| 624 |
+
},
|
| 625 |
+
"outputs": [],
|
| 626 |
+
"source": [
|
| 627 |
+
"def FullyConnected(embedding_dim, fully_connected_dim):\n",
|
| 628 |
+
" return tf.keras.Sequential([\n",
|
| 629 |
+
" tf.keras.layers.Dense(fully_connected_dim, activation='relu'), # (batch_size, seq_len, dff)\n",
|
| 630 |
+
" tf.keras.layers.Dense(embedding_dim) # (batch_size, seq_len, embedding_dim)\n",
|
| 631 |
+
" ])"
|
| 632 |
+
]
|
| 633 |
+
},
|
| 634 |
+
{
|
| 635 |
+
"cell_type": "markdown",
|
| 636 |
+
"metadata": {
|
| 637 |
+
"id": "R65WbX5wqYYH"
|
| 638 |
+
},
|
| 639 |
+
"source": [
|
| 640 |
+
"<a name='4-1'></a>\n",
|
| 641 |
+
"### 4.1 Encoder Layer\n",
|
| 642 |
+
"\n",
|
| 643 |
+
"Now you can pair multi-head attention and feed forward neural network together in an encoder layer! You will also use residual connections and layer normalization to help speed up training (Figure 2a).\n",
|
| 644 |
+
"\n",
|
| 645 |
+
"<a name='ex-4'></a>\n",
|
| 646 |
+
"### Exercise 4 - EncoderLayer\n",
|
| 647 |
+
"\n",
|
| 648 |
+
"Implement `EncoderLayer()` using the `call()` method\n",
|
| 649 |
+
"\n",
|
| 650 |
+
"In this exercise, you will implement one encoder block (Figure 2) using the `call()` method. The function should perform the following steps: \n",
|
| 651 |
+
"1. You will pass the Q, V, K matrices and a boolean mask to a multi-head attention layer. Remember that to compute *self*-attention Q, V and K should be the same. Set the default values for `return_attention_scores` and `training`. You will also perform Dropout in this multi-head attention layer during training. \n",
|
| 652 |
+
"2. Now add a skip connection by adding your original input `x` and the output of the your multi-head attention layer. \n",
|
| 653 |
+
"3. After adding the skip connection, pass the output through the first normalization layer.\n",
|
| 654 |
+
"4. Finally, repeat steps 1-3 but with the feed forward neural network with a dropout layer instead of the multi-head attention layer. \n",
|
| 655 |
+
"\n",
|
| 656 |
+
"<details>\n",
|
| 657 |
+
" <summary><font size=\"2\" color=\"darkgreen\"><b>Additional Hints (Click to expand)</b></font></summary>\n",
|
| 658 |
+
" \n",
|
| 659 |
+
"* The `__init__` method creates all the layers that will be accesed by the the `call` method. Wherever you want to use a layer defined inside the `__init__` method you will have to use the syntax `self.[insert layer name]`. \n",
|
| 660 |
+
"* You will find the documentation of [MultiHeadAttention](https://www.tensorflow.org/api_docs/python/tf/keras/layers/MultiHeadAttention) helpful. *Note that if query, key and value are the same, then this function performs self-attention.*\n",
|
| 661 |
+
"* The call arguments for `self.mha` are (Where B is for batch_size, T is for target sequence shapes, and S is output_shape):\n",
|
| 662 |
+
" - `query`: Query Tensor of shape (B, T, dim).\n",
|
| 663 |
+
" - `value`: Value Tensor of shape (B, S, dim).\n",
|
| 664 |
+
" - `key`: Optional key Tensor of shape (B, S, dim). If not given, will use value for both key and value, which is the most common case.\n",
|
| 665 |
+
" - `attention_mask`: a boolean mask of shape (B, T, S), that prevents attention to certain positions. The boolean mask specifies which query elements can attend to which key elements, 1 indicates attention and 0 indicates no attention. Broadcasting can happen for the missing batch dimensions and the head dimension.\n",
|
| 666 |
+
" - `return_attention_scores`: A boolean to indicate whether the output should be (attention_output, attention_scores) if True, or attention_output if False. Defaults to False.\n",
|
| 667 |
+
" - `training`: Python boolean indicating whether the layer should behave in training mode (adding dropout) or in inference mode (no dropout). Defaults to either using the training mode of the parent layer/model, or False (inference) if there is no parent layer. Take a look at [tf.keras.layers.Dropout](https://www.tensorflow.org/versions/r2.4/api_docs/python/tf/keras/layers/Dropout) for more details (Additional reading in [Keras FAQ](https://keras.io/getting_started/faq/#whats-the-difference-between-the-training-argument-in-call-and-the-trainable-attribute))"
|
| 668 |
+
]
|
| 669 |
+
},
|
| 670 |
+
{
|
| 671 |
+
"cell_type": "code",
|
| 672 |
+
"execution_count": null,
|
| 673 |
+
"metadata": {
|
| 674 |
+
"id": "tIufbrc-9_2u"
|
| 675 |
+
},
|
| 676 |
+
"outputs": [],
|
| 677 |
+
"source": [
|
| 678 |
+
"# UNQ_C4 (UNIQUE CELL IDENTIFIER, DO NOT EDIT)\n",
|
| 679 |
+
"# GRADED FUNCTION EncoderLayer\n",
|
| 680 |
+
"class EncoderLayer(tf.keras.layers.Layer):\n",
|
| 681 |
+
" \"\"\"\n",
|
| 682 |
+
" The encoder layer is composed by a multi-head self-attention mechanism,\n",
|
| 683 |
+
" followed by a simple, positionwise fully connected feed-forward network. \n",
|
| 684 |
+
" This architecture includes a residual connection around each of the two \n",
|
| 685 |
+
" sub-layers, followed by layer normalization.\n",
|
| 686 |
+
" \"\"\"\n",
|
| 687 |
+
" def __init__(self, embedding_dim, num_heads, fully_connected_dim,\n",
|
| 688 |
+
" dropout_rate=0.1, layernorm_eps=1e-6):\n",
|
| 689 |
+
" super(EncoderLayer, self).__init__()\n",
|
| 690 |
+
"\n",
|
| 691 |
+
" self.mha = MultiHeadAttention(num_heads=num_heads,\n",
|
| 692 |
+
" key_dim=embedding_dim,\n",
|
| 693 |
+
" dropout=dropout_rate)\n",
|
| 694 |
+
"\n",
|
| 695 |
+
" self.ffn = FullyConnected(embedding_dim=embedding_dim,\n",
|
| 696 |
+
" fully_connected_dim=fully_connected_dim)\n",
|
| 697 |
+
"\n",
|
| 698 |
+
" self.layernorm1 = LayerNormalization(epsilon=layernorm_eps)\n",
|
| 699 |
+
" self.layernorm2 = LayerNormalization(epsilon=layernorm_eps)\n",
|
| 700 |
+
"\n",
|
| 701 |
+
" self.dropout_ffn = Dropout(dropout_rate)\n",
|
| 702 |
+
" \n",
|
| 703 |
+
" def call(self, x, training, mask):\n",
|
| 704 |
+
" \"\"\"\n",
|
| 705 |
+
" Forward pass for the Encoder Layer\n",
|
| 706 |
+
" \n",
|
| 707 |
+
" Arguments:\n",
|
| 708 |
+
" x -- Tensor of shape (batch_size, input_seq_len, embedding_dim)\n",
|
| 709 |
+
" training -- Boolean, set to true to activate\n",
|
| 710 |
+
" the training mode for dropout layers\n",
|
| 711 |
+
" mask -- Boolean mask to ensure that the padding is not \n",
|
| 712 |
+
" treated as part of the input\n",
|
| 713 |
+
" Returns:\n",
|
| 714 |
+
" encoder_layer_out -- Tensor of shape (batch_size, input_seq_len, embedding_dim)\n",
|
| 715 |
+
" \"\"\"\n",
|
| 716 |
+
" # START CODE HERE\n",
|
| 717 |
+
" # calculate self-attention using mha(~1 line).\n",
|
| 718 |
+
" # Dropout is added by Keras automatically if the dropout parameter is non-zero during training\n",
|
| 719 |
+
" self_mha_output = None # Self attention (batch_size, input_seq_len, embedding_dim)\n",
|
| 720 |
+
" \n",
|
| 721 |
+
" # skip connection\n",
|
| 722 |
+
" # apply layer normalization on sum of the input and the attention output to get the \n",
|
| 723 |
+
" # output of the multi-head attention layer (~1 line)\n",
|
| 724 |
+
" skip_x_attention = None # (batch_size, input_seq_len, embedding_dim)\n",
|
| 725 |
+
"\n",
|
| 726 |
+
" # pass the output of the multi-head attention layer through a ffn (~1 line)\n",
|
| 727 |
+
" ffn_output = None # (batch_size, input_seq_len, embedding_dim)\n",
|
| 728 |
+
" \n",
|
| 729 |
+
" # apply dropout layer to ffn output during training (~1 line)\n",
|
| 730 |
+
" # use `training=training` \n",
|
| 731 |
+
" ffn_output = None\n",
|
| 732 |
+
" \n",
|
| 733 |
+
" # apply layer normalization on sum of the output from multi-head attention (skip connection) and ffn output to get the\n",
|
| 734 |
+
" # output of the encoder layer (~1 line)\n",
|
| 735 |
+
" encoder_layer_out = None # (batch_size, input_seq_len, embedding_dim)\n",
|
| 736 |
+
" # END CODE HERE\n",
|
| 737 |
+
" \n",
|
| 738 |
+
" return encoder_layer_out\n",
|
| 739 |
+
" "
|
| 740 |
+
]
|
| 741 |
+
},
|
| 742 |
+
{
|
| 743 |
+
"cell_type": "code",
|
| 744 |
+
"execution_count": null,
|
| 745 |
+
"metadata": {},
|
| 746 |
+
"outputs": [],
|
| 747 |
+
"source": [
|
| 748 |
+
"# UNIT TEST\n",
|
| 749 |
+
"EncoderLayer_test(EncoderLayer)"
|
| 750 |
+
]
|
| 751 |
+
},
|
| 752 |
+
{
|
| 753 |
+
"cell_type": "markdown",
|
| 754 |
+
"metadata": {},
|
| 755 |
+
"source": [
|
| 756 |
+
"<a name='4-2'></a>\n",
|
| 757 |
+
"### 4.2 - Full Encoder\n",
|
| 758 |
+
"\n",
|
| 759 |
+
"Awesome job! You have now successfully implemented positional encoding, self-attention, and an encoder layer - give yourself a pat on the back. Now you're ready to build the full Transformer Encoder (Figure 2b), where you will embed your input and add the positional encodings you calculated. You will then feed your encoded embeddings to a stack of Encoder layers. \n",
|
| 760 |
+
"\n",
|
| 761 |
+
"<img src=\"encoder.png\" alt=\"Encoder\" width=\"330\"/>\n",
|
| 762 |
+
"<caption><center><font color='purple'><b>Figure 2b: Transformer Encoder</font></center></caption>\n",
|
| 763 |
+
"\n",
|
| 764 |
+
"\n",
|
| 765 |
+
"<a name='ex-5'></a>\n",
|
| 766 |
+
"### Exercise 5 - Encoder\n",
|
| 767 |
+
"\n",
|
| 768 |
+
"Complete the `Encoder()` function using the `call()` method to embed your input, add positional encoding, and implement multiple encoder layers. \n",
|
| 769 |
+
"\n",
|
| 770 |
+
"In this exercise, you will initialize your Encoder with an Embedding layer, positional encoding, and multiple EncoderLayers. Your `call()` method will perform the following steps: \n",
|
| 771 |
+
"1. Pass your input through the Embedding layer.\n",
|
| 772 |
+
"2. Scale your embedding by multiplying it by the square root of your embedding dimension. Remember to cast the embedding dimension to data type `tf.float32` before computing the square root.\n",
|
| 773 |
+
"3. Add the position encoding: self.pos_encoding `[:, :seq_len, :]` to your embedding.\n",
|
| 774 |
+
"4. Pass the encoded embedding through a dropout layer, remembering to use the `training` parameter to set the model training mode. \n",
|
| 775 |
+
"5. Pass the output of the dropout layer through the stack of encoding layers using a for loop."
|
| 776 |
+
]
|
| 777 |
+
},
|
| 778 |
+
{
|
| 779 |
+
"cell_type": "code",
|
| 780 |
+
"execution_count": null,
|
| 781 |
+
"metadata": {
|
| 782 |
+
"id": "7j2Tjr0K0t0I"
|
| 783 |
+
},
|
| 784 |
+
"outputs": [],
|
| 785 |
+
"source": [
|
| 786 |
+
" # UNQ_C5 (UNIQUE CELL IDENTIFIER, DO NOT EDIT)\n",
|
| 787 |
+
"# GRADED FUNCTION\n",
|
| 788 |
+
"class Encoder(tf.keras.layers.Layer):\n",
|
| 789 |
+
" \"\"\"\n",
|
| 790 |
+
" The entire Encoder starts by passing the input to an embedding layer \n",
|
| 791 |
+
" and using positional encoding to then pass the output through a stack of\n",
|
| 792 |
+
" encoder Layers\n",
|
| 793 |
+
" \n",
|
| 794 |
+
" \"\"\" \n",
|
| 795 |
+
" def __init__(self, num_layers, embedding_dim, num_heads, fully_connected_dim, input_vocab_size,\n",
|
| 796 |
+
" maximum_position_encoding, dropout_rate=0.1, layernorm_eps=1e-6):\n",
|
| 797 |
+
" super(Encoder, self).__init__()\n",
|
| 798 |
+
"\n",
|
| 799 |
+
" self.embedding_dim = embedding_dim\n",
|
| 800 |
+
" self.num_layers = num_layers\n",
|
| 801 |
+
"\n",
|
| 802 |
+
" self.embedding = Embedding(input_vocab_size, self.embedding_dim)\n",
|
| 803 |
+
" self.pos_encoding = positional_encoding(maximum_position_encoding, \n",
|
| 804 |
+
" self.embedding_dim)\n",
|
| 805 |
+
"\n",
|
| 806 |
+
"\n",
|
| 807 |
+
" self.enc_layers = [EncoderLayer(embedding_dim=self.embedding_dim,\n",
|
| 808 |
+
" num_heads=num_heads,\n",
|
| 809 |
+
" fully_connected_dim=fully_connected_dim,\n",
|
| 810 |
+
" dropout_rate=dropout_rate,\n",
|
| 811 |
+
" layernorm_eps=layernorm_eps) \n",
|
| 812 |
+
" for _ in range(self.num_layers)]\n",
|
| 813 |
+
"\n",
|
| 814 |
+
" self.dropout = Dropout(dropout_rate)\n",
|
| 815 |
+
" \n",
|
| 816 |
+
" def call(self, x, training, mask):\n",
|
| 817 |
+
" \"\"\"\n",
|
| 818 |
+
" Forward pass for the Encoder\n",
|
| 819 |
+
" \n",
|
| 820 |
+
" Arguments:\n",
|
| 821 |
+
" x -- Tensor of shape (batch_size, input_seq_len)\n",
|
| 822 |
+
" training -- Boolean, set to true to activate\n",
|
| 823 |
+
" the training mode for dropout layers\n",
|
| 824 |
+
" mask -- Boolean mask to ensure that the padding is not \n",
|
| 825 |
+
" treated as part of the input\n",
|
| 826 |
+
" Returns:\n",
|
| 827 |
+
" x -- Tensor of shape (batch_size, input_seq_len, embedding_dim)\n",
|
| 828 |
+
" \"\"\"\n",
|
| 829 |
+
" seq_len = tf.shape(x)[1]\n",
|
| 830 |
+
" \n",
|
| 831 |
+
" # START CODE HERE\n",
|
| 832 |
+
" # Pass input through the Embedding layer\n",
|
| 833 |
+
" x = None # (batch_size, input_seq_len, embedding_dim)\n",
|
| 834 |
+
" # Scale embedding by multiplying it by the square root of the embedding dimension\n",
|
| 835 |
+
" x *= None\n",
|
| 836 |
+
" # Add the position encoding to embedding\n",
|
| 837 |
+
" x += None\n",
|
| 838 |
+
" # Pass the encoded embedding through a dropout layer\n",
|
| 839 |
+
" # use `training=training`\n",
|
| 840 |
+
" x = None\n",
|
| 841 |
+
" # Pass the output through the stack of encoding layers \n",
|
| 842 |
+
" for i in range(self.num_layers):\n",
|
| 843 |
+
" x = None\n",
|
| 844 |
+
" # END CODE HERE\n",
|
| 845 |
+
"\n",
|
| 846 |
+
" return x # (batch_size, input_seq_len, embedding_dim)"
|
| 847 |
+
]
|
| 848 |
+
},
|
| 849 |
+
{
|
| 850 |
+
"cell_type": "code",
|
| 851 |
+
"execution_count": null,
|
| 852 |
+
"metadata": {},
|
| 853 |
+
"outputs": [],
|
| 854 |
+
"source": [
|
| 855 |
+
"# UNIT TEST \n",
|
| 856 |
+
"Encoder_test(Encoder)"
|
| 857 |
+
]
|
| 858 |
+
},
|
| 859 |
+
{
|
| 860 |
+
"cell_type": "markdown",
|
| 861 |
+
"metadata": {},
|
| 862 |
+
"source": [
|
| 863 |
+
"<a name='5'></a>\n",
|
| 864 |
+
"## 5 - Decoder\n",
|
| 865 |
+
"\n",
|
| 866 |
+
"The Decoder layer takes the K and V matrices generated by the Encoder and computes the second multi-head attention layer with the Q matrix from the output (Figure 3a).\n",
|
| 867 |
+
"\n",
|
| 868 |
+
"<img src=\"decoder_layer.png\" alt=\"Encoder\" width=\"250\"/>\n",
|
| 869 |
+
"<caption><center><font color='purple'><b>Figure 3a: Transformer Decoder layer</font></center></caption>\n",
|
| 870 |
+
"\n",
|
| 871 |
+
"<a name='5-1'></a> \n",
|
| 872 |
+
"### 5.1 - Decoder Layer\n",
|
| 873 |
+
"Again, you'll pair multi-head attention with a feed forward neural network, but this time you'll implement two multi-head attention layers. You will also use residual connections and layer normalization to help speed up training (Figure 3a).\n",
|
| 874 |
+
"\n",
|
| 875 |
+
"<a name='ex-6'></a> \n",
|
| 876 |
+
"### Exercise 6 - DecoderLayer\n",
|
| 877 |
+
" \n",
|
| 878 |
+
"Implement `DecoderLayer()` using the `call()` method\n",
|
| 879 |
+
" \n",
|
| 880 |
+
"1. Block 1 is a multi-head attention layer with a residual connection, and look-ahead mask. Like in the `EncoderLayer`, Dropout is defined within the multi-head attention layer.\n",
|
| 881 |
+
"2. Block 2 will take into account the output of the Encoder, so the multi-head attention layer will receive K and V from the encoder, and Q from the Block 1. You will then apply a normalization layer and a residual connection, just like you did before with the `EncoderLayer`.\n",
|
| 882 |
+
"3. Finally, Block 3 is a feed forward neural network with dropout and normalization layers and a residual connection.\n",
|
| 883 |
+
" \n",
|
| 884 |
+
"**Additional Hints:**\n",
|
| 885 |
+
"* The first two blocks are fairly similar to the EncoderLayer except you will return `attention_scores` when computing self-attention"
|
| 886 |
+
]
|
| 887 |
+
},
|
| 888 |
+
{
|
| 889 |
+
"cell_type": "code",
|
| 890 |
+
"execution_count": null,
|
| 891 |
+
"metadata": {
|
| 892 |
+
"id": "wEouNFvCzMeT"
|
| 893 |
+
},
|
| 894 |
+
"outputs": [],
|
| 895 |
+
"source": [
|
| 896 |
+
"# UNQ_C6 (UNIQUE CELL IDENTIFIER, DO NOT EDIT)\n",
|
| 897 |
+
"# GRADED FUNCTION DecoderLayer\n",
|
| 898 |
+
"class DecoderLayer(tf.keras.layers.Layer):\n",
|
| 899 |
+
" \"\"\"\n",
|
| 900 |
+
" The decoder layer is composed by two multi-head attention blocks, \n",
|
| 901 |
+
" one that takes the new input and uses self-attention, and the other \n",
|
| 902 |
+
" one that combines it with the output of the encoder, followed by a\n",
|
| 903 |
+
" fully connected block. \n",
|
| 904 |
+
" \"\"\"\n",
|
| 905 |
+
" def __init__(self, embedding_dim, num_heads, fully_connected_dim, dropout_rate=0.1, layernorm_eps=1e-6):\n",
|
| 906 |
+
" super(DecoderLayer, self).__init__()\n",
|
| 907 |
+
"\n",
|
| 908 |
+
" self.mha1 = MultiHeadAttention(num_heads=num_heads,\n",
|
| 909 |
+
" key_dim=embedding_dim,\n",
|
| 910 |
+
" dropout=dropout_rate)\n",
|
| 911 |
+
"\n",
|
| 912 |
+
" self.mha2 = MultiHeadAttention(num_heads=num_heads,\n",
|
| 913 |
+
" key_dim=embedding_dim,\n",
|
| 914 |
+
" dropout=dropout_rate)\n",
|
| 915 |
+
"\n",
|
| 916 |
+
" self.ffn = FullyConnected(embedding_dim=embedding_dim,\n",
|
| 917 |
+
" fully_connected_dim=fully_connected_dim)\n",
|
| 918 |
+
"\n",
|
| 919 |
+
" self.layernorm1 = LayerNormalization(epsilon=layernorm_eps)\n",
|
| 920 |
+
" self.layernorm2 = LayerNormalization(epsilon=layernorm_eps)\n",
|
| 921 |
+
" self.layernorm3 = LayerNormalization(epsilon=layernorm_eps)\n",
|
| 922 |
+
"\n",
|
| 923 |
+
" self.dropout_ffn = Dropout(dropout_rate)\n",
|
| 924 |
+
" \n",
|
| 925 |
+
" def call(self, x, enc_output, training, look_ahead_mask, padding_mask):\n",
|
| 926 |
+
" \"\"\"\n",
|
| 927 |
+
" Forward pass for the Decoder Layer\n",
|
| 928 |
+
" \n",
|
| 929 |
+
" Arguments:\n",
|
| 930 |
+
" x -- Tensor of shape (batch_size, target_seq_len, embedding_dim)\n",
|
| 931 |
+
" enc_output -- Tensor of shape(batch_size, input_seq_len, embedding_dim)\n",
|
| 932 |
+
" training -- Boolean, set to true to activate\n",
|
| 933 |
+
" the training mode for dropout layers\n",
|
| 934 |
+
" look_ahead_mask -- Boolean mask for the target_input\n",
|
| 935 |
+
" padding_mask -- Boolean mask for the second multihead attention layer\n",
|
| 936 |
+
" Returns:\n",
|
| 937 |
+
" out3 -- Tensor of shape (batch_size, target_seq_len, embedding_dim)\n",
|
| 938 |
+
" attn_weights_block1 -- Tensor of shape(batch_size, num_heads, target_seq_len, input_seq_len)\n",
|
| 939 |
+
" attn_weights_block2 -- Tensor of shape(batch_size, num_heads, target_seq_len, input_seq_len)\n",
|
| 940 |
+
" \"\"\"\n",
|
| 941 |
+
" \n",
|
| 942 |
+
" # START CODE HERE\n",
|
| 943 |
+
" # enc_output.shape == (batch_size, input_seq_len, embedding_dim)\n",
|
| 944 |
+
" \n",
|
| 945 |
+
" # BLOCK 1\n",
|
| 946 |
+
" # calculate self-attention and return attention scores as attn_weights_block1.\n",
|
| 947 |
+
" # Dropout will be applied during training (~1 line).\n",
|
| 948 |
+
" mult_attn_out1, attn_weights_block1 = self.mha1(None, None, None, None, return_attention_scores=True) # (batch_size, target_seq_len, embedding_dim)\n",
|
| 949 |
+
" \n",
|
| 950 |
+
" # apply layer normalization (layernorm1) to the sum of the attention output and the input (~1 line)\n",
|
| 951 |
+
" Q1 = None\n",
|
| 952 |
+
"\n",
|
| 953 |
+
" # BLOCK 2\n",
|
| 954 |
+
" # calculate self-attention using the Q from the first block and K and V from the encoder output. \n",
|
| 955 |
+
" # Dropout will be applied during training\n",
|
| 956 |
+
" # Return attention scores as attn_weights_block2 (~1 line) \n",
|
| 957 |
+
" mult_attn_out2, attn_weights_block2 = self.mha2(None, None, None, None, return_attention_scores=True) # (batch_size, target_seq_len, embedding_dim)\n",
|
| 958 |
+
" \n",
|
| 959 |
+
" # apply layer normalization (layernorm2) to the sum of the attention output and the output of the first block (~1 line)\n",
|
| 960 |
+
" mult_attn_out2 = None # (batch_size, target_seq_len, embedding_dim)\n",
|
| 961 |
+
" \n",
|
| 962 |
+
" #BLOCK 3\n",
|
| 963 |
+
" # pass the output of the second block through a ffn\n",
|
| 964 |
+
" ffn_output = None # (batch_size, target_seq_len, embedding_dim)\n",
|
| 965 |
+
" \n",
|
| 966 |
+
" # apply a dropout layer to the ffn output\n",
|
| 967 |
+
" # use `training=training`\n",
|
| 968 |
+
" ffn_output = None\n",
|
| 969 |
+
" \n",
|
| 970 |
+
" # apply layer normalization (layernorm3) to the sum of the ffn output and the output of the second block\n",
|
| 971 |
+
" out3 = None # (batch_size, target_seq_len, embedding_dim)\n",
|
| 972 |
+
" # END CODE HERE\n",
|
| 973 |
+
"\n",
|
| 974 |
+
" return out3, attn_weights_block1, attn_weights_block2\n",
|
| 975 |
+
" "
|
| 976 |
+
]
|
| 977 |
+
},
|
| 978 |
+
{
|
| 979 |
+
"cell_type": "code",
|
| 980 |
+
"execution_count": null,
|
| 981 |
+
"metadata": {},
|
| 982 |
+
"outputs": [],
|
| 983 |
+
"source": [
|
| 984 |
+
"# UNIT TEST\n",
|
| 985 |
+
"DecoderLayer_test(DecoderLayer, create_look_ahead_mask)"
|
| 986 |
+
]
|
| 987 |
+
},
|
| 988 |
+
{
|
| 989 |
+
"cell_type": "markdown",
|
| 990 |
+
"metadata": {},
|
| 991 |
+
"source": [
|
| 992 |
+
"<a name='5-2'></a> \n",
|
| 993 |
+
"### 5.2 - Full Decoder\n",
|
| 994 |
+
"You're almost there! Time to use your Decoder layer to build a full Transformer Decoder (Figure 3b). You will embed your output and add positional encodings. You will then feed your encoded embeddings to a stack of Decoder layers. \n",
|
| 995 |
+
"\n",
|
| 996 |
+
"\n",
|
| 997 |
+
"<img src=\"decoder.png\" alt=\"Encoder\" width=\"300\"/>\n",
|
| 998 |
+
"<caption><center><font color='purple'><b>Figure 3b: Transformer Decoder</font></center></caption>\n",
|
| 999 |
+
"\n",
|
| 1000 |
+
"<a name='ex-7'></a> \n",
|
| 1001 |
+
"### Exercise 7 - Decoder\n",
|
| 1002 |
+
"\n",
|
| 1003 |
+
"Implement `Decoder()` using the `call()` method to embed your output, add positional encoding, and implement multiple decoder layers.\n",
|
| 1004 |
+
" \n",
|
| 1005 |
+
"In this exercise, you will initialize your Decoder with an Embedding layer, positional encoding, and multiple DecoderLayers. Your `call()` method will perform the following steps: \n",
|
| 1006 |
+
"1. Pass your generated output through the Embedding layer.\n",
|
| 1007 |
+
"2. Scale your embedding by multiplying it by the square root of your embedding dimension. Remember to cast the embedding dimension to data type `tf.float32` before computing the square root.\n",
|
| 1008 |
+
"3. Add the position encoding: self.pos_encoding `[:, :seq_len, :]` to your embedding.\n",
|
| 1009 |
+
"4. Pass the encoded embedding through a dropout layer, remembering to use the `training` parameter to set the model training mode. \n",
|
| 1010 |
+
"5. Pass the output of the dropout layer through the stack of Decoding layers using a for loop."
|
| 1011 |
+
]
|
| 1012 |
+
},
|
| 1013 |
+
{
|
| 1014 |
+
"cell_type": "code",
|
| 1015 |
+
"execution_count": null,
|
| 1016 |
+
"metadata": {
|
| 1017 |
+
"id": "McS3by6k4pnP"
|
| 1018 |
+
},
|
| 1019 |
+
"outputs": [],
|
| 1020 |
+
"source": [
|
| 1021 |
+
"# UNQ_C7 (UNIQUE CELL IDENTIFIER, DO NOT EDIT)\n",
|
| 1022 |
+
"# GRADED FUNCTION Decoder\n",
|
| 1023 |
+
"class Decoder(tf.keras.layers.Layer):\n",
|
| 1024 |
+
" \"\"\"\n",
|
| 1025 |
+
" The entire Encoder starts by passing the target input to an embedding layer \n",
|
| 1026 |
+
" and using positional encoding to then pass the output through a stack of\n",
|
| 1027 |
+
" decoder Layers\n",
|
| 1028 |
+
" \n",
|
| 1029 |
+
" \"\"\" \n",
|
| 1030 |
+
" def __init__(self, num_layers, embedding_dim, num_heads, fully_connected_dim, target_vocab_size,\n",
|
| 1031 |
+
" maximum_position_encoding, dropout_rate=0.1, layernorm_eps=1e-6):\n",
|
| 1032 |
+
" super(Decoder, self).__init__()\n",
|
| 1033 |
+
"\n",
|
| 1034 |
+
" self.embedding_dim = embedding_dim\n",
|
| 1035 |
+
" self.num_layers = num_layers\n",
|
| 1036 |
+
"\n",
|
| 1037 |
+
" self.embedding = Embedding(target_vocab_size, self.embedding_dim)\n",
|
| 1038 |
+
" self.pos_encoding = positional_encoding(maximum_position_encoding, self.embedding_dim)\n",
|
| 1039 |
+
"\n",
|
| 1040 |
+
" self.dec_layers = [DecoderLayer(embedding_dim=self.embedding_dim,\n",
|
| 1041 |
+
" num_heads=num_heads,\n",
|
| 1042 |
+
" fully_connected_dim=fully_connected_dim,\n",
|
| 1043 |
+
" dropout_rate=dropout_rate,\n",
|
| 1044 |
+
" layernorm_eps=layernorm_eps) \n",
|
| 1045 |
+
" for _ in range(self.num_layers)]\n",
|
| 1046 |
+
" self.dropout = Dropout(dropout_rate)\n",
|
| 1047 |
+
" \n",
|
| 1048 |
+
" def call(self, x, enc_output, training, \n",
|
| 1049 |
+
" look_ahead_mask, padding_mask):\n",
|
| 1050 |
+
" \"\"\"\n",
|
| 1051 |
+
" Forward pass for the Decoder\n",
|
| 1052 |
+
" \n",
|
| 1053 |
+
" Arguments:\n",
|
| 1054 |
+
" x -- Tensor of shape (batch_size, target_seq_len, embedding_dim)\n",
|
| 1055 |
+
" enc_output -- Tensor of shape(batch_size, input_seq_len, embedding_dim)\n",
|
| 1056 |
+
" training -- Boolean, set to true to activate\n",
|
| 1057 |
+
" the training mode for dropout layers\n",
|
| 1058 |
+
" look_ahead_mask -- Boolean mask for the target_input\n",
|
| 1059 |
+
" padding_mask -- Boolean mask for the second multihead attention layer\n",
|
| 1060 |
+
" Returns:\n",
|
| 1061 |
+
" x -- Tensor of shape (batch_size, target_seq_len, embedding_dim)\n",
|
| 1062 |
+
" attention_weights - Dictionary of tensors containing all the attention weights\n",
|
| 1063 |
+
" each of shape Tensor of shape (batch_size, num_heads, target_seq_len, input_seq_len)\n",
|
| 1064 |
+
" \"\"\"\n",
|
| 1065 |
+
"\n",
|
| 1066 |
+
" seq_len = tf.shape(x)[1]\n",
|
| 1067 |
+
" attention_weights = {}\n",
|
| 1068 |
+
" \n",
|
| 1069 |
+
" # START CODE HERE\n",
|
| 1070 |
+
" # create word embeddings \n",
|
| 1071 |
+
" x = None # (batch_size, target_seq_len, embedding_dim)\n",
|
| 1072 |
+
" \n",
|
| 1073 |
+
" # scale embeddings by multiplying by the square root of their dimension\n",
|
| 1074 |
+
" x *= None\n",
|
| 1075 |
+
" \n",
|
| 1076 |
+
" # calculate positional encodings and add to word embedding\n",
|
| 1077 |
+
" x += None\n",
|
| 1078 |
+
"\n",
|
| 1079 |
+
" # apply a dropout layer to x\n",
|
| 1080 |
+
" # use `training=training`\n",
|
| 1081 |
+
" x = None\n",
|
| 1082 |
+
"\n",
|
| 1083 |
+
" # use a for loop to pass x through a stack of decoder layers and update attention_weights (~4 lines total)\n",
|
| 1084 |
+
" for i in range(self.num_layers):\n",
|
| 1085 |
+
" # pass x and the encoder output through a stack of decoder layers and save the attention weights\n",
|
| 1086 |
+
" # of block 1 and 2 (~1 line)\n",
|
| 1087 |
+
" x, block1, block2 = self.dec_layers[i](None, None, None,\n",
|
| 1088 |
+
" None, None)\n",
|
| 1089 |
+
"\n",
|
| 1090 |
+
" #update attention_weights dictionary with the attention weights of block 1 and block 2\n",
|
| 1091 |
+
" attention_weights['decoder_layer{}_block1_self_att'.format(i+1)] = None\n",
|
| 1092 |
+
" attention_weights['decoder_layer{}_block2_decenc_att'.format(i+1)] = None\n",
|
| 1093 |
+
" # END CODE HERE\n",
|
| 1094 |
+
" \n",
|
| 1095 |
+
" # x.shape == (batch_size, target_seq_len, embedding_dim)\n",
|
| 1096 |
+
" return x, attention_weights"
|
| 1097 |
+
]
|
| 1098 |
+
},
|
| 1099 |
+
{
|
| 1100 |
+
"cell_type": "code",
|
| 1101 |
+
"execution_count": null,
|
| 1102 |
+
"metadata": {},
|
| 1103 |
+
"outputs": [],
|
| 1104 |
+
"source": [
|
| 1105 |
+
"# UNIT TEST\n",
|
| 1106 |
+
"Decoder_test(Decoder, create_look_ahead_mask, create_padding_mask)"
|
| 1107 |
+
]
|
| 1108 |
+
},
|
| 1109 |
+
{
|
| 1110 |
+
"cell_type": "markdown",
|
| 1111 |
+
"metadata": {},
|
| 1112 |
+
"source": [
|
| 1113 |
+
"<a name='6'></a> \n",
|
| 1114 |
+
"## 6 - Transformer\n",
|
| 1115 |
+
"\n",
|
| 1116 |
+
"Phew! This has been quite the assignment, and now you've made it to your last exercise of the Deep Learning Specialization. Congratulations! You've done all the hard work, now it's time to put it all together. \n",
|
| 1117 |
+
"\n",
|
| 1118 |
+
"<img src=\"transformer.png\" alt=\"Transformer\" width=\"550\"/>\n",
|
| 1119 |
+
"<caption><center><font color='purple'><b>Figure 4: Transformer</font></center></caption>\n",
|
| 1120 |
+
" \n",
|
| 1121 |
+
"The flow of data through the Transformer Architecture is as follows:\n",
|
| 1122 |
+
"* First your input passes through an Encoder, which is just repeated Encoder layers that you implemented:\n",
|
| 1123 |
+
" - embedding and positional encoding of your input\n",
|
| 1124 |
+
" - multi-head attention on your input\n",
|
| 1125 |
+
" - feed forward neural network to help detect features\n",
|
| 1126 |
+
"* Then the predicted output passes through a Decoder, consisting of the decoder layers that you implemented:\n",
|
| 1127 |
+
" - embedding and positional encoding of the output\n",
|
| 1128 |
+
" - multi-head attention on your generated output\n",
|
| 1129 |
+
" - multi-head attention with the Q from the first multi-head attention layer and the K and V from the Encoder\n",
|
| 1130 |
+
" - a feed forward neural network to help detect features\n",
|
| 1131 |
+
"* Finally, after the Nth Decoder layer, one dense layer and a softmax are applied to generate prediction for the next output in your sequence.\n",
|
| 1132 |
+
"\n",
|
| 1133 |
+
"<a name='ex-8'></a> \n",
|
| 1134 |
+
"### Exercise 8 - Transformer\n",
|
| 1135 |
+
"\n",
|
| 1136 |
+
"Implement `Transformer()` using the `call()` method\n",
|
| 1137 |
+
"1. Pass the input through the Encoder with the appropiate mask.\n",
|
| 1138 |
+
"2. Pass the encoder output and the target through the Decoder with the appropiate mask.\n",
|
| 1139 |
+
"3. Apply a linear transformation and a softmax to get a prediction."
|
| 1140 |
+
]
|
| 1141 |
+
},
|
| 1142 |
+
{
|
| 1143 |
+
"cell_type": "code",
|
| 1144 |
+
"execution_count": null,
|
| 1145 |
+
"metadata": {
|
| 1146 |
+
"id": "QHymPmaj-2ba"
|
| 1147 |
+
},
|
| 1148 |
+
"outputs": [],
|
| 1149 |
+
"source": [
|
| 1150 |
+
"# UNQ_C8 (UNIQUE CELL IDENTIFIER, DO NOT EDIT)\n",
|
| 1151 |
+
"# GRADED FUNCTION Transformer\n",
|
| 1152 |
+
"class Transformer(tf.keras.Model):\n",
|
| 1153 |
+
" \"\"\"\n",
|
| 1154 |
+
" Complete transformer with an Encoder and a Decoder\n",
|
| 1155 |
+
" \"\"\"\n",
|
| 1156 |
+
" def __init__(self, num_layers, embedding_dim, num_heads, fully_connected_dim, input_vocab_size, \n",
|
| 1157 |
+
" target_vocab_size, max_positional_encoding_input,\n",
|
| 1158 |
+
" max_positional_encoding_target, dropout_rate=0.1, layernorm_eps=1e-6):\n",
|
| 1159 |
+
" super(Transformer, self).__init__()\n",
|
| 1160 |
+
"\n",
|
| 1161 |
+
" self.encoder = Encoder(num_layers=num_layers,\n",
|
| 1162 |
+
" embedding_dim=embedding_dim,\n",
|
| 1163 |
+
" num_heads=num_heads,\n",
|
| 1164 |
+
" fully_connected_dim=fully_connected_dim,\n",
|
| 1165 |
+
" input_vocab_size=input_vocab_size,\n",
|
| 1166 |
+
" maximum_position_encoding=max_positional_encoding_input,\n",
|
| 1167 |
+
" dropout_rate=dropout_rate,\n",
|
| 1168 |
+
" layernorm_eps=layernorm_eps)\n",
|
| 1169 |
+
"\n",
|
| 1170 |
+
" self.decoder = Decoder(num_layers=num_layers, \n",
|
| 1171 |
+
" embedding_dim=embedding_dim,\n",
|
| 1172 |
+
" num_heads=num_heads,\n",
|
| 1173 |
+
" fully_connected_dim=fully_connected_dim,\n",
|
| 1174 |
+
" target_vocab_size=target_vocab_size, \n",
|
| 1175 |
+
" maximum_position_encoding=max_positional_encoding_target,\n",
|
| 1176 |
+
" dropout_rate=dropout_rate,\n",
|
| 1177 |
+
" layernorm_eps=layernorm_eps)\n",
|
| 1178 |
+
"\n",
|
| 1179 |
+
" self.final_layer = Dense(target_vocab_size, activation='softmax')\n",
|
| 1180 |
+
" \n",
|
| 1181 |
+
" def call(self, input_sentence, output_sentence, training, enc_padding_mask, look_ahead_mask, dec_padding_mask):\n",
|
| 1182 |
+
" \"\"\"\n",
|
| 1183 |
+
" Forward pass for the entire Transformer\n",
|
| 1184 |
+
" Arguments:\n",
|
| 1185 |
+
" input_sentence -- Tensor of shape (batch_size, input_seq_len)\n",
|
| 1186 |
+
" An array of the indexes of the words in the input sentence\n",
|
| 1187 |
+
" output_sentence -- Tensor of shape (batch_size, target_seq_len)\n",
|
| 1188 |
+
" An array of the indexes of the words in the output sentence\n",
|
| 1189 |
+
" training -- Boolean, set to true to activate\n",
|
| 1190 |
+
" the training mode for dropout layers\n",
|
| 1191 |
+
" enc_padding_mask -- Boolean mask to ensure that the padding is not \n",
|
| 1192 |
+
" treated as part of the input\n",
|
| 1193 |
+
" look_ahead_mask -- Boolean mask for the target_input\n",
|
| 1194 |
+
" dec_padding_mask -- Boolean mask for the second multihead attention layer\n",
|
| 1195 |
+
" Returns:\n",
|
| 1196 |
+
" final_output -- Describe me\n",
|
| 1197 |
+
" attention_weights - Dictionary of tensors containing all the attention weights for the decoder\n",
|
| 1198 |
+
" each of shape Tensor of shape (batch_size, num_heads, target_seq_len, input_seq_len)\n",
|
| 1199 |
+
" \n",
|
| 1200 |
+
" \"\"\"\n",
|
| 1201 |
+
" # START CODE HERE\n",
|
| 1202 |
+
" # call self.encoder with the appropriate arguments to get the encoder output\n",
|
| 1203 |
+
" enc_output = None # (batch_size, inp_seq_len, embedding_dim)\n",
|
| 1204 |
+
" \n",
|
| 1205 |
+
" # call self.decoder with the appropriate arguments to get the decoder output\n",
|
| 1206 |
+
" # dec_output.shape == (batch_size, tar_seq_len, embedding_dim)\n",
|
| 1207 |
+
" dec_output, attention_weights = self.decoder(None, None, None, None, None)\n",
|
| 1208 |
+
" \n",
|
| 1209 |
+
" # pass decoder output through a linear layer and softmax (~2 lines)\n",
|
| 1210 |
+
" final_output = None # (batch_size, tar_seq_len, target_vocab_size)\n",
|
| 1211 |
+
" # END CODE HERE\n",
|
| 1212 |
+
"\n",
|
| 1213 |
+
" return final_output, attention_weights"
|
| 1214 |
+
]
|
| 1215 |
+
},
|
| 1216 |
+
{
|
| 1217 |
+
"cell_type": "code",
|
| 1218 |
+
"execution_count": null,
|
| 1219 |
+
"metadata": {},
|
| 1220 |
+
"outputs": [],
|
| 1221 |
+
"source": [
|
| 1222 |
+
"# UNIT TEST\n",
|
| 1223 |
+
"Transformer_test(Transformer, create_look_ahead_mask, create_padding_mask)"
|
| 1224 |
+
]
|
| 1225 |
+
},
|
| 1226 |
+
{
|
| 1227 |
+
"cell_type": "markdown",
|
| 1228 |
+
"metadata": {},
|
| 1229 |
+
"source": [
|
| 1230 |
+
"## Conclusion\n",
|
| 1231 |
+
"\n",
|
| 1232 |
+
"You've come to the end of the graded portion of the assignment. By now, you've: \n",
|
| 1233 |
+
"\n",
|
| 1234 |
+
"* Created positional encodings to capture sequential relationships in data\n",
|
| 1235 |
+
"* Calculated scaled dot-product self-attention with word embeddings\n",
|
| 1236 |
+
"* Implemented masked multi-head attention\n",
|
| 1237 |
+
"* Built and trained a Transformer model"
|
| 1238 |
+
]
|
| 1239 |
+
},
|
| 1240 |
+
{
|
| 1241 |
+
"cell_type": "markdown",
|
| 1242 |
+
"metadata": {},
|
| 1243 |
+
"source": [
|
| 1244 |
+
"<font color='blue'>\n",
|
| 1245 |
+
" <b>What you should remember</b>:\n",
|
| 1246 |
+
"\n",
|
| 1247 |
+
"- The combination of self-attention and convolutional network layers allows of parallelization of training and *faster training*.\n",
|
| 1248 |
+
"- Self-attention is calculated using the generated query Q, key K, and value V matrices.\n",
|
| 1249 |
+
"- Adding positional encoding to word embeddings is an effective way to include sequence information in self-attention calculations. \n",
|
| 1250 |
+
"- Multi-head attention can help detect multiple features in your sentence.\n",
|
| 1251 |
+
"- Masking stops the model from 'looking ahead' during training, or weighting zeroes too much when processing cropped sentences. "
|
| 1252 |
+
]
|
| 1253 |
+
},
|
| 1254 |
+
{
|
| 1255 |
+
"cell_type": "markdown",
|
| 1256 |
+
"metadata": {},
|
| 1257 |
+
"source": [
|
| 1258 |
+
"Now that you have completed the Transformer assignment, make sure you check out the ungraded labs to apply the Transformer model to practical use cases such as Name Entity Recogntion (NER) and Question Answering (QA). \n",
|
| 1259 |
+
"\n",
|
| 1260 |
+
"\n",
|
| 1261 |
+
"# Congratulations on finishing the Deep Learning Specialization!!!!!! 🎉🎉🎉🎉🎉\n",
|
| 1262 |
+
"\n",
|
| 1263 |
+
"This was the last graded assignment of the specialization. It is now time to celebrate all your hard work and dedication! \n",
|
| 1264 |
+
"\n",
|
| 1265 |
+
"<a name='7'></a> \n",
|
| 1266 |
+
"## 7 - References\n",
|
| 1267 |
+
"\n",
|
| 1268 |
+
"The Transformer algorithm was due to Vaswani et al. (2017). \n",
|
| 1269 |
+
"\n",
|
| 1270 |
+
"- Ashish Vaswani, Noam Shazeer, Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N. Gomez, Lukasz Kaiser, Illia Polosukhin (2017). [Attention Is All You Need](https://arxiv.org/abs/1706.03762) "
|
| 1271 |
+
]
|
| 1272 |
+
},
|
| 1273 |
+
{
|
| 1274 |
+
"cell_type": "code",
|
| 1275 |
+
"execution_count": null,
|
| 1276 |
+
"metadata": {},
|
| 1277 |
+
"outputs": [],
|
| 1278 |
+
"source": []
|
| 1279 |
+
}
|
| 1280 |
+
],
|
| 1281 |
+
"metadata": {
|
| 1282 |
+
"accelerator": "GPU",
|
| 1283 |
+
"kernelspec": {
|
| 1284 |
+
"display_name": "Python 3",
|
| 1285 |
+
"language": "python",
|
| 1286 |
+
"name": "python3"
|
| 1287 |
+
},
|
| 1288 |
+
"language_info": {
|
| 1289 |
+
"codemirror_mode": {
|
| 1290 |
+
"name": "ipython",
|
| 1291 |
+
"version": 3
|
| 1292 |
+
},
|
| 1293 |
+
"file_extension": ".py",
|
| 1294 |
+
"mimetype": "text/x-python",
|
| 1295 |
+
"name": "python",
|
| 1296 |
+
"nbconvert_exporter": "python",
|
| 1297 |
+
"pygments_lexer": "ipython3",
|
| 1298 |
+
"version": "3.7.6"
|
| 1299 |
+
}
|
| 1300 |
+
},
|
| 1301 |
+
"nbformat": 4,
|
| 1302 |
+
"nbformat_minor": 4
|
| 1303 |
+
}
|
Transformer Mechanism/Transformer_Implementation/home/jovyan/work/W4A1/C5_W4_A1_Transformer_Subclass_v1.ipynb
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
Transformer Mechanism/Transformer_Implementation/home/jovyan/work/W4A1/__pycache__/public_tests.cpython-37.pyc
ADDED
|
Binary file (11.3 kB). View file
|
|
|
Transformer Mechanism/Transformer_Implementation/home/jovyan/work/W4A1/decoder.png
ADDED
|
Git LFS Details
|
Transformer Mechanism/Transformer_Implementation/home/jovyan/work/W4A1/decoder_layer.png
ADDED
|
Git LFS Details
|
Transformer Mechanism/Transformer_Implementation/home/jovyan/work/W4A1/encoder.png
ADDED
|
Git LFS Details
|
Transformer Mechanism/Transformer_Implementation/home/jovyan/work/W4A1/encoder_layer.png
ADDED
|
Git LFS Details
|
Transformer Mechanism/Transformer_Implementation/home/jovyan/work/W4A1/ner.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
Transformer Mechanism/Transformer_Implementation/home/jovyan/work/W4A1/public_tests.py
ADDED
|
@@ -0,0 +1,315 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
import tensorflow as tf
|
| 3 |
+
|
| 4 |
+
def get_angles_test(target):
|
| 5 |
+
position = 4
|
| 6 |
+
d_model = 16
|
| 7 |
+
pos_m = np.arange(position)[:, np.newaxis]
|
| 8 |
+
dims = np.arange(d_model)[np.newaxis, :]
|
| 9 |
+
|
| 10 |
+
result = target(pos_m, dims, d_model)
|
| 11 |
+
|
| 12 |
+
assert type(result) == np.ndarray, "You must return a numpy ndarray"
|
| 13 |
+
assert result.shape == (position, d_model), f"Wrong shape. We expected: ({position}, {d_model})"
|
| 14 |
+
assert np.sum(result[0, :]) == 0
|
| 15 |
+
assert np.isclose(np.sum(result[:, 0]), position * (position - 1) / 2)
|
| 16 |
+
even_cols = result[:, 0::2]
|
| 17 |
+
odd_cols = result[:, 1::2]
|
| 18 |
+
assert np.all(even_cols == odd_cols), "Submatrices of odd and even columns must be equal"
|
| 19 |
+
limit = (position - 1) / np.power(10000,14.0/16.0)
|
| 20 |
+
assert np.isclose(result[position - 1, d_model -1], limit ), f"Last value must be {limit}"
|
| 21 |
+
|
| 22 |
+
print("\033[92mAll tests passed")
|
| 23 |
+
|
| 24 |
+
def positional_encoding_test(target, get_angles):
|
| 25 |
+
position = 8
|
| 26 |
+
d_model = 16
|
| 27 |
+
|
| 28 |
+
pos_encoding = target(position, d_model)
|
| 29 |
+
sin_part = pos_encoding[:, :, 0::2]
|
| 30 |
+
cos_part = pos_encoding[:, :, 1::2]
|
| 31 |
+
|
| 32 |
+
assert tf.is_tensor(pos_encoding), "Output is not a tensor"
|
| 33 |
+
assert pos_encoding.shape == (1, position, d_model), f"Wrong shape. We expected: (1, {position}, {d_model})"
|
| 34 |
+
|
| 35 |
+
ones = sin_part ** 2 + cos_part ** 2
|
| 36 |
+
assert np.allclose(ones, np.ones((1, position, d_model // 2))), "Sum of square pairs must be 1 = sin(a)**2 + cos(a)**2"
|
| 37 |
+
|
| 38 |
+
angs = np.arctan(sin_part / cos_part)
|
| 39 |
+
angs[angs < 0] += np.pi
|
| 40 |
+
angs[sin_part.numpy() < 0] += np.pi
|
| 41 |
+
angs = angs % (2 * np.pi)
|
| 42 |
+
|
| 43 |
+
pos_m = np.arange(position)[:, np.newaxis]
|
| 44 |
+
dims = np.arange(d_model)[np.newaxis, :]
|
| 45 |
+
|
| 46 |
+
trueAngs = get_angles(pos_m, dims, d_model)[:, 0::2] % (2 * np.pi)
|
| 47 |
+
|
| 48 |
+
assert np.allclose(angs[0], trueAngs), "Did you apply sin and cos to even and odd parts respectively?"
|
| 49 |
+
|
| 50 |
+
print("\033[92mAll tests passed")
|
| 51 |
+
|
| 52 |
+
def scaled_dot_product_attention_test(target):
|
| 53 |
+
q = np.array([[1, 0, 1, 1], [0, 1, 1, 1], [1, 0, 0, 1]]).astype(np.float32)
|
| 54 |
+
k = np.array([[1, 1, 0, 1], [1, 0, 1, 1 ], [0, 1, 1, 0], [0, 0, 0, 1]]).astype(np.float32)
|
| 55 |
+
v = np.array([[0, 0], [1, 0], [1, 0], [1, 1]]).astype(np.float32)
|
| 56 |
+
|
| 57 |
+
attention, weights = target(q, k, v, None)
|
| 58 |
+
assert tf.is_tensor(weights), "Weights must be a tensor"
|
| 59 |
+
assert tuple(tf.shape(weights).numpy()) == (q.shape[0], k.shape[1]), f"Wrong shape. We expected ({q.shape[0]}, {k.shape[1]})"
|
| 60 |
+
assert np.allclose(weights, [[0.2589478, 0.42693272, 0.15705977, 0.15705977],
|
| 61 |
+
[0.2772748, 0.2772748, 0.2772748, 0.16817567],
|
| 62 |
+
[0.33620113, 0.33620113, 0.12368149, 0.2039163 ]]), "Wrong unmasked weights"
|
| 63 |
+
|
| 64 |
+
assert tf.is_tensor(attention), "Output must be a tensor"
|
| 65 |
+
assert tuple(tf.shape(attention).numpy()) == (q.shape[0], v.shape[1]), f"Wrong shape. We expected ({q.shape[0]}, {v.shape[1]})"
|
| 66 |
+
assert np.allclose(attention, [[0.74105227, 0.15705977],
|
| 67 |
+
[0.7227253, 0.16817567],
|
| 68 |
+
[0.6637989, 0.2039163 ]]), "Wrong unmasked attention"
|
| 69 |
+
|
| 70 |
+
mask = np.array([[[1, 1, 0, 1], [1, 1, 0, 1], [1, 1, 0, 1]]])
|
| 71 |
+
attention, weights = target(q, k, v, mask)
|
| 72 |
+
|
| 73 |
+
assert np.allclose(weights, [[0.30719590187072754, 0.5064803957939148, 0.0, 0.18632373213768005],
|
| 74 |
+
[0.3836517333984375, 0.3836517333984375, 0.0, 0.2326965481042862],
|
| 75 |
+
[0.3836517333984375, 0.3836517333984375, 0.0, 0.2326965481042862]]), "Wrong masked weights"
|
| 76 |
+
assert np.allclose(attention, [[0.6928040981292725, 0.18632373213768005],
|
| 77 |
+
[0.6163482666015625, 0.2326965481042862],
|
| 78 |
+
[0.6163482666015625, 0.2326965481042862]]), "Wrong masked attention"
|
| 79 |
+
|
| 80 |
+
print("\033[92mAll tests passed")
|
| 81 |
+
|
| 82 |
+
def EncoderLayer_test(target):
|
| 83 |
+
q = np.array([[[1, 0, 1, 1], [0, 1, 1, 1], [1, 0, 0, 1]]]).astype(np.float32)
|
| 84 |
+
encoder_layer1 = target(4, 2, 8)
|
| 85 |
+
tf.random.set_seed(10)
|
| 86 |
+
encoded = encoder_layer1(q, True, np.array([[1, 0, 1]]))
|
| 87 |
+
|
| 88 |
+
assert tf.is_tensor(encoded), "Wrong type. Output must be a tensor"
|
| 89 |
+
assert tuple(tf.shape(encoded).numpy()) == (1, q.shape[1], q.shape[2]), f"Wrong shape. We expected ((1, {q.shape[1]}, {q.shape[2]}))"
|
| 90 |
+
|
| 91 |
+
assert np.allclose(encoded.numpy(),
|
| 92 |
+
[[ 0.23017104, -0.98100424, -0.78707516, 1.5379084 ],
|
| 93 |
+
[-1.2280797 , 0.76477575, -0.7169283 , 1.1802323 ],
|
| 94 |
+
[ 0.14880152, -0.48318022, -1.1908402 , 1.5252188 ]]), "Wrong values when training=True"
|
| 95 |
+
|
| 96 |
+
encoded = encoder_layer1(q, False, np.array([[1, 1, 0]]))
|
| 97 |
+
assert np.allclose(encoded.numpy(), [[ 0.5167701 , -0.92981905, -0.9731106 , 1.3861597 ],
|
| 98 |
+
[-1.120878 , 1.0826552 , -0.8671041 , 0.905327 ],
|
| 99 |
+
[ 0.28154755, -0.3661362 , -1.3330412 , 1.4176297 ]]), "Wrong values when training=False"
|
| 100 |
+
print("\033[92mAll tests passed")
|
| 101 |
+
|
| 102 |
+
def Encoder_test(target):
|
| 103 |
+
tf.random.set_seed(10)
|
| 104 |
+
|
| 105 |
+
embedding_dim=4
|
| 106 |
+
|
| 107 |
+
encoderq = target(num_layers=2,
|
| 108 |
+
embedding_dim=embedding_dim,
|
| 109 |
+
num_heads=2,
|
| 110 |
+
fully_connected_dim=8,
|
| 111 |
+
input_vocab_size=32,
|
| 112 |
+
maximum_position_encoding=5)
|
| 113 |
+
|
| 114 |
+
x = np.array([[2, 1, 3], [1, 2, 0]])
|
| 115 |
+
|
| 116 |
+
encoderq_output = encoderq(x, True, None)
|
| 117 |
+
|
| 118 |
+
assert tf.is_tensor(encoderq_output), "Wrong type. Output must be a tensor"
|
| 119 |
+
assert tuple(tf.shape(encoderq_output).numpy()) == (x.shape[0], x.shape[1], embedding_dim), f"Wrong shape. We expected ({x.shape[0]}, {x.shape[1]}, {embedding_dim})"
|
| 120 |
+
assert np.allclose(encoderq_output.numpy(),
|
| 121 |
+
[[[-0.6906098 , 1.0988709 , -1.260586 , 0.85232526],
|
| 122 |
+
[ 0.7319228 , -0.3826024 , -1.4507656 , 1.1014453 ],
|
| 123 |
+
[ 1.0995713 , -1.1686686 , -0.80888665, 0.8779839 ]],
|
| 124 |
+
[[-0.4612937 , 1.0697356 , -1.4127715 , 0.8043293 ],
|
| 125 |
+
[ 0.27027237, 0.28793618, -1.6370889 , 1.0788803 ],
|
| 126 |
+
[ 1.2370994 , -1.0687275 , -0.8945037 , 0.7261319 ]]]), "Wrong values case 1"
|
| 127 |
+
|
| 128 |
+
encoderq_output = encoderq(x, True, np.array([[[[1., 1., 1.]]], [[[1., 1., 0.]]]]))
|
| 129 |
+
assert np.allclose(encoderq_output.numpy(),
|
| 130 |
+
[[[-0.36764443, 0.98527074, -1.4714274 , 0.85380095],
|
| 131 |
+
[-0.50018215, 0.66005886, -1.3647256 , 1.204849 ],
|
| 132 |
+
[ 0.99951494, -1.0142792 , -0.9856176 , 1.0003818 ]],
|
| 133 |
+
[[ 0.01838917, 1.038109 , -1.6154225 , 0.55892444],
|
| 134 |
+
[ 0.3872563 , -0.40960154, -1.3456631 , 1.3680083 ],
|
| 135 |
+
[ 0.534565 , -0.70262754, -1.18215 , 1.3502126 ]]]), "Wrong values case 2"
|
| 136 |
+
|
| 137 |
+
encoderq_output = encoderq(x, False, np.array([[[[1., 1., 1.]]], [[[1., 1., 0.]]]]))
|
| 138 |
+
assert np.allclose(encoderq_output.numpy(),
|
| 139 |
+
[[[-0.5642399 , 1.0386591 , -1.3530676 , 0.87864864],
|
| 140 |
+
[ 0.5261332 , 0.21861789, -1.6758442 , 0.93109316],
|
| 141 |
+
[ 1.2870724 , -1.1545564 , -0.7739521 , 0.6414361 ]],
|
| 142 |
+
[[-0.01885331, 0.8866553 , -1.624897 , 0.75709504],
|
| 143 |
+
[ 0.4165045 , 0.27912217, -1.6719477 , 0.97632086],
|
| 144 |
+
[ 0.71298015, -0.7565592 , -1.1861688 , 1.2297478 ]]]), "Wrong values case 3"
|
| 145 |
+
|
| 146 |
+
print("\033[92mAll tests passed")
|
| 147 |
+
|
| 148 |
+
def DecoderLayer_test(target, create_look_ahead_mask):
|
| 149 |
+
|
| 150 |
+
num_heads=8
|
| 151 |
+
tf.random.set_seed(10)
|
| 152 |
+
|
| 153 |
+
decoderLayerq = target(
|
| 154 |
+
embedding_dim=4,
|
| 155 |
+
num_heads=num_heads,
|
| 156 |
+
fully_connected_dim=32,
|
| 157 |
+
dropout_rate=0.1,
|
| 158 |
+
layernorm_eps=1e-6)
|
| 159 |
+
|
| 160 |
+
encoderq_output = tf.constant([[[-0.40172306, 0.11519244, -1.2322885, 1.5188192 ],
|
| 161 |
+
[ 0.4017268, 0.33922842, -1.6836855, 0.9427304 ],
|
| 162 |
+
[ 0.4685002, -1.6252842, 0.09368491, 1.063099 ]]])
|
| 163 |
+
|
| 164 |
+
q = np.array([[[1, 0, 1, 1], [0, 1, 1, 1], [1, 0, 0, 1]]]).astype(np.float32)
|
| 165 |
+
|
| 166 |
+
look_ahead_mask = create_look_ahead_mask(q.shape[1])
|
| 167 |
+
|
| 168 |
+
padding_mask = None
|
| 169 |
+
out, attn_w_b1, attn_w_b2 = decoderLayerq(q, encoderq_output, True, look_ahead_mask, padding_mask)
|
| 170 |
+
|
| 171 |
+
assert tf.is_tensor(attn_w_b1), "Wrong type for attn_w_b1. Output must be a tensor"
|
| 172 |
+
assert tf.is_tensor(attn_w_b2), "Wrong type for attn_w_b2. Output must be a tensor"
|
| 173 |
+
assert tf.is_tensor(out), "Wrong type for out. Output must be a tensor"
|
| 174 |
+
|
| 175 |
+
shape1 = (q.shape[0], num_heads, q.shape[1], q.shape[1])
|
| 176 |
+
assert tuple(tf.shape(attn_w_b1).numpy()) == shape1, f"Wrong shape. We expected {shape1}"
|
| 177 |
+
assert tuple(tf.shape(attn_w_b2).numpy()) == shape1, f"Wrong shape. We expected {shape1}"
|
| 178 |
+
assert tuple(tf.shape(out).numpy()) == q.shape, f"Wrong shape. We expected {q.shape}"
|
| 179 |
+
|
| 180 |
+
assert np.allclose(attn_w_b1[0, 0, 1], [0.5271505, 0.47284946, 0.], atol=1e-2), "Wrong values in attn_w_b1. Check the call to self.mha1"
|
| 181 |
+
assert np.allclose(attn_w_b2[0, 0, 1], [0.32048798, 0.390301, 0.28921106]), "Wrong values in attn_w_b2. Check the call to self.mha2"
|
| 182 |
+
assert np.allclose(out[0, 0], [-0.22109576, -1.5455486, 0.852692, 0.9139523]), "Wrong values in out"
|
| 183 |
+
|
| 184 |
+
|
| 185 |
+
# Now let's try a example with padding mask
|
| 186 |
+
padding_mask = np.array([[[1, 1, 0]]])
|
| 187 |
+
out, attn_w_b1, attn_w_b2 = decoderLayerq(q, encoderq_output, True, look_ahead_mask, padding_mask)
|
| 188 |
+
assert np.allclose(out[0, 0], [0.14950314, -1.6444231, 1.0268553, 0.4680646]), "Wrong values in out when we mask the last word. Are you passing the padding_mask to the inner functions?"
|
| 189 |
+
|
| 190 |
+
print("\033[92mAll tests passed")
|
| 191 |
+
|
| 192 |
+
def Decoder_test(target, create_look_ahead_mask, create_padding_mask):
|
| 193 |
+
tf.random.set_seed(10)
|
| 194 |
+
|
| 195 |
+
num_layers=7
|
| 196 |
+
embedding_dim=4
|
| 197 |
+
num_heads=3
|
| 198 |
+
fully_connected_dim=8
|
| 199 |
+
target_vocab_size=33
|
| 200 |
+
maximum_position_encoding=6
|
| 201 |
+
|
| 202 |
+
x_array = np.array([[3, 2, 1], [2, 1, 0]])
|
| 203 |
+
|
| 204 |
+
|
| 205 |
+
encoderq_output = tf.constant([[[-0.40172306, 0.11519244, -1.2322885, 1.5188192 ],
|
| 206 |
+
[ 0.4017268, 0.33922842, -1.6836855, 0.9427304 ],
|
| 207 |
+
[ 0.4685002, -1.6252842, 0.09368491, 1.063099 ]],
|
| 208 |
+
[[-0.3489219, 0.31335592, -1.3568854, 1.3924513 ],
|
| 209 |
+
[-0.08761203, -0.1680029, -1.2742313, 1.5298463 ],
|
| 210 |
+
[ 0.2627198, -1.6140151, 0.2212624 , 1.130033 ]]])
|
| 211 |
+
|
| 212 |
+
look_ahead_mask = create_look_ahead_mask(x_array.shape[1])
|
| 213 |
+
|
| 214 |
+
decoderk = target(num_layers,
|
| 215 |
+
embedding_dim,
|
| 216 |
+
num_heads,
|
| 217 |
+
fully_connected_dim,
|
| 218 |
+
target_vocab_size,
|
| 219 |
+
maximum_position_encoding)
|
| 220 |
+
x, attention_weights = decoderk(x_array, encoderq_output, False, look_ahead_mask, None)
|
| 221 |
+
assert tf.is_tensor(x), "Wrong type for x. It must be a dict"
|
| 222 |
+
assert np.allclose(tf.shape(x), tf.shape(encoderq_output)), f"Wrong shape. We expected { tf.shape(encoderq_output)}"
|
| 223 |
+
assert np.allclose(x[1, 1], [-0.2715261, -0.5606001, -0.861783, 1.69390933]), "Wrong values in x"
|
| 224 |
+
|
| 225 |
+
keys = list(attention_weights.keys())
|
| 226 |
+
assert type(attention_weights) == dict, "Wrong type for attention_weights[0]. Output must be a tensor"
|
| 227 |
+
assert len(keys) == 2 * num_layers, f"Wrong length for attention weights. It must be 2 x num_layers = {2*num_layers}"
|
| 228 |
+
assert tf.is_tensor(attention_weights[keys[0]]), f"Wrong type for attention_weights[{keys[0]}]. Output must be a tensor"
|
| 229 |
+
shape1 = (x_array.shape[0], num_heads, x_array.shape[1], x_array.shape[1])
|
| 230 |
+
assert tuple(tf.shape(attention_weights[keys[1]]).numpy()) == shape1, f"Wrong shape. We expected {shape1}"
|
| 231 |
+
assert np.allclose(attention_weights[keys[0]][0, 0, 1], [0.52145624, 0.47854376, 0.]), f"Wrong values in attention_weights[{keys[0]}]"
|
| 232 |
+
|
| 233 |
+
x, attention_weights = decoderk(x_array, encoderq_output, True, look_ahead_mask, None)
|
| 234 |
+
assert np.allclose(x[1, 1], [-0.30814743, -0.6213016, -0.77767026, 1.7071193]), "Wrong values in x when training=True"
|
| 235 |
+
|
| 236 |
+
x, attention_weights = decoderk(x_array, encoderq_output, True, look_ahead_mask, create_padding_mask(x_array))
|
| 237 |
+
assert np.allclose(x[1, 1], [-0.0250004, 0.50791883, -1.5877104, 1.1047921]), "Wrong values in x when training=True and use padding mask"
|
| 238 |
+
|
| 239 |
+
print("\033[92mAll tests passed")
|
| 240 |
+
|
| 241 |
+
def Transformer_test(target, create_look_ahead_mask, create_padding_mask):
|
| 242 |
+
|
| 243 |
+
tf.random.set_seed(10)
|
| 244 |
+
|
| 245 |
+
|
| 246 |
+
num_layers = 6
|
| 247 |
+
embedding_dim = 4
|
| 248 |
+
num_heads = 4
|
| 249 |
+
fully_connected_dim = 8
|
| 250 |
+
input_vocab_size = 30
|
| 251 |
+
target_vocab_size = 35
|
| 252 |
+
max_positional_encoding_input = 5
|
| 253 |
+
max_positional_encoding_target = 6
|
| 254 |
+
|
| 255 |
+
trans = target(num_layers,
|
| 256 |
+
embedding_dim,
|
| 257 |
+
num_heads,
|
| 258 |
+
fully_connected_dim,
|
| 259 |
+
input_vocab_size,
|
| 260 |
+
target_vocab_size,
|
| 261 |
+
max_positional_encoding_input,
|
| 262 |
+
max_positional_encoding_target)
|
| 263 |
+
# 0 is the padding value
|
| 264 |
+
sentence_lang_a = np.array([[2, 1, 4, 3, 0]])
|
| 265 |
+
sentence_lang_b = np.array([[3, 2, 1, 0, 0]])
|
| 266 |
+
|
| 267 |
+
enc_padding_mask = create_padding_mask(sentence_lang_a)
|
| 268 |
+
dec_padding_mask = create_padding_mask(sentence_lang_b)
|
| 269 |
+
|
| 270 |
+
look_ahead_mask = create_look_ahead_mask(sentence_lang_a.shape[1])
|
| 271 |
+
|
| 272 |
+
translation, weights = trans(
|
| 273 |
+
sentence_lang_a,
|
| 274 |
+
sentence_lang_b,
|
| 275 |
+
True, # Training
|
| 276 |
+
enc_padding_mask,
|
| 277 |
+
look_ahead_mask,
|
| 278 |
+
dec_padding_mask
|
| 279 |
+
)
|
| 280 |
+
|
| 281 |
+
|
| 282 |
+
assert tf.is_tensor(translation), "Wrong type for translation. Output must be a tensor"
|
| 283 |
+
shape1 = (sentence_lang_a.shape[0], max_positional_encoding_input, target_vocab_size)
|
| 284 |
+
assert tuple(tf.shape(translation).numpy()) == shape1, f"Wrong shape. We expected {shape1}"
|
| 285 |
+
|
| 286 |
+
assert np.allclose(translation[0, 0, 0:8],
|
| 287 |
+
[0.017416516, 0.030932948, 0.024302809, 0.01997807,
|
| 288 |
+
0.014861834, 0.034384135, 0.054789476, 0.032087505]), "Wrong values in translation"
|
| 289 |
+
|
| 290 |
+
keys = list(weights.keys())
|
| 291 |
+
assert type(weights) == dict, "Wrong type for weights. It must be a dict"
|
| 292 |
+
assert len(keys) == 2 * num_layers, f"Wrong length for attention weights. It must be 2 x num_layers = {2*num_layers}"
|
| 293 |
+
assert tf.is_tensor(weights[keys[0]]), f"Wrong type for att_weights[{keys[0]}]. Output must be a tensor"
|
| 294 |
+
|
| 295 |
+
shape1 = (sentence_lang_a.shape[0], num_heads, sentence_lang_a.shape[1], sentence_lang_a.shape[1])
|
| 296 |
+
assert tuple(tf.shape(weights[keys[1]]).numpy()) == shape1, f"Wrong shape. We expected {shape1}"
|
| 297 |
+
assert np.allclose(weights[keys[0]][0, 0, 1], [0.4805548, 0.51944524, 0.0, 0.0, 0.0]), f"Wrong values in weights[{keys[0]}]"
|
| 298 |
+
|
| 299 |
+
translation, weights = trans(
|
| 300 |
+
sentence_lang_a,
|
| 301 |
+
sentence_lang_b,
|
| 302 |
+
False, # Training
|
| 303 |
+
enc_padding_mask,
|
| 304 |
+
look_ahead_mask,
|
| 305 |
+
dec_padding_mask
|
| 306 |
+
)
|
| 307 |
+
|
| 308 |
+
assert np.allclose(translation[0, 0, 0:8],
|
| 309 |
+
[0.01751175, 0.029051155, 0.024785805, 0.020421047,
|
| 310 |
+
0.0149451075, 0.033235606, 0.053800166, 0.028556924]), "Wrong values in outd"
|
| 311 |
+
|
| 312 |
+
print(translation)
|
| 313 |
+
|
| 314 |
+
print("\033[92mAll tests passed")
|
| 315 |
+
|
Transformer Mechanism/Transformer_Implementation/home/jovyan/work/W4A1/self-attention.png
ADDED
|
Git LFS Details
|
Transformer Mechanism/Transformer_Implementation/home/jovyan/work/W4A1/transformer.png
ADDED
|
Git LFS Details
|