From edf3811cd7e99c817ecd8d3560cf3c65b7c585ff Mon Sep 17 00:00:00 2001 From: Filip Gralinski Date: Mon, 14 Jun 2021 08:23:02 +0200 Subject: [PATCH] new --- wyk/14_pretrenowanie.org | 155 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 wyk/14_pretrenowanie.org diff --git a/wyk/14_pretrenowanie.org b/wyk/14_pretrenowanie.org new file mode 100644 index 0000000..1b33f10 --- /dev/null +++ b/wyk/14_pretrenowanie.org @@ -0,0 +1,155 @@ +* Pretrenowanie modeli + +System AlphaZero uczy się grając sam ze sobą — wystarczy 24 godziny, +by system nauczył się grać w szachy lub go na nadludzkim poziomie. + +*Pytanie*: Dlaczego granie samemu ze sobą nie jest dobrym sposobem + nauczenia się grania w szachy dla człowieka, a dla maszyny jest? + +Co jest odpowiednikiem grania samemu ze sobą w świecie przetwarzania tekstu? +Tzn. *pretrenowanie* (/pretraining/) na dużym korpusie tekstu. (Tekst jest tani!) + +Jest kilka sposobów na pretrenowanie modelu, w każdym razie sprowadza +się do odgadywania następnego bądź zamaskowanego słowa. +W każdym razie zawsze stosujemy softmax (być może ze „sztuczkami” takimi jak +negatywne próbkowanie albo hierarchiczny softamx) na pewnej *representecji kontekstowej*: + +$$\vec{p} = \operatorname{softmax}(f(\vec{c})).$$ + +Model jest karany używając funkcji log loss: + +$$-\log(p_j),$$ + +gdzie $w_j$ jest wyrazem, który pojawił się rzeczywiście w korpusie. + +** Przewidywanie słowa (GPT-2) + +Jeden ze sposobów pretrenowania modelu to po prostu przewidywanie +następnego słowa. + +Zainstalujmy najpierw bibliotekę transformers. + +#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer +! pip install transformers +#+END_SRC + +#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer + import torch + from transformers import GPT2Tokenizer, GPT2LMHeadModel + tokenizer = GPT2Tokenizer.from_pretrained('gpt2-large') + model = GPT2LMHeadModel.from_pretrained('gpt2-large') + text = "Warsaw is the capital city of" + encoded_input = tokenizer(text, return_tensors='pt') + output = model(**encoded_input) + next_token_probs = torch.softmax(output[0][:, -1, :][0], dim=0) + + nb_of_tokens = next_token_probs.size()[0] + + _, top_k_indices = torch.topk(next_token_probs, 30, sorted=True) + top_k_indices + # words = tokenizer.convert_ids_to_tokens(top) + + # top_probs = [] + + # for ix in range(len(top)): + # top_probs.append((words[ix], next_token_probs[top[ix]].item())) + + # top_probs +#+END_SRC + +#+RESULTS: +:results: +# Out[8]: +#+BEGIN_EXAMPLE + [('Ġthe', 0.4415026307106018), + ('ĠPoland', 0.236798495054245), + ('ĠBelarus', 0.10114768147468567), + ('ĠUkraine', 0.058283545076847076), + ('Ġeastern', 0.020564062520861626), + ('ĠEastern', 0.011137397028505802), + ('ĠPolish', 0.010205904021859169), + ('ĠWestern', 0.00833223108202219), + ('Ġwestern', 0.006872199941426516), + ('Ġa', 0.004939113277941942), + ('ĠSlovakia', 0.003553805174306035), + ('ĠLithuania', 0.003335304092615843), + ('ĠRussia', 0.002872465644031763), + ('Ġcentral', 0.002493523992598057), + ('Ġmodern', 0.0022767107002437115), + ('ĠCzech', 0.0022264323197305202), + ('ĠPr', 0.002146221464499831), + ('Ġformer', 0.0021054286044090986), + ('Ġwhat', 0.0017435317859053612), + ('ĠSlov', 0.0014634730760008097), + ('ĠUkrainian', 0.0014347084797918797), + ('ĠCentral', 0.0013676199596375227), + ('ĠSouth', 0.0013484350638464093), + ('Ġone', 0.001204205909743905), + ('ĠNorthern', 0.0011802552035078406), + ('ĠWest', 0.001175572513602674), + ('ĠEast', 0.0011596156982704997), + ('Ġsouthern', 0.0011580033460631967), + ('Ġnorthern', 0.001110077602788806), + ('Ġ"', 0.0010494199814274907)] +#+END_EXAMPLE +:end: + +Zalety tego podejścia: + +- prostota, +- dobra podstawa do strojenia systemów generowania tekstu zwłaszcza + „otwartego” (systemy dialogowe, generowanie (fake) newsów, streszczanie tekstu), + ale niekoniecznie tłumaczenia maszynowego, +- zaskakująca skuteczność przy uczeniu /few-shot/ i /zero-shot/. + +Wady: + +- asymetryczność, przetwarzanie tylko z lewej do prawej, preferencja + dla lewego kontekstu, +- mniejsza skuteczność przy dostrajaniu do zadań klasyfikacji i innych zadań + niepolegających na prostym generowaniu. + +Przykłady modeli: GPT, GPT-2, GPT-3, DialoGPT. + +** Maskowanie słów (BERT) + +Inną metodą jest maskowanie słów (/Masked Language Modeling/, /MLM/). + +W tym podejściu losowe wybrane zastępujemy losowe słowa specjalnym +tokenem (~[MASK]~) i każemy modelowi odgadywać w ten sposób +zamaskowane słowa (z uwzględnieniem również prawego kontekstu!). + +Móciąc ściśle, w jednym z pierwszych modeli tego typu (BERT) +zastosowano schemat, w którym również niezamaskowane słowa są odgadywane (!): + +- wybieramy losowe 15% wyrazów do odgadnięcia +- 80% z nich zastępujemy tokenem ~[MASK]~, +- 10% zastępujemy innym losowym wyrazem, +- 10% pozostawiamy bez zmian. + + +#+BEGIN_SRC ipython :session mysession :exports both :results raw drawer +from transformers import AutoModelWithLMHead, AutoTokenizer +import torch + +tokenizer = AutoTokenizer.from_pretrained("distilroberta-base") +model = AutoModelWithLMHead.from_pretrained("distilroberta-base") + +sequence = f"Hugging Face is a French company based in {tokenizer.mask_token}" + +input_ids = tokenizer.encode(sequence, return_tensors="pt") +mask_token_index = torch.where(input_ids == tokenizer.mask_token_id)[1] + +token_logits = model(input_ids)[0] +mask_token_logits = token_logits[0, mask_token_index, :] +mask_token_logits = torch.softmax(mask_token_logits, dim=1) + +top_5 = torch.topk(mask_token_logits, 5, dim=1) +top_5_tokens = zip(top_5.indices[0].tolist(), top_5.values[0].tolist()) + +for token, score in top_5_tokens: + print(sequence.replace(tokenizer.mask_token, tokenizer.decode([token])), f"(score: {score})") +#+END_SRC + + +Przykłady: BERT, RoBERTa (również Polish RoBERTa).