Buckets:

rtrm's picture
|
download
raw
15.5 kB

బహుళ సీక్వెన్స్‌ల నిర్వహణ[[handling-multiple-sequences]]

మునుపటి విభాగంలో, చిన్న పొడవు ఉన్న ఒకే సీక్వెన్స్‌పై inference చేయడం లాంటి అత్యంత సరళమైన ఉపయోగం చూశాం. కానీ అక్కడే కొన్ని ప్రశ్నలు వస్తాయి:

  • బహుళ సీక్వెన్స్‌లను ఎలా హ్యాండిల్ చేస్తాం?
  • భిన్నమైన పొడవు ఉన్న బహుళ సీక్వెన్స్‌లను ఎలా హ్యాండిల్ చేస్తాం?
  • vocabulary indices (input IDs) మాత్రమే మోడల్ బాగా పని చేయడానికి సరిపోతాయా?
  • సీక్వెన్స్ చాలా ఎక్కువగా ఉండటం కూడా సమస్యగా మారుతుందా?

ఇప్పుడు ఈ ప్రశ్నలు ఏరకమైన సమస్యలను కలిగిస్తాయో, వాటిని 🤗 Transformers API తో ఎలా పరిష్కరించాలో చూద్దాం.

మోడళ్లు batch రూపంలో ఇన్‌పుట్‌లను ఆశిస్తాయి[[models-expect-a-batch-of-inputs]]

మునుపటి exercise లో, సీక్వెన్స్‌లు సంఖ్యల జాబితాగా ఎలా మారతాయో చూశారు.
ఇప్పుడు ఆ సంఖ్యల జాబితాను టెన్సర్‌గా మార్చి మోడల్‌కి పంపుదాం:

import torch
from transformers import AutoTokenizer, AutoModelForSequenceClassification

checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = AutoModelForSequenceClassification.from_pretrained(checkpoint)

sequence = "I've been waiting for a HuggingFace course my whole life."

tokens = tokenizer.tokenize(sequence)
ids = tokenizer.convert_tokens_to_ids(tokens)
input_ids = torch.tensor(ids)
# This line will fail.
model(input_ids)
IndexError: Dimension out of range (expected to be in range of [-1, 0], but got 1)

అయ్యో! ఇది ఎందుకు fail అయింది? సెక్షన్ 2 లో pipeline ఉపయోగించిన స్టెప్పులనే ఇక్కడ కూడా పాటించాం కదా.

సమస్య ఏమిటంటే, మనం మోడల్‌కి ఒక్క సీక్వెన్స్ మాత్రమే పంపాం, కానీ 🤗 Transformers మోడళ్లు default గా బహుళ వాక్యాలను (multiple sentences) ఆశిస్తాయి.
ఇక్కడ మనం tokenizer sequence మీద వెనుకపట్లో చేసే పని మనమే చేతితో చేయడానికి ప్రయత్నించాం. కానీ బాగా గమనిస్తే, tokenizer input IDs లిస్ట్‌ను టెన్సర్‌గా మార్చడమే కాకుండా, దానిపై అదనంగా ఒక dimension కూడా వేసింది:

tokenized_inputs = tokenizer(sequence, return_tensors="pt")
print(tokenized_inputs["input_ids"])
tensor([[  101,  1045,  1005,  2310,  2042,  3403,  2005,  1037, 17662, 12172,
          2607,  2026,  2878,  2166,  1012,   102]])

ఇప్పుడు మనమే ఆ కొత్త dimension ను జోడించి మళ్లీ ప్రయత్నిద్దాం:

import torch
from transformers import AutoTokenizer, AutoModelForSequenceClassification

checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = AutoModelForSequenceClassification.from_pretrained(checkpoint)

sequence = "I've been waiting for a HuggingFace course my whole life."

tokens = tokenizer.tokenize(sequence)
ids = tokenizer.convert_tokens_to_ids(tokens)

input_ids = torch.tensor([ids])
print("Input IDs:", input_ids)

output = model(input_ids)
print("Logits:", output.logits)

ఇప్పుడు input IDs ని, అలాగే లభించిన logits ని ప్రింట్ చేస్తాం — అవి ఈ విధంగా ఉంటాయి:

Input IDs: [[ 1045,  1005,  2310,  2042,  3403,  2005,  1037, 17662, 12172,  2607, 2026,  2878,  2166,  1012]]
Logits: [[-2.7276,  2.8789]]

Batching అంటే, ఒకేసారి బహుళ వాక్యాలను (multiple sentences) మోడల్‌కి పంపడం.
మీ దగ్గర ఒక్క sentence మాత్రమే ఉన్నా, ఆ ఒక్క సీక్వెన్స్‌తోనే ఒక batch నిర్మించవచ్చు:

