Package: fastai-ulmfit
fast.ai ULMFiT with SentencePiece from pretraining to deploymentMotivation:Why even bother with a non-BERT / Transformer language model? Short answer: you can train a state of the art text classifier with ULMFiT with limited data and affordable hardware. The whole process (preparing the Wikipedia dump, pretrain the language model, fine tune the language model and training the classifier) takes about 5 hours on my workstation with a RTX 3090. The training of the model with FP16 requires less than 8 GB VRAM - so you can train the model on affordable GPUs.I also saw this paper on the roadmap for fast.ai 2.3Single Headed Attention RNN: Stop Thinking With Your Headwhich could improve the performance further.This Repo is based on:https://github.com/fastai/fastaiULMFiT Paperthe fast.ai NLP-course repository:https://github.com/fastai/course-nlpPretrained modelsLanguage(local)codePerplexityVocab SizeTokenizerDownload (.tgz files)GermanDeutschde16.115kSPhttps://bit.ly/ulmfit-dewikiDutchNederlandsnl20.515kSPhttps://bit.ly/ulmfit-nlwikiRussianРусскийru29.815kSPhttps://bit.ly/ulmfit-ruwikiPortuguesePortuguêspt17.315kSPhttps://bit.ly/ulmfit-ptwikiVietnameseTiếng Việtvi18.815kSPhttps://bit.ly/ulmfit-viwikiJapanese日本語ja42.615kSPhttps://bit.ly/ulmfit-jawikiItalianItalianoit23.715kSPhttps://bit.ly/ulmfit-itwikiSpanishEspañoles21.915kSPhttps://bit.ly/ulmfit-eswikiKorean한국어ko39.615kSPhttps://bit.ly/ulmfit-kowikiThaiไทยth56.415kSPhttps://bit.ly/ulmfit-thwikiHebrewעבריתhe46.315kSPhttps://bit.ly/ulmfit-hewikiArabicالعربيةar50.015kSPhttps://bit.ly/ulmfit-arwikiMongolianМонголmnsee:Github: RobertRitzDownload with wget# to preserve the filenames (.tgz!) when downloading with wget use --content-disposition
wget --content-disposition https://bit.ly/ulmfit-dewikiUsage of pretrained models - library fastai_ulmfit.pretrainedI've written a small library around this repo, to easily use the pretrained models. You don't have to bother with model, vocab and tokenizer files and paths - the following functions will take care of that.Tutorial:fastai_ulmfit_pretrained_usage.ipynbInstallationpip install fastai-ulmfitUsage# import
from fastai_ulmfit.pretrained import *

url = 'http://bit.ly/ulmfit-dewiki'

# get tokenizer - if pretrained=True, the SentencePiece Model used for language model pretraining will be used. Default: False 
tok = tokenizer_from_pretrained(url, pretrained=False)

# get language model learner for fine-tuning
learn = language_model_from_pretrained(dls, url=url, drop_mult=0.5).to_fp16()

# save fine-tuned model for classification
path = learn.save_lm('tmp/test_lm')

# get text classifier learner from fine-tuned model
learn = text_classifier_from_lm(dls, path=path, metrics=[accuracy]).to_fp16()Extract Sentence Embeddingsfrom fastai_ulmfit.embeddings import SentenceEmbeddingCallback

se = SentenceEmbeddingCallback(pool_mode='concat')
_ = learn.get_preds(cbs=[se])

feat = se.feat
pca = PCA(n_components=2)
pca.fit(feat['vec'])
coords = pca.transform(feat['vec'])Model pretrainingSetupPython environmentfastai-2.2.7
fastcore-1.3.19
sentencepiece-0.1.95
fastinference-0.0.36Install packagespip install -r requirements.txtThe trained language models are compatible with other fastai versions!DockerThe Wikipedia-dump preprocessing requires dockerhttps://docs.docker.com/get-docker/.Project structure.
├── we                         Docker image for the preperation of the Wikipedia-dump / wikiextractor
└── data          
    └── {language-code}wiki         
        ├── dump                    downloaded Wikipedia dump
        │   └── extract             extracted wikipedia-articles using wikiextractor
        ├── docs 
        │   ├── all                 all extracted Wikipedia articles as single txt-files
        │   ├── sampled             sampled Wikipedia articles for language model pretraining
        │   └── sampled_tok         cached tokenized sampled articles - created by fastai / sentencepiece
        └── model 
            ├── lm                  language model trained in step 2
            │   ├── fwd             forward model
            │   ├── bwd             backwards model
            │   └── spm             SentencePiece model
            │
            ├── ft                  fine tuned model trained in step 3
            │   ├── fwd             forward model
            │   ├── bwd             backwards model
            │   └── spm             SentencePiece model
            │
            └── class               classifier trained in step 4
                ├── fwd             forward learner
                └── bwd             backwards learner1. Prepare Wikipedia-dump for pretrainingULMFiT can be peretrained on relativly small datasets - 100 million tokens are sufficient to get state-of-the art classification results (compared to Transformer models as BERT, which need huge amounts of training data). The easiest way is to pretrain a language model on Wikipedia.The code for the preperation steps is heavily inspired by / copied from thefast.ai NLP-course:https://github.com/fastai/course-nlp/blob/master/nlputils.pyI built a docker container and script, that automates the following steps:Download Wikipedia XML-dumpExtract the text from the dumpSample 160.000 documents with a minimum length of 1800 characters (results in 100m-120m tokens) both parameters can be changed - see the usage belowThe whole process will take some time depending on the download speed and your hardware. For the 'dewiki' the preperation took about 45 min.Run the following commands in the current directory# build the wikiextractor docker file
