This notebook demonstrates how we can use Blurr to train, or fine-tune, a causal language model against examples defined in individual files (similar to how the raw wiki-103 data comes). We demonstrate how to use `get_text_files` and create a custom `splitter` function to build our train and validation datasets.
 
Here's what we're running with ...

torch: 1.9.0+cu102
fastai: 2.5.2
transformers: 4.10.0

Get your data

raw_data_path = Path('./data/task-language-modeling/pt-2/')
raw_data_path.ls()
(#3) [Path('data/task-language-modeling/pt-2/valid'),Path('data/task-language-modeling/pt-2/train'),Path('data/task-language-modeling/pt-2/test')]
(raw_data_path/'train').ls()
(#730) [Path('data/task-language-modeling/pt-2/train/Bandeira_de_Angola.txt'),Path('data/task-language-modeling/pt-2/train/Pâncreas.txt'),Path('data/task-language-modeling/pt-2/train/Governo_Federal_do_Brasil.txt'),Path('data/task-language-modeling/pt-2/train/Monte_da_Pedra.txt'),Path('data/task-language-modeling/pt-2/train/Pouso_Alegre.txt'),Path('data/task-language-modeling/pt-2/train/Ararinha-azul.txt'),Path('data/task-language-modeling/pt-2/train/Deus.txt'),Path('data/task-language-modeling/pt-2/train/Ernest_Hemingway.txt'),Path('data/task-language-modeling/pt-2/train/Brasileiros.txt'),Path('data/task-language-modeling/pt-2/train/Distrito_de_Beja.txt')...]
len((raw_data_path/'train').ls()), len((raw_data_path/'valid').ls())
(730, 56)

Get your HF objects

model_cls = AutoModelForCausalLM

pretrained_model_name = "gpt2"
hf_arch, hf_config, hf_tokenizer, hf_model = BLURR.get_hf_objects(pretrained_model_name, model_cls=model_cls)

if (hf_tokenizer.pad_token is None): 
    hf_tokenizer.add_special_tokens({'pad_token': '<pad>'})  
    hf_config.pad_token_id = hf_tokenizer.get_vocab()['<pad>']
    hf_model.resize_token_embeddings(len(hf_tokenizer))
Using pad_token, but it is not set yet.

Build your DataBlock

Define how to get the raw data

get_wiki_files = partial(get_text_files, folders=['train', 'valid'])
fnames = get_wiki_files(raw_data_path)
fnames[0]
Path('data/task-language-modeling/pt-2/valid/Hipótese_de_Riemann.txt')

Define how we want to split our validation and training datasets

splitter = FuncSplitter(lambda fpath: Path(fpath).parent.name == 'valid')
splitter(fnames)
((#730) [56,57,58,59,60,61,62,63,64,65...], (#56) [0,1,2,3,4,5,6,7,8,9...])

Define our DataBlock using the appropriate Blurr transforms

bbtfm = HF_LMBeforeBatchTransform(hf_arch, hf_config, hf_tokenizer, hf_model, lm_strategy_cls=CausalLMStrategy)
blocks = (HF_TextBlock(before_batch_tfm=bbtfm, input_return_type=HF_CausalLMInput), noop)

# our DataBlock
dblock = DataBlock(
    blocks=blocks, 
    get_x=lambda x: x.read_text(),   # read each text file
    get_items=get_wiki_files,        # grab the text files
    splitter=splitter                # split on parent folder name (validation = 'valid')
)
 
dls = dblock.dataloaders(raw_data_path, bs=2, val_bs=4)
b = dls.one_batch()
b[0]['input_ids'].shape, b[1].shape
(torch.Size([2, 1024]), torch.Size([2, 1024]))
dls.show_batch(dataloaders=dls, trunc_at=500, max_n=2)
text target
0 Aquecimento global é o processo de aumento da temperatura média dos oceanos e da atmosfera da Terra causado por massivas emissões de gases que intensificam o efeito estufa, originados de uma série de atividades humanas, especialmente a queima de combustíveis fósseis e mudanças no uso da terra, como o desmatamento, bem como de várias outras fontes secundárias. Essas causas são um produto direto da explosão populacional, do crescimento econômico, do uso de tecnologias e fontes de energia poluidor ecimento global é o processo de aumento da temperatura média dos oceanos e da atmosfera da Terra causado por massivas emissões de gases que intensificam o efeito estufa, originados de uma série de atividades humanas, especialmente a queima de combustíveis fósseis e mudanças no uso da terra, como o desmatamento, bem como de várias outras fontes secundárias. Essas causas são um produto direto da explosão populacional, do crescimento econômico, do uso de tecnologias e fontes de energia poluidoras e
1 Os astecas eram uma cultura mesoamericana que floresceu no centro do México no período pós-clássico, de 1300 a 1521. Os povos astecas incluíam diferentes grupos étnicos do México central, particularmente aqueles grupos que falavam a língua náuatle e dominaram grandes partes da Mesoamérica entre os séculos XIV ao XVI. A cultura asteca era organizada em cidades-Estados ( &quot; altepetl &quot; ), algumas das quais se juntaram para formar alianças, confederações políticas ou impérios. O Império As astecas eram uma cultura mesoamericana que floresceu no centro do México no período pós-clássico, de 1300 a 1521. Os povos astecas incluíam diferentes grupos étnicos do México central, particularmente aqueles grupos que falavam a língua náuatle e dominaram grandes partes da Mesoamérica entre os séculos XIV ao XVI. A cultura asteca era organizada em cidades-Estados ( &quot; altepetl &quot; ), algumas das quais se juntaram para formar alianças, confederações políticas ou impérios. O Império Astec

Train

model = HF_BaseModelWrapper(hf_model)
fit_cbs = [LM_MetricsCallback()]

learn = Learner(dls, 
                model,
                opt_func=partial(Adam),
                loss_func=HF_PreCalculatedLoss(),
                cbs=[HF_BaseModelCallback],
                metrics=[perplexity],
                splitter=hf_splitter).to_fp16()

# learn.freeze()
learn.lr_find(suggest_funcs=[minimum, steep, valley, slide])
/home/wgilliam/miniconda3/envs/blurr/lib/python3.9/site-packages/fastai/callback/schedule.py:269: UserWarning: color is redundantly defined by the 'color' keyword argument and the fmt string "ro" (-> color='r'). The keyword argument will take precedence.
  ax.plot(val, idx, 'ro', label=nm, c=color)
SuggestedLRs(minimum=0.02089296132326126, steep=0.17378008365631104, valley=0.00019054606673307717, slide=0.2089296132326126)
learn.fit_one_cycle(1, lr_max=3e-3, cbs=fit_cbs)
epoch train_loss valid_loss perplexity lm_accuracy time
0 3.192033 3.088641 21.947229 0.427133 02:30
learn.show_results(learner=learn, max_n=2, trunc_at=500)
text target prediction
0 A Idade Média ( adj. medieval ) é um período da história da Europa entre os séculos V e XV. Inicia-se com a Queda do Império Romano do Ocidente e termina durante a transição para a Idade Moderna. A Idade Média é o período intermédio da divisão clássica da História ocidental em três períodos : a Antiguidade, Idade Média e Idade Moderna, sendo frequentemente dividido em Alta e Baixa Idade Média.\nDurante a Alta Idade Média verifica-se a continuidade dos processos de despovoamento, regressão urbana Idade Média ( adj. medieval ) é um período da história da Europa entre os séculos V e XV. Inicia-se com a Queda do Império Romano do Ocidente e termina durante a transição para a Idade Moderna. A Idade Média é o período intermédio da divisão clássica da História ocidental em três períodos : a Antiguidade, Idade Média e Idade Moderna, sendo frequentemente dividido em Alta e Baixa Idade Média.\nDurante a Alta Idade Média verifica-se a continuidade dos processos de despovoamento, regressão urbana, aade dedia é o. & & é u �íodo de �ória da Id,re os �éculos X. V,\nicialisse ao �úa, Estério daano, Sulcidente, aou aante o sumissção de a Europaade Méa.\n Idade Média fo a período daaédio de Europaisão daássica, Europaória,uidental. queês estíodos. a Idiguidade, aade Média, Idade Méa. ao aemente aido em �enteç aixa,ade,dia,\nAante o Idta,ade Média,dou-se aoarade de �os de estó eo e aando ebana, a aasão�es deritsicnicas,iciaadas.ante a Idiguidade Méambin,\n �cados doárbaras deam avos,os de comenado
1 Itália ( ), oficialmente República Italiana, é uma república parlamentar unitária localizada no centro-sul da Europa. Ao norte, faz fronteira com França, Suíça, Áustria e Eslovênia ao longo dos Alpes. A parte sul consiste na totalidade da península Itálica, Sicília, Sardenha, as duas maiores ilhas no mar Mediterrâneo, e muitas outras ilhas menores ficam no entorno do território italiano. Os Estados independentes de San Marino e do Vaticano são enclaves no interior da Itália, enquanto Campione d ália ( ), oficialmente República Italiana, é uma república parlamentar unitária localizada no centro-sul da Europa. Ao norte, faz fronteira com França, Suíça, Áustria e Eslovênia ao longo dos Alpes. A parte sul consiste na totalidade da península Itálica, Sicília, Sardenha, as duas maiores ilhas no mar Mediterrâneo, e muitas outras ilhas menores ficam no entorno do território italiano. Os Estados independentes de San Marino e do Vaticano são enclaves no interior da Itália, enquanto Campione d &a ario é ) é éicialmente,ública (a, é umma freública dealentoá deário doizada pel Brasro daameró, Uni.\n Repe da comaz partonteira com oa, queíça e E�rearia, �spanâinania,o longo do paente.\n suir do doe em � deade de Europaínsula,áliaa, queâlia, Itãoia, S fras principaiores dohas, �,iterrâno, e oaiso mras ilhas door.azç- santo do paório.aliano.\n principados Unes do Portugal Marino e S Brasilaano,ão aadas em territ do Europaálic, queanto ao,asquos; Repá & a paéminist doaliano. Europaíça.\n paório It
learn.blurr_generate('Itália ( ), oficialmente República Italiana', max_length=100, do_sample=True, top_k=25)
[' Itália ( ), oficialmente República Italiana , que o estudante do Brasil , é um município da Beira e suporte com o Brasileiro de Portugal em 1824 . No Brasil , ao município da Beira é o distrito de Beira . A sua capital da Beira é o seu capital , do nome da América do Sul e do nordeste']

Summary

This example demonstrates how to train a causal language model where the raw data examples are in individual files (similar to how the standard wikitext-103 is defined). We also defined a custom splitter function so as to put all the files under /valid as part of the validation set and all the files under /train in the training set.