batched_ids = [ids, ids]

ఇది ఇప్పుడు రెండు ఒకే సీక్వెన్స్‌లను కలిగిన ఒక batch!

✏️ ప్రయత్నించండి!batched_ids లిస్ట్‌ను టెన్సర్‌గా మార్చి మీ మోడల్‌లోకి పంపండి.
ముందు వచ్చిన logits మాదిరిగానే (కానీ రెండుసార్లు) వస్తున్నాయో చూడండి!

Batching ద్వారా, మీరు బహుళ వాక్యాలను మోడల్‌కి పంపినప్పుడు అది సరిగ్గా పని చేస్తుంది.
ఒక సీక్వెన్స్‌తో batch తయారుచేసినట్లే, బహుళ సీక్వెన్స్‌లతో కూడా batch తయారుచేయడం అంతే సులభం.

కానీ ఇక్కడ రెండో సమస్య వస్తుంది: మీరు రెండు (లేదా అంతకంటే ఎక్కువ) వాక్యాలను batch లో కలపాలనుకుంటే, అవి ఒక్కోటి ఒక్కో పొడవు (length) లో ఉండవచ్చు.
టెన్సర్‌లతో ముందే పని చేసి ఉంటే, అవి rectangular shape లో ఉండాల్సిందేనని మీకు తెలుసు; కాబట్టి input IDs జాబితాను నేరుగా టెన్సర్‌గా మార్చలేం.
ఈ సమస్యను పరిష్కరించడానికి, సాధారణంగా మనం ఇన్‌పుట్‌లను pad చేస్తాం.

ఇన్‌పుట్‌లను padding చేయడం[[padding-the-inputs]]

క్రింద ఉన్న list of lists ను నేరుగా టెన్సర్‌గా మార్చలేం:

batched_ids = [
    [200, 200, 200],
    [200, 200]
]

దీనిని పరిష్కరించడానికి, మనం padding ఉపయోగిస్తాం, తద్వారా టెన్సర్‌లు rectangular shape లో ఉంటాయి.
Padding ద్వారా, అన్ని వాక్యాలూ ఒకే పొడవు కలిగేలా, తక్కువ పదాలు ఉన్న వాక్యాలకు ప్రత్యేక పదమైన padding token ను చివరలో జోడిస్తాం.
ఉదాహరణకు, 10 వాక్యాలు ఒక్కోటి 10 పదాలతో ఉండి, మరో ఒక వాక్యం 20 పదాలతో ఉందనుకోండి; padding చేసిన తర్వాత, అన్ని వాక్యాలూ 20 పదాలు కలిగి ఉంటాయి.
మన ఉదాహరణలో, చివరికి వచ్చిన టెన్సర్ ఇలా కనిపిస్తుంది:

padding_id = 100

batched_ids = [
    [200, 200, 200],
    [200, 200, padding_id],
]

Padding token యొక్క ID ని tokenizer.pad_token_id లో చూడవచ్చు.
ఇప్పుడిదాన్ని ఉపయోగించి, మన రెండు వాక్యాలను ఒక్కోసారి విడివిడిగా, అలాగే batch గా కలిపి మోడల్‌లోకి పంపుదాం:

model = AutoModelForSequenceClassification.from_pretrained(checkpoint)

sequence1_ids = [[200, 200, 200]]
sequence2_ids = [[200, 200]]
batched_ids = [
    [200, 200, 200],
    [200, 200, tokenizer.pad_token_id],
]

print(model(torch.tensor(sequence1_ids)).logits)
print(model(torch.tensor(sequence2_ids)).logits)
print(model(torch.tensor(batched_ids)).logits)
tensor([[ 1.5694, -1.3895]], grad_fn=)
tensor([[ 0.5803, -0.4125]], grad_fn=)
tensor([[ 1.5694, -1.3895],
        [ 1.3373, -1.2163]], grad_fn=)

ఇక్కడ batched predictions లో logits లో ఏదో తేడా ఉంది: రెండో row, రెండో వాక్యాన్ని విడిగా పంపినప్పుడు వచ్చిన logits మాదిరిగానే ఉండాలి, కానీ పూర్తిగా వేరు values వచ్చాయి!

