LLM Course documentation
QA Pipeline ထဲက Fast Tokenizers များ
QA Pipeline ထဲက Fast Tokenizers များ
ကျွန်တော်တို့ အခု question-answering pipeline ထဲကို နက်နက်နဲနဲ လေ့လာပြီး၊ ယခင်အပိုင်းက grouped entities တွေအတွက် ကျွန်တော်တို့ လုပ်ခဲ့သလိုပဲ၊ လက်ရှိမေးခွန်းရဲ့ အဖြေကို context ကနေ ရယူဖို့ offsets တွေကို ဘယ်လိုအကျိုးယူရမလဲဆိုတာ ကြည့်ရပါမယ်။ ထို့နောက် truncate လုပ်ခံရတဲ့ အလွန်ရှည်လျားတဲ့ contexts တွေကို ဘယ်လိုကိုင်တွယ်ရမလဲဆိုတာ မြင်ရပါမယ်။ သင် question answering task ကို စိတ်မဝင်စားဘူးဆိုရင် ဒီအပိုင်းကို ကျော်သွားနိုင်ပါတယ်။
question-answering pipeline ကို အသုံးပြုခြင်း
Chapter 1 မှာ ကျွန်တော်တို့ တွေ့ခဲ့ရတဲ့အတိုင်း၊ မေးခွန်းတစ်ခုရဲ့ အဖြေကို ရယူဖို့ question-answering pipeline ကို အခုလို အသုံးပြုနိုင်ပါတယ်။
from transformers import pipeline
question_answerer = pipeline("question-answering")
context = """
🤗 Transformers is backed by the three most popular deep learning libraries — Jax, PyTorch, and TensorFlow — with a seamless integration
between them. It's straightforward to train your models with one before loading them for inference with the other.
"""
question = "Which deep learning libraries back 🤗 Transformers?"
question_answerer(question=question, context=context){'score': 0.97773,
'start': 78,
'end': 105,
'answer': 'Jax, PyTorch and TensorFlow'}တခြား pipelines တွေနဲ့ မတူဘဲ၊ model လက်ခံတဲ့ အမြင့်ဆုံးအရှည်ထက် ပိုရှည်တဲ့ texts တွေကို truncate လုပ်ပြီး split လုပ်လို့ မရတဲ့ (ဒါကြောင့် document တစ်ခုရဲ့ အဆုံးမှာ အချက်အလက်တွေ လွတ်သွားနိုင်တဲ့) တခြား pipelines တွေနဲ့ မတူဘဲ၊ ဒီ pipeline က အလွန်ရှည်လျားတဲ့ contexts တွေကို ကိုင်တွယ်နိုင်ပြီး၊ အဖြေက အဆုံးမှာ ရှိနေရင်တောင် မေးခွန်းရဲ့ အဖြေကို ပြန်ပေးပါလိမ့်မယ်။
long_context = """
🤗 Transformers: State of the Art NLP
🤗 Transformers provides thousands of pretrained models to perform tasks on texts such as classification, information extraction,
question answering, summarization, translation, text generation and more in over 100 languages.
Its aim is to make cutting-edge NLP easier to use for everyone.
🤗 Transformers provides APIs to quickly download and use those pretrained models on a given text, fine-tune them on your own datasets and
then share them with the community on our model hub. At the same time, each python module defining an architecture is fully standalone and
can be modified to enable quick research experiments.
Why should I use transformers?
1. Easy-to-use state-of-the-art models:
- High performance on NLU and NLG tasks.
- Low barrier to entry for educators and practitioners.
- Few user-facing abstractions with just three classes to learn.
- A unified API for using all our pretrained models.
- Lower compute costs, smaller carbon footprint:
2. Researchers can share trained models instead of always retraining.
- Practitioners can reduce compute time and production costs.
- Dozens of architectures with over 10,000 pretrained models, some in more than 100 languages.
3. Choose the right framework for every part of a model's lifetime:
- Train state-of-the-art models in 3 lines of code.
- Move a single model between TF2.0/PyTorch frameworks at will.
- Seamlessly pick the right framework for training, evaluation and production.
4. Easily customize a model or an example to your needs:
- We provide examples for each architecture to reproduce the results published by its original authors.
- Model internals are exposed as consistently as possible.
- Model files can be used independently of the library for quick experiments.
🤗 Transformers is backed by the three most popular deep learning libraries — Jax, PyTorch and TensorFlow — with a seamless integration
between them. It's straightforward to train your models with one before loading them for inference with the other.
"""
question = "Which deep learning libraries back 🤗 Transformers?"
question_answerer(question=question, context=long_context){'score': 0.97149,
'start': 1892,
'end': 1919,
'answer': 'Jax, PyTorch and TensorFlow'}ဒါတွေအားလုံးကို ဘယ်လိုလုပ်ဆောင်လဲ ကြည့်ရအောင်။
Question Answering အတွက် Model တစ်ခုကို အသုံးပြုခြင်း
အခြား pipelines တွေလိုပဲ၊ ကျွန်တော်တို့ input ကို tokenize လုပ်ပြီးမှ model ထဲကို ပို့ခြင်းဖြင့် စတင်ပါတယ်။ question-answering pipeline အတွက် default အားဖြင့် အသုံးပြုတဲ့ checkpoint က distilbert-base-cased-distilled-squad ဖြစ်ပါတယ်။ (နာမည်ထဲက “squad” က model ကို fine-tune လုပ်ခဲ့တဲ့ dataset ကနေ လာတာပါ; SQuAD dataset အကြောင်းကို Chapter 7 မှာ ပိုပြီး ဆွေးနွေးပါမယ်။)
from transformers import AutoTokenizer, AutoModelForQuestionAnswering
model_checkpoint = "distilbert-base-cased-distilled-squad"
tokenizer = AutoTokenizer.from_pretrained(model_checkpoint)
model = AutoModelForQuestionAnswering.from_pretrained(model_checkpoint)
inputs = tokenizer(question, context, return_tensors="pt")
outputs = model(**inputs)ကျွန်တော်တို့ question နဲ့ context ကို pair အဖြစ် tokenize လုပ်ပြီး၊ question ကို အရင်ထားတယ်ဆိုတာ သတိပြုပါ။
question answering အတွက် models တွေက ကျွန်တော်တို့ အခုထိ မြင်တွေ့ခဲ့ရတဲ့ models တွေနဲ့ နည်းနည်း ကွာခြားစွာ အလုပ်လုပ်ပါတယ်။ အပေါ်ကပုံကို ဥပမာအနေနဲ့ အသုံးပြုရင်၊ model ကို အဖြေစတင်တဲ့ token ရဲ့ index (ဒီနေရာမှာ 21) နဲ့ အဖြေအဆုံးသတ်တဲ့ token ရဲ့ index (ဒီနေရာမှာ 24) ကို ခန့်မှန်းဖို့ train လုပ်ထားပါတယ်။ ဒါကြောင့် ဒီ models တွေက logits tensor တစ်ခုတည်း ပြန်မပေးဘဲ နှစ်ခု ပြန်ပေးတာပါ- တစ်ခုက အဖြေရဲ့ start token နဲ့ ကိုက်ညီတဲ့ logits တွေအတွက်ဖြစ်ပြီး၊ နောက်တစ်ခုက အဖြေရဲ့ end token နဲ့ ကိုက်ညီတဲ့ logits တွေအတွက် ဖြစ်ပါတယ်။ ဒီကိစ္စမှာ ကျွန်တော်တို့မှာ tokens ၆၆ ခုပါဝင်တဲ့ input တစ်ခုတည်းသာ ရှိတဲ့အတွက်၊ ကျွန်တော်တို့ ရရှိတာက…
start_logits = outputs.start_logits
end_logits = outputs.end_logits
print(start_logits.shape, end_logits.shape)torch.Size([1, 66]) torch.Size([1, 66])ဒီ logits တွေကို probabilities အဖြစ် ပြောင်းလဲဖို့၊ ကျွန်တော်တို့ softmax function ကို အသုံးပြုပါမယ်၊ ဒါပေမယ့် အဲဒါမတိုင်ခင်၊ context ရဲ့ အစိတ်အပိုင်း မဟုတ်တဲ့ indices တွေကို mask လုပ်ထားဖို့ သေချာအောင် လုပ်ဖို့လိုပါတယ်။ ကျွန်တော်တို့ရဲ့ input က [CLS] question [SEP] context [SEP] ဖြစ်တာကြောင့်၊ question ရဲ့ tokens တွေနဲ့ [SEP] token ကိုပါ mask လုပ်ဖို့လိုပါတယ်။ [CLS] token ကိုတော့ ထားရှိပါမယ်၊ ဘာလို့လဲဆိုတော့ တချို့ models တွေက အဖြေဟာ context ထဲမှာ မရှိဘူးဆိုတာ ပြဖို့ အဲဒါကို အသုံးပြုလို့ပါပဲ။
ကျွန်တော်တို့ နောက်ပိုင်းမှာ softmax ကို အသုံးပြုမှာဖြစ်တဲ့အတွက်၊ mask လုပ်ချင်တဲ့ logits တွေကို ကြီးမားတဲ့ negative number တစ်ခုနဲ့ အစားထိုးဖို့ပဲ လိုပါတယ်။ ဒီနေရာမှာ၊ ကျွန်တော်တို့ -10000 ကို အသုံးပြုပါတယ်။
import torch
sequence_ids = inputs.sequence_ids()
# context ရဲ့ tokens တွေကလွဲပြီး အားလုံးကို Mask လုပ်ပါ
mask = [i != 1 for i in sequence_ids]
# [CLS] token ကို Unmask လုပ်ပါ
mask[0] = False
mask = torch.tensor(mask)[None]
start_logits[mask] = -10000
end_logits[mask] = -10000အခု ကျွန်တော်တို့ မခန့်မှန်းချင်တဲ့ နေရာတွေနဲ့ ကိုက်ညီတဲ့ logits တွေကို မှန်ကန်စွာ mask လုပ်ပြီးသွားပြီဆိုတော့၊ softmax ကို အသုံးပြုနိုင်ပါပြီ။
start_probabilities = torch.nn.functional.softmax(start_logits, dim=-1)[0]
end_probabilities = torch.nn.functional.softmax(end_logits, dim=-1)[0]ဒီအဆင့်မှာ၊ ကျွန်တော်တို့ start နဲ့ end probabilities တွေရဲ့ argmax ကို ယူနိုင်ပါတယ်၊ ဒါပေမယ့် start index က end index ထက် ပိုကြီးတဲ့ ရလဒ်နဲ့ အဆုံးသတ်နိုင်တာကြောင့်၊ နောက်ထပ် ကြိုတင်ကာကွယ်မှုအချို့ လုပ်ဖို့လိုပါတယ်။ ကျွန်တော်တို့ဟာ ဖြစ်နိုင်ခြေရှိတဲ့ start_index နဲ့ end_index တစ်ခုစီ ( start_index <= end_index ဖြစ်ရမယ့်) ရဲ့ probabilities တွေကို တွက်ချက်ပြီး၊ အမြင့်ဆုံး probability ရှိတဲ့ (start_index, end_index) tuple ကို ယူပါမယ်။
“အဖြေက start_index မှာ စတယ်” နဲ့ “အဖြေက end_index မှာ ဆုံးတယ်” ဆိုတဲ့ events တွေဟာ သီးခြားစီ ဖြစ်တယ်လို့ ယူဆရင်၊ အဖြေက start_index မှာ စတင်ပြီး end_index မှာ ဆုံးတဲ့ probability က…
ဒါကြောင့် scores အားလုံးကို တွက်ချက်ဖို့၊ start_index <= end_index ဖြစ်တဲ့ products အားလုံးကို တွက်ချက်ဖို့ပဲ လိုပါတယ်။
ပထမဆုံး ဖြစ်နိုင်ခြေရှိတဲ့ products အားလုံးကို တွက်ချက်ကြစို့။
scores = start_probabilities[:, None] * end_probabilities[None, :]ထို့နောက် start_index > end_index ဖြစ်တဲ့ values တွေကို 0 နဲ့ သတ်မှတ်ခြင်းဖြင့် mask လုပ်ပါမယ် (အခြား probabilities တွေက အားလုံး positive numbers တွေပါ)။ torch.triu() function က 2D tensor ရဲ့ upper triangular part ကို ပြန်ပေးတာကြောင့်၊ ဒါက ကျွန်တော်တို့အတွက် masking ကို လုပ်ဆောင်ပေးပါလိမ့်မယ်။
scores = torch.triu(scores)
အခု ကျွန်တော်တို့ အမြင့်ဆုံး index ကို ရယူဖို့ပဲ လိုပါတယ်။ PyTorch က flattened tensor ထဲက index ကို ပြန်ပေးမှာဖြစ်တာကြောင့်၊ start_index နဲ့ end_index ကို ရရှိဖို့ floor division // နဲ့ modulus % operations တွေကို အသုံးပြုဖို့လိုပါတယ်။
max_index = scores.argmax().item()
start_index = max_index // scores.shape[1]
end_index = max_index % scores.shape[1]
print(scores[start_index, end_index])ကျွန်တော်တို့ အခုထိ အပြီးသတ် မလုပ်ရသေးပါဘူး၊ ဒါပေမယ့် အနည်းဆုံး အဖြေအတွက် မှန်ကန်တဲ့ score ကို ရရှိနေပါပြီ (ယခင်အပိုင်းက ပထမဆုံးရလဒ်နဲ့ နှိုင်းယှဉ်ခြင်းဖြင့် စစ်ဆေးနိုင်ပါတယ်)။
0.97773✏️ စမ်းသပ်ကြည့်ပါ။ ဖြစ်နိုင်ခြေအများဆုံး အဖြေငါးခုအတွက် start နဲ့ end indices တွေကို တွက်ချက်ပါ။
ကျွန်တော်တို့မှာ tokens တွေရဲ့ start_index နဲ့ end_index ရှိနေပြီဆိုတော့၊ အခု context ထဲက character indices တွေအဖြစ် ပြောင်းလဲဖို့ပဲ လိုပါတယ်။ ဒီနေရာမှာ offsets တွေက အလွန်အသုံးဝင်ပါလိမ့်မယ်။ ဒါတွေကို ယူပြီး token classification task မှာ ကျွန်တော်တို့ လုပ်ခဲ့သလိုပဲ အသုံးပြုနိုင်ပါတယ်။
inputs_with_offsets = tokenizer(question, context, return_offsets_mapping=True)
offsets = inputs_with_offsets["offset_mapping"]
start_char, _ = offsets[start_index]
_, end_char = offsets[end_index]
answer = context[start_char:end_char]အခု ကျွန်တော်တို့ ရလဒ်ရရှိဖို့ အရာအားလုံးကို format လုပ်ဖို့ပဲ လိုပါတယ်။
result = {
"answer": answer,
"start": start_char,
"end": end_char,
"score": scores[start_index, end_index],
}
print(result){'answer': 'Jax, PyTorch and TensorFlow',
'start': 78,
'end': 105,
'score': 0.97773}ကောင်းပါပြီ! ဒါက ကျွန်တော်တို့ရဲ့ ပထမဥပမာနဲ့ အတူတူပါပဲ!
✏️ စမ်းသပ်ကြည့်ပါ။ သင်အရင်က တွက်ချက်ခဲ့တဲ့ best scores တွေကို အသုံးပြုပြီး ဖြစ်နိုင်ခြေအများဆုံး အဖြေငါးခုကို ပြသပါ။ သင်ရဲ့ ရလဒ်တွေကို စစ်ဆေးဖို့၊ ပထမ pipeline ကို ပြန်သွားပြီး ခေါ်ဆိုတဲ့အခါ
top_k=5ကို ထည့်သွင်းပေးပါ။
Long Contexts တွေကို ကိုင်တွယ်ခြင်း
ကျွန်တော်တို့ ယခင်က ဥပမာအဖြစ် အသုံးပြုခဲ့တဲ့ question နဲ့ long context ကို tokenize လုပ်ဖို့ ကြိုးစားမယ်ဆိုရင်၊ question-answering pipeline က လက်ခံတဲ့ အမြင့်ဆုံးအရှည် (384) ထက် ပိုများတဲ့ tokens အရေအတွက်ကို ရရှိပါလိမ့်မယ်။
inputs = tokenizer(question, long_context)
print(len(inputs["input_ids"]))461ဒါကြောင့်၊ ကျွန်တော်တို့ inputs တွေကို အဲဒီအမြင့်ဆုံးအရှည်မှာ truncate လုပ်ဖို့ လိုပါလိမ့်မယ်။ ဒီလိုလုပ်ဖို့ နည်းလမ်းများစွာရှိပါတယ်၊ ဒါပေမယ့် ကျွန်တော်တို့ question ကို truncate လုပ်ချင်တာ မဟုတ်ဘဲ context ကိုသာ truncate လုပ်ချင်တာပါ။ context က ဒုတိယ sentence ဖြစ်တာကြောင့်၊ ကျွန်တော်တို့ "only_second" truncation strategy ကို အသုံးပြုပါမယ်။ အဲဒီအခါမှာ ဖြစ်ပေါ်လာတဲ့ ပြဿနာကတော့ မေးခွန်းရဲ့ အဖြေက truncated context ထဲမှာ မပါဝင်နိုင်တာပါပဲ။ ဒီနေရာမှာ ဥပမာအားဖြင့်၊ ကျွန်တော်တို့ အဖြေက context ရဲ့ အဆုံးနားမှာရှိတဲ့ မေးခွန်းတစ်ခုကို ရွေးချယ်ခဲ့ပြီး၊ ကျွန်တော်တို့ truncate လုပ်တဲ့အခါ အဲဒီအဖြေက မရှိပါဘူး။
inputs = tokenizer(question, long_context, max_length=384, truncation="only_second")
print(tokenizer.decode(inputs["input_ids"]))"""
[CLS] Which deep learning libraries back [UNK] Transformers? [SEP] [UNK] Transformers : State of the Art NLP
[UNK] Transformers provides thousands of pretrained models to perform tasks on texts such as classification, information extraction,
question answering, summarization, translation, text generation and more in over 100 languages.
Its aim is to make cutting-edge NLP easier to use for everyone.
[UNK] Transformers provides APIs to quickly download and use those pretrained models on a given text, fine-tune them on your own datasets and
then share them with the community on our model hub. At the same time, each python module defining an architecture is fully standalone and
can be modified to enable quick research experiments.
Why should I use transformers?
1. Easy-to-use state-of-the-art models:
- High performance on NLU and NLG tasks.
- Low barrier to entry for educators and practitioners.
- Few user-facing abstractions with just three classes to learn.
- A unified API for using all our pretrained models.
- Lower compute costs, smaller carbon footprint:
2. Researchers can share trained models instead of always retraining.
- Practitioners can reduce compute time and production costs.
- Dozens of architectures with over 10,000 pretrained models, some in more than 100 languages.
3. Choose the right framework for every part of a model's lifetime:
- Train state-of-the-art models in 3 lines of code.
- Move a single model between TF2.0/PyTorch frameworks at will.
- Seamlessly pick the right framework for training, evaluation and production.
4. Easily customize a model or an example to your needs:
- We provide examples for each architecture to reproduce the results published by its original authors.
- Model internal [SEP]
"""ဒါက model က မှန်ကန်တဲ့ အဖြေကို ရွေးချယ်ရာမှာ ခက်ခဲစေလိမ့်မယ်လို့ ဆိုလိုပါတယ်။ ဒါကို ဖြေရှင်းဖို့၊ question-answering pipeline က context ကို သေးငယ်တဲ့ chunks တွေအဖြစ် ခွဲထုတ်နိုင်စေပြီး၊ အမြင့်ဆုံးအရှည်ကို သတ်မှတ်နိုင်ပါတယ်။ အဖြေကို ရှာမတွေ့အောင် အတိအကျမှားယွင်းတဲ့နေရာမှာ context ကို မခွဲမိစေဖို့ သေချာစေရန်၊ ၎င်းက chunks တွေကြားမှာ overlap အချို့ကိုလည်း ထည့်သွင်းထားပါတယ်။
tokenizer (fast ဒါမှမဟုတ် slow) က ဒါကို ကျွန်တော်တို့အတွက် လုပ်ပေးနိုင်ပါတယ်။ return_overflowing_tokens=True ကို ထည့်သွင်းခြင်းဖြင့်ဖြစ်ပြီး၊ stride argument နဲ့ လိုချင်တဲ့ overlap ကို သတ်မှတ်နိုင်ပါတယ်။ ဒီမှာတော့ သေးငယ်တဲ့ sentence တစ်ခုကို အသုံးပြုထားတဲ့ ဥပမာတစ်ခုပါ…
sentence = "This sentence is not too long but we are going to split it anyway."
inputs = tokenizer(
sentence, truncation=True, return_overflowing_tokens=True, max_length=6, stride=2
)
for ids in inputs["input_ids"]:
print(tokenizer.decode(ids))'[CLS] This sentence is not [SEP]'
'[CLS] is not too long [SEP]'
'[CLS] too long but we [SEP]'
'[CLS] but we are going [SEP]'
'[CLS] are going to split [SEP]'
'[CLS] to split it anyway [SEP]'
'[CLS] it anyway. [SEP]'ကျွန်တော်တို့ မြင်တွေ့ရတဲ့အတိုင်း၊ sentence ကို chunks တွေအဖြစ် ခွဲထုတ်ထားတဲ့အတွက် inputs["input_ids"] ထဲက entry တစ်ခုစီမှာ အများဆုံး tokens ၆ ခု ပါဝင်ပါတယ် (ကျန်တဲ့ entry တွေကို တူညီတဲ့ အရွယ်အစားဖြစ်အောင် padding ထည့်ဖို့ လိုပါလိမ့်မယ်)၊ ပြီးတော့ entries တစ်ခုစီကြားမှာ tokens ၂ ခု overlap ဖြစ်နေပါတယ်။
tokenization ရဲ့ ရလဒ်ကို ပိုပြီး အနီးကပ်ကြည့်ရအောင်-
print(inputs.keys())dict_keys(['input_ids', 'attention_mask', 'overflow_to_sample_mapping'])မျှော်လင့်ထားတဲ့အတိုင်း၊ ကျွန်တော်တို့ input IDs နဲ့ attention mask ကို ရရှိပါတယ်။ နောက်ဆုံး key ဖြစ်တဲ့ overflow_to_sample_mapping ကတော့ results တစ်ခုစီ ဘယ် sentence ကနေ လာလဲဆိုတာကို ပြောပြတဲ့ map တစ်ခုပါ — ဒီနေရာမှာ ကျွန်တော်တို့ tokenizer ကို ပေးခဲ့တဲ့ (တစ်ခုတည်းသော) sentence ကနေ လာတဲ့ results ၇ ခု ရှိပါတယ်။
print(inputs["overflow_to_sample_mapping"])[0, 0, 0, 0, 0, 0, 0]ဒါက sentences အများအပြားကို အတူတကွ tokenize လုပ်တဲ့အခါ ပိုပြီး အသုံးဝင်ပါတယ်။ ဥပမာအားဖြင့်…
sentences = [
"This sentence is not too long but we are going to split it anyway.",
"This sentence is shorter but will still get split.",
]
inputs = tokenizer(
sentences, truncation=True, return_overflowing_tokens=True, max_length=6, stride=2
)
print(inputs["overflow_to_sample_mapping"])ဒါက ကျွန်တော်တို့ကို…
[0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1]လို့ ပြသပါတယ်၊ ဒါက ပထမ sentence ကို chunks ၇ ခုအဖြစ် ခွဲထားပြီး၊ နောက်ထပ် chunks ၄ ခုက ဒုတိယ sentence ကနေ လာတာ ဖြစ်ပါတယ်။
အခု ကျွန်တော်တို့ရဲ့ long context ကို ပြန်သွားကြစို့။ default အားဖြင့် question-answering pipeline က အမြင့်ဆုံးအရှည် 384 ကို အသုံးပြုပါတယ်၊ ကျွန်တော်တို့ အစောပိုင်းမှာ ဖော်ပြခဲ့တဲ့အတိုင်းပါပဲ၊ ပြီးတော့ stride 128 ကို အသုံးပြုပါတယ်။ ဒါတွေဟာ model ကို fine-tune လုပ်ခဲ့တဲ့ ပုံစံနဲ့ ကိုက်ညီပါတယ် (pipeline ကို ခေါ်ဆိုတဲ့အခါ max_seq_len နဲ့ stride arguments တွေကို ထည့်သွင်းပေးခြင်းဖြင့် ဒီ parameters တွေကို ချိန်ညှိနိုင်ပါတယ်)။ ဒါကြောင့် tokenize လုပ်တဲ့အခါ အဲဒီ parameters တွေကို ကျွန်တော်တို့ အသုံးပြုပါမယ်။ padding ကိုလည်း ထည့်ပါမယ် (တူညီတဲ့ အရှည်ရှိတဲ့ samples တွေရဖို့၊ ဒါမှ tensors တွေ တည်ဆောက်နိုင်ဖို့) အပြင် offsets တွေကိုလည်း တောင်းဆိုပါမယ်။
inputs = tokenizer(
question,
long_context,
stride=128,
max_length=384,
padding="longest",
truncation="only_second",
return_overflowing_tokens=True,
return_offsets_mapping=True,
)အဲဒီ inputs တွေမှာ model က မျှော်လင့်ထားတဲ့ input IDs နဲ့ attention masks တွေအပြင်၊ offsets တွေနဲ့ ကျွန်တော်တို့ အခုလေးတင် ပြောခဲ့တဲ့ overflow_to_sample_mapping တွေ ပါဝင်ပါလိမ့်မယ်။ အဲဒီနှစ်ခုက model က အသုံးပြုတဲ့ parameters တွေ မဟုတ်တာကြောင့်၊ tensor အဖြစ် မပြောင်းလဲခင် ၎င်းတို့ကို inputs ကနေ ဖယ်ရှားပါမယ် (ဒီနေရာမှာ အသုံးမဝင်တဲ့အတွက် map ကို သိမ်းဆည်းထားမှာ မဟုတ်ပါဘူး)။
_ = inputs.pop("overflow_to_sample_mapping")
offsets = inputs.pop("offset_mapping")
inputs = inputs.convert_to_tensors("pt")
print(inputs["input_ids"].shape)torch.Size([2, 384])ကျွန်တော်တို့ရဲ့ long context ကို နှစ်ပိုင်းခွဲထားတာကြောင့်၊ model ထဲကို ဖြတ်သန်းပြီးနောက်မှာ၊ start နဲ့ end logits အစုနှစ်ခု ရရှိပါလိမ့်မယ်။
outputs = model(**inputs)
start_logits = outputs.start_logits
end_logits = outputs.end_logits
print(start_logits.shape, end_logits.shape)torch.Size([2, 384]) torch.Size([2, 384])အရင်လိုပဲ၊ softmax ကို အသုံးမပြုခင် context ရဲ့ အစိတ်အပိုင်း မဟုတ်တဲ့ tokens တွေကို အရင် mask လုပ်ပါတယ်။ padding tokens အားလုံးကိုလည်း mask လုပ်ပါတယ် (attention mask ကနေ ဖော်ပြထားတဲ့အတိုင်းပါ)။
sequence_ids = inputs.sequence_ids()
# context ရဲ့ tokens တွေကလွဲပြီး အားလုံးကို Mask လုပ်ပါ
mask = [i != 1 for i in sequence_ids]
# [CLS] token ကို Unmask လုပ်ပါ
mask[0] = False
# [PAD] tokens အားလုံးကို Mask လုပ်ပါ
mask = torch.logical_or(torch.tensor(mask)[None], (inputs["attention_mask"] == 0))
start_logits[mask] = -10000
end_logits[mask] = -10000ထို့နောက် softmax ကို အသုံးပြုပြီး ကျွန်တော်တို့ရဲ့ logits တွေကို probabilities အဖြစ် ပြောင်းလဲနိုင်ပါတယ်။
start_probabilities = torch.nn.functional.softmax(start_logits, dim=-1)
end_probabilities = torch.nn.functional.softmax(end_logits, dim=-1)နောက်တစ်ဆင့်က small context အတွက် ကျွန်တော်တို့ လုပ်ခဲ့တာနဲ့ ဆင်တူပါတယ်၊ ဒါပေမယ့် ကျွန်တော်တို့ရဲ့ chunks နှစ်ခုစီအတွက် ပြန်လည်လုပ်ဆောင်တာပါ။ ဖြစ်နိုင်ခြေရှိတဲ့ အဖြေ spans အားလုံးကို score ပေးပြီး၊ အကောင်းဆုံး score ရှိတဲ့ span ကို ယူပါတယ်။
candidates = []
for start_probs, end_probs in zip(start_probabilities, end_probabilities):
scores = start_probs[:, None] * end_probs[None, :]
idx = torch.triu(scores).argmax().item()
start_idx = idx // scores.shape[1]
end_idx = idx % scores.shape[1]
score = scores[start_idx, end_idx].item()
candidates.append((start_idx, end_idx, score))
print(candidates)[(0, 18, 0.33867), (173, 184, 0.97149)]အဲဒီ candidates နှစ်ခုက model က chunk တစ်ခုစီမှာ ရှာဖွေနိုင်ခဲ့တဲ့ အကောင်းဆုံးအဖြေတွေနဲ့ ကိုက်ညီပါတယ်။ model က မှန်ကန်တဲ့ အဖြေဟာ ဒုတိယအပိုင်းမှာ ရှိတယ်လို့ ပိုပြီး ယုံကြည်မှုရှိပါတယ် (ဒါက ကောင်းတဲ့ လက္ခဏာပါပဲ!)။ အခု ကျွန်တော်တို့ အဲဒီ token spans နှစ်ခုကို context ထဲက character spans တွေအဖြစ် map လုပ်ဖို့ပဲ လိုပါတယ် (ကျွန်တော်တို့ အဖြေရဖို့ ဒုတိယတစ်ခုကိုပဲ map လုပ်ဖို့ လိုအပ်ပါတယ်၊ ဒါပေမယ့် ပထမ chunk မှာ model က ဘာရွေးခဲ့လဲဆိုတာ ကြည့်ရတာ စိတ်ဝင်စားစရာပါ)။
✏️ စမ်းသပ်ကြည့်ပါ။ ဖြစ်နိုင်ခြေအများဆုံး အဖြေငါးခုအတွက် scores နဲ့ spans တွေကို ပြန်ပေးဖို့ အပေါ်က code ကို ပြောင်းလဲပါ။
ကျွန်တော်တို့ အရင်က ယူခဲ့တဲ့ offsets တွေက တကယ်တော့ offsets တွေရဲ့ list တစ်ခုဖြစ်ပြီး၊ text chunk တစ်ခုစီအတွက် list တစ်ခုစီ ပါဝင်ပါတယ်-
for candidate, offset in zip(candidates, offsets):
start_token, end_token, score = candidate
start_char, _ = offset[start_token]
_, end_char = offset[end_token]
answer = long_context[start_char:end_char]
result = {"answer": answer, "start": start_char, "end": end_char, "score": score}
print(result){'answer': '\n🤗 Transformers: State of the Art NLP', 'start': 0, 'end': 37, 'score': 0.33867}
{'answer': 'Jax, PyTorch and TensorFlow', 'start': 1892, 'end': 1919, 'score': 0.97149}ပထမရလဒ်ကို လျစ်လျူရှုမယ်ဆိုရင်၊ ဒီ long context အတွက် ကျွန်တော်တို့ရဲ့ pipeline နဲ့ တူညီတဲ့ ရလဒ်ကို ရရှိပါတယ်၊ ကောင်းပါပြီ!
✏️ စမ်းသပ်ကြည့်ပါ။ သင်အရင်က တွက်ချက်ခဲ့တဲ့ best scores တွေကို အသုံးပြုပြီး ဖြစ်နိုင်ခြေအများဆုံး အဖြေငါးခုကို ပြသပါ။ (context တစ်ခုလုံးအတွက်၊ chunk တစ်ခုစီအတွက် မဟုတ်ပါ)။ သင်ရဲ့ ရလဒ်တွေကို စစ်ဆေးဖို့၊ ပထမ pipeline ကို ပြန်သွားပြီး ခေါ်ဆိုတဲ့အခါ
top_k=5ကို ထည့်သွင်းပေးပါ။
ဒါက tokenizer ရဲ့ စွမ်းဆောင်ရည်တွေကို နက်နက်နဲနဲ လေ့လာခြင်းကို နိဂုံးချုပ်လိုက်ပါပြီ။ နောက်အခန်းမှာ၊ common NLP tasks အမျိုးမျိုးပေါ်မှာ model တစ်ခုကို ဘယ်လို fine-tune လုပ်ရမလဲဆိုတာ ပြသတဲ့အခါ ဒါတွေအားလုံးကို ပြန်လည်အသုံးချသွားပါမယ်။
ဝေါဟာရ ရှင်းလင်းချက် (Glossary)
- QA Pipeline (Question-Answering Pipeline): မေးခွန်းတစ်ခုကို စာသား document တစ်ခုမှ အဖြေရှာရန် ဒီဇိုင်းထုတ်ထားသော 🤗 Transformers library ရှိ
pipeline()function။ - Fast Tokenizers: Rust ဘာသာစကားဖြင့် အကောင်အထည်ဖော်ထားသော tokenizers များဖြစ်ပြီး Python-based “slow” tokenizers များထက် အလွန်မြန်ဆန်သည်။
- Offsets: token တစ်ခုစီသည် မူရင်းစာသား၏ မည်သည့်စတင်ခြင်းနှင့် အဆုံးသတ် character index များကြားတွင် ရှိနေသည်ကို ဖော်ပြသော map။
- Context: မေးခွန်းတစ်ခုကို ဖြေရန်အတွက် ပေးထားသော စာသားအပိုဒ်။
- Truncated: အရှည်ကို လျှော့ချရန်အတွက် ဖြတ်တောက်ခြင်း။
pipeline()Function: Hugging Face Transformers library မှာ ပါဝင်တဲ့ လုပ်ဆောင်ချက်တစ်ခုဖြစ်ပြီး မော်ဒယ်တွေကို သီးခြားလုပ်ငန်းတာဝန်များ (ဥပမာ- စာသားခွဲခြားသတ်မှတ်ခြင်း၊ စာသားထုတ်လုပ်ခြင်း) အတွက် အသုံးပြုရလွယ်ကူအောင် ပြုလုပ်ပေးပါတယ်။- Deep Learning Libraries: Deep learning မော်ဒယ်များကို တည်ဆောက်ရန်၊ လေ့ကျင့်ရန်နှင့် အသုံးပြုရန်အတွက် ကိရိယာများနှင့် library များ (ဥပမာ- Jax, PyTorch, TensorFlow)။
- Jax: Google မှ ထုတ်လုပ်သော high-performance numerical computation library။
- PyTorch: Facebook (ယခု Meta) က ဖန်တီးထားတဲ့ open-source machine learning library တစ်ခုဖြစ်ပြီး deep learning မော်ဒယ်တွေ တည်ဆောက်ဖို့အတွက် အသုံးပြုပါတယ်။
- TensorFlow: Google က ဖန်တီးထားတဲ့ open-source machine learning library တစ်ခုဖြစ်ပြီး deep learning မော်ဒယ်တွေ တည်ဆောက်ဖို့အတွက် အသုံးပြုပါတယ်။
- Seamless Integration: ကွဲပြားခြားနားသော အစိတ်အပိုင်းများကြားတွင် ချောမွေ့စွာ ပေါင်းစပ်အလုပ်လုပ်နိုင်ခြင်း။
- Inference: လေ့ကျင့်ပြီးသား Artificial Intelligence (AI) မော်ဒယ်တစ်ခုကို အသုံးပြုပြီး input data ကနေ ခန့်မှန်းချက်တွေ ဒါမှမဟုတ် output တွေကို ထုတ်လုပ်တဲ့ လုပ်ငန်းစဉ်။
- Model: Artificial Intelligence (AI) နယ်ပယ်တွင် အချက်အလက်များကို လေ့လာပြီး ခန့်မှန်းချက်များ ပြုလုပ်ရန် ဒီဇိုင်းထုတ်ထားသော သင်္ချာဆိုင်ရာဖွဲ့စည်းပုံများ။
- Truncate (Text): စာသား sequence တစ်ခုကို သတ်မှတ်ထားသော အရှည်တစ်ခုအထိ ဖြတ်တောက်ခြင်း။
- Maximum Length: Model တစ်ခုလက်ခံနိုင်သော အမြင့်ဆုံး input sequence အရှည်။
- Long Contexts: အလွန်ရှည်လျားသော စာသားအပိုဒ်များ။
distilbert-base-cased-distilled-squad: SQuAD dataset ပေါ်တွင် fine-tune လုပ်ထားသော DistilBERT cased model အတွက် Hugging Face Hub ရှိ ID။- SQuAD Dataset (Stanford Question Answering Dataset): မေးခွန်းဖြေဆိုခြင်း (Question Answering) အတွက် လူသိများသော dataset တစ်ခု။
- Fine-tuned: ကြိုတင်လေ့ကျင့်ထားပြီးသား (pre-trained) မော်ဒယ်တစ်ခုကို သီးခြားလုပ်ငန်းတစ်ခု (specific task) အတွက် အနည်းငယ်သော ဒေတာနဲ့ ထပ်မံလေ့ကျင့်ပေးခြင်းကို ဆိုလိုပါတယ်။
AutoTokenizer: Hugging Face Transformers library မှာ ပါဝင်တဲ့ class တစ်ခုဖြစ်ပြီး မော်ဒယ်အမည်ကို အသုံးပြုပြီး သက်ဆိုင်ရာ tokenizer ကို အလိုအလျောက် load လုပ်ပေးသည်။AutoModelForQuestionAnswering: Hugging Face Transformers library မှ question answering task အတွက် model class ကို အလိုအလျောက် load လုပ်ပေးသော class။TFAutoModelForQuestionAnswering: TensorFlow framework အတွက် question answering task အတွက် model class ကို အလိုအလျောက် load လုပ်ပေးသော class။model_checkpoint: Pretrained model ၏ ID။return_tensors="pt"/"tf": Tokenizer မှ output tensors များကို PyTorch ("pt") သို့မဟုတ် TensorFlow ("tf") format ဖြင့် ပြန်ပေးရန် သတ်မှတ်ခြင်း။- Tokens: စာသားကို ပိုင်းခြားထားသော အခြေခံယူနစ်များ။
- Logits: Model ၏ output ဖြစ်ပြီး raw, unnormalized scores များကို ဖော်ပြသည်။
- Start Logits: အဖြေစတင်မည့် token ၏ အနေအထား (index) ကို ခန့်မှန်းရန် model မှ ထုတ်ပေးသော logits များ။
- End Logits: အဖြေအဆုံးသတ်မည့် token ၏ အနေအထား (index) ကို ခန့်မှန်းရန် model မှ ထုတ်ပေးသော logits များ။
- Tensor: Machine Learning frameworks (PyTorch, TensorFlow) များတွင် ဒေတာများကို ကိုယ်စားပြုသော multi-dimensional array များ။
[CLS]Token: BERT model တွင် sequence ၏ အစကို ကိုယ်စားပြုသော special token။[SEP]Token: BERT model တွင် sentence တစ်ခု၏ အဆုံး သို့မဟုတ် sentence နှစ်ခုကြား ပိုင်းခြားရန် အသုံးပြုသော special token။- Mask (Logits): မလိုချင်သော နေရာများမှ logits များကို အလွန်ကြီးမားသော negative number ဖြင့် အစားထိုးခြင်းဖြင့် ၎င်းတို့၏ probability ကို သုညနီးပါး ဖြစ်စေခြင်း။
- Softmax Function: ဂဏန်းတန်ဖိုးများ (logits) အစုအဝေးတစ်ခုကို probability distribution (ပေါင်းလဒ် ၁ ဖြစ်သော တန်ဖိုးများ) အဖြစ် ပြောင်းလဲပေးသော သင်္ချာဆိုင်ရာ function။
- Probabilities: ဖြစ်နိုင်ခြေ တန်ဖိုးများ။
- Argmax: array တစ်ခုအတွင်းရှိ အမြင့်ဆုံးတန်ဖိုး၏ index ကို ပြန်ပေးသော function။
start_index: အဖြေစတင်မည့် token ၏ index။end_index: အဖြေအဆုံးသတ်မည့် token ၏ index။scores = start_probabilities[:, None] * end_probabilities[None, :]: start နှင့် end probabilities များကို မြှောက်ခြင်းဖြင့် ဖြစ်နိုင်ခြေရှိသော answer span အားလုံးအတွက် score matrix ကို တွက်ချက်ခြင်း။[:, None]နှင့်[None, :]သည် broadcasting အတွက် dimension ထည့်ပေးသည်။torch.triu()/np.triu(): PyTorch/NumPy မှ function တစ်ခုဖြစ်ပြီး matrix တစ်ခု၏ upper triangular part ကို ပြန်ပေးသည်။start_index > end_indexဖြစ်သော scores များကို0ပြုလုပ်ရန် အသုံးပြုသည်။argmax(): array တစ်ခုအတွင်းရှိ အမြင့်ဆုံးတန်ဖိုး၏ index ကို ပြန်ပေးသော method။item()Method: PyTorch/NumPy tensor မှ single element value ကို Python standard type အဖြစ် ပြောင်းလဲပေးသော method။- Floor Division (
//): အကြွင်းမပါသော စားခြင်း။ - Modulus (
%): စားပြီးနောက် ကျန်ရှိသောအကြွင်းကို ပြန်ပေးခြင်း။ top_kArgument:pipeline()function တွင် အကောင်းဆုံးရလဒ်kခုကို ပြန်ပေးရန် သတ်မှတ်သော argument။return_offsets_mapping=True: Tokenizer ကို အသုံးပြုသောအခါ offset mapping အချက်အလက်များကို output တွင် ထည့်သွင်းရန် သတ်မှတ်ခြင်း။return_overflowing_tokens=True: Tokenizer ကို အသုံးပြုသောအခါ max length ထက် ပိုနေသော tokens များကို သီးခြား sequence အဖြစ် ပြန်ပေးရန် သတ်မှတ်ခြင်း။strideArgument:return_overflowing_tokens=Trueနှင့်အတူ အသုံးပြုပြီး overlapping chunks များအတွက် tokens မည်မျှ ထပ်နေစေလိုသည်ကို သတ်မှတ်သည်။truncation="only_second": Tokenizer တွင် ဒုတိယ sentence ကိုသာ truncate လုပ်ရန် သတ်မှတ်ခြင်း။- Padding: sequence များကို တူညီသော အရှည်ဖြစ်စေရန် အတုအယောင် tokens များ (padding tokens) ထည့်သွင်းခြင်း။
padding="longest": Batch အတွင်းရှိ အရှည်ဆုံး sequence ၏ အရှည်အထိ padding လုပ်ရန် သတ်မှတ်ခြင်း။overflow_to_sample_mapping: Tokenizer မှ output အဖြစ် ပြန်ပေးသော map တစ်ခုဖြစ်ပြီး overflowing token sequence တစ်ခုစီသည် မူရင်း sample (input sentence) မည်သည့်နံပါတ်မှ လာသည်ကို ဖော်ပြသည်။