docker build -t wikiextractor ./we

# run the docker container for a specific language
# docker run -v $(pwd)/data:/data -it wikiextractor -l <language-code> 
# for German language-code de run:
docker run -v $(pwd)/data:/data -it wikiextractor -l de
...
sucessfully prepared dewiki - /data/dewiki/docs/sampled, number of docs 160000/160000 with 110699119 words / tokens!

# To change the number of sampled documents or the minimum length see
usage: preprocess.py [-h] -l LANG [-n NUMBER_DOCS] [-m MIN_DOC_LENGTH] [--mirror MIRROR] [--cleanup]

# To cleanup indermediate files (wikiextractor and all splitted documents) run the following command. 
# The Wikipedia-XML-Dump and the sampled docs will not be deleted!
docker run -v $(pwd)/data:/data -it wikiextractor -l <language-code> --cleanup2. Language model pretraining on Wikipedia DumpNotebook:2_ulmfit_lm_pretraining.ipynbTo get the best result, you can train two seperate language models - a forward and a backward model. You'll have to run the complete notebook twice and set thebackwardsparameter accordingly. The models will be saved in seperate folders (fwd / bwd). The same applies to fine-tuning and training of the classifier.ParametersChange the following parameters according to your needs:lang = 'de' # language of the Wikipedia-Dump
backwards = False # Train backwards model? Default: False for forward model
bs=128 # batch size
vocab_sz = 15000 # vocab size - 15k / 30k work fine with sentence piece
num_workers=18 # num_workers for the dataloaders
step = 'lm' # language model - don't changeTraining Logs + configmodel.jsoncontains theparametersthe language model was trained with and thestatistics(looses and metrics) of the last epoch{"lang":"de","step":"lm","backwards":false,"batch_size":128,"vocab_size":15000,"lr":0.01,"num_epochs":10,"drop_mult":0.5,"stats":{"train_loss":2.894167184829712,"valid_loss":2.7784812450408936,"accuracy":0.46221256256103516,"perplexity":16.094558715820312}}history.csvlog of the training metrics (epochs, losses, accuracy, perplexity)epoch,train_loss,valid_loss,accuracy,perplexity,time
0,3.375441551208496,3.369227886199951,0.3934227228164673,29.05608367919922,23:00
...
9,2.894167184829712,2.7784812450408936,0.46221256256103516,16.094558715820312,22:443. Language model fine-tuning on unlabled dataNotebook:3_ulmfit_lm_finetuning.ipynbTo improve the performance on the downstream-task, the language model should be fine-tuned. We are using a Twitter dataset (GermEval2018/2019), so we fine-tune the LM on unlabled tweets.To use the notebook on your own dataset, create a.csv-file containing your (unlabled) data in thetextcolumn.Files required from the Language Model (previous step):Model (*model.pth)Vocab (*vocab.pkl)I am not reusing the SentencePiece-Model from the language model! This could lead to slightly different tokenization but fast.ai (-> language_model_learner()) and the fine-tuning takes care of adding and training unknown tokens! This approch gave slightly better results than reusing the SP-Model from the language model.4. Train the classifierNotebook:4_ulmfit_train_classifier.ipynbThe (fine-tuned) language model now can be used to train a classifier on a (small) labled dataset.To use the notebook on your own dataset, create a.csv-file containing your texts in thetextand labels in thelabelcolumn.Files required from the fine-tuned LM (previous step):Encoder (*encoder.pth)Vocab (*vocab.pkl)SentencePiece-Model (spm/spm.model)5. Use the classifier for predictions / inference on new dataNotebook:5_ulmfit_inference.ipynbEvaluationGerman pretrained modelResults with an ensemble of forward + backward model (see the inference notebook). Neither the fine-tuning of the LM, nor the training of the classifier was optimized - so there is still room for improvement.Official results:https://ids-pub.bsz-bw.de/frontdoor/deliver/index/docId/9319/file/Struss_etal._Overview_of_GermEval_task_2_2019.pdfTask 1 Coarse ClassificationClasses: OTHER, OFFENSEAccuracy: 79,68
F1: 75,96 (best BERT 76,95)Task 2 Fine ClassificationClasses: OTHER, PROFANITY, INSULT, ABUSEAccuracy: 74,56 %
F1: 52,54 (best BERT 53.59)Dutch modelCompared result with:https://arxiv.org/pdf/1912.09582.pdfDatasethttps://github.com/benjaminvdb/DBRDAccuracy 93,97 % (best BERT 93,0 %)Japanese modelCopared results with:https://github.com/laboroai/Laboro-BERT-Japanesehttps://github.com/yoheikikuta/bert-japaneseLivedoor news corpusAccuracy 97,1% (best BERT ~98 %)Korean modelCompared with:https://github.com/namdori61/BERT-Korean-ClassificationDataset:https://github.com/e9t/nsmcAccuracy 89,6 % (best BERT 90,1 %)Deployment as REST-APIseehttps://github.com/floleuerer/fastai-docker-deploy.