దీనికి కారణం, Transformer మోడళ్లలో ప్రధాన పాత్ర పోషించే attention layers — ఇవి ప్రతి token ను దాని context తో కలిపి చూడడానికి ప్రయత్నిస్తాయి.
ఇవి padding tokens ను కూడా గమనిస్తాయి, ఎందుకంటే అవి సీక్వెన్స్‌లోని అన్ని tokens పై దృష్టి పెడతాయి.
కాబట్టి, వేర్వేరు పొడవు ఉన్న వాక్యాలను విడిగా మోడల్‌కి పంపినా, అదే వాక్యాలను padding తో కూడిన batch గా పంపినా, ఒకే ఫలితాలు రావాలంటే, attention layers‌కు padding tokens ను పట్టించుకోవద్దు అని చెప్పాలి. ఇది attention mask ద్వారా చేస్తాం.

Attention masks[[attention-masks]]

Attention mask అనేది input IDs టెన్సర్‌కి అచ్చం అదే రూపంలో ఉండే టెన్సర్, కానీ 0లూ 1లతో నిండినది:
1 ఉన్న స్థానాల్లోని tokens పై మోడల్ దృష్టి పెట్టాలి, 0 ఉన్న స్థానాల్లోని tokens ను దృష్టి పెట్టకూడదు (అంటే, ఆ tokens ను attention layers పూర్తిగా ignore చేయాలి).

ఇప్పుడు ముందున్న ఉదాహరణకే ఒక attention mask జోడిద్దాం:

batched_ids = [
    [200, 200, 200],
    [200, 200, tokenizer.pad_token_id],
]

attention_mask = [
    [1, 1, 1],
    [1, 1, 0],
]

outputs = model(torch.tensor(batched_ids), attention_mask=torch.tensor(attention_mask))
print(outputs.logits)
tensor([[ 1.5694, -1.3895],
        [ 0.5803, -0.4125]], grad_fn=)

ఇప్పుడు batch లో రెండో వాక్యానికి వచ్చిన logits, ఆ వాక్యాన్ని విడిగా పంపినప్పుడు వచ్చిన logits‌ల మాదిరిగానే ఉన్నాయి.

గమనించండి: రెండో సీక్వెన్స్ లో చివరి విలువ padding ID కి సంబంధించినది; దానికి attention mask లో 0 ఉంది.

✏️ ప్రయత్నించండి! సెక్షన్ 2 లో ఉపయోగించిన రెండు వాక్యాల ("I've been waiting for a HuggingFace course my whole life." మరియు "I hate this so much!") మీద టోకనైజేషన్‌ను చేతితో చేయండి.
వాటిని మోడల్‌కి విడివిడిగా పంపి, సెక్షన్ 2 లో వచ్చిన logits మాదిరిగానే వస్తున్నాయో చూసుకోండి.
తర్వాత వాటిని padding token తో కలిపి ఒక batch చేయండి, సరైన attention mask నిర్మించండి, మళ్లీ మోడల్‌లోకి పంపి ఫలితాలు ఒకటేనా చూడండి!

పొడవైన సీక్వెన్స్‌లు[[longer-sequences]]

Transformer మోడళ్లతో పని చేసేప్పుడు, మోడల్ అంగీకరించే సీక్వెన్స్‌ల పొడవుకు ఒక పరిమితి ఉంటుంది.
చాలా మోడళ్లు గరిష్టంగా 512 లేదా 1024 tokens వరకు మాత్రమే సీక్వెన్స్‌లను హ్యాండిల్ చేయగలవు; అంతకంటే పొడవైన సీక్వెన్స్‌లను పంపితే, అవి క్రాష్ కావచ్చు.
ఈ సమస్యకు రెండు పరిష్కారాలు ఉన్నాయి:

  • పొడవైన సీక్వెన్స్‌లను సపోర్ట్ చేసే మోడల్ ఉపయోగించడం.
  • మీ సీక్వెన్స్‌లను truncation ద్వారా చిన్నవిగా కత్తిరించడం.

వివిధ మోడళ్లకు వివిధ గరిష్ట సీక్వెన్స్ పొడవులు ఉంటాయి; కొన్ని మోడళ్లు చాలా పొడవైన సీక్వెన్స్‌ల కోసం ప్రత్యేకంగా రూపొందించబడ్డాయి.
ఉదాహరణకు, Longformer, LED లాంటి మోడళ్లు.
మీ పని చాలా పొడవైన సీక్వెన్స్‌లను అవసరం చేసుకుంటే, ఇటువంటి మోడళ్లపై ఒకసారి పరిశీలించమని సూచిస్తాము.

లేదంటే, మీ సీక్వెన్స్‌లను truncate చేయడం మంచిది; దానికి max_sequence_length పరామీటర్‌ను ఇవ్వవచ్చు:

sequence = sequence[:max_sequence_length]

Xet Storage Details

Size:
15.5 kB
·
Xet hash:
2bfa5060af186c33c3146060136a4679dd4fd32467a5f00b4eb7874ae98a2375

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.