Spaces:
No application file
No application file
Upload 2 files
Browse files- .gitattributes +1 -0
- Lesson 4(NLP notes) (1).ipynb +2614 -0
- text-classifier-model-sentiment-movie-reviews (1) +3 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
text-classifier-model-sentiment-movie-reviews[[:space:]](1) filter=lfs diff=lfs merge=lfs -text
|
Lesson 4(NLP notes) (1).ipynb
ADDED
|
@@ -0,0 +1,2614 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cells": [
|
| 3 |
+
{
|
| 4 |
+
"cell_type": "markdown",
|
| 5 |
+
"id": "5c9cf9c8-4458-42ec-b736-deb68e85be0b",
|
| 6 |
+
"metadata": {},
|
| 7 |
+
"source": [
|
| 8 |
+
"# NLP Deep Dive: RNNs"
|
| 9 |
+
]
|
| 10 |
+
},
|
| 11 |
+
{
|
| 12 |
+
"cell_type": "code",
|
| 13 |
+
"execution_count": 1,
|
| 14 |
+
"id": "01cfeab4-b755-4fac-9ddc-f99ce1f30234",
|
| 15 |
+
"metadata": {},
|
| 16 |
+
"outputs": [],
|
| 17 |
+
"source": [
|
| 18 |
+
"#hide\n",
|
| 19 |
+
"! [ -e /content ] && pip install -Uqq fastbook\n",
|
| 20 |
+
"import fastbook\n",
|
| 21 |
+
"fastbook.setup_book()"
|
| 22 |
+
]
|
| 23 |
+
},
|
| 24 |
+
{
|
| 25 |
+
"cell_type": "code",
|
| 26 |
+
"execution_count": 2,
|
| 27 |
+
"id": "600871ad-cb6c-47a1-afd1-56a39419599a",
|
| 28 |
+
"metadata": {},
|
| 29 |
+
"outputs": [],
|
| 30 |
+
"source": [
|
| 31 |
+
"#hide\n",
|
| 32 |
+
"from fastbook import *\n",
|
| 33 |
+
"from IPython.display import display,HTML"
|
| 34 |
+
]
|
| 35 |
+
},
|
| 36 |
+
{
|
| 37 |
+
"cell_type": "markdown",
|
| 38 |
+
"id": "424d5492-60a7-45c6-8796-e23e1315bef6",
|
| 39 |
+
"metadata": {},
|
| 40 |
+
"source": [
|
| 41 |
+
"Generally in NLP, the pretrained model is trained on different task.\n",
|
| 42 |
+
"\n",
|
| 43 |
+
"*Language model* is one that has been trained to predict the next word in a text having read the ones before and this kind of task is called *self-supervised learning*.\n",
|
| 44 |
+
"\n",
|
| 45 |
+
"Self-supervised learning is not used for model directly trained but is used for pretrained model used for transfer learning.\n",
|
| 46 |
+
"\n",
|
| 47 |
+
">Self-supervised learning: Training a model using labels that are embedded in the independent variable instead of requiring external labels.\n",
|
| 48 |
+
"\n",
|
| 49 |
+
"**Why are we learning to train a language model in detail?**\n",
|
| 50 |
+
"- it will be helpful to understand the foundations of model you're using.\n",
|
| 51 |
+
"- practical reason is, we can fine-tune the model(i.e. language model) to get better results prior to fine-tuning classification model.\n",
|
| 52 |
+
"\n",
|
| 53 |
+
"The IMDb reviews data consists of reviews. We can use all of these reviews to fine-tune the language model that was trained on Wikipedia articles prior to transfer learning to a classification task to get better at predicting the next word of a movie review(ultimately getting better results). This is known as the *Universal Language Model Fine-tuning(ULMFit)* approach.\n",
|
| 54 |
+
"\n",
|
| 55 |
+
"3 stages for TL in NLP:\n",
|
| 56 |
+
"1. Language model (trained on Wikipedia articles)\n",
|
| 57 |
+
"2. Language model (fine-tuned previous model using IMDb reviews data)\n",
|
| 58 |
+
"3. Then train classification model"
|
| 59 |
+
]
|
| 60 |
+
},
|
| 61 |
+
{
|
| 62 |
+
"cell_type": "markdown",
|
| 63 |
+
"id": "c03e511e-daf9-4ced-b28d-878a78c46470",
|
| 64 |
+
"metadata": {},
|
| 65 |
+
"source": [
|
| 66 |
+
"## Text Preprocessing\n",
|
| 67 |
+
"\n",
|
| 68 |
+
"Approach for a single categorical variable to be used for a NN as independent variable:(not understanding the steps 3&4)\n",
|
| 69 |
+
"1. Make a list of all possible levels of that categorical variable(this is vocab)\n",
|
| 70 |
+
"2. Replace each level with its index in the vocab.\n",
|
| 71 |
+
"3. Create an embedding matrix for this containing a row for each level(??)\n",
|
| 72 |
+
"4. Use the embedding matrix as the first layer of NN.\n",
|
| 73 |
+
"\n",
|
| 74 |
+
"The same thing can be done for text but\n",
|
| 75 |
+
"- first we concatenate the documents in our dataset to form a single long list\n",
|
| 76 |
+
"- then split it into words which gives a long list of words(or tokens)\n",
|
| 77 |
+
"Our independent variable is sequence of words starting from first word in long list and ending with second to last(does it mean start from first word and ends at the last word).\n",
|
| 78 |
+
"\n",
|
| 79 |
+
"Our *vocab* contains mix of common words already present in the vocab of pretrained model and new words specific to the movie reviews corpus.\n",
|
| 80 |
+
"\n",
|
| 81 |
+
"Our *embedding matrix* will be built accordingly: \n",
|
| 82 |
+
"1) For words already present in the pretrained vocabulary: When a word from our current task is also present in the vocabulary of pretrained model, we simply copy the corresponding row from the preatrained model's embedding matrix.\n",
|
| 83 |
+
"2) For new words: When we encounter a new word that wasn't in the pretrained vocabulary and therfore there will be no embedding for that word. So we initialise a new row in our embedding matrix with random vector."
|
| 84 |
+
]
|
| 85 |
+
},
|
| 86 |
+
{
|
| 87 |
+
"cell_type": "markdown",
|
| 88 |
+
"id": "24b796e6-59df-4b9a-924e-6d9160a77359",
|
| 89 |
+
"metadata": {},
|
| 90 |
+
"source": [
|
| 91 |
+
"The steps necessary to create a language model has following jargon:\n",
|
| 92 |
+
"\n",
|
| 93 |
+
"- Tokenization: Convert text into list of words\n",
|
| 94 |
+
"- Numericalization: Make up a list of all unique words (i.e. vocab), convert them into numbers by looking up its index from vocab.\n",
|
| 95 |
+
"- Language model data loader creation: fastai provides an `LMDataLoader` class which automatically handles creating a dependent variable which is offset from independent variable by one token.(meaning the dependent and independent variables differ by one token since our task is to predict the next word in text). It also handles some important functions such as shuffling data in order to maintain proper structure of dependent and independent variables.\n",
|
| 96 |
+
"- Language model creation: we need a special kind of model that takes input lists(big or small). There are number of ways to do this but here we'll use RNNs(recurrent neural nets)."
|
| 97 |
+
]
|
| 98 |
+
},
|
| 99 |
+
{
|
| 100 |
+
"cell_type": "markdown",
|
| 101 |
+
"id": "559b77a4-3ae1-4830-bbb4-2bd353694ef7",
|
| 102 |
+
"metadata": {},
|
| 103 |
+
"source": [
|
| 104 |
+
"### Tokenization\n",
|
| 105 |
+
"\n",
|
| 106 |
+
"When we said \"convert the text into a list of words,\" we left out a lot of details. For instance, what do we do with punctuation? How do we deal with a word like \"don't\"? Is it one word, or two? What about long medical or chemical words? Should they be split into their separate pieces of meaning? How about hyphenated words? What about languages like German and Polish where we can create really long words from many, many pieces? What about languages like Japanese and Chinese that don't use bases at all, and don't really have a well-defined idea of word?\n",
|
| 107 |
+
"\n",
|
| 108 |
+
"Because there is no one correct answer to these questions, there is no one approach to tokenization.\n",
|
| 109 |
+
"\n",
|
| 110 |
+
"There are three main approaches-\n",
|
| 111 |
+
"1. word-based tokenization: split sentence on spaces and taking care of language specific rules to separate parts of meaning even when there is no space.\n",
|
| 112 |
+
"2. sub-word based tokenization: split words into smaller parts based on commonly occuring substrings.\n",
|
| 113 |
+
"3. character based tokenization: split sentece into individual characters.\n",
|
| 114 |
+
"\n",
|
| 115 |
+
">token: One element of list created using tokenization process."
|
| 116 |
+
]
|
| 117 |
+
},
|
| 118 |
+
{
|
| 119 |
+
"cell_type": "markdown",
|
| 120 |
+
"id": "4385df82-61df-4e3d-be12-04ad48e1f38c",
|
| 121 |
+
"metadata": {},
|
| 122 |
+
"source": [
|
| 123 |
+
"### Word tokenization with fastai\n",
|
| 124 |
+
"\n",
|
| 125 |
+
"This relies on an assumption that spaces provide useful separation of components of meaning in sentence.\n",
|
| 126 |
+
"fastai provides a consistent interface to range of tokenizers instead of providing its own tokenizers."
|
| 127 |
+
]
|
| 128 |
+
},
|
| 129 |
+
{
|
| 130 |
+
"cell_type": "code",
|
| 131 |
+
"execution_count": 3,
|
| 132 |
+
"id": "6a0112bb-ced2-49c9-8e4a-ba0e820297b7",
|
| 133 |
+
"metadata": {},
|
| 134 |
+
"outputs": [],
|
| 135 |
+
"source": [
|
| 136 |
+
"from fastai.text.all import *\n",
|
| 137 |
+
"path=untar_data(URLs.IMDB)"
|
| 138 |
+
]
|
| 139 |
+
},
|
| 140 |
+
{
|
| 141 |
+
"cell_type": "markdown",
|
| 142 |
+
"id": "32dd4c8b-9fa9-4b80-a12f-6542d790bc9d",
|
| 143 |
+
"metadata": {},
|
| 144 |
+
"source": [
|
| 145 |
+
"To try tokenizers, we need to get the text files. Similar to `get_image_files` fot CV tasks, we have `get_text_files` for NLP tasks to get all text files in a path."
|
| 146 |
+
]
|
| 147 |
+
},
|
| 148 |
+
{
|
| 149 |
+
"cell_type": "code",
|
| 150 |
+
"execution_count": 4,
|
| 151 |
+
"id": "373acfea-ba21-414c-a4c0-a92fed27c3c9",
|
| 152 |
+
"metadata": {},
|
| 153 |
+
"outputs": [],
|
| 154 |
+
"source": [
|
| 155 |
+
"files=get_text_files(path,folders=['train','test','unsup'])"
|
| 156 |
+
]
|
| 157 |
+
},
|
| 158 |
+
{
|
| 159 |
+
"cell_type": "markdown",
|
| 160 |
+
"id": "84104613-1ab6-4a04-810f-06f5a91cf737",
|
| 161 |
+
"metadata": {},
|
| 162 |
+
"source": [
|
| 163 |
+
"The `folders` parameter is used to restrict the search to particular list of folders."
|
| 164 |
+
]
|
| 165 |
+
},
|
| 166 |
+
{
|
| 167 |
+
"cell_type": "code",
|
| 168 |
+
"execution_count": 5,
|
| 169 |
+
"id": "83677b1e-d9a1-4811-ab66-83528d5cb68a",
|
| 170 |
+
"metadata": {},
|
| 171 |
+
"outputs": [
|
| 172 |
+
{
|
| 173 |
+
"data": {
|
| 174 |
+
"text/plain": [
|
| 175 |
+
"Path('/teamspace/studios/this_studio/.fastai/data/imdb/test/neg/0_2.txt')"
|
| 176 |
+
]
|
| 177 |
+
},
|
| 178 |
+
"execution_count": 5,
|
| 179 |
+
"metadata": {},
|
| 180 |
+
"output_type": "execute_result"
|
| 181 |
+
}
|
| 182 |
+
],
|
| 183 |
+
"source": [
|
| 184 |
+
"# grab the first file and view some part of it\n",
|
| 185 |
+
"files[0]"
|
| 186 |
+
]
|
| 187 |
+
},
|
| 188 |
+
{
|
| 189 |
+
"cell_type": "code",
|
| 190 |
+
"execution_count": 6,
|
| 191 |
+
"id": "976a1c13-1baa-452d-bec9-6b39ed51ad98",
|
| 192 |
+
"metadata": {},
|
| 193 |
+
"outputs": [
|
| 194 |
+
{
|
| 195 |
+
"data": {
|
| 196 |
+
"text/plain": [
|
| 197 |
+
"<_io.TextIOWrapper name='/teamspace/studios/this_studio/.fastai/data/imdb/test/neg/0_2.txt' mode='r' encoding='UTF-8'>"
|
| 198 |
+
]
|
| 199 |
+
},
|
| 200 |
+
"execution_count": 6,
|
| 201 |
+
"metadata": {},
|
| 202 |
+
"output_type": "execute_result"
|
| 203 |
+
}
|
| 204 |
+
],
|
| 205 |
+
"source": [
|
| 206 |
+
"files[0].open()"
|
| 207 |
+
]
|
| 208 |
+
},
|
| 209 |
+
{
|
| 210 |
+
"cell_type": "code",
|
| 211 |
+
"execution_count": 7,
|
| 212 |
+
"id": "97766ce1-68d9-4d59-862e-b14b2f629071",
|
| 213 |
+
"metadata": {},
|
| 214 |
+
"outputs": [],
|
| 215 |
+
"source": [
|
| 216 |
+
"txt=files[0].open().read()[:100]"
|
| 217 |
+
]
|
| 218 |
+
},
|
| 219 |
+
{
|
| 220 |
+
"cell_type": "code",
|
| 221 |
+
"execution_count": 8,
|
| 222 |
+
"id": "abdc41d5-87c4-49c3-b2fa-2c5e05d56fac",
|
| 223 |
+
"metadata": {},
|
| 224 |
+
"outputs": [
|
| 225 |
+
{
|
| 226 |
+
"data": {
|
| 227 |
+
"text/plain": [
|
| 228 |
+
"'Once again Mr. Costner has dragged out a movie for far longer than necessary. Aside from the terrifi'"
|
| 229 |
+
]
|
| 230 |
+
},
|
| 231 |
+
"execution_count": 8,
|
| 232 |
+
"metadata": {},
|
| 233 |
+
"output_type": "execute_result"
|
| 234 |
+
}
|
| 235 |
+
],
|
| 236 |
+
"source": [
|
| 237 |
+
"txt"
|
| 238 |
+
]
|
| 239 |
+
},
|
| 240 |
+
{
|
| 241 |
+
"cell_type": "markdown",
|
| 242 |
+
"id": "87f46d64-f56c-497d-9201-9da74ed6ee51",
|
| 243 |
+
"metadata": {},
|
| 244 |
+
"source": [
|
| 245 |
+
"spaCy is the deafult English word tokenizer when the book was written and instead of using `SpacyTokenizer`, we'll use `WordTokenizer` by fastai which refers to the default tokenizer used now.\n",
|
| 246 |
+
"\n",
|
| 247 |
+
"fastai's `coll_repr()` is used to display results. Displays first n items of collection along with full size and it's what `L`(which is a list-like collection with added-functionality) uses by default for string representation.\n",
|
| 248 |
+
"\n",
|
| 249 |
+
"**Note**: fastai's tokenizer takes a list of text so we need to wrap txt in list."
|
| 250 |
+
]
|
| 251 |
+
},
|
| 252 |
+
{
|
| 253 |
+
"cell_type": "code",
|
| 254 |
+
"execution_count": 9,
|
| 255 |
+
"id": "4d83ce26-8a1d-4e51-a540-31b35b7a0538",
|
| 256 |
+
"metadata": {},
|
| 257 |
+
"outputs": [
|
| 258 |
+
{
|
| 259 |
+
"name": "stdout",
|
| 260 |
+
"output_type": "stream",
|
| 261 |
+
"text": [
|
| 262 |
+
"(#19) ['Once','again','Mr.','Costner','has','dragged','out','a','movie','for','far','longer','than','necessary','.','Aside','from','the','terrifi']\n"
|
| 263 |
+
]
|
| 264 |
+
}
|
| 265 |
+
],
|
| 266 |
+
"source": [
|
| 267 |
+
"spacy=WordTokenizer()\n",
|
| 268 |
+
"toks=first(spacy([txt]))\n",
|
| 269 |
+
"print(coll_repr(toks,30))"
|
| 270 |
+
]
|
| 271 |
+
},
|
| 272 |
+
{
|
| 273 |
+
"cell_type": "markdown",
|
| 274 |
+
"id": "9f45e3d9-3672-4b38-8cb3-e4e4f0e74a98",
|
| 275 |
+
"metadata": {},
|
| 276 |
+
"source": [
|
| 277 |
+
"spaCy handles the all little details in text."
|
| 278 |
+
]
|
| 279 |
+
},
|
| 280 |
+
{
|
| 281 |
+
"cell_type": "markdown",
|
| 282 |
+
"id": "6b71cf9b-b203-4bab-bdb6-4d4ed6689b65",
|
| 283 |
+
"metadata": {},
|
| 284 |
+
"source": [
|
| 285 |
+
"fastai adds some additional functionality to tokenization process with the `Tokenizer` class."
|
| 286 |
+
]
|
| 287 |
+
},
|
| 288 |
+
{
|
| 289 |
+
"cell_type": "code",
|
| 290 |
+
"execution_count": 10,
|
| 291 |
+
"id": "276ffa86-741b-4c52-9ba7-37bcb87f2261",
|
| 292 |
+
"metadata": {},
|
| 293 |
+
"outputs": [
|
| 294 |
+
{
|
| 295 |
+
"name": "stdout",
|
| 296 |
+
"output_type": "stream",
|
| 297 |
+
"text": [
|
| 298 |
+
"(#25) ['xxbos','xxmaj','once','again','xxmaj','mr','.','xxmaj','costner','has','dragged','out','a','movie','for','far','longer','than','necessary','.','xxmaj','aside','from','the','terrifi']\n"
|
| 299 |
+
]
|
| 300 |
+
}
|
| 301 |
+
],
|
| 302 |
+
"source": [
|
| 303 |
+
"tkn=Tokenizer(spacy)\n",
|
| 304 |
+
"print(coll_repr(tkn(txt),30))"
|
| 305 |
+
]
|
| 306 |
+
},
|
| 307 |
+
{
|
| 308 |
+
"cell_type": "markdown",
|
| 309 |
+
"id": "19d9b3a3-91cd-4e18-b5bb-e0d3043b9258",
|
| 310 |
+
"metadata": {},
|
| 311 |
+
"source": [
|
| 312 |
+
"The tokens which start with characters 'xx' are called special tokens. By recognising the start token(xxbos), the model will be able to learn it needs to forget what was said previously and focus on upcoming words.\n",
|
| 313 |
+
"\n",
|
| 314 |
+
"These are not by deafult from spaCy, fastai adds them when processing text and desgined for model to understand important parts of sentence.\n",
|
| 315 |
+
"\n",
|
| 316 |
+
"Some main special tokens:\n",
|
| 317 |
+
"\n",
|
| 318 |
+
"- `xxbos`: indicates beginning of text\n",
|
| 319 |
+
"- `xxmaj`: indicates the next word begins with a capital letter(since everything is lowercased)\n",
|
| 320 |
+
"- `xxunk`: indicates word is unknown\n",
|
| 321 |
+
"\n",
|
| 322 |
+
"To see the rules that were used, we can check thedefault rules usinf the line below:"
|
| 323 |
+
]
|
| 324 |
+
},
|
| 325 |
+
{
|
| 326 |
+
"cell_type": "code",
|
| 327 |
+
"execution_count": 11,
|
| 328 |
+
"id": "54a10034-1447-4f0d-bb84-4ec686431884",
|
| 329 |
+
"metadata": {},
|
| 330 |
+
"outputs": [
|
| 331 |
+
{
|
| 332 |
+
"data": {
|
| 333 |
+
"text/plain": [
|
| 334 |
+
"[<function fastai.text.core.fix_html(x)>,\n",
|
| 335 |
+
" <function fastai.text.core.replace_rep(t)>,\n",
|
| 336 |
+
" <function fastai.text.core.replace_wrep(t)>,\n",
|
| 337 |
+
" <function fastai.text.core.spec_add_spaces(t)>,\n",
|
| 338 |
+
" <function fastai.text.core.rm_useless_spaces(t)>,\n",
|
| 339 |
+
" <function fastai.text.core.replace_all_caps(t)>,\n",
|
| 340 |
+
" <function fastai.text.core.replace_maj(t)>,\n",
|
| 341 |
+
" <function fastai.text.core.lowercase(t, add_bos=True, add_eos=False)>]"
|
| 342 |
+
]
|
| 343 |
+
},
|
| 344 |
+
"execution_count": 11,
|
| 345 |
+
"metadata": {},
|
| 346 |
+
"output_type": "execute_result"
|
| 347 |
+
}
|
| 348 |
+
],
|
| 349 |
+
"source": [
|
| 350 |
+
"defaults.text_proc_rules"
|
| 351 |
+
]
|
| 352 |
+
},
|
| 353 |
+
{
|
| 354 |
+
"cell_type": "markdown",
|
| 355 |
+
"id": "a286be44-bae6-4ee8-b5eb-abece30fded9",
|
| 356 |
+
"metadata": {},
|
| 357 |
+
"source": [
|
| 358 |
+
"Summary of what each does:\n",
|
| 359 |
+
"- `fix_html`: replaces special HTML characs with readable version\n",
|
| 360 |
+
"- `replace_rep`: replaces any character repeated more than three times with a special token(`xxrep`) followed by number of times and then the character\n",
|
| 361 |
+
"- `replace_wrep`: replaces any word repeated more than three times with a special token(`xxwrep`) followed by number of times and then the word.\n",
|
| 362 |
+
"- `spec_add_spaces`: adds spaces arong / and #\n",
|
| 363 |
+
"- `rm_useless_spaces`: removes all repition of space character\n",
|
| 364 |
+
"- `replace_maj`: lowercases a capitalised word and adds a specila token for capitalises(`xxmaj`) in front.\n",
|
| 365 |
+
"- `replace_all_caps`: lowercases a word written in all caps and adds a specialised token `xxup`\n",
|
| 366 |
+
"- `lowercase`: lowercases all text and adds special token at beginning(`xxbos`) and/or end(`xxeos`)"
|
| 367 |
+
]
|
| 368 |
+
},
|
| 369 |
+
{
|
| 370 |
+
"cell_type": "markdown",
|
| 371 |
+
"id": "53bfd6ff-fb49-4df5-9ba5-cbfbed93e9c0",
|
| 372 |
+
"metadata": {},
|
| 373 |
+
"source": [
|
| 374 |
+
"### Subword tokenization \n",
|
| 375 |
+
"\n",
|
| 376 |
+
"This tokenization is best for languages such as chinese, hungarian etc where the words are not separated by space.\n",
|
| 377 |
+
"\n",
|
| 378 |
+
"To handle these, we use this tokenization which has the 2 steps:\n",
|
| 379 |
+
"1. Analyse corpus of documents to find the most *commonly occuring groups of letters* and this becomes the vocab.\n",
|
| 380 |
+
"2. Tokenise the corpus using this vocab of subword units."
|
| 381 |
+
]
|
| 382 |
+
},
|
| 383 |
+
{
|
| 384 |
+
"cell_type": "code",
|
| 385 |
+
"execution_count": 12,
|
| 386 |
+
"id": "7f3f5ad6-2bca-489e-973d-cf33b1a9f80b",
|
| 387 |
+
"metadata": {},
|
| 388 |
+
"outputs": [],
|
| 389 |
+
"source": [
|
| 390 |
+
"txts=L(o.open().read() for o in files[:2000])"
|
| 391 |
+
]
|
| 392 |
+
},
|
| 393 |
+
{
|
| 394 |
+
"cell_type": "markdown",
|
| 395 |
+
"id": "6e22e42f-b8b3-4e75-893a-16b5dc96add3",
|
| 396 |
+
"metadata": {},
|
| 397 |
+
"source": [
|
| 398 |
+
"We instantiate tokenizer and pass size of vocab and then train it, i.e. we want it to read our documnets and find out the common sequence of characters to create the vocab. This is done using `setup` which is automatically called in usual data processing pipelines."
|
| 399 |
+
]
|
| 400 |
+
},
|
| 401 |
+
{
|
| 402 |
+
"cell_type": "code",
|
| 403 |
+
"execution_count": 13,
|
| 404 |
+
"id": "cbe29142-ed85-4984-9f4e-ca373de050cd",
|
| 405 |
+
"metadata": {},
|
| 406 |
+
"outputs": [],
|
| 407 |
+
"source": [
|
| 408 |
+
"def subword(sz):\n",
|
| 409 |
+
" sp=SubwordTokenizer(vocab_sz=sz)\n",
|
| 410 |
+
" sp.setup(txts)\n",
|
| 411 |
+
" return ' '.join(first(sp([txt])))"
|
| 412 |
+
]
|
| 413 |
+
},
|
| 414 |
+
{
|
| 415 |
+
"cell_type": "code",
|
| 416 |
+
"execution_count": 14,
|
| 417 |
+
"id": "15baf9db-8f29-477e-af19-fe25cf63f128",
|
| 418 |
+
"metadata": {},
|
| 419 |
+
"outputs": [
|
| 420 |
+
{
|
| 421 |
+
"data": {
|
| 422 |
+
"text/html": [
|
| 423 |
+
"\n",
|
| 424 |
+
"<style>\n",
|
| 425 |
+
" /* Turns off some styling */\n",
|
| 426 |
+
" progress {\n",
|
| 427 |
+
" /* gets rid of default border in Firefox and Opera. */\n",
|
| 428 |
+
" border: none;\n",
|
| 429 |
+
" /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
|
| 430 |
+
" background-size: auto;\n",
|
| 431 |
+
" }\n",
|
| 432 |
+
" progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
|
| 433 |
+
" background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
|
| 434 |
+
" }\n",
|
| 435 |
+
" .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
|
| 436 |
+
" background: #F44336;\n",
|
| 437 |
+
" }\n",
|
| 438 |
+
"</style>\n"
|
| 439 |
+
],
|
| 440 |
+
"text/plain": [
|
| 441 |
+
"<IPython.core.display.HTML object>"
|
| 442 |
+
]
|
| 443 |
+
},
|
| 444 |
+
"metadata": {},
|
| 445 |
+
"output_type": "display_data"
|
| 446 |
+
},
|
| 447 |
+
{
|
| 448 |
+
"data": {
|
| 449 |
+
"text/html": [],
|
| 450 |
+
"text/plain": [
|
| 451 |
+
"<IPython.core.display.HTML object>"
|
| 452 |
+
]
|
| 453 |
+
},
|
| 454 |
+
"metadata": {},
|
| 455 |
+
"output_type": "display_data"
|
| 456 |
+
},
|
| 457 |
+
{
|
| 458 |
+
"name": "stderr",
|
| 459 |
+
"output_type": "stream",
|
| 460 |
+
"text": [
|
| 461 |
+
"sentencepiece_trainer.cc(178) LOG(INFO) Running command: --input=tmp/texts.out --vocab_size=1000 --model_prefix=tmp/spm --character_coverage=0.99999 --model_type=unigram --unk_id=9 --pad_id=-1 --bos_id=-1 --eos_id=-1 --minloglevel=2 --user_defined_symbols=▁xxunk,▁xxpad,▁xxbos,▁xxeos,▁xxfld,▁xxrep,▁xxwrep,▁xxup,▁xxmaj --hard_vocab_limit=false\n"
|
| 462 |
+
]
|
| 463 |
+
},
|
| 464 |
+
{
|
| 465 |
+
"data": {
|
| 466 |
+
"text/plain": [
|
| 467 |
+
"'▁O n ce ▁again ▁M r . ▁Co st n er ▁has ▁ d ra g g ed ▁out ▁a ▁movie ▁for ▁far ▁long er ▁than ▁ ne ce s s ar y . ▁A side ▁from ▁the ▁ ter ri f i'"
|
| 468 |
+
]
|
| 469 |
+
},
|
| 470 |
+
"execution_count": 14,
|
| 471 |
+
"metadata": {},
|
| 472 |
+
"output_type": "execute_result"
|
| 473 |
+
}
|
| 474 |
+
],
|
| 475 |
+
"source": [
|
| 476 |
+
"subword(1000)"
|
| 477 |
+
]
|
| 478 |
+
},
|
| 479 |
+
{
|
| 480 |
+
"cell_type": "code",
|
| 481 |
+
"execution_count": 15,
|
| 482 |
+
"id": "a1b95d33-836b-43d3-bcec-98637b586618",
|
| 483 |
+
"metadata": {},
|
| 484 |
+
"outputs": [
|
| 485 |
+
{
|
| 486 |
+
"data": {
|
| 487 |
+
"text/html": [
|
| 488 |
+
"\n",
|
| 489 |
+
"<style>\n",
|
| 490 |
+
" /* Turns off some styling */\n",
|
| 491 |
+
" progress {\n",
|
| 492 |
+
" /* gets rid of default border in Firefox and Opera. */\n",
|
| 493 |
+
" border: none;\n",
|
| 494 |
+
" /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
|
| 495 |
+
" background-size: auto;\n",
|
| 496 |
+
" }\n",
|
| 497 |
+
" progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
|
| 498 |
+
" background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
|
| 499 |
+
" }\n",
|
| 500 |
+
" .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
|
| 501 |
+
" background: #F44336;\n",
|
| 502 |
+
" }\n",
|
| 503 |
+
"</style>\n"
|
| 504 |
+
],
|
| 505 |
+
"text/plain": [
|
| 506 |
+
"<IPython.core.display.HTML object>"
|
| 507 |
+
]
|
| 508 |
+
},
|
| 509 |
+
"metadata": {},
|
| 510 |
+
"output_type": "display_data"
|
| 511 |
+
},
|
| 512 |
+
{
|
| 513 |
+
"data": {
|
| 514 |
+
"text/html": [],
|
| 515 |
+
"text/plain": [
|
| 516 |
+
"<IPython.core.display.HTML object>"
|
| 517 |
+
]
|
| 518 |
+
},
|
| 519 |
+
"metadata": {},
|
| 520 |
+
"output_type": "display_data"
|
| 521 |
+
},
|
| 522 |
+
{
|
| 523 |
+
"data": {
|
| 524 |
+
"text/plain": [
|
| 525 |
+
"'▁ O n ce ▁a g a in ▁ M r . ▁ C o s t n er ▁ h a s ▁ d ra g g ed ▁ o u t ▁a ▁movie ▁for ▁f ar ▁ l on g er ▁ th an ▁ n e ce s s ar y . ▁A s i d e ▁f ro m ▁the ▁ ter ri f i'"
|
| 526 |
+
]
|
| 527 |
+
},
|
| 528 |
+
"execution_count": 15,
|
| 529 |
+
"metadata": {},
|
| 530 |
+
"output_type": "execute_result"
|
| 531 |
+
}
|
| 532 |
+
],
|
| 533 |
+
"source": [
|
| 534 |
+
"subword(200)"
|
| 535 |
+
]
|
| 536 |
+
},
|
| 537 |
+
{
|
| 538 |
+
"cell_type": "code",
|
| 539 |
+
"execution_count": 16,
|
| 540 |
+
"id": "c6cfbd46-d1b2-410d-95e3-aa526138e63b",
|
| 541 |
+
"metadata": {},
|
| 542 |
+
"outputs": [
|
| 543 |
+
{
|
| 544 |
+
"data": {
|
| 545 |
+
"text/html": [
|
| 546 |
+
"\n",
|
| 547 |
+
"<style>\n",
|
| 548 |
+
" /* Turns off some styling */\n",
|
| 549 |
+
" progress {\n",
|
| 550 |
+
" /* gets rid of default border in Firefox and Opera. */\n",
|
| 551 |
+
" border: none;\n",
|
| 552 |
+
" /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
|
| 553 |
+
" background-size: auto;\n",
|
| 554 |
+
" }\n",
|
| 555 |
+
" progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
|
| 556 |
+
" background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
|
| 557 |
+
" }\n",
|
| 558 |
+
" .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
|
| 559 |
+
" background: #F44336;\n",
|
| 560 |
+
" }\n",
|
| 561 |
+
"</style>\n"
|
| 562 |
+
],
|
| 563 |
+
"text/plain": [
|
| 564 |
+
"<IPython.core.display.HTML object>"
|
| 565 |
+
]
|
| 566 |
+
},
|
| 567 |
+
"metadata": {},
|
| 568 |
+
"output_type": "display_data"
|
| 569 |
+
},
|
| 570 |
+
{
|
| 571 |
+
"data": {
|
| 572 |
+
"text/html": [],
|
| 573 |
+
"text/plain": [
|
| 574 |
+
"<IPython.core.display.HTML object>"
|
| 575 |
+
]
|
| 576 |
+
},
|
| 577 |
+
"metadata": {},
|
| 578 |
+
"output_type": "display_data"
|
| 579 |
+
},
|
| 580 |
+
{
|
| 581 |
+
"data": {
|
| 582 |
+
"text/plain": [
|
| 583 |
+
"'▁On ce ▁again ▁Mr . ▁Costner ▁has ▁dragged ▁out ▁a ▁movie ▁for ▁far ▁longer ▁than ▁necessary . ▁A side ▁from ▁the ▁ ter ri fi'"
|
| 584 |
+
]
|
| 585 |
+
},
|
| 586 |
+
"execution_count": 16,
|
| 587 |
+
"metadata": {},
|
| 588 |
+
"output_type": "execute_result"
|
| 589 |
+
}
|
| 590 |
+
],
|
| 591 |
+
"source": [
|
| 592 |
+
"subword(10000)"
|
| 593 |
+
]
|
| 594 |
+
},
|
| 595 |
+
{
|
| 596 |
+
"cell_type": "markdown",
|
| 597 |
+
"id": "e89434f5-0955-46c5-b02b-37f2ab9fe113",
|
| 598 |
+
"metadata": {},
|
| 599 |
+
"source": [
|
| 600 |
+
"When we use fastai's subword tokenizer, `_` character represents a space in actual text.\n",
|
| 601 |
+
"\n",
|
| 602 |
+
"- If we use a *smaller vocab*, then each token will represent *fewer characters* and it will take *more tokens to represent the sentence*.\n",
|
| 603 |
+
"- If we use a *larger vocab*, the most common English words will end up in the vocab themselves and we *will not need as many to represent a sentence*.\n",
|
| 604 |
+
"\n",
|
| 605 |
+
"Picking a subword vocab size represents a compromise:\n",
|
| 606 |
+
"\n",
|
| 607 |
+
"- a *larger vocab* means *fewer tokens per sentence*, which means faster training, lesser memory and less state for model to remember but it means *larger embedding matrix* and require more data to learn.\n",
|
| 608 |
+
"\n",
|
| 609 |
+
"Overall, subword tokenization provides a way to scale between character tokenizatio(i.e using small subword vocab) and word tokenizatio(i.e using large subword vocab) and handles every language without needing language specific models to be developed.\n",
|
| 610 |
+
"\n",
|
| 611 |
+
"Once our text is split into tokens, we need to convert them into numbers."
|
| 612 |
+
]
|
| 613 |
+
},
|
| 614 |
+
{
|
| 615 |
+
"cell_type": "markdown",
|
| 616 |
+
"id": "4a7975c2-522a-4457-9581-65243487f469",
|
| 617 |
+
"metadata": {},
|
| 618 |
+
"source": [
|
| 619 |
+
"### Numerilization with fastai\n",
|
| 620 |
+
"\n",
|
| 621 |
+
"*Numericalization* is process of mapping tokens to integers. Steps are similar to those needed to create `Category` variable.\n",
|
| 622 |
+
"\n",
|
| 623 |
+
"1. Make a list of all possible levels of categorical variable(this is vocab)\n",
|
| 624 |
+
"2. Replace each level with its index value in vocab."
|
| 625 |
+
]
|
| 626 |
+
},
|
| 627 |
+
{
|
| 628 |
+
"cell_type": "code",
|
| 629 |
+
"execution_count": 17,
|
| 630 |
+
"id": "98e65ad1-4b13-4929-b792-55ce1205b505",
|
| 631 |
+
"metadata": {},
|
| 632 |
+
"outputs": [
|
| 633 |
+
{
|
| 634 |
+
"name": "stdout",
|
| 635 |
+
"output_type": "stream",
|
| 636 |
+
"text": [
|
| 637 |
+
"(#25) ['xxbos','xxmaj','once','again','xxmaj','mr','.','xxmaj','costner','has'...] 31\n"
|
| 638 |
+
]
|
| 639 |
+
}
|
| 640 |
+
],
|
| 641 |
+
"source": [
|
| 642 |
+
"toks=tkn(txt)\n",
|
| 643 |
+
"print(coll_repr(tkn(txt)),31)"
|
| 644 |
+
]
|
| 645 |
+
},
|
| 646 |
+
{
|
| 647 |
+
"cell_type": "markdown",
|
| 648 |
+
"id": "43f50521-23d2-4789-95bd-7852b1263a36",
|
| 649 |
+
"metadata": {},
|
| 650 |
+
"source": [
|
| 651 |
+
"Just like `SubwordTokenizer`, we need to call `setup` on `Numericalize`, in order to create vocab.\n",
|
| 652 |
+
"So first we need our tokenized corpus."
|
| 653 |
+
]
|
| 654 |
+
},
|
| 655 |
+
{
|
| 656 |
+
"cell_type": "code",
|
| 657 |
+
"execution_count": 18,
|
| 658 |
+
"id": "d1d5f6d3-5c51-4e6d-b722-186adecb8e9b",
|
| 659 |
+
"metadata": {},
|
| 660 |
+
"outputs": [
|
| 661 |
+
{
|
| 662 |
+
"data": {
|
| 663 |
+
"text/plain": [
|
| 664 |
+
"(#207) ['xxbos','xxmaj','once','again','xxmaj','mr','.','xxmaj','costner','has'...]"
|
| 665 |
+
]
|
| 666 |
+
},
|
| 667 |
+
"execution_count": 18,
|
| 668 |
+
"metadata": {},
|
| 669 |
+
"output_type": "execute_result"
|
| 670 |
+
}
|
| 671 |
+
],
|
| 672 |
+
"source": [
|
| 673 |
+
"toks200=txts[:200].map(tkn)\n",
|
| 674 |
+
"toks200[0]"
|
| 675 |
+
]
|
| 676 |
+
},
|
| 677 |
+
{
|
| 678 |
+
"cell_type": "code",
|
| 679 |
+
"execution_count": 19,
|
| 680 |
+
"id": "0c4a320b-ff04-4ce5-abb9-98c2f941b94f",
|
| 681 |
+
"metadata": {},
|
| 682 |
+
"outputs": [
|
| 683 |
+
{
|
| 684 |
+
"data": {
|
| 685 |
+
"text/plain": [
|
| 686 |
+
"\"(#1968) ['xxunk','xxpad','xxbos','xxeos','xxfld','xxrep','xxwrep','xxup','xxmaj','the','.',',','a','and','of','to','is','it','i','in'...]\""
|
| 687 |
+
]
|
| 688 |
+
},
|
| 689 |
+
"execution_count": 19,
|
| 690 |
+
"metadata": {},
|
| 691 |
+
"output_type": "execute_result"
|
| 692 |
+
}
|
| 693 |
+
],
|
| 694 |
+
"source": [
|
| 695 |
+
"# we then pass this to setup\n",
|
| 696 |
+
"num=Numericalize()\n",
|
| 697 |
+
"num.setup(toks200)\n",
|
| 698 |
+
"coll_repr(num.vocab,20)"
|
| 699 |
+
]
|
| 700 |
+
},
|
| 701 |
+
{
|
| 702 |
+
"cell_type": "markdown",
|
| 703 |
+
"id": "97cdd2b1-cc1d-45bd-a3cb-6ef7c73b52ee",
|
| 704 |
+
"metadata": {},
|
| 705 |
+
"source": [
|
| 706 |
+
"Our special rules tokens appear first followed by every word appearing once in frequency order. The defaults of `Numericalize` are `min_freq=3, max_vocab=60000`. `max_vocab=60000` results in fastai replacing the words other than most common 60000 words with a special token `xxunk` means unknown word. This is useful to avoid haing large embedding matrix which can slow down traing. `min_freq=3` means any word woith freq<3 is replaced by `xxunk`.\n",
|
| 707 |
+
"\n",
|
| 708 |
+
"fastai can also numericalize our dataset using vocab that you provide, by passing a list of words as `vocab` parameter.\n",
|
| 709 |
+
"\n",
|
| 710 |
+
"Once we have created `Numericalize` object, we can use it as a function:"
|
| 711 |
+
]
|
| 712 |
+
},
|
| 713 |
+
{
|
| 714 |
+
"cell_type": "code",
|
| 715 |
+
"execution_count": 20,
|
| 716 |
+
"id": "fbafd886-1146-403b-8d08-2b655bdfad40",
|
| 717 |
+
"metadata": {},
|
| 718 |
+
"outputs": [
|
| 719 |
+
{
|
| 720 |
+
"data": {
|
| 721 |
+
"text/plain": [
|
| 722 |
+
"TensorText([ 2, 8, 349, 183, 8, 1177, 10, 8, 1178, 60, 1455, 62, 12, 25, 28, 189, 957, 93, 958, 10])"
|
| 723 |
+
]
|
| 724 |
+
},
|
| 725 |
+
"execution_count": 20,
|
| 726 |
+
"metadata": {},
|
| 727 |
+
"output_type": "execute_result"
|
| 728 |
+
}
|
| 729 |
+
],
|
| 730 |
+
"source": [
|
| 731 |
+
"nums=num(toks)[:20]\n",
|
| 732 |
+
"nums"
|
| 733 |
+
]
|
| 734 |
+
},
|
| 735 |
+
{
|
| 736 |
+
"cell_type": "markdown",
|
| 737 |
+
"id": "9c74d413-fb75-4e8a-a31e-b5539e429c59",
|
| 738 |
+
"metadata": {},
|
| 739 |
+
"source": [
|
| 740 |
+
"This time our tokens have been converted to a tensor of integers that our model can recieve. We can that they map back to original text as follows."
|
| 741 |
+
]
|
| 742 |
+
},
|
| 743 |
+
{
|
| 744 |
+
"cell_type": "code",
|
| 745 |
+
"execution_count": 21,
|
| 746 |
+
"id": "d5adb361-9088-4a03-8749-7b1067e8b953",
|
| 747 |
+
"metadata": {},
|
| 748 |
+
"outputs": [
|
| 749 |
+
{
|
| 750 |
+
"data": {
|
| 751 |
+
"text/plain": [
|
| 752 |
+
"'xxbos xxmaj once again xxmaj mr . xxmaj costner has dragged out a movie for far longer than necessary .'"
|
| 753 |
+
]
|
| 754 |
+
},
|
| 755 |
+
"execution_count": 21,
|
| 756 |
+
"metadata": {},
|
| 757 |
+
"output_type": "execute_result"
|
| 758 |
+
}
|
| 759 |
+
],
|
| 760 |
+
"source": [
|
| 761 |
+
"' '.join(num.vocab[o] for o in nums)"
|
| 762 |
+
]
|
| 763 |
+
},
|
| 764 |
+
{
|
| 765 |
+
"cell_type": "markdown",
|
| 766 |
+
"id": "ec674dd1-1e69-4476-872d-d3c2d1a7e604",
|
| 767 |
+
"metadata": {},
|
| 768 |
+
"source": [
|
| 769 |
+
"Now that we have numbers, we need to put them into batches for our model."
|
| 770 |
+
]
|
| 771 |
+
},
|
| 772 |
+
{
|
| 773 |
+
"cell_type": "markdown",
|
| 774 |
+
"id": "a64b6774-1b4e-49cf-987b-9bba45e6af68",
|
| 775 |
+
"metadata": {},
|
| 776 |
+
"source": [
|
| 777 |
+
"### Putting our texts into batches for a language model\n",
|
| 778 |
+
"\n",
|
| 779 |
+
"Our language model should read text in order such that each new batch should begin precisely where the previous one left off and this unlike images where we had to resize the images to get same height and width before grouping them into mini-batch so they can stack together efficiently in a single tensor.\n",
|
| 780 |
+
"\n",
|
| 781 |
+
"Suppose we have the following text:\n",
|
| 782 |
+
"\n",
|
| 783 |
+
"> : In this chapter, we will go back over the example of classifying movie reviews we studied in chapter 1 and dig deeper under the surface. First we will look at the processing steps necessary to convert text into numbers and how to customize it. By doing this, we'll have another example of the PreProcessor used in the data block API.\\nThen we will study how we build a language model and train it for a while.\n",
|
| 784 |
+
"\n",
|
| 785 |
+
"The tokenization process will add special tokens and deal with punctuation to return this text:\n",
|
| 786 |
+
"\n",
|
| 787 |
+
"> : xxbos xxmaj in this chapter , we will go back over the example of classifying movie reviews we studied in chapter 1 and dig deeper under the surface . xxmaj first we will look at the processing steps necessary to convert text into numbers and how to customize it . xxmaj by doing this , we 'll have another example of the preprocessor used in the data block xxup api . \\n xxmaj then we will study how we build a language model and train it for a while .\n",
|
| 788 |
+
"\n",
|
| 789 |
+
"We now have 90 tokens, separated by spaces. Let's say we want a batch size of 6. We need to break this text into 6 contiguous parts of length 15:"
|
| 790 |
+
]
|
| 791 |
+
},
|
| 792 |
+
{
|
| 793 |
+
"cell_type": "code",
|
| 794 |
+
"execution_count": 22,
|
| 795 |
+
"id": "aa7c6cc3-ec70-43c9-9b6e-57f67c2a7941",
|
| 796 |
+
"metadata": {},
|
| 797 |
+
"outputs": [
|
| 798 |
+
{
|
| 799 |
+
"data": {
|
| 800 |
+
"text/html": [
|
| 801 |
+
"<table border=\"1\" class=\"dataframe\">\n",
|
| 802 |
+
" <tbody>\n",
|
| 803 |
+
" <tr>\n",
|
| 804 |
+
" <td>xxbos</td>\n",
|
| 805 |
+
" <td>xxmaj</td>\n",
|
| 806 |
+
" <td>in</td>\n",
|
| 807 |
+
" <td>this</td>\n",
|
| 808 |
+
" <td>chapter</td>\n",
|
| 809 |
+
" <td>,</td>\n",
|
| 810 |
+
" <td>we</td>\n",
|
| 811 |
+
" <td>will</td>\n",
|
| 812 |
+
" <td>go</td>\n",
|
| 813 |
+
" <td>back</td>\n",
|
| 814 |
+
" <td>over</td>\n",
|
| 815 |
+
" <td>the</td>\n",
|
| 816 |
+
" <td>example</td>\n",
|
| 817 |
+
" <td>of</td>\n",
|
| 818 |
+
" <td>classifying</td>\n",
|
| 819 |
+
" </tr>\n",
|
| 820 |
+
" <tr>\n",
|
| 821 |
+
" <td>movie</td>\n",
|
| 822 |
+
" <td>reviews</td>\n",
|
| 823 |
+
" <td>we</td>\n",
|
| 824 |
+
" <td>studied</td>\n",
|
| 825 |
+
" <td>in</td>\n",
|
| 826 |
+
" <td>chapter</td>\n",
|
| 827 |
+
" <td>1</td>\n",
|
| 828 |
+
" <td>and</td>\n",
|
| 829 |
+
" <td>dig</td>\n",
|
| 830 |
+
" <td>deeper</td>\n",
|
| 831 |
+
" <td>under</td>\n",
|
| 832 |
+
" <td>the</td>\n",
|
| 833 |
+
" <td>surface</td>\n",
|
| 834 |
+
" <td>.</td>\n",
|
| 835 |
+
" <td>xxmaj</td>\n",
|
| 836 |
+
" </tr>\n",
|
| 837 |
+
" <tr>\n",
|
| 838 |
+
" <td>first</td>\n",
|
| 839 |
+
" <td>we</td>\n",
|
| 840 |
+
" <td>will</td>\n",
|
| 841 |
+
" <td>look</td>\n",
|
| 842 |
+
" <td>at</td>\n",
|
| 843 |
+
" <td>the</td>\n",
|
| 844 |
+
" <td>processing</td>\n",
|
| 845 |
+
" <td>steps</td>\n",
|
| 846 |
+
" <td>necessary</td>\n",
|
| 847 |
+
" <td>to</td>\n",
|
| 848 |
+
" <td>convert</td>\n",
|
| 849 |
+
" <td>text</td>\n",
|
| 850 |
+
" <td>into</td>\n",
|
| 851 |
+
" <td>numbers</td>\n",
|
| 852 |
+
" <td>and</td>\n",
|
| 853 |
+
" </tr>\n",
|
| 854 |
+
" <tr>\n",
|
| 855 |
+
" <td>how</td>\n",
|
| 856 |
+
" <td>to</td>\n",
|
| 857 |
+
" <td>customize</td>\n",
|
| 858 |
+
" <td>it</td>\n",
|
| 859 |
+
" <td>.</td>\n",
|
| 860 |
+
" <td>xxmaj</td>\n",
|
| 861 |
+
" <td>by</td>\n",
|
| 862 |
+
" <td>doing</td>\n",
|
| 863 |
+
" <td>this</td>\n",
|
| 864 |
+
" <td>,</td>\n",
|
| 865 |
+
" <td>we</td>\n",
|
| 866 |
+
" <td>'ll</td>\n",
|
| 867 |
+
" <td>have</td>\n",
|
| 868 |
+
" <td>another</td>\n",
|
| 869 |
+
" <td>example</td>\n",
|
| 870 |
+
" </tr>\n",
|
| 871 |
+
" <tr>\n",
|
| 872 |
+
" <td>of</td>\n",
|
| 873 |
+
" <td>the</td>\n",
|
| 874 |
+
" <td>preprocessor</td>\n",
|
| 875 |
+
" <td>used</td>\n",
|
| 876 |
+
" <td>in</td>\n",
|
| 877 |
+
" <td>the</td>\n",
|
| 878 |
+
" <td>data</td>\n",
|
| 879 |
+
" <td>block</td>\n",
|
| 880 |
+
" <td>xxup</td>\n",
|
| 881 |
+
" <td>api</td>\n",
|
| 882 |
+
" <td>.</td>\n",
|
| 883 |
+
" <td>\\n</td>\n",
|
| 884 |
+
" <td>xxmaj</td>\n",
|
| 885 |
+
" <td>then</td>\n",
|
| 886 |
+
" <td>we</td>\n",
|
| 887 |
+
" </tr>\n",
|
| 888 |
+
" <tr>\n",
|
| 889 |
+
" <td>will</td>\n",
|
| 890 |
+
" <td>study</td>\n",
|
| 891 |
+
" <td>how</td>\n",
|
| 892 |
+
" <td>we</td>\n",
|
| 893 |
+
" <td>build</td>\n",
|
| 894 |
+
" <td>a</td>\n",
|
| 895 |
+
" <td>language</td>\n",
|
| 896 |
+
" <td>model</td>\n",
|
| 897 |
+
" <td>and</td>\n",
|
| 898 |
+
" <td>train</td>\n",
|
| 899 |
+
" <td>it</td>\n",
|
| 900 |
+
" <td>for</td>\n",
|
| 901 |
+
" <td>a</td>\n",
|
| 902 |
+
" <td>while</td>\n",
|
| 903 |
+
" <td>.</td>\n",
|
| 904 |
+
" </tr>\n",
|
| 905 |
+
" </tbody>\n",
|
| 906 |
+
"</table>"
|
| 907 |
+
],
|
| 908 |
+
"text/plain": [
|
| 909 |
+
"<IPython.core.display.HTML object>"
|
| 910 |
+
]
|
| 911 |
+
},
|
| 912 |
+
"metadata": {},
|
| 913 |
+
"output_type": "display_data"
|
| 914 |
+
}
|
| 915 |
+
],
|
| 916 |
+
"source": [
|
| 917 |
+
"stream = \"In this chapter, we will go back over the example of classifying movie reviews we studied in chapter 1 and dig deeper under the surface. First we will look at the processing steps necessary to convert text into numbers and how to customize it. By doing this, we'll have another example of the PreProcessor used in the data block API.\\nThen we will study how we build a language model and train it for a while.\"\n",
|
| 918 |
+
"tokens=tkn(stream)\n",
|
| 919 |
+
"bs,seq_len=6,15\n",
|
| 920 |
+
"d_tokens=np.array([tokens[i*seq_len:(i+1)*seq_len] for i in range(bs)])\n",
|
| 921 |
+
"df=pd.DataFrame(d_tokens)\n",
|
| 922 |
+
"display(HTML(df.to_html(index=False,header=None)))"
|
| 923 |
+
]
|
| 924 |
+
},
|
| 925 |
+
{
|
| 926 |
+
"cell_type": "markdown",
|
| 927 |
+
"id": "0870a3e0-1d96-467b-bfd9-64087e9c5ff3",
|
| 928 |
+
"metadata": {},
|
| 929 |
+
"source": [
|
| 930 |
+
"We need to divide this array more finely into subarrays of a fixed sequence length. It is impostant to maintain order within and across these subarrays, because we will use a model that maintains a state so that it remembers what it read previously when predicting what comes next.\n",
|
| 931 |
+
"\n",
|
| 932 |
+
"**Next didn't understand why we need the two blocks of code**."
|
| 933 |
+
]
|
| 934 |
+
},
|
| 935 |
+
{
|
| 936 |
+
"cell_type": "code",
|
| 937 |
+
"execution_count": 23,
|
| 938 |
+
"id": "ebfea93b-eccd-44f8-9073-c037ad8cdeef",
|
| 939 |
+
"metadata": {},
|
| 940 |
+
"outputs": [
|
| 941 |
+
{
|
| 942 |
+
"data": {
|
| 943 |
+
"text/html": [
|
| 944 |
+
"<table border=\"1\" class=\"dataframe\">\n",
|
| 945 |
+
" <tbody>\n",
|
| 946 |
+
" <tr>\n",
|
| 947 |
+
" <td>xxbos</td>\n",
|
| 948 |
+
" <td>xxmaj</td>\n",
|
| 949 |
+
" <td>in</td>\n",
|
| 950 |
+
" <td>this</td>\n",
|
| 951 |
+
" <td>chapter</td>\n",
|
| 952 |
+
" </tr>\n",
|
| 953 |
+
" <tr>\n",
|
| 954 |
+
" <td>movie</td>\n",
|
| 955 |
+
" <td>reviews</td>\n",
|
| 956 |
+
" <td>we</td>\n",
|
| 957 |
+
" <td>studied</td>\n",
|
| 958 |
+
" <td>in</td>\n",
|
| 959 |
+
" </tr>\n",
|
| 960 |
+
" <tr>\n",
|
| 961 |
+
" <td>first</td>\n",
|
| 962 |
+
" <td>we</td>\n",
|
| 963 |
+
" <td>will</td>\n",
|
| 964 |
+
" <td>look</td>\n",
|
| 965 |
+
" <td>at</td>\n",
|
| 966 |
+
" </tr>\n",
|
| 967 |
+
" <tr>\n",
|
| 968 |
+
" <td>how</td>\n",
|
| 969 |
+
" <td>to</td>\n",
|
| 970 |
+
" <td>customize</td>\n",
|
| 971 |
+
" <td>it</td>\n",
|
| 972 |
+
" <td>.</td>\n",
|
| 973 |
+
" </tr>\n",
|
| 974 |
+
" <tr>\n",
|
| 975 |
+
" <td>of</td>\n",
|
| 976 |
+
" <td>the</td>\n",
|
| 977 |
+
" <td>preprocessor</td>\n",
|
| 978 |
+
" <td>used</td>\n",
|
| 979 |
+
" <td>in</td>\n",
|
| 980 |
+
" </tr>\n",
|
| 981 |
+
" <tr>\n",
|
| 982 |
+
" <td>will</td>\n",
|
| 983 |
+
" <td>study</td>\n",
|
| 984 |
+
" <td>how</td>\n",
|
| 985 |
+
" <td>we</td>\n",
|
| 986 |
+
" <td>build</td>\n",
|
| 987 |
+
" </tr>\n",
|
| 988 |
+
" </tbody>\n",
|
| 989 |
+
"</table>"
|
| 990 |
+
],
|
| 991 |
+
"text/plain": [
|
| 992 |
+
"<IPython.core.display.HTML object>"
|
| 993 |
+
]
|
| 994 |
+
},
|
| 995 |
+
"metadata": {},
|
| 996 |
+
"output_type": "display_data"
|
| 997 |
+
}
|
| 998 |
+
],
|
| 999 |
+
"source": [
|
| 1000 |
+
"bs,seq_len=6,5\n",
|
| 1001 |
+
"d_tokens=np.array([tokens[i*15:i*15+seq_len] for i in range(bs)])\n",
|
| 1002 |
+
"df = pd.DataFrame(d_tokens)\n",
|
| 1003 |
+
"display(HTML(df.to_html(index=False,header=None)))"
|
| 1004 |
+
]
|
| 1005 |
+
},
|
| 1006 |
+
{
|
| 1007 |
+
"cell_type": "code",
|
| 1008 |
+
"execution_count": 24,
|
| 1009 |
+
"id": "c1c97fa8-b3fd-4dd9-a74f-5d975580784b",
|
| 1010 |
+
"metadata": {},
|
| 1011 |
+
"outputs": [
|
| 1012 |
+
{
|
| 1013 |
+
"data": {
|
| 1014 |
+
"text/html": [
|
| 1015 |
+
"<table border=\"1\" class=\"dataframe\">\n",
|
| 1016 |
+
" <tbody>\n",
|
| 1017 |
+
" <tr>\n",
|
| 1018 |
+
" <td>,</td>\n",
|
| 1019 |
+
" <td>we</td>\n",
|
| 1020 |
+
" <td>will</td>\n",
|
| 1021 |
+
" <td>go</td>\n",
|
| 1022 |
+
" <td>back</td>\n",
|
| 1023 |
+
" </tr>\n",
|
| 1024 |
+
" <tr>\n",
|
| 1025 |
+
" <td>chapter</td>\n",
|
| 1026 |
+
" <td>1</td>\n",
|
| 1027 |
+
" <td>and</td>\n",
|
| 1028 |
+
" <td>dig</td>\n",
|
| 1029 |
+
" <td>deeper</td>\n",
|
| 1030 |
+
" </tr>\n",
|
| 1031 |
+
" <tr>\n",
|
| 1032 |
+
" <td>the</td>\n",
|
| 1033 |
+
" <td>processing</td>\n",
|
| 1034 |
+
" <td>steps</td>\n",
|
| 1035 |
+
" <td>necessary</td>\n",
|
| 1036 |
+
" <td>to</td>\n",
|
| 1037 |
+
" </tr>\n",
|
| 1038 |
+
" <tr>\n",
|
| 1039 |
+
" <td>xxmaj</td>\n",
|
| 1040 |
+
" <td>by</td>\n",
|
| 1041 |
+
" <td>doing</td>\n",
|
| 1042 |
+
" <td>this</td>\n",
|
| 1043 |
+
" <td>,</td>\n",
|
| 1044 |
+
" </tr>\n",
|
| 1045 |
+
" <tr>\n",
|
| 1046 |
+
" <td>the</td>\n",
|
| 1047 |
+
" <td>data</td>\n",
|
| 1048 |
+
" <td>block</td>\n",
|
| 1049 |
+
" <td>xxup</td>\n",
|
| 1050 |
+
" <td>api</td>\n",
|
| 1051 |
+
" </tr>\n",
|
| 1052 |
+
" <tr>\n",
|
| 1053 |
+
" <td>a</td>\n",
|
| 1054 |
+
" <td>language</td>\n",
|
| 1055 |
+
" <td>model</td>\n",
|
| 1056 |
+
" <td>and</td>\n",
|
| 1057 |
+
" <td>train</td>\n",
|
| 1058 |
+
" </tr>\n",
|
| 1059 |
+
" </tbody>\n",
|
| 1060 |
+
"</table>"
|
| 1061 |
+
],
|
| 1062 |
+
"text/plain": [
|
| 1063 |
+
"<IPython.core.display.HTML object>"
|
| 1064 |
+
]
|
| 1065 |
+
},
|
| 1066 |
+
"metadata": {},
|
| 1067 |
+
"output_type": "display_data"
|
| 1068 |
+
}
|
| 1069 |
+
],
|
| 1070 |
+
"source": [
|
| 1071 |
+
"# this one\n",
|
| 1072 |
+
"bs,seq_len = 6,5\n",
|
| 1073 |
+
"d_tokens = np.array([tokens[i*15+seq_len:i*15+2*seq_len] for i in range(bs)])\n",
|
| 1074 |
+
"df = pd.DataFrame(d_tokens)\n",
|
| 1075 |
+
"display(HTML(df.to_html(index=False,header=None)))"
|
| 1076 |
+
]
|
| 1077 |
+
},
|
| 1078 |
+
{
|
| 1079 |
+
"cell_type": "code",
|
| 1080 |
+
"execution_count": 25,
|
| 1081 |
+
"id": "4bd212b9-c832-4ba8-9526-089accbd729c",
|
| 1082 |
+
"metadata": {},
|
| 1083 |
+
"outputs": [
|
| 1084 |
+
{
|
| 1085 |
+
"data": {
|
| 1086 |
+
"text/html": [
|
| 1087 |
+
"<table border=\"1\" class=\"dataframe\">\n",
|
| 1088 |
+
" <tbody>\n",
|
| 1089 |
+
" <tr>\n",
|
| 1090 |
+
" <td>over</td>\n",
|
| 1091 |
+
" <td>the</td>\n",
|
| 1092 |
+
" <td>example</td>\n",
|
| 1093 |
+
" <td>of</td>\n",
|
| 1094 |
+
" <td>classifying</td>\n",
|
| 1095 |
+
" </tr>\n",
|
| 1096 |
+
" <tr>\n",
|
| 1097 |
+
" <td>under</td>\n",
|
| 1098 |
+
" <td>the</td>\n",
|
| 1099 |
+
" <td>surface</td>\n",
|
| 1100 |
+
" <td>.</td>\n",
|
| 1101 |
+
" <td>xxmaj</td>\n",
|
| 1102 |
+
" </tr>\n",
|
| 1103 |
+
" <tr>\n",
|
| 1104 |
+
" <td>convert</td>\n",
|
| 1105 |
+
" <td>text</td>\n",
|
| 1106 |
+
" <td>into</td>\n",
|
| 1107 |
+
" <td>numbers</td>\n",
|
| 1108 |
+
" <td>and</td>\n",
|
| 1109 |
+
" </tr>\n",
|
| 1110 |
+
" <tr>\n",
|
| 1111 |
+
" <td>we</td>\n",
|
| 1112 |
+
" <td>'ll</td>\n",
|
| 1113 |
+
" <td>have</td>\n",
|
| 1114 |
+
" <td>another</td>\n",
|
| 1115 |
+
" <td>example</td>\n",
|
| 1116 |
+
" </tr>\n",
|
| 1117 |
+
" <tr>\n",
|
| 1118 |
+
" <td>.</td>\n",
|
| 1119 |
+
" <td>\\n</td>\n",
|
| 1120 |
+
" <td>xxmaj</td>\n",
|
| 1121 |
+
" <td>then</td>\n",
|
| 1122 |
+
" <td>we</td>\n",
|
| 1123 |
+
" </tr>\n",
|
| 1124 |
+
" <tr>\n",
|
| 1125 |
+
" <td>it</td>\n",
|
| 1126 |
+
" <td>for</td>\n",
|
| 1127 |
+
" <td>a</td>\n",
|
| 1128 |
+
" <td>while</td>\n",
|
| 1129 |
+
" <td>.</td>\n",
|
| 1130 |
+
" </tr>\n",
|
| 1131 |
+
" </tbody>\n",
|
| 1132 |
+
"</table>"
|
| 1133 |
+
],
|
| 1134 |
+
"text/plain": [
|
| 1135 |
+
"<IPython.core.display.HTML object>"
|
| 1136 |
+
]
|
| 1137 |
+
},
|
| 1138 |
+
"metadata": {},
|
| 1139 |
+
"output_type": "display_data"
|
| 1140 |
+
}
|
| 1141 |
+
],
|
| 1142 |
+
"source": [
|
| 1143 |
+
"# and this one\n",
|
| 1144 |
+
"bs,seq_len = 6,5\n",
|
| 1145 |
+
"d_tokens = np.array([tokens[i*15+10:i*15+15] for i in range(bs)])\n",
|
| 1146 |
+
"df = pd.DataFrame(d_tokens)\n",
|
| 1147 |
+
"display(HTML(df.to_html(index=False,header=None)))"
|
| 1148 |
+
]
|
| 1149 |
+
},
|
| 1150 |
+
{
|
| 1151 |
+
"cell_type": "markdown",
|
| 1152 |
+
"id": "f0ba40f2-9df7-4190-ab7e-8a4e1627ac1a",
|
| 1153 |
+
"metadata": {},
|
| 1154 |
+
"source": [
|
| 1155 |
+
"First step is to transform individual texts into stream by concatenating them together and at the beginning of each epoch, we will shuffle entries to make a new stream(we shuffle order of documents and not the order of words inside them).\n",
|
| 1156 |
+
"\n",
|
| 1157 |
+
"We then cut the stream into a certain number of batches(batch size). For examples, if stream has 50,000 tokens and we set batch size as 10, this gives us 10 min-streams of 5000 tokens. What is important is that we preserve the order of tokens(i.e first mini-batch from 1-5000 second from 5001-10000 and so on). An `xxbos` is added so that the model knows when a new stream is beginning when it reads it.\n",
|
| 1158 |
+
"\n",
|
| 1159 |
+
"So to recap:\n",
|
| 1160 |
+
"\n",
|
| 1161 |
+
"- First we shuffle collection of docs(such as articles,text,reviews,etc) at each epoch\n",
|
| 1162 |
+
"- Concatenate them into a long stream\n",
|
| 1163 |
+
"- Cut the stream into mini-streams\n",
|
| 1164 |
+
"- Group mini-streams into batches\n",
|
| 1165 |
+
"- Then the model will read mini-streams in order. It maintains an internal state allowing it to carry context from one mini-stream to next within a batch.\n",
|
| 1166 |
+
"\n",
|
| 1167 |
+
"This is all done behind the scenes by fastai library when we create an `LMDataLoader`. We do this by applying our `Numericalize` object to tokenised texts."
|
| 1168 |
+
]
|
| 1169 |
+
},
|
| 1170 |
+
{
|
| 1171 |
+
"cell_type": "code",
|
| 1172 |
+
"execution_count": 26,
|
| 1173 |
+
"id": "545ce1bb-25c6-4fa5-bd99-ad0a21e5077f",
|
| 1174 |
+
"metadata": {},
|
| 1175 |
+
"outputs": [],
|
| 1176 |
+
"source": [
|
| 1177 |
+
"nums200=toks200.map(num)"
|
| 1178 |
+
]
|
| 1179 |
+
},
|
| 1180 |
+
{
|
| 1181 |
+
"cell_type": "code",
|
| 1182 |
+
"execution_count": 27,
|
| 1183 |
+
"id": "f9545e84-4691-4d78-8acd-e8e345f78afa",
|
| 1184 |
+
"metadata": {},
|
| 1185 |
+
"outputs": [],
|
| 1186 |
+
"source": [
|
| 1187 |
+
"# then pass to LMDataLoader\n",
|
| 1188 |
+
"dl=LMDataLoader(nums200)"
|
| 1189 |
+
]
|
| 1190 |
+
},
|
| 1191 |
+
{
|
| 1192 |
+
"cell_type": "code",
|
| 1193 |
+
"execution_count": 28,
|
| 1194 |
+
"id": "09c03299-39a6-4266-bb87-973d47a1e53f",
|
| 1195 |
+
"metadata": {},
|
| 1196 |
+
"outputs": [
|
| 1197 |
+
{
|
| 1198 |
+
"data": {
|
| 1199 |
+
"text/plain": [
|
| 1200 |
+
"(torch.Size([64, 72]), torch.Size([64, 72]))"
|
| 1201 |
+
]
|
| 1202 |
+
},
|
| 1203 |
+
"execution_count": 28,
|
| 1204 |
+
"metadata": {},
|
| 1205 |
+
"output_type": "execute_result"
|
| 1206 |
+
}
|
| 1207 |
+
],
|
| 1208 |
+
"source": [
|
| 1209 |
+
"# let's confirm it gives expected length by grabbing the first batch\n",
|
| 1210 |
+
"x,y=first(dl)\n",
|
| 1211 |
+
"x.shape,y.shape"
|
| 1212 |
+
]
|
| 1213 |
+
},
|
| 1214 |
+
{
|
| 1215 |
+
"cell_type": "markdown",
|
| 1216 |
+
"id": "b932bddc-c7c1-430f-9672-50d187cecc2b",
|
| 1217 |
+
"metadata": {},
|
| 1218 |
+
"source": [
|
| 1219 |
+
"then we look the independent variable which should be the start of first text."
|
| 1220 |
+
]
|
| 1221 |
+
},
|
| 1222 |
+
{
|
| 1223 |
+
"cell_type": "code",
|
| 1224 |
+
"execution_count": 29,
|
| 1225 |
+
"id": "29108e71-1229-45fe-87ee-038c435e1e28",
|
| 1226 |
+
"metadata": {},
|
| 1227 |
+
"outputs": [
|
| 1228 |
+
{
|
| 1229 |
+
"data": {
|
| 1230 |
+
"text/plain": [
|
| 1231 |
+
"'xxbos xxmaj once again xxmaj mr . xxmaj costner has dragged out a movie for far longer than necessary .'"
|
| 1232 |
+
]
|
| 1233 |
+
},
|
| 1234 |
+
"execution_count": 29,
|
| 1235 |
+
"metadata": {},
|
| 1236 |
+
"output_type": "execute_result"
|
| 1237 |
+
}
|
| 1238 |
+
],
|
| 1239 |
+
"source": [
|
| 1240 |
+
"' '.join(num.vocab[o] for o in x[0][:20])"
|
| 1241 |
+
]
|
| 1242 |
+
},
|
| 1243 |
+
{
|
| 1244 |
+
"cell_type": "markdown",
|
| 1245 |
+
"id": "799bfb8a-4175-4dd4-b5ee-87b99080cb7b",
|
| 1246 |
+
"metadata": {},
|
| 1247 |
+
"source": [
|
| 1248 |
+
"The dependent variable is the same thing offset by one token"
|
| 1249 |
+
]
|
| 1250 |
+
},
|
| 1251 |
+
{
|
| 1252 |
+
"cell_type": "code",
|
| 1253 |
+
"execution_count": 30,
|
| 1254 |
+
"id": "c570202c-0806-46aa-9f38-d8b9e0361f4a",
|
| 1255 |
+
"metadata": {},
|
| 1256 |
+
"outputs": [
|
| 1257 |
+
{
|
| 1258 |
+
"data": {
|
| 1259 |
+
"text/plain": [
|
| 1260 |
+
"'xxmaj once again xxmaj mr . xxmaj costner has dragged out a movie for far longer than necessary . xxmaj'"
|
| 1261 |
+
]
|
| 1262 |
+
},
|
| 1263 |
+
"execution_count": 30,
|
| 1264 |
+
"metadata": {},
|
| 1265 |
+
"output_type": "execute_result"
|
| 1266 |
+
}
|
| 1267 |
+
],
|
| 1268 |
+
"source": [
|
| 1269 |
+
"' '.join(num.vocab[o] for o in y[0][:20])"
|
| 1270 |
+
]
|
| 1271 |
+
},
|
| 1272 |
+
{
|
| 1273 |
+
"cell_type": "markdown",
|
| 1274 |
+
"id": "b541d6e3-dbb9-4889-840c-17078d32a623",
|
| 1275 |
+
"metadata": {},
|
| 1276 |
+
"source": [
|
| 1277 |
+
"This includes all the preprocessing steps we need to apply to our data and now we are ready to train our text classifier."
|
| 1278 |
+
]
|
| 1279 |
+
},
|
| 1280 |
+
{
|
| 1281 |
+
"cell_type": "markdown",
|
| 1282 |
+
"id": "640d5d9b-6bc5-49ee-8bdf-720656b452a2",
|
| 1283 |
+
"metadata": {},
|
| 1284 |
+
"source": [
|
| 1285 |
+
"## Training a text classifier\n",
|
| 1286 |
+
"\n",
|
| 1287 |
+
"There are 2 steps to training a state-of-the-art text classifierusing transfer learning:\n",
|
| 1288 |
+
"\n",
|
| 1289 |
+
"1. fine-tune language model pretrained on Wikipedia to corpus of IMDb reviews\n",
|
| 1290 |
+
"2. use the model to train a text classifier.\n",
|
| 1291 |
+
"\n",
|
| 1292 |
+
"Lets' start by assembling our data."
|
| 1293 |
+
]
|
| 1294 |
+
},
|
| 1295 |
+
{
|
| 1296 |
+
"cell_type": "markdown",
|
| 1297 |
+
"id": "c1bdab2f-fd9b-4623-b264-540bb2d1322a",
|
| 1298 |
+
"metadata": {},
|
| 1299 |
+
"source": [
|
| 1300 |
+
"### Language model using DataBlock\n",
|
| 1301 |
+
"\n",
|
| 1302 |
+
"fastai handles tokenization and numericalization automatically when `TextBlock` is passed to `DataBlock`. All arguments that can be passed to `Tokenize` and `Numericalize` can alse be passed to `TextBlock`.\n",
|
| 1303 |
+
"\n",
|
| 1304 |
+
"In order to debug, we can run them manually on a subset of data as we have done before and also `DataBlock`'s `summary` method is very useful fo debugging data issues.\n",
|
| 1305 |
+
"\n",
|
| 1306 |
+
"Here's how we use `TextBlock` to create a language model using fastai's deafults\n",
|
| 1307 |
+
"\n",
|
| 1308 |
+
"```\n",
|
| 1309 |
+
"get_imdb=partial(get_text_files,folders=['train','test','unsup'])\n",
|
| 1310 |
+
"```\n",
|
| 1311 |
+
"partial is used to create a new function with some of arguments of original function partially applied/prefilled.\n",
|
| 1312 |
+
"\n",
|
| 1313 |
+
"This line of code creates a new function get_imdb which always calls `get_text_files` with folders argument set to `['train', 'test', 'unsup']`."
|
| 1314 |
+
]
|
| 1315 |
+
},
|
| 1316 |
+
{
|
| 1317 |
+
"cell_type": "code",
|
| 1318 |
+
"execution_count": 31,
|
| 1319 |
+
"id": "59dde28c-7d57-4db7-9a14-21a91acab793",
|
| 1320 |
+
"metadata": {},
|
| 1321 |
+
"outputs": [
|
| 1322 |
+
{
|
| 1323 |
+
"data": {
|
| 1324 |
+
"text/html": [
|
| 1325 |
+
"\n",
|
| 1326 |
+
"<style>\n",
|
| 1327 |
+
" /* Turns off some styling */\n",
|
| 1328 |
+
" progress {\n",
|
| 1329 |
+
" /* gets rid of default border in Firefox and Opera. */\n",
|
| 1330 |
+
" border: none;\n",
|
| 1331 |
+
" /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
|
| 1332 |
+
" background-size: auto;\n",
|
| 1333 |
+
" }\n",
|
| 1334 |
+
" progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
|
| 1335 |
+
" background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
|
| 1336 |
+
" }\n",
|
| 1337 |
+
" .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
|
| 1338 |
+
" background: #F44336;\n",
|
| 1339 |
+
" }\n",
|
| 1340 |
+
"</style>\n"
|
| 1341 |
+
],
|
| 1342 |
+
"text/plain": [
|
| 1343 |
+
"<IPython.core.display.HTML object>"
|
| 1344 |
+
]
|
| 1345 |
+
},
|
| 1346 |
+
"metadata": {},
|
| 1347 |
+
"output_type": "display_data"
|
| 1348 |
+
},
|
| 1349 |
+
{
|
| 1350 |
+
"data": {
|
| 1351 |
+
"text/html": [],
|
| 1352 |
+
"text/plain": [
|
| 1353 |
+
"<IPython.core.display.HTML object>"
|
| 1354 |
+
]
|
| 1355 |
+
},
|
| 1356 |
+
"metadata": {},
|
| 1357 |
+
"output_type": "display_data"
|
| 1358 |
+
}
|
| 1359 |
+
],
|
| 1360 |
+
"source": [
|
| 1361 |
+
"get_imdb=partial(get_text_files,folders=['train','test','unsup'])\n",
|
| 1362 |
+
"dls_lm=DataBlock(\n",
|
| 1363 |
+
" blocks=TextBlock.from_folder(path,is_lm=True),\n",
|
| 1364 |
+
" get_items=get_imdb,splitter=RandomSplitter(0.1)\n",
|
| 1365 |
+
").dataloaders(path,path=path,bs=128,seq_len=80)"
|
| 1366 |
+
]
|
| 1367 |
+
},
|
| 1368 |
+
{
|
| 1369 |
+
"cell_type": "markdown",
|
| 1370 |
+
"id": "92905fcf-2a17-4241-a1f7-3b5d26c4f8ce",
|
| 1371 |
+
"metadata": {},
|
| 1372 |
+
"source": [
|
| 1373 |
+
"In this `DataBlock`, we are not using the `TextBlock` class directly but we are using the class method. We need to tell `TextBlock` how to access the texts, so that it can do initial preprocessing- that's what `from_folder` does."
|
| 1374 |
+
]
|
| 1375 |
+
},
|
| 1376 |
+
{
|
| 1377 |
+
"cell_type": "code",
|
| 1378 |
+
"execution_count": 32,
|
| 1379 |
+
"id": "a1a7d1b0-a411-4e14-a781-e78bfd18bf9f",
|
| 1380 |
+
"metadata": {},
|
| 1381 |
+
"outputs": [
|
| 1382 |
+
{
|
| 1383 |
+
"data": {
|
| 1384 |
+
"text/html": [
|
| 1385 |
+
"<table border=\"1\" class=\"dataframe\">\n",
|
| 1386 |
+
" <thead>\n",
|
| 1387 |
+
" <tr style=\"text-align: right;\">\n",
|
| 1388 |
+
" <th></th>\n",
|
| 1389 |
+
" <th>text</th>\n",
|
| 1390 |
+
" <th>text_</th>\n",
|
| 1391 |
+
" </tr>\n",
|
| 1392 |
+
" </thead>\n",
|
| 1393 |
+
" <tbody>\n",
|
| 1394 |
+
" <tr>\n",
|
| 1395 |
+
" <th>0</th>\n",
|
| 1396 |
+
" <td>xxbos xxmaj africa xxmaj screams , one of the least seen of abbott&costello 's films was an independent production that was released through xxmaj united xxmaj artists . xxmaj the thin plot has xxmaj hillary xxmaj brooke believing xxmaj costello has the map to a hidden territory that is rich with diamonds . xxmaj bud and xxmaj lou go to xxmaj africa at her behest with her two companions , the fighting xxmaj baer xxmaj brothers . xxmaj of course</td>\n",
|
| 1397 |
+
" <td>xxmaj africa xxmaj screams , one of the least seen of abbott&costello 's films was an independent production that was released through xxmaj united xxmaj artists . xxmaj the thin plot has xxmaj hillary xxmaj brooke believing xxmaj costello has the map to a hidden territory that is rich with diamonds . xxmaj bud and xxmaj lou go to xxmaj africa at her behest with her two companions , the fighting xxmaj baer xxmaj brothers . xxmaj of course the</td>\n",
|
| 1398 |
+
" </tr>\n",
|
| 1399 |
+
" <tr>\n",
|
| 1400 |
+
" <th>1</th>\n",
|
| 1401 |
+
" <td>xxmaj xxunk and they got the balls to make the xxmaj christians out to be the intolerant , xenophobic and reactionary half - wits . \\n\\n xxmaj moral xxmaj orel is still an interesting watch ( as long as it comes between superior shows on xxmaj adult xxmaj swim ) because it is a satire . xxmaj however , xxmaj it is more a satire on the people that make it rather then the people it is depicting . \\n\\n</td>\n",
|
| 1402 |
+
" <td>xxunk and they got the balls to make the xxmaj christians out to be the intolerant , xenophobic and reactionary half - wits . \\n\\n xxmaj moral xxmaj orel is still an interesting watch ( as long as it comes between superior shows on xxmaj adult xxmaj swim ) because it is a satire . xxmaj however , xxmaj it is more a satire on the people that make it rather then the people it is depicting . \\n\\n xxmaj</td>\n",
|
| 1403 |
+
" </tr>\n",
|
| 1404 |
+
" </tbody>\n",
|
| 1405 |
+
"</table>"
|
| 1406 |
+
],
|
| 1407 |
+
"text/plain": [
|
| 1408 |
+
"<IPython.core.display.HTML object>"
|
| 1409 |
+
]
|
| 1410 |
+
},
|
| 1411 |
+
"metadata": {},
|
| 1412 |
+
"output_type": "display_data"
|
| 1413 |
+
}
|
| 1414 |
+
],
|
| 1415 |
+
"source": [
|
| 1416 |
+
"dls_lm.show_batch(max_n=2)"
|
| 1417 |
+
]
|
| 1418 |
+
},
|
| 1419 |
+
{
|
| 1420 |
+
"cell_type": "markdown",
|
| 1421 |
+
"id": "d8be9de0-3a29-4784-a45e-692f9cb8486f",
|
| 1422 |
+
"metadata": {},
|
| 1423 |
+
"source": [
|
| 1424 |
+
"Now since our data is ready, we can fine-tune the pretrained language model."
|
| 1425 |
+
]
|
| 1426 |
+
},
|
| 1427 |
+
{
|
| 1428 |
+
"cell_type": "markdown",
|
| 1429 |
+
"id": "539c7395-4e5d-48bb-9601-a5f4b5983b31",
|
| 1430 |
+
"metadata": {},
|
| 1431 |
+
"source": [
|
| 1432 |
+
"### Fine-tuning Language model\n",
|
| 1433 |
+
"\n",
|
| 1434 |
+
"- To convert integer word indices into activations that we can use for our NN, we will use embeddings.\n",
|
| 1435 |
+
"- Then we'll feed those embeddings into a RNN using an architecture called *AWD-LSTM*.\n",
|
| 1436 |
+
"\n",
|
| 1437 |
+
"The embeddings of pretrained model are merged with random embeddings added for words that were not in the preatrained vocab. This is handled automatically inside `language_model_learner`."
|
| 1438 |
+
]
|
| 1439 |
+
},
|
| 1440 |
+
{
|
| 1441 |
+
"cell_type": "code",
|
| 1442 |
+
"execution_count": 33,
|
| 1443 |
+
"id": "6096ebdb-5bc7-4df3-a349-3f8a0790f20e",
|
| 1444 |
+
"metadata": {},
|
| 1445 |
+
"outputs": [
|
| 1446 |
+
{
|
| 1447 |
+
"data": {
|
| 1448 |
+
"text/html": [
|
| 1449 |
+
"\n",
|
| 1450 |
+
"<style>\n",
|
| 1451 |
+
" /* Turns off some styling */\n",
|
| 1452 |
+
" progress {\n",
|
| 1453 |
+
" /* gets rid of default border in Firefox and Opera. */\n",
|
| 1454 |
+
" border: none;\n",
|
| 1455 |
+
" /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
|
| 1456 |
+
" background-size: auto;\n",
|
| 1457 |
+
" }\n",
|
| 1458 |
+
" progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
|
| 1459 |
+
" background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
|
| 1460 |
+
" }\n",
|
| 1461 |
+
" .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
|
| 1462 |
+
" background: #F44336;\n",
|
| 1463 |
+
" }\n",
|
| 1464 |
+
"</style>\n"
|
| 1465 |
+
],
|
| 1466 |
+
"text/plain": [
|
| 1467 |
+
"<IPython.core.display.HTML object>"
|
| 1468 |
+
]
|
| 1469 |
+
},
|
| 1470 |
+
"metadata": {},
|
| 1471 |
+
"output_type": "display_data"
|
| 1472 |
+
},
|
| 1473 |
+
{
|
| 1474 |
+
"data": {
|
| 1475 |
+
"text/html": [
|
| 1476 |
+
"\n",
|
| 1477 |
+
" <div>\n",
|
| 1478 |
+
" <progress value='105070592' class='' max='105067061' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
|
| 1479 |
+
" 100.00% [105070592/105067061 00:00<00:00]\n",
|
| 1480 |
+
" </div>\n",
|
| 1481 |
+
" "
|
| 1482 |
+
],
|
| 1483 |
+
"text/plain": [
|
| 1484 |
+
"<IPython.core.display.HTML object>"
|
| 1485 |
+
]
|
| 1486 |
+
},
|
| 1487 |
+
"metadata": {},
|
| 1488 |
+
"output_type": "display_data"
|
| 1489 |
+
}
|
| 1490 |
+
],
|
| 1491 |
+
"source": [
|
| 1492 |
+
"learn=language_model_learner(\n",
|
| 1493 |
+
" dls_lm,AWD_LSTM, drop_mult=0.3,\n",
|
| 1494 |
+
" metrics=[accuracy,Perplexity()]).to_fp16()"
|
| 1495 |
+
]
|
| 1496 |
+
},
|
| 1497 |
+
{
|
| 1498 |
+
"cell_type": "markdown",
|
| 1499 |
+
"id": "2230d39c-e941-491e-bed7-8615e4168edc",
|
| 1500 |
+
"metadata": {},
|
| 1501 |
+
"source": [
|
| 1502 |
+
"The loss function used is cross-entropy since this is a classification problem.\n",
|
| 1503 |
+
"\n",
|
| 1504 |
+
"Perplexity is a metric that is exponential of loss `torch.exp(cross_entropy)`.\n",
|
| 1505 |
+
"\n",
|
| 1506 |
+
"We'll use `fit_one_cycle` and save intermediate results during model training. Just like `vision_learner`, `language_model_learner` autimatically calls `freeze` when using a pretrained model, so this will only train the embeddings, the only part of model that contains randomly initialised weights i.e. embeddings of words that aren;'t in the pretrained vocabulary but are in the IMDb vocab.\n",
|
| 1507 |
+
"\n",
|
| 1508 |
+
"By choosing `fit_one_cycle` over `fine_tune`, you're opting for more manual control over the training process, which is often necessary when working with large models or datasets where you need to carefully manage resources and want to ensure you can resume training from checkpoints if needed.\n",
|
| 1509 |
+
"Remember, you'll need to manually handle aspects like unfreezing layers if you switch from `fine_tune` to `fit_one_cycle`, as `fine_tune` automatically handles some of these steps for you."
|
| 1510 |
+
]
|
| 1511 |
+
},
|
| 1512 |
+
{
|
| 1513 |
+
"cell_type": "code",
|
| 1514 |
+
"execution_count": 34,
|
| 1515 |
+
"id": "c273b87a-6980-44bd-bf45-702afb6f4874",
|
| 1516 |
+
"metadata": {},
|
| 1517 |
+
"outputs": [
|
| 1518 |
+
{
|
| 1519 |
+
"data": {
|
| 1520 |
+
"text/html": [
|
| 1521 |
+
"\n",
|
| 1522 |
+
"<style>\n",
|
| 1523 |
+
" /* Turns off some styling */\n",
|
| 1524 |
+
" progress {\n",
|
| 1525 |
+
" /* gets rid of default border in Firefox and Opera. */\n",
|
| 1526 |
+
" border: none;\n",
|
| 1527 |
+
" /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
|
| 1528 |
+
" background-size: auto;\n",
|
| 1529 |
+
" }\n",
|
| 1530 |
+
" progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
|
| 1531 |
+
" background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
|
| 1532 |
+
" }\n",
|
| 1533 |
+
" .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
|
| 1534 |
+
" background: #F44336;\n",
|
| 1535 |
+
" }\n",
|
| 1536 |
+
"</style>\n"
|
| 1537 |
+
],
|
| 1538 |
+
"text/plain": [
|
| 1539 |
+
"<IPython.core.display.HTML object>"
|
| 1540 |
+
]
|
| 1541 |
+
},
|
| 1542 |
+
"metadata": {},
|
| 1543 |
+
"output_type": "display_data"
|
| 1544 |
+
},
|
| 1545 |
+
{
|
| 1546 |
+
"data": {
|
| 1547 |
+
"text/html": [
|
| 1548 |
+
"<table border=\"1\" class=\"dataframe\">\n",
|
| 1549 |
+
" <thead>\n",
|
| 1550 |
+
" <tr style=\"text-align: left;\">\n",
|
| 1551 |
+
" <th>epoch</th>\n",
|
| 1552 |
+
" <th>train_loss</th>\n",
|
| 1553 |
+
" <th>valid_loss</th>\n",
|
| 1554 |
+
" <th>accuracy</th>\n",
|
| 1555 |
+
" <th>perplexity</th>\n",
|
| 1556 |
+
" <th>time</th>\n",
|
| 1557 |
+
" </tr>\n",
|
| 1558 |
+
" </thead>\n",
|
| 1559 |
+
" <tbody>\n",
|
| 1560 |
+
" <tr>\n",
|
| 1561 |
+
" <td>0</td>\n",
|
| 1562 |
+
" <td>4.004734</td>\n",
|
| 1563 |
+
" <td>3.904704</td>\n",
|
| 1564 |
+
" <td>0.300501</td>\n",
|
| 1565 |
+
" <td>49.635380</td>\n",
|
| 1566 |
+
" <td>20:57</td>\n",
|
| 1567 |
+
" </tr>\n",
|
| 1568 |
+
" </tbody>\n",
|
| 1569 |
+
"</table>"
|
| 1570 |
+
],
|
| 1571 |
+
"text/plain": [
|
| 1572 |
+
"<IPython.core.display.HTML object>"
|
| 1573 |
+
]
|
| 1574 |
+
},
|
| 1575 |
+
"metadata": {},
|
| 1576 |
+
"output_type": "display_data"
|
| 1577 |
+
}
|
| 1578 |
+
],
|
| 1579 |
+
"source": [
|
| 1580 |
+
"learn.fit_one_cycle(1,2e-2)"
|
| 1581 |
+
]
|
| 1582 |
+
},
|
| 1583 |
+
{
|
| 1584 |
+
"cell_type": "markdown",
|
| 1585 |
+
"id": "aa198661-09ee-4e26-a42a-28315582afd8",
|
| 1586 |
+
"metadata": {},
|
| 1587 |
+
"source": [
|
| 1588 |
+
"### Saving and loading models\n",
|
| 1589 |
+
"\n",
|
| 1590 |
+
"We can easily save the staate of our model"
|
| 1591 |
+
]
|
| 1592 |
+
},
|
| 1593 |
+
{
|
| 1594 |
+
"cell_type": "code",
|
| 1595 |
+
"execution_count": 35,
|
| 1596 |
+
"id": "46714e01-4f33-4966-9079-9c76c3babcf4",
|
| 1597 |
+
"metadata": {},
|
| 1598 |
+
"outputs": [
|
| 1599 |
+
{
|
| 1600 |
+
"data": {
|
| 1601 |
+
"text/plain": [
|
| 1602 |
+
"Path('/teamspace/studios/this_studio/.fastai/data/imdb/models/1epoch.pth')"
|
| 1603 |
+
]
|
| 1604 |
+
},
|
| 1605 |
+
"execution_count": 35,
|
| 1606 |
+
"metadata": {},
|
| 1607 |
+
"output_type": "execute_result"
|
| 1608 |
+
}
|
| 1609 |
+
],
|
| 1610 |
+
"source": [
|
| 1611 |
+
"learn.save('1epoch')"
|
| 1612 |
+
]
|
| 1613 |
+
},
|
| 1614 |
+
{
|
| 1615 |
+
"cell_type": "markdown",
|
| 1616 |
+
"id": "ab818ed4-79f8-4ad7-808b-e27d9700b2e0",
|
| 1617 |
+
"metadata": {},
|
| 1618 |
+
"source": [
|
| 1619 |
+
"This will create a file in `learn.path/models/` named *1epoch.pth*. We can then load the contents of the loaded model to resume training or load it on another machine after creating our `Learner` as creatred here."
|
| 1620 |
+
]
|
| 1621 |
+
},
|
| 1622 |
+
{
|
| 1623 |
+
"cell_type": "code",
|
| 1624 |
+
"execution_count": 36,
|
| 1625 |
+
"id": "89d0120f-0813-415e-b8d8-45f326b9b75e",
|
| 1626 |
+
"metadata": {},
|
| 1627 |
+
"outputs": [],
|
| 1628 |
+
"source": [
|
| 1629 |
+
"learn=learn.load('1epoch')"
|
| 1630 |
+
]
|
| 1631 |
+
},
|
| 1632 |
+
{
|
| 1633 |
+
"cell_type": "markdown",
|
| 1634 |
+
"id": "0d679c1c-a9c2-4602-919b-29ab209b8f47",
|
| 1635 |
+
"metadata": {},
|
| 1636 |
+
"source": [
|
| 1637 |
+
"Once initial training has been completed, we continue fine-tuning model after unfreezing.\n",
|
| 1638 |
+
"\n",
|
| 1639 |
+
"`unfreeze()` is used to make all laeyrs of NN trainable.\n",
|
| 1640 |
+
"\n",
|
| 1641 |
+
"In context of TL,\n",
|
| 1642 |
+
"\n",
|
| 1643 |
+
"- we often start witha pre-trained model\n",
|
| 1644 |
+
"- initially, we freeze the early layers and train only last few layers on our new data.\n",
|
| 1645 |
+
"\n",
|
| 1646 |
+
"What it does?\n",
|
| 1647 |
+
"\n",
|
| 1648 |
+
"- it sets `requires_grad_` to `True` for all parameters of the model, therefore during backpropagation, gradienst will be computed for all layers allowing them to be updated during training.\n",
|
| 1649 |
+
"\n",
|
| 1650 |
+
"When to Use unfreeze():\n",
|
| 1651 |
+
"\n",
|
| 1652 |
+
"- After initial training with frozen layers, when you want to fine-tune the entire model.\n",
|
| 1653 |
+
"- When you have enough data and computational resources to train the entire network.\n",
|
| 1654 |
+
"- When you want to allow the model to adapt more deeply to your specific task or dataset.\n",
|
| 1655 |
+
"\n",
|
| 1656 |
+
"Typical Workflow:\n",
|
| 1657 |
+
"\n",
|
| 1658 |
+
"- Start with a pre-trained model with most layers frozen.\n",
|
| 1659 |
+
"- Train only the last few layers for some epochs.\n",
|
| 1660 |
+
"- Call learn.unfreeze() to unfreeze all layers.\n",
|
| 1661 |
+
"- Continue training with a lower learning rate."
|
| 1662 |
+
]
|
| 1663 |
+
},
|
| 1664 |
+
{
|
| 1665 |
+
"cell_type": "code",
|
| 1666 |
+
"execution_count": 37,
|
| 1667 |
+
"id": "9a9cfc05-c470-4728-85c9-2027343d7f39",
|
| 1668 |
+
"metadata": {},
|
| 1669 |
+
"outputs": [
|
| 1670 |
+
{
|
| 1671 |
+
"data": {
|
| 1672 |
+
"text/html": [
|
| 1673 |
+
"\n",
|
| 1674 |
+
"<style>\n",
|
| 1675 |
+
" /* Turns off some styling */\n",
|
| 1676 |
+
" progress {\n",
|
| 1677 |
+
" /* gets rid of default border in Firefox and Opera. */\n",
|
| 1678 |
+
" border: none;\n",
|
| 1679 |
+
" /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
|
| 1680 |
+
" background-size: auto;\n",
|
| 1681 |
+
" }\n",
|
| 1682 |
+
" progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
|
| 1683 |
+
" background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
|
| 1684 |
+
" }\n",
|
| 1685 |
+
" .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
|
| 1686 |
+
" background: #F44336;\n",
|
| 1687 |
+
" }\n",
|
| 1688 |
+
"</style>\n"
|
| 1689 |
+
],
|
| 1690 |
+
"text/plain": [
|
| 1691 |
+
"<IPython.core.display.HTML object>"
|
| 1692 |
+
]
|
| 1693 |
+
},
|
| 1694 |
+
"metadata": {},
|
| 1695 |
+
"output_type": "display_data"
|
| 1696 |
+
},
|
| 1697 |
+
{
|
| 1698 |
+
"data": {
|
| 1699 |
+
"text/html": [
|
| 1700 |
+
"<table border=\"1\" class=\"dataframe\">\n",
|
| 1701 |
+
" <thead>\n",
|
| 1702 |
+
" <tr style=\"text-align: left;\">\n",
|
| 1703 |
+
" <th>epoch</th>\n",
|
| 1704 |
+
" <th>train_loss</th>\n",
|
| 1705 |
+
" <th>valid_loss</th>\n",
|
| 1706 |
+
" <th>accuracy</th>\n",
|
| 1707 |
+
" <th>perplexity</th>\n",
|
| 1708 |
+
" <th>time</th>\n",
|
| 1709 |
+
" </tr>\n",
|
| 1710 |
+
" </thead>\n",
|
| 1711 |
+
" <tbody>\n",
|
| 1712 |
+
" <tr>\n",
|
| 1713 |
+
" <td>0</td>\n",
|
| 1714 |
+
" <td>3.774635</td>\n",
|
| 1715 |
+
" <td>3.761657</td>\n",
|
| 1716 |
+
" <td>0.317040</td>\n",
|
| 1717 |
+
" <td>43.019672</td>\n",
|
| 1718 |
+
" <td>21:39</td>\n",
|
| 1719 |
+
" </tr>\n",
|
| 1720 |
+
" <tr>\n",
|
| 1721 |
+
" <td>1</td>\n",
|
| 1722 |
+
" <td>3.712948</td>\n",
|
| 1723 |
+
" <td>3.701956</td>\n",
|
| 1724 |
+
" <td>0.323748</td>\n",
|
| 1725 |
+
" <td>40.526478</td>\n",
|
| 1726 |
+
" <td>21:18</td>\n",
|
| 1727 |
+
" </tr>\n",
|
| 1728 |
+
" <tr>\n",
|
| 1729 |
+
" <td>2</td>\n",
|
| 1730 |
+
" <td>3.622169</td>\n",
|
| 1731 |
+
" <td>3.654953</td>\n",
|
| 1732 |
+
" <td>0.329183</td>\n",
|
| 1733 |
+
" <td>38.665722</td>\n",
|
| 1734 |
+
" <td>21:09</td>\n",
|
| 1735 |
+
" </tr>\n",
|
| 1736 |
+
" <tr>\n",
|
| 1737 |
+
" <td>3</td>\n",
|
| 1738 |
+
" <td>3.570991</td>\n",
|
| 1739 |
+
" <td>3.620903</td>\n",
|
| 1740 |
+
" <td>0.333016</td>\n",
|
| 1741 |
+
" <td>37.371307</td>\n",
|
| 1742 |
+
" <td>21:28</td>\n",
|
| 1743 |
+
" </tr>\n",
|
| 1744 |
+
" <tr>\n",
|
| 1745 |
+
" <td>4</td>\n",
|
| 1746 |
+
" <td>3.512937</td>\n",
|
| 1747 |
+
" <td>3.600293</td>\n",
|
| 1748 |
+
" <td>0.335536</td>\n",
|
| 1749 |
+
" <td>36.608948</td>\n",
|
| 1750 |
+
" <td>21:28</td>\n",
|
| 1751 |
+
" </tr>\n",
|
| 1752 |
+
" <tr>\n",
|
| 1753 |
+
" <td>5</td>\n",
|
| 1754 |
+
" <td>3.410577</td>\n",
|
| 1755 |
+
" <td>3.586111</td>\n",
|
| 1756 |
+
" <td>0.337969</td>\n",
|
| 1757 |
+
" <td>36.093430</td>\n",
|
| 1758 |
+
" <td>21:14</td>\n",
|
| 1759 |
+
" </tr>\n",
|
| 1760 |
+
" <tr>\n",
|
| 1761 |
+
" <td>6</td>\n",
|
| 1762 |
+
" <td>3.365716</td>\n",
|
| 1763 |
+
" <td>3.577701</td>\n",
|
| 1764 |
+
" <td>0.339490</td>\n",
|
| 1765 |
+
" <td>35.791176</td>\n",
|
| 1766 |
+
" <td>21:41</td>\n",
|
| 1767 |
+
" </tr>\n",
|
| 1768 |
+
" <tr>\n",
|
| 1769 |
+
" <td>7</td>\n",
|
| 1770 |
+
" <td>3.294542</td>\n",
|
| 1771 |
+
" <td>3.575607</td>\n",
|
| 1772 |
+
" <td>0.340427</td>\n",
|
| 1773 |
+
" <td>35.716278</td>\n",
|
| 1774 |
+
" <td>21:36</td>\n",
|
| 1775 |
+
" </tr>\n",
|
| 1776 |
+
" <tr>\n",
|
| 1777 |
+
" <td>8</td>\n",
|
| 1778 |
+
" <td>3.241257</td>\n",
|
| 1779 |
+
" <td>3.578088</td>\n",
|
| 1780 |
+
" <td>0.340611</td>\n",
|
| 1781 |
+
" <td>35.805027</td>\n",
|
| 1782 |
+
" <td>21:28</td>\n",
|
| 1783 |
+
" </tr>\n",
|
| 1784 |
+
" <tr>\n",
|
| 1785 |
+
" <td>9</td>\n",
|
| 1786 |
+
" <td>3.224428</td>\n",
|
| 1787 |
+
" <td>3.582369</td>\n",
|
| 1788 |
+
" <td>0.340430</td>\n",
|
| 1789 |
+
" <td>35.958630</td>\n",
|
| 1790 |
+
" <td>21:28</td>\n",
|
| 1791 |
+
" </tr>\n",
|
| 1792 |
+
" </tbody>\n",
|
| 1793 |
+
"</table>"
|
| 1794 |
+
],
|
| 1795 |
+
"text/plain": [
|
| 1796 |
+
"<IPython.core.display.HTML object>"
|
| 1797 |
+
]
|
| 1798 |
+
},
|
| 1799 |
+
"metadata": {},
|
| 1800 |
+
"output_type": "display_data"
|
| 1801 |
+
}
|
| 1802 |
+
],
|
| 1803 |
+
"source": [
|
| 1804 |
+
"learn.unfreeze()\n",
|
| 1805 |
+
"learn.fit_one_cycle(10,2e-3)"
|
| 1806 |
+
]
|
| 1807 |
+
},
|
| 1808 |
+
{
|
| 1809 |
+
"cell_type": "markdown",
|
| 1810 |
+
"id": "aeb319ee-922f-4d97-a0af-54d971af5139",
|
| 1811 |
+
"metadata": {},
|
| 1812 |
+
"source": [
|
| 1813 |
+
"Once this is completed, we save all of our model except the final layer that converts activatioins to probabilities of picking each token in our vocabulary.\n",
|
| 1814 |
+
"\n",
|
| 1815 |
+
"The model not including the final layer is called encoder and we save it using `save_encoder`."
|
| 1816 |
+
]
|
| 1817 |
+
},
|
| 1818 |
+
{
|
| 1819 |
+
"cell_type": "code",
|
| 1820 |
+
"execution_count": 38,
|
| 1821 |
+
"id": "d9b44fd9-6310-4037-9e1d-5eea33455b40",
|
| 1822 |
+
"metadata": {},
|
| 1823 |
+
"outputs": [],
|
| 1824 |
+
"source": [
|
| 1825 |
+
"learn.save_encoder('fine_tuned')"
|
| 1826 |
+
]
|
| 1827 |
+
},
|
| 1828 |
+
{
|
| 1829 |
+
"cell_type": "markdown",
|
| 1830 |
+
"id": "0fee79d2-497f-4ea0-9d90-f224a19c2e3d",
|
| 1831 |
+
"metadata": {},
|
| 1832 |
+
"source": [
|
| 1833 |
+
">encoder : The model not including the task specific final layer(s). This term means the same as body in CNNs but encoder is more used in NLP.\n"
|
| 1834 |
+
]
|
| 1835 |
+
},
|
| 1836 |
+
{
|
| 1837 |
+
"cell_type": "markdown",
|
| 1838 |
+
"id": "43b958af-33cf-41e0-8b92-070065319682",
|
| 1839 |
+
"metadata": {},
|
| 1840 |
+
"source": [
|
| 1841 |
+
"This completes the second stage, fine-tuning the language model. We can now use it to fine-tune a classifier using IMDb senetiment labels."
|
| 1842 |
+
]
|
| 1843 |
+
},
|
| 1844 |
+
{
|
| 1845 |
+
"cell_type": "markdown",
|
| 1846 |
+
"id": "28c890dd-c93d-4158-9b90-c71e1bc7a9f2",
|
| 1847 |
+
"metadata": {},
|
| 1848 |
+
"source": [
|
| 1849 |
+
"### Text generation\n",
|
| 1850 |
+
"\n",
|
| 1851 |
+
"Before we go to fine-tuning classifier, we will use the model to generate random reviews."
|
| 1852 |
+
]
|
| 1853 |
+
},
|
| 1854 |
+
{
|
| 1855 |
+
"cell_type": "code",
|
| 1856 |
+
"execution_count": 39,
|
| 1857 |
+
"id": "3046722c-b702-4131-8fed-4a7a980c0903",
|
| 1858 |
+
"metadata": {},
|
| 1859 |
+
"outputs": [
|
| 1860 |
+
{
|
| 1861 |
+
"data": {
|
| 1862 |
+
"text/html": [
|
| 1863 |
+
"\n",
|
| 1864 |
+
"<style>\n",
|
| 1865 |
+
" /* Turns off some styling */\n",
|
| 1866 |
+
" progress {\n",
|
| 1867 |
+
" /* gets rid of default border in Firefox and Opera. */\n",
|
| 1868 |
+
" border: none;\n",
|
| 1869 |
+
" /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
|
| 1870 |
+
" background-size: auto;\n",
|
| 1871 |
+
" }\n",
|
| 1872 |
+
" progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
|
| 1873 |
+
" background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
|
| 1874 |
+
" }\n",
|
| 1875 |
+
" .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
|
| 1876 |
+
" background: #F44336;\n",
|
| 1877 |
+
" }\n",
|
| 1878 |
+
"</style>\n"
|
| 1879 |
+
],
|
| 1880 |
+
"text/plain": [
|
| 1881 |
+
"<IPython.core.display.HTML object>"
|
| 1882 |
+
]
|
| 1883 |
+
},
|
| 1884 |
+
"metadata": {},
|
| 1885 |
+
"output_type": "display_data"
|
| 1886 |
+
},
|
| 1887 |
+
{
|
| 1888 |
+
"data": {
|
| 1889 |
+
"text/html": [],
|
| 1890 |
+
"text/plain": [
|
| 1891 |
+
"<IPython.core.display.HTML object>"
|
| 1892 |
+
]
|
| 1893 |
+
},
|
| 1894 |
+
"metadata": {},
|
| 1895 |
+
"output_type": "display_data"
|
| 1896 |
+
},
|
| 1897 |
+
{
|
| 1898 |
+
"data": {
|
| 1899 |
+
"text/html": [
|
| 1900 |
+
"\n",
|
| 1901 |
+
"<style>\n",
|
| 1902 |
+
" /* Turns off some styling */\n",
|
| 1903 |
+
" progress {\n",
|
| 1904 |
+
" /* gets rid of default border in Firefox and Opera. */\n",
|
| 1905 |
+
" border: none;\n",
|
| 1906 |
+
" /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
|
| 1907 |
+
" background-size: auto;\n",
|
| 1908 |
+
" }\n",
|
| 1909 |
+
" progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
|
| 1910 |
+
" background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
|
| 1911 |
+
" }\n",
|
| 1912 |
+
" .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
|
| 1913 |
+
" background: #F44336;\n",
|
| 1914 |
+
" }\n",
|
| 1915 |
+
"</style>\n"
|
| 1916 |
+
],
|
| 1917 |
+
"text/plain": [
|
| 1918 |
+
"<IPython.core.display.HTML object>"
|
| 1919 |
+
]
|
| 1920 |
+
},
|
| 1921 |
+
"metadata": {},
|
| 1922 |
+
"output_type": "display_data"
|
| 1923 |
+
},
|
| 1924 |
+
{
|
| 1925 |
+
"data": {
|
| 1926 |
+
"text/html": [],
|
| 1927 |
+
"text/plain": [
|
| 1928 |
+
"<IPython.core.display.HTML object>"
|
| 1929 |
+
]
|
| 1930 |
+
},
|
| 1931 |
+
"metadata": {},
|
| 1932 |
+
"output_type": "display_data"
|
| 1933 |
+
}
|
| 1934 |
+
],
|
| 1935 |
+
"source": [
|
| 1936 |
+
"TEXT='I liked this movie because'\n",
|
| 1937 |
+
"N_WORDS=40\n",
|
| 1938 |
+
"N_SENTENCES=2\n",
|
| 1939 |
+
"preds=[learn.predict(TEXT,N_WORDS,temperature=0.75)\n",
|
| 1940 |
+
" for _ in range(N_SENTENCES)]"
|
| 1941 |
+
]
|
| 1942 |
+
},
|
| 1943 |
+
{
|
| 1944 |
+
"cell_type": "code",
|
| 1945 |
+
"execution_count": 40,
|
| 1946 |
+
"id": "4acc8091-132d-4130-a295-3491500e7f11",
|
| 1947 |
+
"metadata": {},
|
| 1948 |
+
"outputs": [
|
| 1949 |
+
{
|
| 1950 |
+
"name": "stdout",
|
| 1951 |
+
"output_type": "stream",
|
| 1952 |
+
"text": [
|
| 1953 |
+
"i liked this movie because it was a \" b \" movie . If you like some of the worst movies you 'll ever see , you 'll like this one . If you 're looking for a good horror flick , watch\n",
|
| 1954 |
+
"i liked this movie because it actually turned out to be a real good movie . i thought it was predictable and you could see it coming a mile away . If you can plan on watching the movie you have to please make\n"
|
| 1955 |
+
]
|
| 1956 |
+
}
|
| 1957 |
+
],
|
| 1958 |
+
"source": [
|
| 1959 |
+
"print(\"\\n\".join(preds))"
|
| 1960 |
+
]
|
| 1961 |
+
},
|
| 1962 |
+
{
|
| 1963 |
+
"cell_type": "markdown",
|
| 1964 |
+
"id": "619ee507-c3cd-4951-b8d5-852fa265fab2",
|
| 1965 |
+
"metadata": {},
|
| 1966 |
+
"source": [
|
| 1967 |
+
"### Creating a classifier DataLoaders\n",
|
| 1968 |
+
"\n",
|
| 1969 |
+
"Recap - A language model predicts next word of a documnet and doesn't require external labels, whereas our classifier requires external label in this case the sentiment of document.\n",
|
| 1970 |
+
"\n",
|
| 1971 |
+
"This means the structure of `DataBlock` for NLP classification will look familiar to image classification datasets."
|
| 1972 |
+
]
|
| 1973 |
+
},
|
| 1974 |
+
{
|
| 1975 |
+
"cell_type": "code",
|
| 1976 |
+
"execution_count": 41,
|
| 1977 |
+
"id": "ad44458f-4739-415a-b94c-8d29da0b773e",
|
| 1978 |
+
"metadata": {},
|
| 1979 |
+
"outputs": [],
|
| 1980 |
+
"source": [
|
| 1981 |
+
"dls_clas=DataBlock(\n",
|
| 1982 |
+
" blocks=(TextBlock.from_folder(path,vocab=dls_lm.vocab),CategoryBlock),\n",
|
| 1983 |
+
" get_y=parent_label,\n",
|
| 1984 |
+
" get_items=partial(get_text_files,folders=['train','test']),\n",
|
| 1985 |
+
" splitter=GrandparentSplitter(valid_name='test')\n",
|
| 1986 |
+
").dataloaders(path,path=path,bs=128,seq_len=72)"
|
| 1987 |
+
]
|
| 1988 |
+
},
|
| 1989 |
+
{
|
| 1990 |
+
"cell_type": "markdown",
|
| 1991 |
+
"id": "d8bfd1d2-d513-4261-ace2-434d5318a6b1",
|
| 1992 |
+
"metadata": {},
|
| 1993 |
+
"source": [
|
| 1994 |
+
"The first path is positional argument in dataloaders and specifies the root directory where data is located.\n",
|
| 1995 |
+
"\n",
|
| 1996 |
+
"The second path=path is a keywrod argument and in context of text classification it specifies where to save tokenised inputs.\n",
|
| 1997 |
+
"\n",
|
| 1998 |
+
"Why we use `GrandparentSplitter`?\n",
|
| 1999 |
+
"\n",
|
| 2000 |
+
"because the `GrandparentSplitter` looks at the grandparent folder name to determine the split. The structure of the IDMDb dataset is as follows\n",
|
| 2001 |
+
"```\n",
|
| 2002 |
+
"path/\n",
|
| 2003 |
+
" train/\n",
|
| 2004 |
+
" pos/\n",
|
| 2005 |
+
" review1.txt\n",
|
| 2006 |
+
" review2.txt\n",
|
| 2007 |
+
" ...\n",
|
| 2008 |
+
" neg/\n",
|
| 2009 |
+
" review1.txt\n",
|
| 2010 |
+
" review2.txt\n",
|
| 2011 |
+
" ...\n",
|
| 2012 |
+
" test/\n",
|
| 2013 |
+
" pos/\n",
|
| 2014 |
+
" review1.txt\n",
|
| 2015 |
+
" review2.txt\n",
|
| 2016 |
+
" ...\n",
|
| 2017 |
+
" neg/\n",
|
| 2018 |
+
" review1.txt\n",
|
| 2019 |
+
" review2.txt\n",
|
| 2020 |
+
" ...\n",
|
| 2021 |
+
"```"
|
| 2022 |
+
]
|
| 2023 |
+
},
|
| 2024 |
+
{
|
| 2025 |
+
"cell_type": "code",
|
| 2026 |
+
"execution_count": 42,
|
| 2027 |
+
"id": "23e4c155-732b-4065-81d7-8e0692a46fc8",
|
| 2028 |
+
"metadata": {},
|
| 2029 |
+
"outputs": [
|
| 2030 |
+
{
|
| 2031 |
+
"data": {
|
| 2032 |
+
"text/html": [
|
| 2033 |
+
"<table border=\"1\" class=\"dataframe\">\n",
|
| 2034 |
+
" <thead>\n",
|
| 2035 |
+
" <tr style=\"text-align: right;\">\n",
|
| 2036 |
+
" <th></th>\n",
|
| 2037 |
+
" <th>text</th>\n",
|
| 2038 |
+
" <th>category</th>\n",
|
| 2039 |
+
" </tr>\n",
|
| 2040 |
+
" </thead>\n",
|
| 2041 |
+
" <tbody>\n",
|
| 2042 |
+
" <tr>\n",
|
| 2043 |
+
" <th>0</th>\n",
|
| 2044 |
+
" <td>xxbos xxmaj match 1 : xxmaj tag xxmaj team xxmaj table xxmaj match xxmaj bubba xxmaj ray and xxmaj spike xxmaj dudley vs xxmaj eddie xxmaj guerrero and xxmaj chris xxmaj benoit xxmaj bubba xxmaj ray and xxmaj spike xxmaj dudley started things off with a xxmaj tag xxmaj team xxmaj table xxmaj match against xxmaj eddie xxmaj guerrero and xxmaj chris xxmaj benoit . xxmaj according to the rules of the match , both opponents have to go through tables in order to get the win . xxmaj benoit and xxmaj guerrero heated up early on by taking turns hammering first xxmaj spike and then xxmaj bubba xxmaj ray . a xxmaj german xxunk by xxmaj benoit to xxmaj bubba took the wind out of the xxmaj dudley brother . xxmaj spike tried to help his brother , but the referee restrained him while xxmaj benoit and xxmaj guerrero</td>\n",
|
| 2045 |
+
" <td>pos</td>\n",
|
| 2046 |
+
" </tr>\n",
|
| 2047 |
+
" <tr>\n",
|
| 2048 |
+
" <th>1</th>\n",
|
| 2049 |
+
" <td>xxbos xxmaj some have praised _ xxunk _ as a xxmaj disney adventure for adults . i do n't think so -- at least not for thinking adults . \\n\\n xxmaj this script suggests a beginning as a live - action movie , that struck someone as the type of crap you can not sell to adults anymore . xxmaj the \" crack staff \" of many older adventure movies has been done well before , ( think _ the xxmaj dirty xxmaj dozen _ ) but _ atlantis _ represents one of the worse films in that motif . xxmaj the characters are weak . xxmaj even the background that each member trots out seems stock and awkward at best . xxmaj an xxup md / xxmaj medicine xxmaj man , a tomboy mechanic whose father always wanted sons , if we have not at least seen these before</td>\n",
|
| 2050 |
+
" <td>neg</td>\n",
|
| 2051 |
+
" </tr>\n",
|
| 2052 |
+
" <tr>\n",
|
| 2053 |
+
" <th>2</th>\n",
|
| 2054 |
+
" <td>xxbos xxmaj some have praised xxunk xxmaj lost xxmaj xxunk as a xxmaj disney adventure for adults . i do n't think so -- at least not for thinking adults . \\n\\n xxmaj this script suggests a beginning as a live - action movie , that struck someone as the type of crap you can not sell to adults anymore . xxmaj the \" crack staff \" of many older adventure movies has been done well before , ( think xxmaj the xxmaj dirty xxmaj dozen ) but xxunk represents one of the worse films in that motif . xxmaj the characters are weak . xxmaj even the background that each member trots out seems stock and awkward at best . xxmaj an xxup md / xxmaj medicine xxmaj man , a tomboy mechanic whose father always wanted sons , if we have not at least seen these before ,</td>\n",
|
| 2055 |
+
" <td>neg</td>\n",
|
| 2056 |
+
" </tr>\n",
|
| 2057 |
+
" </tbody>\n",
|
| 2058 |
+
"</table>"
|
| 2059 |
+
],
|
| 2060 |
+
"text/plain": [
|
| 2061 |
+
"<IPython.core.display.HTML object>"
|
| 2062 |
+
]
|
| 2063 |
+
},
|
| 2064 |
+
"metadata": {},
|
| 2065 |
+
"output_type": "display_data"
|
| 2066 |
+
}
|
| 2067 |
+
],
|
| 2068 |
+
"source": [
|
| 2069 |
+
"dls_clas.show_batch(max_n=3)"
|
| 2070 |
+
]
|
| 2071 |
+
},
|
| 2072 |
+
{
|
| 2073 |
+
"cell_type": "markdown",
|
| 2074 |
+
"id": "a1912546-c498-4e22-ac48-ba5dfdd9ec5c",
|
| 2075 |
+
"metadata": {},
|
| 2076 |
+
"source": [
|
| 2077 |
+
"The DataBlock definition is similiar to previous definition of DataBlock except two chnages\n",
|
| 2078 |
+
"\n",
|
| 2079 |
+
"1. `TextBlock.from_folder` no longer has `is_lm=True`\n",
|
| 2080 |
+
"2. We pass the `vocab` we created for the language model fine-tuning.\n",
|
| 2081 |
+
"\n",
|
| 2082 |
+
"The reason why we pass the vocab of language model is to make sure we use the same correspondance of token to index. Otherwise the embeddings we learned in our fine-tuned language model won't make any sense to this model and fine-tuning step won't be of any use.\n",
|
| 2083 |
+
"\n",
|
| 2084 |
+
"And by not passing `is_lm=True`, we tell `TextBlock` that we have regular labeled data rather than using next tokens as labels.\n",
|
| 2085 |
+
"\n",
|
| 2086 |
+
"However one challenge is collating multiple docs into a mini-batch. An example of creating a mini-batch containing first 10 docs but fiirst we need to numericalize them."
|
| 2087 |
+
]
|
| 2088 |
+
},
|
| 2089 |
+
{
|
| 2090 |
+
"cell_type": "code",
|
| 2091 |
+
"execution_count": 43,
|
| 2092 |
+
"id": "34136991-9528-47c0-bbfb-e4e9d4c6983e",
|
| 2093 |
+
"metadata": {},
|
| 2094 |
+
"outputs": [],
|
| 2095 |
+
"source": [
|
| 2096 |
+
"nums_samp=toks200[:10].map(num)"
|
| 2097 |
+
]
|
| 2098 |
+
},
|
| 2099 |
+
{
|
| 2100 |
+
"cell_type": "markdown",
|
| 2101 |
+
"id": "a210facd-8b11-4923-a718-156d71e7a9a8",
|
| 2102 |
+
"metadata": {},
|
| 2103 |
+
"source": [
|
| 2104 |
+
"Now let's see how many tokens each of 10 reviews have"
|
| 2105 |
+
]
|
| 2106 |
+
},
|
| 2107 |
+
{
|
| 2108 |
+
"cell_type": "code",
|
| 2109 |
+
"execution_count": 44,
|
| 2110 |
+
"id": "07a9e9a5-92d3-46b4-a979-398bc86efe90",
|
| 2111 |
+
"metadata": {},
|
| 2112 |
+
"outputs": [
|
| 2113 |
+
{
|
| 2114 |
+
"data": {
|
| 2115 |
+
"text/plain": [
|
| 2116 |
+
"(#10) [207,314,267,378,304,156,197,187,162,229]"
|
| 2117 |
+
]
|
| 2118 |
+
},
|
| 2119 |
+
"execution_count": 44,
|
| 2120 |
+
"metadata": {},
|
| 2121 |
+
"output_type": "execute_result"
|
| 2122 |
+
}
|
| 2123 |
+
],
|
| 2124 |
+
"source": [
|
| 2125 |
+
"nums_samp.map(len)"
|
| 2126 |
+
]
|
| 2127 |
+
},
|
| 2128 |
+
{
|
| 2129 |
+
"cell_type": "markdown",
|
| 2130 |
+
"id": "f677a713-7e2f-47fe-8455-fe8f92df47de",
|
| 2131 |
+
"metadata": {},
|
| 2132 |
+
"source": [
|
| 2133 |
+
"PyTorch `DataLoader`s need to collate/arrange all items in a batch into a single tensor and that has fixed shape.\n",
|
| 2134 |
+
"\n",
|
| 2135 |
+
"We can't crop the doc because we will lose some info. We can't also squish a doc and there's no data augmentation at resent for NLP. So that leaves padding.\n",
|
| 2136 |
+
"\n",
|
| 2137 |
+
"We expand the shortest texts to make them all the same size and to do this, we use a special padding token that is ignored by our model. Additionally, to avoid memory issues and improve performance, we will batch together texts that are roughly the same lengths( with some shuffling for training set). We do this by sortng docs by length prior to each epoch. \n",
|
| 2138 |
+
"\n",
|
| 2139 |
+
"The result of this is that docs collated into a single bath will tend to be of similar lengths. Also we won't pad every batch to same size, but will instead use the size of largest doc in each batch as target size.\n",
|
| 2140 |
+
"\n",
|
| 2141 |
+
"Sorting and padding are automatically done by data block API when we use `TextBlock` with `is_lm=True`.\n",
|
| 2142 |
+
"\n",
|
| 2143 |
+
"We now create a model to classify our texts."
|
| 2144 |
+
]
|
| 2145 |
+
},
|
| 2146 |
+
{
|
| 2147 |
+
"cell_type": "code",
|
| 2148 |
+
"execution_count": 45,
|
| 2149 |
+
"id": "9c54eb3d-da09-4dfd-8e1c-07e0f3bf60cc",
|
| 2150 |
+
"metadata": {},
|
| 2151 |
+
"outputs": [],
|
| 2152 |
+
"source": [
|
| 2153 |
+
"learn=text_classifier_learner(dls_clas, AWD_LSTM, drop_mult=0.5,\n",
|
| 2154 |
+
" metrics=accuracy).to_fp16()"
|
| 2155 |
+
]
|
| 2156 |
+
},
|
| 2157 |
+
{
|
| 2158 |
+
"cell_type": "markdown",
|
| 2159 |
+
"id": "c6f88ebe-80fe-43cc-95b2-c1c89939be13",
|
| 2160 |
+
"metadata": {},
|
| 2161 |
+
"source": [
|
| 2162 |
+
"The final step prior to training classifier is to load the encoder from fine-tuned language model. We use `load_encoder` instead of `load` because we only have pretrained weights avaible for encoder."
|
| 2163 |
+
]
|
| 2164 |
+
},
|
| 2165 |
+
{
|
| 2166 |
+
"cell_type": "code",
|
| 2167 |
+
"execution_count": 46,
|
| 2168 |
+
"id": "b6a2cb8f-87cb-4bb9-bea3-50302b9b99c4",
|
| 2169 |
+
"metadata": {},
|
| 2170 |
+
"outputs": [],
|
| 2171 |
+
"source": [
|
| 2172 |
+
"learn=learn.load_encoder('fine_tuned')"
|
| 2173 |
+
]
|
| 2174 |
+
},
|
| 2175 |
+
{
|
| 2176 |
+
"cell_type": "markdown",
|
| 2177 |
+
"id": "858aef35-9fbb-44ff-885f-aa7b0c99c256",
|
| 2178 |
+
"metadata": {},
|
| 2179 |
+
"source": [
|
| 2180 |
+
"### Fine-Tuning classifier\n",
|
| 2181 |
+
"\n",
|
| 2182 |
+
"The last step is to train with discriminative learning rates and gradual unfreezing. In CV, we often unfreeze the model at once, but for NLP classifiers, we find that unfreezing a few layers at a time makes a real difference."
|
| 2183 |
+
]
|
| 2184 |
+
},
|
| 2185 |
+
{
|
| 2186 |
+
"cell_type": "code",
|
| 2187 |
+
"execution_count": 47,
|
| 2188 |
+
"id": "ce455eb5-a459-4b73-a76f-8bb848b6e5ab",
|
| 2189 |
+
"metadata": {},
|
| 2190 |
+
"outputs": [
|
| 2191 |
+
{
|
| 2192 |
+
"data": {
|
| 2193 |
+
"text/html": [
|
| 2194 |
+
"\n",
|
| 2195 |
+
"<style>\n",
|
| 2196 |
+
" /* Turns off some styling */\n",
|
| 2197 |
+
" progress {\n",
|
| 2198 |
+
" /* gets rid of default border in Firefox and Opera. */\n",
|
| 2199 |
+
" border: none;\n",
|
| 2200 |
+
" /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
|
| 2201 |
+
" background-size: auto;\n",
|
| 2202 |
+
" }\n",
|
| 2203 |
+
" progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
|
| 2204 |
+
" background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
|
| 2205 |
+
" }\n",
|
| 2206 |
+
" .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
|
| 2207 |
+
" background: #F44336;\n",
|
| 2208 |
+
" }\n",
|
| 2209 |
+
"</style>\n"
|
| 2210 |
+
],
|
| 2211 |
+
"text/plain": [
|
| 2212 |
+
"<IPython.core.display.HTML object>"
|
| 2213 |
+
]
|
| 2214 |
+
},
|
| 2215 |
+
"metadata": {},
|
| 2216 |
+
"output_type": "display_data"
|
| 2217 |
+
},
|
| 2218 |
+
{
|
| 2219 |
+
"data": {
|
| 2220 |
+
"text/html": [
|
| 2221 |
+
"<table border=\"1\" class=\"dataframe\">\n",
|
| 2222 |
+
" <thead>\n",
|
| 2223 |
+
" <tr style=\"text-align: left;\">\n",
|
| 2224 |
+
" <th>epoch</th>\n",
|
| 2225 |
+
" <th>train_loss</th>\n",
|
| 2226 |
+
" <th>valid_loss</th>\n",
|
| 2227 |
+
" <th>accuracy</th>\n",
|
| 2228 |
+
" <th>time</th>\n",
|
| 2229 |
+
" </tr>\n",
|
| 2230 |
+
" </thead>\n",
|
| 2231 |
+
" <tbody>\n",
|
| 2232 |
+
" <tr>\n",
|
| 2233 |
+
" <td>0</td>\n",
|
| 2234 |
+
" <td>0.245921</td>\n",
|
| 2235 |
+
" <td>0.180068</td>\n",
|
| 2236 |
+
" <td>0.931320</td>\n",
|
| 2237 |
+
" <td>00:45</td>\n",
|
| 2238 |
+
" </tr>\n",
|
| 2239 |
+
" </tbody>\n",
|
| 2240 |
+
"</table>"
|
| 2241 |
+
],
|
| 2242 |
+
"text/plain": [
|
| 2243 |
+
"<IPython.core.display.HTML object>"
|
| 2244 |
+
]
|
| 2245 |
+
},
|
| 2246 |
+
"metadata": {},
|
| 2247 |
+
"output_type": "display_data"
|
| 2248 |
+
}
|
| 2249 |
+
],
|
| 2250 |
+
"source": [
|
| 2251 |
+
"learn.fit_one_cycle(1,2e-2)"
|
| 2252 |
+
]
|
| 2253 |
+
},
|
| 2254 |
+
{
|
| 2255 |
+
"cell_type": "markdown",
|
| 2256 |
+
"id": "2c928b78-cd6b-4edf-8ae3-22a936e3411f",
|
| 2257 |
+
"metadata": {},
|
| 2258 |
+
"source": [
|
| 2259 |
+
"\"Freezing\" a layer means we're telling the model not to update the weights of that layer during training.\n",
|
| 2260 |
+
"\n",
|
| 2261 |
+
"We can pass -2 to freeze_to to freeze all except the last two parameter groups/layers i.e the last two layers will only be trainable.\n",
|
| 2262 |
+
"\n",
|
| 2263 |
+
"Meaning train only last two layers.\n",
|
| 2264 |
+
"\n",
|
| 2265 |
+
"Negative indices count from end just like Python lists."
|
| 2266 |
+
]
|
| 2267 |
+
},
|
| 2268 |
+
{
|
| 2269 |
+
"cell_type": "code",
|
| 2270 |
+
"execution_count": 48,
|
| 2271 |
+
"id": "4d98aab5-1a76-40e4-a73f-2404660a13b6",
|
| 2272 |
+
"metadata": {},
|
| 2273 |
+
"outputs": [
|
| 2274 |
+
{
|
| 2275 |
+
"data": {
|
| 2276 |
+
"text/html": [
|
| 2277 |
+
"\n",
|
| 2278 |
+
"<style>\n",
|
| 2279 |
+
" /* Turns off some styling */\n",
|
| 2280 |
+
" progress {\n",
|
| 2281 |
+
" /* gets rid of default border in Firefox and Opera. */\n",
|
| 2282 |
+
" border: none;\n",
|
| 2283 |
+
" /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
|
| 2284 |
+
" background-size: auto;\n",
|
| 2285 |
+
" }\n",
|
| 2286 |
+
" progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
|
| 2287 |
+
" background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
|
| 2288 |
+
" }\n",
|
| 2289 |
+
" .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
|
| 2290 |
+
" background: #F44336;\n",
|
| 2291 |
+
" }\n",
|
| 2292 |
+
"</style>\n"
|
| 2293 |
+
],
|
| 2294 |
+
"text/plain": [
|
| 2295 |
+
"<IPython.core.display.HTML object>"
|
| 2296 |
+
]
|
| 2297 |
+
},
|
| 2298 |
+
"metadata": {},
|
| 2299 |
+
"output_type": "display_data"
|
| 2300 |
+
},
|
| 2301 |
+
{
|
| 2302 |
+
"data": {
|
| 2303 |
+
"text/html": [
|
| 2304 |
+
"<table border=\"1\" class=\"dataframe\">\n",
|
| 2305 |
+
" <thead>\n",
|
| 2306 |
+
" <tr style=\"text-align: left;\">\n",
|
| 2307 |
+
" <th>epoch</th>\n",
|
| 2308 |
+
" <th>train_loss</th>\n",
|
| 2309 |
+
" <th>valid_loss</th>\n",
|
| 2310 |
+
" <th>accuracy</th>\n",
|
| 2311 |
+
" <th>time</th>\n",
|
| 2312 |
+
" </tr>\n",
|
| 2313 |
+
" </thead>\n",
|
| 2314 |
+
" <tbody>\n",
|
| 2315 |
+
" <tr>\n",
|
| 2316 |
+
" <td>0</td>\n",
|
| 2317 |
+
" <td>0.221303</td>\n",
|
| 2318 |
+
" <td>0.164449</td>\n",
|
| 2319 |
+
" <td>0.938120</td>\n",
|
| 2320 |
+
" <td>00:51</td>\n",
|
| 2321 |
+
" </tr>\n",
|
| 2322 |
+
" </tbody>\n",
|
| 2323 |
+
"</table>"
|
| 2324 |
+
],
|
| 2325 |
+
"text/plain": [
|
| 2326 |
+
"<IPython.core.display.HTML object>"
|
| 2327 |
+
]
|
| 2328 |
+
},
|
| 2329 |
+
"metadata": {},
|
| 2330 |
+
"output_type": "display_data"
|
| 2331 |
+
}
|
| 2332 |
+
],
|
| 2333 |
+
"source": [
|
| 2334 |
+
"learn.freeze_to(-2)\n",
|
| 2335 |
+
"learn.fit_one_cycle(1,slice(1e-2/(2.6**4),1e-2))"
|
| 2336 |
+
]
|
| 2337 |
+
},
|
| 2338 |
+
{
|
| 2339 |
+
"cell_type": "markdown",
|
| 2340 |
+
"id": "7372cdf7-f42e-438e-8886-899696aa2174",
|
| 2341 |
+
"metadata": {},
|
| 2342 |
+
"source": [
|
| 2343 |
+
"Then unfreeze at bit more and continue training"
|
| 2344 |
+
]
|
| 2345 |
+
},
|
| 2346 |
+
{
|
| 2347 |
+
"cell_type": "code",
|
| 2348 |
+
"execution_count": 49,
|
| 2349 |
+
"id": "4c55c179-f3ec-4934-9313-a1d4c6b02305",
|
| 2350 |
+
"metadata": {},
|
| 2351 |
+
"outputs": [
|
| 2352 |
+
{
|
| 2353 |
+
"data": {
|
| 2354 |
+
"text/html": [
|
| 2355 |
+
"\n",
|
| 2356 |
+
"<style>\n",
|
| 2357 |
+
" /* Turns off some styling */\n",
|
| 2358 |
+
" progress {\n",
|
| 2359 |
+
" /* gets rid of default border in Firefox and Opera. */\n",
|
| 2360 |
+
" border: none;\n",
|
| 2361 |
+
" /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
|
| 2362 |
+
" background-size: auto;\n",
|
| 2363 |
+
" }\n",
|
| 2364 |
+
" progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
|
| 2365 |
+
" background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
|
| 2366 |
+
" }\n",
|
| 2367 |
+
" .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
|
| 2368 |
+
" background: #F44336;\n",
|
| 2369 |
+
" }\n",
|
| 2370 |
+
"</style>\n"
|
| 2371 |
+
],
|
| 2372 |
+
"text/plain": [
|
| 2373 |
+
"<IPython.core.display.HTML object>"
|
| 2374 |
+
]
|
| 2375 |
+
},
|
| 2376 |
+
"metadata": {},
|
| 2377 |
+
"output_type": "display_data"
|
| 2378 |
+
},
|
| 2379 |
+
{
|
| 2380 |
+
"data": {
|
| 2381 |
+
"text/html": [
|
| 2382 |
+
"<table border=\"1\" class=\"dataframe\">\n",
|
| 2383 |
+
" <thead>\n",
|
| 2384 |
+
" <tr style=\"text-align: left;\">\n",
|
| 2385 |
+
" <th>epoch</th>\n",
|
| 2386 |
+
" <th>train_loss</th>\n",
|
| 2387 |
+
" <th>valid_loss</th>\n",
|
| 2388 |
+
" <th>accuracy</th>\n",
|
| 2389 |
+
" <th>time</th>\n",
|
| 2390 |
+
" </tr>\n",
|
| 2391 |
+
" </thead>\n",
|
| 2392 |
+
" <tbody>\n",
|
| 2393 |
+
" <tr>\n",
|
| 2394 |
+
" <td>0</td>\n",
|
| 2395 |
+
" <td>0.190569</td>\n",
|
| 2396 |
+
" <td>0.148871</td>\n",
|
| 2397 |
+
" <td>0.944920</td>\n",
|
| 2398 |
+
" <td>01:07</td>\n",
|
| 2399 |
+
" </tr>\n",
|
| 2400 |
+
" </tbody>\n",
|
| 2401 |
+
"</table>"
|
| 2402 |
+
],
|
| 2403 |
+
"text/plain": [
|
| 2404 |
+
"<IPython.core.display.HTML object>"
|
| 2405 |
+
]
|
| 2406 |
+
},
|
| 2407 |
+
"metadata": {},
|
| 2408 |
+
"output_type": "display_data"
|
| 2409 |
+
}
|
| 2410 |
+
],
|
| 2411 |
+
"source": [
|
| 2412 |
+
"learn.freeze_to(-3)\n",
|
| 2413 |
+
"learn.fit_one_cycle(1,slice(5e-3/(2.6**4),5e-3))"
|
| 2414 |
+
]
|
| 2415 |
+
},
|
| 2416 |
+
{
|
| 2417 |
+
"cell_type": "markdown",
|
| 2418 |
+
"id": "ca5e211c-adb7-406f-ab0c-2370fdbdb890",
|
| 2419 |
+
"metadata": {},
|
| 2420 |
+
"source": [
|
| 2421 |
+
"Finally unfreeze the whole model"
|
| 2422 |
+
]
|
| 2423 |
+
},
|
| 2424 |
+
{
|
| 2425 |
+
"cell_type": "code",
|
| 2426 |
+
"execution_count": 50,
|
| 2427 |
+
"id": "bff4c568-7a87-46e7-b2d1-7f05217774ca",
|
| 2428 |
+
"metadata": {},
|
| 2429 |
+
"outputs": [
|
| 2430 |
+
{
|
| 2431 |
+
"data": {
|
| 2432 |
+
"text/html": [
|
| 2433 |
+
"\n",
|
| 2434 |
+
"<style>\n",
|
| 2435 |
+
" /* Turns off some styling */\n",
|
| 2436 |
+
" progress {\n",
|
| 2437 |
+
" /* gets rid of default border in Firefox and Opera. */\n",
|
| 2438 |
+
" border: none;\n",
|
| 2439 |
+
" /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
|
| 2440 |
+
" background-size: auto;\n",
|
| 2441 |
+
" }\n",
|
| 2442 |
+
" progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
|
| 2443 |
+
" background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
|
| 2444 |
+
" }\n",
|
| 2445 |
+
" .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
|
| 2446 |
+
" background: #F44336;\n",
|
| 2447 |
+
" }\n",
|
| 2448 |
+
"</style>\n"
|
| 2449 |
+
],
|
| 2450 |
+
"text/plain": [
|
| 2451 |
+
"<IPython.core.display.HTML object>"
|
| 2452 |
+
]
|
| 2453 |
+
},
|
| 2454 |
+
"metadata": {},
|
| 2455 |
+
"output_type": "display_data"
|
| 2456 |
+
},
|
| 2457 |
+
{
|
| 2458 |
+
"data": {
|
| 2459 |
+
"text/html": [
|
| 2460 |
+
"<table border=\"1\" class=\"dataframe\">\n",
|
| 2461 |
+
" <thead>\n",
|
| 2462 |
+
" <tr style=\"text-align: left;\">\n",
|
| 2463 |
+
" <th>epoch</th>\n",
|
| 2464 |
+
" <th>train_loss</th>\n",
|
| 2465 |
+
" <th>valid_loss</th>\n",
|
| 2466 |
+
" <th>accuracy</th>\n",
|
| 2467 |
+
" <th>time</th>\n",
|
| 2468 |
+
" </tr>\n",
|
| 2469 |
+
" </thead>\n",
|
| 2470 |
+
" <tbody>\n",
|
| 2471 |
+
" <tr>\n",
|
| 2472 |
+
" <td>0</td>\n",
|
| 2473 |
+
" <td>0.161605</td>\n",
|
| 2474 |
+
" <td>0.145473</td>\n",
|
| 2475 |
+
" <td>0.946080</td>\n",
|
| 2476 |
+
" <td>01:25</td>\n",
|
| 2477 |
+
" </tr>\n",
|
| 2478 |
+
" <tr>\n",
|
| 2479 |
+
" <td>1</td>\n",
|
| 2480 |
+
" <td>0.146006</td>\n",
|
| 2481 |
+
" <td>0.146676</td>\n",
|
| 2482 |
+
" <td>0.947240</td>\n",
|
| 2483 |
+
" <td>01:25</td>\n",
|
| 2484 |
+
" </tr>\n",
|
| 2485 |
+
" </tbody>\n",
|
| 2486 |
+
"</table>"
|
| 2487 |
+
],
|
| 2488 |
+
"text/plain": [
|
| 2489 |
+
"<IPython.core.display.HTML object>"
|
| 2490 |
+
]
|
| 2491 |
+
},
|
| 2492 |
+
"metadata": {},
|
| 2493 |
+
"output_type": "display_data"
|
| 2494 |
+
}
|
| 2495 |
+
],
|
| 2496 |
+
"source": [
|
| 2497 |
+
"learn.unfreeze()\n",
|
| 2498 |
+
"learn.fit_one_cycle(2,slice(1e-3/(2.6**4),1e-3))"
|
| 2499 |
+
]
|
| 2500 |
+
},
|
| 2501 |
+
{
|
| 2502 |
+
"cell_type": "code",
|
| 2503 |
+
"execution_count": 53,
|
| 2504 |
+
"id": "12a6d889-c20a-4c01-a134-04f6e1c8fff3",
|
| 2505 |
+
"metadata": {},
|
| 2506 |
+
"outputs": [],
|
| 2507 |
+
"source": [
|
| 2508 |
+
"learn.export('text-classifier-model-sentiment-movie-reviews')"
|
| 2509 |
+
]
|
| 2510 |
+
},
|
| 2511 |
+
{
|
| 2512 |
+
"cell_type": "markdown",
|
| 2513 |
+
"id": "07ca849b-04c0-4b3f-a04b-37c4a416ce05",
|
| 2514 |
+
"metadata": {},
|
| 2515 |
+
"source": [
|
| 2516 |
+
"Certainly! Let's break down the concept of **discriminative learning rates** and then explain the code you've provided.\n",
|
| 2517 |
+
"\n",
|
| 2518 |
+
"Discriminative Learning Rates:\n",
|
| 2519 |
+
"\n",
|
| 2520 |
+
"1. Basic Concept:\n",
|
| 2521 |
+
" - Instead of using a single learning rate for all layers of the network, we use different learning rates for different parts of the model.\n",
|
| 2522 |
+
"\n",
|
| 2523 |
+
"2. Rationale:\n",
|
| 2524 |
+
" - In transfer learning, earlier layers often capture more general features, while later layers are more task-specific.\n",
|
| 2525 |
+
" - We want to change the earlier layers less (lower learning rate) and the later layers more (higher learning rate).\n",
|
| 2526 |
+
"\n",
|
| 2527 |
+
"3. Implementation:\n",
|
| 2528 |
+
" - Usually, we set lower learning rates for earlier layers and higher rates for later layers.\n",
|
| 2529 |
+
" - This allows fine-tuning without destroying the useful features learned during pre-training.\n",
|
| 2530 |
+
"\n",
|
| 2531 |
+
"Now, let's look at the code:\n",
|
| 2532 |
+
"\n",
|
| 2533 |
+
"```python\n",
|
| 2534 |
+
"learn.fit_one_cycle(1, slice(5e-3/(2.6**4), 5e-3))\n",
|
| 2535 |
+
"```\n",
|
| 2536 |
+
"\n",
|
| 2537 |
+
"Breaking it down:\n",
|
| 2538 |
+
"\n",
|
| 2539 |
+
"1. `learn.fit_one_cycle(1, ...)`:\n",
|
| 2540 |
+
" - This runs the training for 1 epoch using the \"one cycle\" policy.\n",
|
| 2541 |
+
" - One cycle policy involves varying the learning rate and momentum during training for better performance.\n",
|
| 2542 |
+
"\n",
|
| 2543 |
+
"2. `slice(5e-3/(2.6**4), 5e-3)`:\n",
|
| 2544 |
+
" - This creates a range of learning rates.\n",
|
| 2545 |
+
" - The lower bound is `5e-3/(2.6**4)` ≈ 0.000137\n",
|
| 2546 |
+
" - The upper bound is `5e-3` = 0.005\n",
|
| 2547 |
+
"\n",
|
| 2548 |
+
"3. Discriminative Learning Rates in Action:\n",
|
| 2549 |
+
" - The `slice` object tells fastai to use a range of learning rates.\n",
|
| 2550 |
+
" - The earliest layers (those that were frozen) will use the lower learning rate (0.000137).\n",
|
| 2551 |
+
" - The latest layers will use the higher learning rate (0.005).\n",
|
| 2552 |
+
" - Layers in between will use learning rates interpolated between these values.\n",
|
| 2553 |
+
"\n",
|
| 2554 |
+
"4. The Specific Values:\n",
|
| 2555 |
+
" - `5e-3` (0.005) is chosen as a reasonable maximum learning rate.\n",
|
| 2556 |
+
" - Dividing by `2.6**4` for the minimum creates a spread where each layer group's learning rate is about 2.6 times larger than the previous one.\n",
|
| 2557 |
+
"\n",
|
| 2558 |
+
"5. Why These Values:\n",
|
| 2559 |
+
" - The factor of 2.6 and the use of 5e-3 are often empirically determined to work well for many transfer learning tasks.\n",
|
| 2560 |
+
" - The exact values might be adjusted based on specific model performance.\n",
|
| 2561 |
+
"\n",
|
| 2562 |
+
"In summary, this code sets up a training run with discriminative learning rates, allowing different parts of the model to learn at different speeds. This approach often leads to more effective fine-tuning in transfer learning scenarios."
|
| 2563 |
+
]
|
| 2564 |
+
},
|
| 2565 |
+
{
|
| 2566 |
+
"cell_type": "markdown",
|
| 2567 |
+
"id": "1a58261a-38f1-4dcf-984b-3375e1bbebe9",
|
| 2568 |
+
"metadata": {},
|
| 2569 |
+
"source": [
|
| 2570 |
+
"## Conclusion\n",
|
| 2571 |
+
"\n",
|
| 2572 |
+
"We saw two models here\n",
|
| 2573 |
+
"\n",
|
| 2574 |
+
"1. language model\n",
|
| 2575 |
+
"2. classifier\n",
|
| 2576 |
+
"\n",
|
| 2577 |
+
"To build a state-of-the-art classifier, \n",
|
| 2578 |
+
"\n",
|
| 2579 |
+
"- we used a preatrained language model\n",
|
| 2580 |
+
"- fine-tuned it on corpus of our task\n",
|
| 2581 |
+
"- then used its body(encoder) with a new head to do the classification."
|
| 2582 |
+
]
|
| 2583 |
+
},
|
| 2584 |
+
{
|
| 2585 |
+
"cell_type": "code",
|
| 2586 |
+
"execution_count": null,
|
| 2587 |
+
"id": "b1c6290a-2802-4957-9dff-e4b0af7023b4",
|
| 2588 |
+
"metadata": {},
|
| 2589 |
+
"outputs": [],
|
| 2590 |
+
"source": []
|
| 2591 |
+
}
|
| 2592 |
+
],
|
| 2593 |
+
"metadata": {
|
| 2594 |
+
"kernelspec": {
|
| 2595 |
+
"display_name": "Python 3",
|
| 2596 |
+
"language": "python",
|
| 2597 |
+
"name": "python3"
|
| 2598 |
+
},
|
| 2599 |
+
"language_info": {
|
| 2600 |
+
"codemirror_mode": {
|
| 2601 |
+
"name": "ipython",
|
| 2602 |
+
"version": 3
|
| 2603 |
+
},
|
| 2604 |
+
"file_extension": ".py",
|
| 2605 |
+
"mimetype": "text/x-python",
|
| 2606 |
+
"name": "python",
|
| 2607 |
+
"nbconvert_exporter": "python",
|
| 2608 |
+
"pygments_lexer": "ipython3",
|
| 2609 |
+
"version": "3.10.10"
|
| 2610 |
+
}
|
| 2611 |
+
},
|
| 2612 |
+
"nbformat": 4,
|
| 2613 |
+
"nbformat_minor": 5
|
| 2614 |
+
}
|
text-classifier-model-sentiment-movie-reviews (1)
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:c95910bba75be4619f5833ab6012ccfac45c448820241f4210c837aec94d7f59
|
| 3 |
+
size 233520166
|