এই পর্বে যা শিখবেন
- Zero-shot, one-shot আর few-shot; in-context learning নিয়ে কী জানা, কী বিতর্কিত
- Label শব্দের log-likelihood দিয়ে few-shot classifier মাপা, seed আর CI-সহ
- Random বনাম similar উদাহরণ বাছাই, আর তার ফাঁদ: k-NN নকল আর যমজ মন্তব্যের ফাঁস
- ক্রম, recency আর majority-label bias নিজে মাপা
- Contextual calibration-এর হিসাব, তার সীমা, আর লম্বা prompt-এর খরচ
এই পর্বের সব মাপ লেখার সময়ের (নভেম্বর ২০২৬) একটি স্থানীয় run-এর, দুটি ছোট open model আর ২০০টি মন্তব্যে। কোনো hosted পণ্য এখানে চালানো হয়নি, আর এই সংখ্যা দিয়ে কোনো বড় model বা পণ্যের মান বিচার করা যায় না; বড় model-এ ফল আলাদা হতেই পারে। Prompt-এর মূল গঠন আগের পর্বে (পর্ব ৬০ · Prompt-এর গঠন); log-likelihood দিয়ে নম্বর দেওয়া আর CI পর্ব ৫৮-এ।
১ · Zero, one আর few-shot — নির্দেশের পাশে নমুনা
বাজারঘরের গুদামে নতুন একজন কর্মী এলেন। তাঁকে বলা হলো, “গ্রাহকের মন্তব্য পড়ে খুশি না অখুশি, খাতায় লিখবেন।” প্রথম দিন তিনি অনেক প্রশ্ন করবেন: “একটু খুশি” কোন ঘরে? শুধু প্রশ্ন করা মন্তব্য? এবার খাতার প্রথম পাতায় আগের চারটি মন্তব্য আর তার পাশে লেখা রায় দেখিয়ে দিলে কাজটি অনেক পরিষ্কার হয়। লেখার ছাঁচ, শব্দ বাছাই, কোন ধরনের লেখা কোন ঘরে, সব নমুনা থেকেই বোঝা যায়। কর্মীর মাথায় নতুন কোনো প্রশিক্ষণ হয়নি, শুধু সামনে নমুনা আছে।
LLM-এর prompt-এ ঠিক এটিই করা হয়। নির্দেশের সঙ্গে কোনো উদাহরণ না দিলে সেটি zero-shot; একটি দিলে one-shot; কয়েকটি দিলে few-shot. প্রতিটি উদাহরণ একটি input আর তার কাঙ্ক্ষিত output-এর জোড়া, যাকে demonstration বলে। Model-এর weight একটুও বদলায় না; বদলায় শুধু input-এর লেখা। তবু আচরণ বদলায়, আর এই ঘটনাকে বলে in-context learning (ICL).
নামগুলো জনপ্রিয় হয় GPT-3-এর প্রবন্ধে (Brown ও সহকর্মী, ২০২০, “Language Models are Few-Shot Learners”). লেখকেরা প্রায় ১৭,৫০০ কোটি parameter-এর model-এ দেখান, prompt-এ কয়েকটি উদাহরণ দিলে অনেক task-এ নির্ভুলতা বাড়ে, আর বড় model-এ এই লাভ বেশি। তাঁরা নিজেরাই সতর্ক ছিলেন: model কি সত্যিই নতুন task “শেখে”, নাকি pretraining-এ দেখা কোনো ছাঁচ চিনে নেয়, তা প্রবন্ধে খোলা প্রশ্ন হিসেবে রাখা। এই বিতর্ক এখনো চলছে, আর এই পর্বে আমরা দাবি না করে মাপব। Prompt-এর বাকি অংশ, যেমন নির্দেশ, প্রসঙ্গ আর ফরম্যাট, আগের পর্বে আলাদা করে দেখেছেন (পর্ব ৬০ · Prompt-এর গঠন)। LLM কীভাবে পরের token অনুমান করে, তার সহজ রূপ AI-এর ভিত্তি কোর্সের পর্ব ৭০-এ।
পণ্যগুলোর নথি কী বলে
পরিচিত সহায়কগুলোর নির্মাতারা উদাহরণ নিয়ে নিজেদের অফিসিয়াল নথিতে কী লিখেছেন, তা নিচে, লেখার সময়ে (নভেম্বর ২০২৬) পড়া। নথি পরিবর্তন হতে পারে, তাই বর্তমান সংস্করণ নিজে পড়ে নিন। এটি কোনো তুলনা বা ক্রম নয়।
| পণ্য (নির্মাতা), নথি | উদাহরণ নিয়ে যা লেখা |
|---|---|
| ChatGPT / GPT (OpenAI) API docs-এর prompt engineering guide | Few-shot মানে fine-tuning-এর বদলে prompt-এ কয়েকটি input/output জোড়া; সাধারণত developer message-এর অংশ হিসেবে; বিভিন্ন রকম input দেখাতে বলা। কয়টি দিতে হবে, তা নথিতে পাইনি। |
| Claude (Anthropic) Prompting best practices | উদাহরণ ফরম্যাট, ভঙ্গি আর গঠন ঠিক করার নির্ভরযোগ্য উপায়; উদাহরণ হবে প্রাসঙ্গিক, বৈচিত্র্যময় আর <example> tag-এ মোড়া; “৩–৫টি” উদাহরণের পরামর্শ। |
| Gemini (Google) Prompt design strategies | সব prompt-এ few-shot উদাহরণ রাখার পরামর্শ; বেশি উদাহরণে উত্তর উদাহরণের দিকে “overfit” করতে পারে; সব উদাহরণের গঠন, ফাঁকা জায়গা আর নতুন লাইন হুবহু এক রাখতে বলা। |
| Grok (xAI) docs.x.ai | উদাহরণ দেওয়া নিয়ে আলাদা পরামর্শ নথিতে পাইনি। |
| DeepSeek DeepSeek-R1-এর প্রবন্ধ ও model card | প্রবন্ধে (২০২৫) লেখা, few-shot prompting R1-এর ফল ধারাবাহিকভাবে কমিয়েছে; zero-shot-এ সমস্যা আর output ফরম্যাট সরাসরি লিখতে বলা। Model card-এ system prompt না দিয়ে সব নির্দেশ user prompt-এ রাখার পরামর্শ। |
| Kimi (Moonshot AI) Best Practices for Prompts | “কাঙ্ক্ষিত output-এর উদাহরণ দিন” নামে একটি অংশ; যে ভঙ্গি কথায় বোঝানো কঠিন, তার জন্য few-shot prompt. |
অভিন্ন কথাটি স্পষ্ট: উদাহরণ ফরম্যাট আর ভঙ্গি ঠিক করে, আর সব উদাহরণ একই ছাঁচে লিখতে হয়। মতভেদও আছে: একটি নথি সব সময় উদাহরণ দিতে বলে, আরেকটি reasoning model-এর জন্য zero-shot-কে ভালো বলে (ভাবনার প্রশ্ন ২)। Hosted পণ্যগুলো এখানে চালানো যায় না (API key নেই), তাই সব মাপ ছোট open model-এ।
২ · একটি 4-shot prompt — গঠন আর label-এর নম্বর
এই পর্বের task: YouTube-এর বাংলা নাটকের মন্তব্য ইতিবাচক না নেতিবাচক। ডেটা Sazzed ও Jayarathna-র (২০১৯) সংগ্রহ, Mendeley Data-তে CC BY 4.0 license-এ (DOI 10.17632/p6zc7krs37.4), যা পর্ব ৪২-এ পরিষ্কার করা হয়েছিল: ১০,৭০৯টি অনন্য মন্তব্য, প্রায় ২৮.৫% নেতিবাচক। প্রায় একই মন্তব্যগুলো একটি দলে রাখা। এখান থেকে নেওয়া হলো ২০০টি মন্তব্যের একটি স্থির test নমুনা, ১০০টি নেতিবাচক আর ১০০টি ইতিবাচক, যাতে “সবসময় ইতিবাচক” বললে ঠিক ০.৫০ আসে। উদাহরণ নেওয়া হয় আলাদা একটি ভাণ্ডার (pool) থেকে: test-এর কোনো দলের সদস্য সেখানে নেই, আর প্রতিটি মন্তব্য ৬০ token-এর মধ্যে, মোট ৬,০০৮টি। অনেক মন্তব্যে গালি আছে; পাতায় শুধু ভদ্রগুলো দেখানো, মাপা হয়েছে সবগুলোতে।
Prompt-এর ছাঁচ সব run-এ এক: প্রথমে এক লাইনের নির্দেশ, তারপর k-টি উদাহরণ “মন্তব্য: … / অনুভূতি: …” আকারে, শেষে নতুন মন্তব্য আর ফাঁকা “অনুভূতি:”। পুরোটা একটি user message, যা model-এর chat template-এ মোড়া হয় (পর্ব ৫৬)। উত্তর লিখতে দেওয়ার বদলে দুটি label শব্দের প্রতিটির log-likelihood মাপা হয়, ঠিক পর্ব ৫৮-এর multiple-choice-এর মতো। যার যোগফল বড়, সেটিই রায়। নিচের stepper-এ একটি 4-shot prompt ধাপে ধাপে জোড়া লাগানো হয়েছে; token-এর হিসাব Qwen2.5-এর tokenizer-এ সত্যিকারের গোনা।
| ধাপ | |
| যোগ হলো | |
| token | |
| p(ইতি) |
- 0-shot. শুধু নির্দেশ আর প্রশ্ন, chat template-সহ ১২৫ token. দুটি label-এর log-likelihood: নেতিবাচক −৭.২৫, ইতিবাচক −৬.৮৬; ইতিবাচকের সম্ভাবনা ০.৫৯৭, তাই রায় ইতিবাচক, যা ভুল। দুটি সংখ্যাই খুব নিচু: model “অনুভূতি:”-এর পরে এই শব্দগুলো আশাই করছিল না।
- প্রথম উদাহরণ. একটি নেতিবাচক মন্তব্য আর তার label যোগ হলো; prompt ১৯৩ token. বাংলায় একটি ছোট মন্তব্যেই প্রায় ৭০ token খরচ হয় (পর্ব ৪০)।
- দ্বিতীয় উদাহরণ. আরেকটি নেতিবাচক; ২৪৮ token. মাঝের ধাপগুলোর নম্বর মাপা হয়নি, তাই “…”।
- তৃতীয় উদাহরণ. এবার একটি ইতিবাচক; ৩১৩ token. দুই label-ই এখন prompt-এ আছে, তাই model দেখতে পাচ্ছে উত্তর এই দুটি শব্দের একটি।
- চতুর্থ উদাহরণ. আরেকটি ইতিবাচক; মোট ৩৫৪ token, 0-shot-এর প্রায় ২.৮ গুণ। ক্রম N, N, P, P; §৬-এ দেখবেন, এই ক্রমও রায়কে প্রভাবিত করে।
- Label-এর নম্বর. নেতিবাচক (৮ token) −১.০২, ইতিবাচক (৭ token) −২.৯৫. p(ইতি) = ১ ÷ (১ + e১.৯৩) ≈ ০.১২৭, রায় নেতিবাচক, যা ঠিক। দুটি সংখ্যাই অনেক ওপরে উঠেছে: উদাহরণ model-কে আগে দেখিয়েছে উত্তর কোন শব্দে।
দুটি label-এর সম্ভাবনা এখানে শুধু এই দুটির মধ্যে আবার ভাগ করা: p(ইতি) = ea ÷ (ea + eb), যেখানে a আর b দুই label-এর log-likelihood. এটি softmax, আর এর মানে শুধু a − b-র ওপর নির্ভর করে। এই পার্থক্যটিকে বলব label-এর log-odds; §৮-এর calibration পুরোটা এর ওপর দাঁড়িয়ে।
৩ · সত্যিকারের run — 0, 1, 4 আর 8-shot
Model দুটি: Qwen/Qwen2.5-1.5B-Instruct (প্রায় ১৫০ কোটি parameter) আর তুলনার জন্য Qwen/Qwen2.5-0.5B-Instruct (প্রায় ৪৯ কোটি), দুটিই Apache 2.0, token ছাড়া নামানো, revision hash ধরে, ফাইলের sha256 মিলিয়ে। সব GPU-তে, bf16-এ: torch 2.15.0, transformers 5.22.2, Python 3.12, লেখার সময়ে। প্রতিটি অবস্থা একই ২০০টি মন্তব্যে। Random উদাহরণ পাঁচটি আলাদা seed-এ টানা, তাই প্রতিটি k-এর পাঁচটি সংখ্যা; similar উদাহরণ প্রতিটি মন্তব্যের জন্য আলাদা, ভাণ্ডারের সবচেয়ে কাছের k-টি (§৫)। Script-এর মূল অংশ আর আউটপুট, নিচে ছোট করে; সংখ্যাগুলো হুবহু।
@torch.no_grad() # মূল অংশ, batch ছাড়া সহজ রূপে
def score(tok, model, prompts): # প্রতিটি prompt-এর পরে দুটি label-এর log-likelihood
lab = [tok(l, add_special_tokens=False)["input_ids"] for l in ["নেতিবাচক", "ইতিবাচক"]]
out = []
for p in prompts:
pid = tok(p, add_special_tokens=False)["input_ids"]
row = []
for li in lab:
ids = torch.tensor([pid + li]).cuda()
h = model.model(input_ids=ids).last_hidden_state[0, len(pid) - 1:-1]
lp = model.lm_head(h).float().log_softmax(-1)
row.append(lp[torch.arange(len(li)), ids[0, len(pid):]].sum().item())
out.append(row)
return np.array(out) # (n, 2); রায় = যে কলাম বড়~/bazarghar-dl$ uv run python fewshot.py q15 sweep cuda # সত্যিকারের run, GPU-তে
q15 k0 acc=0.510 pred_pos=0.590 tokens= 151.3 secs=11.6
q15 rand_k1_s0 acc=0.540 pred_pos=0.060 tokens= 232.3 secs=15.9
q15 rand_k1_s4 acc=0.445 pred_pos=0.465 tokens= 211.3 secs=14.7
q15 sim_k1 acc=0.560 pred_pos=0.070 tokens= 205.6 secs=14.3
q15 rand_k4_s0 acc=0.645 pred_pos=0.195 tokens= 421.3 secs=26.0
q15 rand_k4_s2 acc=0.500 pred_pos=1.000 tokens= 374.3 secs=24.0
q15 rand_k4_s4 acc=0.745 pred_pos=0.305 tokens= 407.3 secs=25.0
q15 sim_k4 acc=0.870 pred_pos=0.500 tokens= 374.1 secs=25.1
q15 rand_k8_s1 acc=0.770 pred_pos=0.580 tokens= 618.3 secs=37.2
q15 rand_k8_s2 acc=0.500 pred_pos=1.000 tokens= 619.3 secs=37.2
q15 sim_k8 acc=0.890 pred_pos=0.510 tokens= 602.6 secs=39.5
… (২১টির ১১টি লাইন দেখানো)
peak GPU memory allocated (GB): 3.74
কলামগুলো: acc ২০০টিতে নির্ভুলতা; pred_pos কত ভাগ মন্তব্যকে ইতিবাচক বলেছে (ঠিক উত্তরে ০.৫০); tokens গড় prompt-এর দৈর্ঘ্য; secs ২০০টি মন্তব্যের মোট সময়। পুরো ছবি এক সারণিতে, সঙ্গে দুটি সাধারণ তুলনা: একই ৬,০০৮টি সারিতে শেখানো TF-IDF + logistic regression (পর্ব ৪২-এর baseline, এখানে একই ২০০টিতে আবার মাপা), আর “সবচেয়ে কাছের k-টি মন্তব্যের label-এর ভোট”, যেখানে কোনো LLM নেই। “ইংরেজি label” কলামে মন্তব্য বাংলাই, শুধু নির্দেশ আর label শব্দ (positive/negative) ইংরেজিতে।
| অবস্থা | 1.5B, বাংলা label | 1.5B, ইংরেজি label | 0.5B, বাংলা label | গড় token (বাংলা) |
|---|---|---|---|---|
| 0-shot | ০.৫১০ | ০.৭৮০ | ০.৫১৫ | ১৫১ |
| Random, k = ১ (৫ seed) | ০.৪৪৫–০.৫৪০ | ০.৭৭৫–০.৮২০ | ০.৪৮৫–০.৫২৫ | ১৯৩–২৩২ |
| Random, k = ৪ (৫ seed) | ০.৫০০–০.৭৪৫, গড় ০.৬৩৭ | ০.৮০৫–০.৮৮৫, গড় ০.৮৩৬ | সব ০.৫০০ | ৩৪১–৪২১ |
| Random, k = ৮ (৫ seed) | ০.৫০০–০.৭৭০, গড় ০.৬৮২ | ০.৮২০–০.৮৬৫, গড় ০.৮৩৮ | ০.৫০০–০.৫১০ | ৬১৮–৭০৭ |
| Similar, k = ১ / ৪ / ৮ | ০.৫৬০ / ০.৮৭০ / ০.৮৯০ | ০.৭৮৫ / ০.৮৫৫ / ০.৮৮৫ | ০.৫৬০ / ০.৬২৫ / ০.৬৫৫ | ২০৬ / ৩৭৪ / ৬০৩ |
| কাছের k-টির label-এর ভোট, k = ১ / ৪ / ৮ | ০.৮৭৫ / ০.৮৯০ / ০.৮৭০ (LLM ছাড়া) | ০ | ||
| TF-IDF + logistic regression | ০.৯৪৫ (১৮৯/২০০) | ০ | ||
এবার CI নিজে হিসাব করুন। প্রতিটি অবস্থার ২০০টি ঠিক-ভুল সত্যিকারের run থেকে ফাইলে রাখা; কোড Wilson interval আর একই মন্তব্যের সূচকে জোড়া bootstrap দেয় (পর্ব ৫৮, মেশিন লার্নিং কোর্সের পর্ব ২১)।
import numpy as np
# runs_ok.txt: প্রতি লাইনে একটি অবস্থা, তারপর ২০০টি test মন্তব্যে ঠিক (1) না ভুল (0)
R = {}
for line in open("runs_ok.txt", encoding="utf-8"):
name, bits = line.strip().split("|")
R[name] = np.array([int(b) for b in bits])
def wilson(c, n, z=1.96): # ছোট n-এ normal-এর চেয়ে ভালো CI
p = c / n; den = 1 + z * z / n
mid = (p + z * z / (2 * n)) / den
h = z * np.sqrt(p * (1 - p) / n + z * z / (4 * n * n)) / den
return mid - h, mid + h
print(f"{'অবস্থা':16}{'acc':>6} 95% Wilson CI")
for k in (0, 1, 4, 8):
names = ["0-shot"] if k == 0 else [f"random k={k} s{s}" for s in range(5)] + [f"similar k={k}"]
for nm in names:
if nm.endswith(("s1", "s2", "s3")): continue # জায়গা বাঁচাতে s0 আর s4 দেখাই
x = R[nm]; lo, hi = wilson(x.sum(), len(x))
print(f"{nm:16}{x.mean():6.3f} [{lo:.3f}, {hi:.3f}]")
if k:
a = [R[f"random k={k} s{s}"].mean() for s in range(5)]
print(f"{' ৫ seed-এর ছড়ানো':16} {min(a):.3f}–{max(a):.3f}, sd {np.std(a, ddof=1):.3f}")
rng = np.random.default_rng(0) # জোড়া bootstrap: একই মন্তব্যের সূচক দুই পাশে
def paired(a, b, B=10000):
i = rng.integers(0, len(a), (B, len(a)))
d = (a[i] - b[i]).mean(1)
return (a - b).mean(), *np.percentile(d, [2.5, 97.5])
for a, b in (("similar k=4", "random k=4 s0"), ("random k=4 s0", "0-shot")):
m, lo, hi = paired(R[a], R[b])
print(f"{a} − {b}: {m:+.3f} [{lo:+.3f}, {hi:+.3f}]")আউটপুট (পাতার Python-এ চালানো):
অবস্থা acc 95% Wilson CI
0-shot 0.510 [0.441, 0.578]
random k=1 s0 0.540 [0.471, 0.608]
random k=1 s4 0.445 [0.378, 0.514]
similar k=1 0.560 [0.491, 0.627]
৫ seed-এর ছড়ানো 0.445–0.540, sd 0.039
random k=4 s0 0.645 [0.577, 0.708]
random k=4 s4 0.745 [0.680, 0.800]
similar k=4 0.870 [0.816, 0.910]
৫ seed-এর ছড়ানো 0.500–0.745, sd 0.098
random k=8 s0 0.710 [0.644, 0.768]
random k=8 s4 0.705 [0.638, 0.764]
similar k=8 0.890 [0.839, 0.926]
৫ seed-এর ছড়ানো 0.500–0.770, sd 0.105
similar k=4 − random k=4 s0: +0.225 [+0.145, +0.305]
random k=4 s0 − 0-shot: +0.135 [+0.030, +0.240]
প্রথম শিক্ষা: 0-shot প্রায় দৈব। ০.৫১০, CI ০.৪৪১ থেকে ০.৫৭৮, যার মাঝে ০.৫০ আছে। নির্দেশ বাংলায় স্পষ্ট, তবু উদাহরণ ছাড়া এই model label শব্দ দুটি ঠিকমতো বসাতে পারেনি; stepper-এ দেখেছেন, দুই label-এরই log-likelihood খুব নিচু ছিল।
দ্বিতীয় শিক্ষা: কোন উদাহরণ, সেটিই বড় কথা। 4-shot-এ পাঁচটি seed ০.৫০০ থেকে ০.৭৪৫ পর্যন্ত ছড়িয়ে, sd প্রায় ০.১০. একটি seed-এর ফল দেখে “4-shot ভালো” বা “4-shot কাজ করে না”, দুটি দাবিই ভুল হতে পারত। ০.৫০০-এর seed-টি §৭-এ ব্যাখ্যা করব: তার চারটি উদাহরণই ইতিবাচক ছিল।
তৃতীয় শিক্ষা: similar অনেক এগিয়ে, তবে কেন, সেটি জরুরি। Similar 4-shot আর random seed ০-এর জোড়া পার্থক্য +০.২২৫, CI পুরোটা শূন্যের ওপরে। কিন্তু সারণির শেষ দিকে দেখুন: LLM ছাড়াই কাছের চারটির ভোট ০.৮৯০, প্রায় একই। §৫-এ দেখব, model আসলে মূলত সেই ভোটই নকল করছে। আর পুরনো TF-IDF baseline ০.৯৪৫, সবার ওপরে, অনেক কম খরচে। ছোট 0.5B model-এ random উদাহরণে কোনো লাভই নেই, প্রায় সব মন্তব্যে “নেতিবাচক”; বাংলায় ছোট model-এর এই সীমা পর্ব ৫৮-এও দেখেছেন।
চতুর্থ শিক্ষা: label শব্দও prompt-এর অংশ। একই 1.5B-এ শুধু নির্দেশ আর label শব্দ ইংরেজিতে দিলে 0-shot ০.৭৮০, random 4-shot গড় ০.৮৩৬, seed-এর ছড়ানোও অনেক কম; similar-এর বাড়তি লাভ তখন ছোট (+০.০১৯, CI শূন্য ছোঁয়)। বাংলা label-এ উদাহরণের বড় লাভের অনেকটাই ছিল “উত্তর কোন শব্দে” চেনানো।
৪ · উদাহরণ কী শেখায় — ফরম্যাট, না label-এর মানে?
Min ও সহকর্মীরা (২০২২, “Rethinking the Role of Demonstrations”) একটি সহজ পরীক্ষা করেন: উদাহরণের সঠিক label সরিয়ে random label বসানো। তাঁদের দেখা অনেক classification task-এ নির্ভুলতা সামান্যই কমে। তাঁদের ব্যাখ্যা, উদাহরণের বড় কাজ তিনটি: label-এর জগৎ দেখানো (উত্তর কোন শব্দগুলো), input-এর ধরন দেখানো, আর ফরম্যাট দেখানো। Wei ও সহকর্মীরা (২০২৩) আবার দেখান, label পুরো উল্টে দিলে বড় model প্রায়ই সেই উল্টো নিয়ম মানে। দুটি দাবিই নিজের model-এ মাপা যায়।
ফরম্যাট। একই 1.5B model-কে label না মেপে উত্তর লিখতে দেওয়া হলো (greedy, ১২টি নতুন token, ইংরেজি label শব্দ positive/negative). 0-shot-এ ২০০টি উত্তরের ১২৬টি “Positive”, ৬৮টি “Negative”, বাকিগুলো “The sentiment of…” ধরনের বাক্য: অর্থে ঠিক উত্তর ০.৭৪৫ (বড়-ছোট হাতের অক্ষর উপেক্ষা করে), কিন্তু label শব্দের হুবহু মিল ০/২০০. মাত্র একটি উদাহরণ দিতেই ২০০টির ২০০টি উত্তর হুবহু positive বা negative, ছোট হাতের অক্ষরে, উদাহরণের মতো। উদাহরণ প্রথমেই শেখাল উত্তর কেমন দেখতে হবে।
Label-এর মানে। ৮টি সুষম উদাহরণ তিন রূপে, তিনটি seed-এ: সঠিক label, পুরো উল্টানো label, আর random label (বাংলা label শব্দ, log-likelihood দিয়ে নম্বর):
| 8-shot-এর label | seed ১০ | seed ১১ | seed ১২ | AUC-এর পরিসর |
|---|---|---|---|---|
| সঠিক | ০.৭৪০ | ০.৭৬৫ | ০.৭৮০ | ০.৮৬–০.৯২ |
| Random | ০.৭৪৫ | ০.৬৬৫ | ০.৬২০ | ০.৭৪–০.৮২ |
| উল্টানো | ০.৪৬০ | ০.৪৪০ | ০.৪৬০ | ০.৪০–০.৪৯ |
Random label-এ পতন মাঝারি, একটি seed-এ কিছুই না: Min ও সহকর্মীদের পর্যবেক্ষণের সঙ্গে মেলে। কিন্তু পুরো উল্টালে নির্ভুলতা দৈবের নিচে নামল, AUC ০.৫-এর নিচে: model উদাহরণের উল্টো mapping কিছুটা মেনেছে, পুরোপুরি নয়। অর্থাৎ এই model-এ উদাহরণ ফরম্যাট আর label-এর মানে, দুটিই কিছুটা বহন করে। ছোট 0.5B-তে বাংলা label-এ তিন রূপেই রায় প্রায় সব “নেতিবাচক”, পার্থক্যই দেখা যায়নি। Model যত ছোট, নিজের ঝোঁক তত বেশি জেতে।
৫ · উদাহরণ বাছাই — random বনাম similar
পরীক্ষার আগে আগের বছরের প্রশ্ন দেখার সময় কেউ এলোমেলো প্রশ্ন দেখেন না; এবারের প্রশ্নের মতো প্রশ্ন খোঁজেন। Few-shot-এও একই ভাবনা: প্রতিটি নতুন মন্তব্যের জন্য ভাণ্ডার থেকে তার সবচেয়ে কাছের উদাহরণ বাছা। Liu ও সহকর্মীরা (২০২২, “What Makes Good In-Context Examples for GPT-3?”) sentence embedding-এর k-nearest neighbors দিয়ে উদাহরণ বেছে GPT-3-এ random-এর চেয়ে ভালো ফল পাওয়ার কথা জানান।
“কাছে” মাপার জন্য এখানে embedding model নয়, অক্ষরের character n-gram-এর TF-IDF আর cosine similarity (AI-এর ভিত্তি কোর্সের পর্ব ৬৭, পর্ব ৩৩)। বাংলা মন্তব্যে বানান এলোমেলো (“অসাধারন”, “অসাধারণ”), তাই অক্ষরের টুকরো শব্দের চেয়ে বেশি মেলে, আর এটি পাতার ভেতরেই চলে। Sentence embedding দিয়ে খোঁজা পর্ব ৬৭ · Sentence embedding আর semantic search-এ আসবে। নিচের কোডে ২০টি আসল মন্তব্যের ছোট ভাণ্ডার; একই prompt-builder random আর similar দুইভাবে চালায়। প্রথম চালাতে scikit-learn আসতে প্রায় ১০ সেকেন্ড লাগে।
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
# ২০টি সত্যিকারের মন্তব্য (Sazzed ও Jayarathna, CC BY 4.0), 0 = নেতিবাচক, 1 = ইতিবাচক
POOL = [("ফিনিশিং টা ভালো লাগলো না।", 0), ("যতসব ফালতু নাটক", 0),
("আসলে পোশাক টা ভালো ছিলো নাহ", 0), ("জোর করে হাসানোর চেষ্টা। ফালতু", 0),
("নাটকে একটু নেকামি বেশি হয়েছে,", 0), ("বাজে একটা নাটক!!", 0),
("ফালতু রকমের নাটক! সময়টাই নষ্ট", 0), ("সম্পূর্ণ ফালতু নাটক.....", 0),
("ঠিক ছিল কিন্তু এতোটা খারাপ অভিনয় না করলেই হতো", 0),
("নাটকের একটা ব্যার্থতা যে আগে থেকেই জানতাম কি হবে", 0),
("নাটকটা অনেক ভালো লাগলো", 1), ("ভালোই লাগছে নাটক", 1), ("খুব সুন্দর .", 1),
("শেষ টুকু খুব ভালো লাগছে", 1), ("গল্প টা সুন্দর ছিলো", 1),
("অসাধারন, পরের পর্ব চাই", 1), ("ভালো লাগার মত নাটক", 1),
("আনন্দ পেলাম এই নাটকটা দেখে", 1), ("অনেক ভাল লেগেছে।সব কিছু গোছানো ছিল", 1),
("ভাই এক কথায় অসাধারণ...", 1)]
LAB = ["নেতিবাচক", "ইতিবাচক"]
vec = TfidfVectorizer(analyzer="char_wb", ngram_range=(2, 4), sublinear_tf=True)
P = vec.fit_transform([t for t, _ in POOL]) # সারি L2-normalised: dot = cosine
def build(query, k=4, how="random", seed=0):
if how == "random":
idx = np.random.default_rng(seed).choice(len(POOL), k, replace=False)
else:
sim = (vec.transform([query]) @ P.T).toarray()[0]
idx = np.argsort(-sim)[:k][::-1] # সবচেয়ে কাছেরটি শেষে, প্রশ্নের ঠিক আগে
lines = [f"মন্তব্য: {POOL[i][0]}\nঅনুভূতি: {LAB[POOL[i][1]]}" for i in idx]
return idx, "\n\n".join(lines + [f"মন্তব্য: {query}\nঅনুভূতি:"])
q = "অভিনয় ভালো হয়নি"
for how in ("random", "similar"):
idx, prompt = build(q, how=how)
labs = [POOL[i][1] for i in idx]
sims = (vec.transform([q]) @ P[idx].T).toarray()[0]
print(f"[{how}] label: ইতি {sum(labs)}, নেতি {len(labs) - sum(labs)}",
"| cosine:", np.round(sims, 2))
print("\n" + prompt)আউটপুট (পাতার Python-এ চালানো):
[random] label: ইতি 2, নেতি 2 | cosine: [0. 0.03 0.03 0.12]
[similar] label: ইতি 1, নেতি 3 | cosine: [0.16 0.19 0.19 0.35]
মন্তব্য: নাটকে একটু নেকামি বেশি হয়েছে,
অনুভূতি: নেতিবাচক
মন্তব্য: নাটকটা অনেক ভালো লাগলো
অনুভূতি: ইতিবাচক
মন্তব্য: ফিনিশিং টা ভালো লাগলো না।
অনুভূতি: নেতিবাচক
মন্তব্য: ঠিক ছিল কিন্তু এতোটা খারাপ অভিনয় না করলেই হতো
অনুভূতি: নেতিবাচক
মন্তব্য: অভিনয় ভালো হয়নি
অনুভূতি:
Random চারটির cosine প্রায় শূন্য: প্রশ্নের সঙ্গে প্রায় কিছুই মেলে না। Similar চারটির cosine ০.১৬ থেকে ০.৩৫, আর তিনটি নেতিবাচক, যা এই মন্তব্যের ঠিক label. তবে লক্ষ করুন, “নাটকটা অনেক ভালো লাগলো” (ইতিবাচক) এসেছে শুধু “ভালো” শব্দের জন্য। “ভালো হয়নি” আর “ভালো লাগলো”-র পার্থক্য, মানে নঞর্থক অংশ, অক্ষরের মিল ধরতে পারে না। সবচেয়ে কাছেরটি সবার শেষে, প্রশ্নের ঠিক আগে বসানো, কারণ শেষের উদাহরণ সাধারণত বেশি প্রভাব ফেলে বলে ধরা হয় (§৬-এ এই ধারণাটিও মাপব)।
Similar কেন এত ভালো: model কি নকল করছে?
§৩-এর সারণিতে similar 4-shot ০.৮৭০, আর LLM ছাড়া কাছের চারটির ভোট ০.৮৯০. দুটির মিল মাপলে: ২০০টির ১৪৮টিতে কাছের চারটির label সব একই, আর সেখানে 1.5B model ৯৬% ক্ষেত্রে সেই label-ই বলেছে। বাকি ৫২টিতে, যেখানে কাছের উদাহরণগুলো দুই ভাগ, model-এর নির্ভুলতা মাত্র ০.৬৫. অর্থাৎ বড় লাভটি মূলত k-NN ভোটের, model সেটি পড়ে নকল করছে। এটি খারাপ নয়, কিন্তু তখন প্রশ্ন ওঠে: একটি ১৫০ কোটি parameter-এর model দিয়ে ভোট গোনার দরকার কী?
দ্বিতীয় ফাঁদ: যমজ মন্তব্য। Test আর ভাণ্ডারে একই দলের কোনো মন্তব্য নেই, তবু ২০০টির ২৬টির সবচেয়ে কাছের প্রতিবেশীর cosine ০.৮-এর বেশি; YouTube-এ একই কথা বহুজন প্রায় একইভাবে লেখেন। Test-এর near-duplicate ভাণ্ডারে থাকলে similar বাছাই নম্বর ফুলিয়ে দেয়, যেমন পর্ব ৪২-এ classifier-এর বেলায় দেখেছিলেন। দল ধরে ভাগ না করলে ফাঁসটি আরও বড় হতো।
৬ · ক্রম — একই চারটি উদাহরণ, ২৪ রকম সাজানো
মানুষের কাছে চারটি উদাহরণ কোন ক্রমে দেওয়া হলো, তাতে খুব একটা আসে যায় না। একটি causal language model-এর কাছে আসে যায়: সে লেখাটি বাঁ থেকে ডানে পড়ে, আর প্রতিটি token-এর অনুমান আগের সব token-এর ওপর নির্ভর করে (পর্ব ৪৯)। Lu ও সহকর্মীরা (২০২২, “Fantastically Ordered Prompts and Where to Find Them”) দেখান, একই উদাহরণের শুধু ক্রম বদলে কিছু task-এ নির্ভুলতা প্রায় দৈব থেকে বেশ উঁচু পর্যন্ত ঘোরে। Zhao ও সহকর্মীরা (২০২১) GPT-3-এ recency bias দেখেন: শেষের দিকের উদাহরণের label model বেশি বলে।
আমরা §২-এর চারটি উদাহরণ (দুটি নেতিবাচক, দুটি ইতিবাচক) সম্ভাব্য সব ৪! = ২৪ ক্রমে সাজিয়ে 1.5B model-এ ২০০টি মন্তব্যে চালালাম। নিচের stepper একটি মন্তব্য দিয়ে শুরু করে পুরো ছবিতে যায়।
| ক্রম | |
| log-lik | |
| ফল |
- N N P P. §২-এর ক্রম। নেতিবাচকের log-likelihood −১.০২, ইতিবাচকের −২.৯৫; p(ইতি) ০.১২৭, রায় নেতিবাচক, ঠিক।
- N P N P. একই চারটি উদাহরণ, পালা করে। p(ইতি) বেড়ে ০.৩০৯, তবু রায় নেতিবাচক, ঠিক।
- P P N N. ইতিবাচক দুটি আগে, নেতিবাচক দুটি শেষে। এবার নেতিবাচকের log-likelihood নেমে −৩.৭২, ইতিবাচক উঠে −১.৬৯; p(ইতি) ০.৮৮৫, রায় ভুল। উদাহরণ, মন্তব্য, নির্দেশ, কিছুই বদলায়নি।
- P P N N, অন্য বিন্যাসে. একই label-এর দুটি উদাহরণ নিজেদের মধ্যে জায়গা বদলেছে। p(ইতি) ০.৭৭০, রায় আবার ভুল। এক মন্তব্যে ক্রমই রায় ঠিক করল।
- ২৪টি ক্রম, ২০০টি মন্তব্য. নির্ভুলতা সবচেয়ে খারাপ ক্রমে ০.৬১০, সবচেয়ে ভালোয় ০.৮২০, গড় ০.৭৩৭, sd ০.০৫৫. ব্যবধান ০.২১, §৩-এর পাঁচ seed-এর ছড়ানোর কাছাকাছি।
- শেষ দুটি উদাহরণ. শেষ দুটি নেতিবাচক হলে (৪টি ক্রম) গড়ে ৬৫.৯% মন্তব্যে রায় ইতিবাচক; শেষ দুটি ইতিবাচক হলে মাত্র ২৬.৬%. টান শেষ label-এর উল্টো দিকে, GPT-3-এর recency bias-এর বিপরীত।
শেষ ধাপের ফল প্রথমে অবাক করে। একটি সম্ভাব্য ব্যাখ্যা: model label-এর ক্রমটিকেও একটি নকশা হিসেবে পড়ছে (দুটি নেতি, দুটি ইতি, তাহলে এবার…?)। আমরা এটি প্রমাণ করিনি; শুধু মেপেছি যে এই model-এ, এই চারটি উদাহরণে, দিকটি উল্টো। শিক্ষা হলো আকার: ক্রম একা ০.২১-এর মতো নির্ভুলতা সরাতে পারে, আর দিকটি model ধরে বদলায়। প্রতিকার: label পালা করে সাজানো, কয়েকটি ক্রমে চালিয়ে ফল মেলানো, আর ক্রম বেছে নিতে হলে আলাদা dev set ব্যবহার করা, test নয়।
৭ · Label-এর ভারসাম্য আর majority-label bias
বাজারের এক দোকানদারকে পরপর চারজন ক্রেতা বললেন “দাম বেশি”। পঞ্চম ক্রেতা কিছু বলার আগেই তিনি ধরে নেন, ইনিও দরাদরি করবেন। Model-এর ক্ষেত্রেও উদাহরণে যে label বেশি, সেটি বেশি বলার প্রবণতাকে Zhao ও সহকর্মীরা (২০২১) বলেন majority-label bias. §৩-এর ০.৫০০-এর seed-টি মনে আছে? তার চারটি উদাহরণই ইতিবাচক ছিল, আর model ২০০টির সবগুলোকেই ইতিবাচক বলেছিল; 8-shot-এ আটটিই ইতিবাচক এমন seed-এও একই ফল।
এবার এটি নিয়ন্ত্রিতভাবে মাপা হলো: ভাণ্ডার থেকে চারটি ইতিবাচক আর চারটি নেতিবাচক মন্তব্যের দুটি আলাদা সেট; প্রতিটি থেকে ০, ১, ২, ৩ বা ৪টি ইতিবাচক নিয়ে বাকিটা নেতিবাচক দিয়ে 4-shot prompt. নিচের কোডে সেই দশটি run-এর গোনা সংখ্যা।
import numpy as np
import matplotlib.pyplot as plt
# সত্যিকারের run, Qwen2.5-1.5B-Instruct: 4-shot prompt-এ কয়টি উদাহরণ ইতিবাচক,
# আর ২০০টি মন্তব্যের (১০০ ইতি, ১০০ নেতি) কয়টিকে model ইতিবাচক বলল
n_pos = np.array([0, 1, 2, 3, 4])
set_a = np.array([5, 18, 122, 169, 199]) # উদাহরণের এক সেট
set_b = np.array([0, 49, 129, 83, 200]) # আরেক সেট
correct = {"set_a": [103, 108, 120, 119, 101], "set_b": [100, 117, 149, 143, 100]}
for name, pred in (("set_a", set_a), ("set_b", set_b)):
print(name)
for k, p, c in zip(n_pos, pred, correct[name]):
bar = "#" * int(p // 20)
print(f" ইতি-উদাহরণ {k}/4 → ইতি-রায় {p:3d} {bar:10s} acc {c / 200:.3f}")
both = np.concatenate([set_a, set_b]) / 200
x = np.concatenate([n_pos, n_pos])
slope, icpt = np.polyfit(x, both, 1)
print(f"প্রতিটি বাড়তি ইতি-উদাহরণে ইতি-রায় গড়ে {slope:+.3f} (ভাগ)")
print("সম্পর্ক r =", round(np.corrcoef(x, both)[0, 1], 3))
fig, ax = plt.subplots(figsize=(5, 3.2))
ax.plot(n_pos, set_a / 200, "o-", label="demo set A")
ax.plot(n_pos, set_b / 200, "s--", label="demo set B")
ax.axhline(0.5, color="gray", lw=1, ls=":", label="true share (0.5)")
ax.set_xlabel("positive examples in the 4-shot prompt")
ax.set_ylabel("share predicted positive")
ax.set_xticks(n_pos); ax.legend(fontsize=8)
plt.show()আউটপুট (পাতার Python-এ চালানো; নিচে একটি ছবিও আসে):
set_a
ইতি-উদাহরণ 0/4 → ইতি-রায় 5 acc 0.515
ইতি-উদাহরণ 1/4 → ইতি-রায় 18 acc 0.540
ইতি-উদাহরণ 2/4 → ইতি-রায় 122 ###### acc 0.600
ইতি-উদাহরণ 3/4 → ইতি-রায় 169 ######## acc 0.595
ইতি-উদাহরণ 4/4 → ইতি-রায় 199 ######### acc 0.505
set_b
ইতি-উদাহরণ 0/4 → ইতি-রায় 0 acc 0.500
ইতি-উদাহরণ 1/4 → ইতি-রায় 49 ## acc 0.585
ইতি-উদাহরণ 2/4 → ইতি-রায় 129 ###### acc 0.745
ইতি-উদাহরণ 3/4 → ইতি-রায় 83 #### acc 0.715
ইতি-উদাহরণ 4/4 → ইতি-রায় 200 ########## acc 0.500
প্রতিটি বাড়তি ইতি-উদাহরণে ইতি-রায় গড়ে +0.243 (ভাগ)
সম্পর্ক r = 0.932
উদাহরণে ইতিবাচক ০ থেকে ৪টি হলে ইতিবাচক রায় প্রায় ০ থেকে প্রায় ২০০টি, আর প্রতিটি বাড়তি ইতিবাচক উদাহরণে গড়ে প্রায় ২৪ শতাংশ-বিন্দু করে। ঠিক উত্তরে ভাগটি সব সময় ১০০/২০০. দুই প্রান্তে নির্ভুলতা ০.৫০-এর কাছে, কারণ model তখন মন্তব্য না পড়ে উদাহরণের label-ই বলছে। সবচেয়ে ভালো ফল দুটি-দুটিতে (০.৬০০ আর ০.৭৪৫)। দ্বিতীয় সেটের ৩/৪-এর বিন্দুটি নিয়ম ভাঙে (৮৩টি); সেই সেটের একটি “নেতিবাচক” উদাহরণ আসলে প্রশংসা, “অস্থির,,, এক কথায় অসাধারণ হইছে”, ডেটার label noise. উদাহরণের ভুল label-ও prompt-এর অংশ।
ব্যবহারিক নিয়ম: উদাহরণে label প্রায় সমান রাখুন; আসল ডেটায় নেতিবাচক মাত্র প্রায় ২৮.৫%, তাই random টানলে ইতিবাচক বেশি আসাই স্বাভাবিক।
৮ · Calibration — content-free input দিয়ে ঝোঁক মাপা
দাঁড়িপাল্লায় কিছু না রেখেই যদি কাঁটা ২০ গ্রাম দেখায়, দোকানদার প্রতিটি ওজন থেকে ২০ গ্রাম বাদ দেন। Zhao ও সহকর্মীদের “Calibrate Before Use” (২০২১) প্রবন্ধের ভাবনাও এমন। Prompt-এ আসল মন্তব্যের জায়গায় অর্থহীন একটি input বসান, যেমন “N/A”, ফাঁকা লেখা বা “[MASK]”; একে বলে content-free input. এখানে model-এর ঠিক উত্তর থাকার কথা নয়, তাই নিরপেক্ষ model দুই label-এ প্রায় ০.৫ দিত। যা দেয়, সেটিই prompt-এর নিজস্ব ঝোঁক, যার মধ্যে majority-label, recency আর common-token bias মিশে থাকে। প্রবন্ধে সংশোধনটি q = softmax(W p), যেখানে W = diag(pcf)−১: প্রতিটি label-এর সম্ভাবনাকে content-free সম্ভাবনা দিয়ে ভাগ করে আবার normalise. দুই label-এ এটি একটি বিয়োগ মাত্র:
calibrated log-odds = log-odds − log(pcf ÷ (১ − pcf))
এর নাম contextual calibration. লেখকেরা GPT-3-এ অনেক task-এ নির্ভুলতা বাড়া আর prompt-ভেদে ছড়ানো কমার কথা জানান। মেশিন লার্নিং কোর্সের পর্ব ২৬-এর Platt scaling-এর সঙ্গে পার্থক্য: এখানে কোনো লেবেল করা ডেটা লাগে না।
| ধাপ | |
| মান | |
| রায় |
- Content-free input. একই prompt-এ মন্তব্যের জায়গায় তিনটি অর্থহীন input. তিনটিতেই p(positive) ০.৮৭ থেকে ০.৯৬: কিছু না দেখেই model “positive”-এর দিকে হেলে আছে।
- গড় ঝোঁক. তিনটির গড় pcf = ০.৯০৬; log-odds-এ c = ln(০.৯০৬ ÷ ০.০৯৪) ≈ ২.২৭. দাঁড়িপাল্লার খালি কাঁটার মতো, এটুকু বাদ দিতে হবে।
- আসল মন্তব্য. “অভিনয় ভালো হয়নি”: negative −৫.১৯, positive −৩.১৯; log-odds ২.০০, p = ০.৮৮১, রায় positive, যা ভুল।
- বিয়োগ. ২.০০ − ২.২৭ = −০.২৭; sigmoid(−০.২৭) ≈ ০.৪৩৩. রায় negative, ঠিক। Model-এর মত বদলায়নি, বদলেছে শুধু সীমা।
- আরেকটি মন্তব্য. “অসাধারণ একটা নাটক…” (ঠিক: positive)-এরও log-odds ঠিক ২.০০, তাই এটিও −০.২৭-এ নেমে negative, ভুল। Calibration দুটি সমান নম্বরকে কখনো আলাদা করতে পারে না; শুধু model-এর নিজের ক্রম যতটা ঠিক, ততটাই কাজে লাগে।
- ২০০টিতে. ইতি-রায় ১৯১ থেকে ৬৭, নির্ভুলতা ০.৫২৫ থেকে ০.৬৪৫. লেবেলহীন সব input-এর গড় log-odds বিয়োগ করলে (batch-গড়) ০.৬৫৫.
এবার একই হিসাব চারটি prompt-এ, নিজে চালিয়ে দেখুন। প্রতিটি মন্তব্যের log-odds সত্যিকারের run থেকে, দুই দশমিকে গোল করে রাখা। তৃতীয় নিয়মটি “batch-গড়”: লেবেলহীন সব input-এর গড় log-odds বিয়োগ, যা Zhou ও সহকর্মীদের batch calibration-এর (২০২৪) সরল রূপ।
import numpy as np
# logodds.txt: প্রথম লাইনে ২০০টি ঠিক label; পরে প্রতি prompt-এ তিনটি content-free
# input-এর log-odds আর ২০০টি মন্তব্যের log-odds (ইতি − নেতি), সত্যিকারের run থেকে
lines = open("logodds.txt", encoding="utf-8").read().split("\n")
y = np.array([int(c) for c in lines[0].split("|")[1]])
def wilson(c, n, z=1.96):
p = c / n; den = 1 + z * z / n; mid = (p + z * z / (2 * n)) / den
h = z * np.sqrt(p * (1 - p) / n + z * z / (4 * n * n)) / den
return f"{p:.3f} [{mid - h:.2f}, {mid + h:.2f}]"
def sigmoid(x): return 1 / (1 + np.exp(-x))
for line in lines[1:]:
if not line: continue
name, cf, m = line.split("|")
cf = np.array(cf.split(), dtype=float); m = np.array(m.split(), dtype=float)
p_cf = sigmoid(cf).mean() # তিন content-free input-এর গড় p(ইতি)
c = np.log(p_cf / (1 - p_cf)) # W = diag(1/p_cf) মানে এই log-odds বিয়োগ
rules = {"কাঁচা": m, "content-free": m - c, "batch-গড়": m - m.mean()}
print(f"{name} p_cf(ইতি)={p_cf:.3f}")
for rule, s in rules.items():
pred = (s > 0).astype(int)
print(f" {rule:13s} acc {wilson((pred == y).sum(), len(y))} ইতি-রায় {pred.sum():3d}")আউটপুট (পাতার Python-এ চালানো):
0.5B EN 0-shot p_cf(ইতি)=0.906
কাঁচা acc 0.525 [0.46, 0.59] ইতি-রায় 191
content-free acc 0.645 [0.58, 0.71] ইতি-রায় 67
batch-গড় acc 0.655 [0.59, 0.72] ইতি-রায় 103
1.5B 4-shot all-pos p_cf(ইতি)=0.856
কাঁচা acc 0.500 [0.43, 0.57] ইতি-রায় 200
content-free acc 0.510 [0.44, 0.58] ইতি-রায় 198
batch-গড় acc 0.645 [0.58, 0.71] ইতি-রায় 99
1.5B 4-shot 1 pos p_cf(ইতি)=0.078
কাঁচা acc 0.745 [0.68, 0.80] ইতি-রায় 61
content-free acc 0.630 [0.56, 0.69] ইতি-রায় 170
batch-গড় acc 0.805 [0.74, 0.85] ইতি-রায় 89
1.5B 4-shot PPNN p_cf(ইতি)=0.473
কাঁচা acc 0.750 [0.69, 0.80] ইতি-রায় 132
content-free acc 0.710 [0.64, 0.77] ইতি-রায় 142
batch-গড় acc 0.735 [0.67, 0.79] ইতি-রায় 97
যেখানে কাজ করল: ছোট model, ইংরেজি label, 0-shot: ০.৫২৫ থেকে ০.৬৪৫. ঝোঁকটি সব input-এ প্রায় সমান ছিল, তাই একটি বিয়োগেই কাজ হলো।
যেখানে কাজ করল না: 1.5B-এর বাংলা prompt-এ। চারটি ইতিবাচক উদাহরণের prompt-এ content-free রায় প্রায় বদলায়নি (০.৫১০), আর একটি ইতিবাচক উদাহরণের prompt-এ নির্ভুলতা ০.৭৪৫ থেকে নেমে ০.৬৩০: “N/A”-এ pcf মাত্র ০.০৭৮, অথচ আসল মন্তব্যে model অতটা নেতিবাচক ঝোঁকে না, তাই বিয়োগটি বেশি হয়ে উল্টো দিকে ঠেলে দিল। সব ৫৯টি নির্দিষ্ট-উদাহরণের prompt মিলিয়ে বাংলায় content-free calibration ৩৩টিতে খারাপ, ২৩টিতে ভালো করেছে, গড় ০.৬৫৮ থেকে ০.৬২৫. বাংলা prompt-এ “N/A” বা “[MASK]” সম্ভবত সত্যিই “অর্থহীন” নয়; এটি একটি অনুমান, প্রমাণ নয়।
Batch-গড় নিয়ে সাবধান: এটি ৫৯টির ৪৩টিতে ভালো করেছে (গড় ০.৭০৫), কিন্তু আমাদের test-এ দুই label ঠিক অর্ধেক-অর্ধেক, তাই গড় বিয়োগ করলে রায়ও প্রায় অর্ধেক-অর্ধেক হয়, যা এখানে সুবিধা পায়। আসল ডেটায় নেতিবাচক প্রায় ২৮.৫%; সেখানে এই নিয়ম ভুল দিকে ঠেলতে পারে। আর যেখানে model-এ সংকেতই নেই (0.5B বাংলায় AUC প্রায় ০.৫ বা কম), কোনো calibration-ই সাহায্য করেনি; সীমা সরিয়ে ক্রম ঠিক করা যায় না। যে নিয়মই নিন, বাছাই করুন আলাদা dev set-এ।
৯ · লম্বা prompt-এর দাম, আর কখন few-shot নয়
প্রতিটি উদাহরণ প্রতিটি অনুরোধে আবার পাঠানো হয়। আমাদের run-এ গড় prompt 0-shot-এ ১৫১ token, random 8-shot-এ ৬১৮ থেকে ৭০৭; ২০০টি মন্তব্যের সময় GPU-তে ১১.৬ সেকেন্ড থেকে প্রায় ৪০ সেকেন্ড। Hosted API-তে দাম সাধারণত input আর output token ধরে। মাসে N-টি মন্তব্য, গড় prompt T token, আর প্রতি ১০ লাখ input token-এর দাম P হলে:
মাসিক input খরচ = N × T × P ÷ ১০৬
N = ১,০০,০০০ হলে 0-shot-এ ১.৫১ কোটি token, 8-shot-এ (T ≈ ৬৫০) ৬.৫ কোটি token, প্রায় ৪.৩ গুণ। P-এর মান নিজের পণ্যের বর্তমান মূল্যতালিকা থেকে বসান; দাম বদলায়, তাই এখানে লিখছি না। বাংলায় খরচ আরও বেশি: “নেতিবাচক” একাই ৮ token, “negative” ১ token (পর্ব ৪০)। দুটি কৌশল: এক, সব অনুরোধে একই উদাহরণ একই ক্রমে রাখলে prompt-এর শুরুটা হুবহু এক থাকে, যা অনেক পণ্যের prompt caching কাজে লাগাতে পারে। প্রতিটি মন্তব্যে আলাদা similar উদাহরণ দিলে সেই সুবিধা হারায়। Caching-এর হিসাব পর্ব ৬৫ · Token, খরচ আর latency-তে। দুই, কম কিন্তু ভালো উদাহরণ: আমাদের run-এ 4 থেকে 8-shot-এ যাওয়ার লাভ (random seed ০-এ +০.০৬৫) CI-তে শূন্য ছুঁয়েছে।
আর একটি সৎ প্রশ্ন: আদৌ LLM কেন? এই task-এ ৬,০০৮টি লেবেল করা মন্তব্য হাতে ছিল, আর তা দিয়ে শেখানো TF-IDF + logistic regression ২০০টিতে ০.৯৪৫, এক সেকেন্ডের ভগ্নাংশে, কোনো GPU ছাড়া। পর্ব ৪৮-এ fine-tuned Bangla BERT-ও একই জায়গায় থেমেছিল। Few-shot-এর আসল জায়গা তখন, যখন লেবেল করা ডেটা প্রায় নেই, task ঘন ঘন বদলায়, বা উত্তর একটি label-এর বেশি কিছু (ব্যাখ্যা, সারাংশ, নির্দিষ্ট ফরম্যাট)। হাজার হাজার লেবেল থাকলে আগে একটি সাধারণ classifier বা fine-tuning (পর্ব ৫৪, পর্ব ৫৫) মেপে দেখুন।
আরও গভীরে: Rubin ও সহকর্মীরা (২০২২) LLM-এর নিজের সংকেত দিয়ে উদাহরণ-retriever শেখান। Calibration-এর পরের রূপগুলোর মধ্যে আছে domain-context calibration (Fei ও সহকর্মী, ২০২৩), যেখানে content-free input-এর বদলে task-এর ডোমেইনের এলোমেলো শব্দ নেওয়া হয়, আর batch calibration (Zhou ও সহকর্মী, ২০২৪), যেখানে লেবেলহীন একগুচ্ছ input-এর গড় সংকেত সরানো হয়। Holtzman ও সহকর্মীরা (২০২১) “surface form competition”-এর কথা বলেন: একই অর্থের অনেক লেখা-রূপ (“Positive”, “positive”, “ভালো”) সম্ভাবনা ভাগ করে নেয়, তাই একটি label শব্দের নিচু সম্ভাবনা সবসময় model-এর মত বোঝায় না।
পরীক্ষা ও ইন্টারভিউতে: Zero, one আর few-shot-এর পার্থক্য? Prompt-এ ০, ১ বা কয়েকটি input–output উদাহরণ; weight বদলায় না। Majority-label bias কী? উদাহরণে যে label বেশি, model সেটিই বেশি বলে। Contextual calibration কীভাবে? “N/A”-এর মতো content-free input-এ pcf মেপে প্রতিটি সম্ভাবনাকে pcf দিয়ে ভাগ করে আবার normalise; দুই label-এ এটি log-odds থেকে content-free log-odds বিয়োগ। Similar উদাহরণের ঝুঁকি? যমজ বা test-এর ফাঁস, আর model কাছের label নকল করতে পারে। Few-shot-এর খরচ? প্রতি অনুরোধে উদাহরণের token; মোট ≈ N × T × P ÷ ১০৬.
১০ · AI-এর যুগে — few-shot prompt বানাতে সহায়কের সাহায্য
AI সহায়ক মুহূর্তে কুড়িটি উদাহরণ আর scoring-এর কোড লিখে দেয়। এখানকার ভুল প্রায় কখনো ক্র্যাশ করে না; নম্বর শুধু একটু বদলায়। সহায়ক প্রবন্ধ বা পণ্যের পরামর্শও প্রায়ই স্মৃতি থেকে বলে; মূল উৎস নিজে খুলে দেখুন।
| AI প্রায়ই যা করে | কেন ভুল | কীভাবে ধরবেন |
|---|---|---|
| নিজেই “উদাহরণ” বানিয়ে দেয়, সব ইতিবাচক বা সব একই ধাঁচের | Label-এর ভারসাম্য আর বাস্তব লেখার বৈচিত্র্য থাকে না; majority-label bias ঢোকে | আসল ডেটা থেকে উদাহরণ; label গুনে দেখা |
| Similar উদাহরণ খুঁজতে test set-কেই ভাণ্ডার বানায় | প্রশ্নের নিজের বা যমজ মন্তব্য উদাহরণে চলে আসে; নম্বর ফুলে ওঠে | দল ধরে আলাদা pool; সবচেয়ে কাছের cosine দেখা |
| একটি ক্রম, একটি seed, “4-shot ৭% ভালো” | ক্রম আর উদাহরণ বদলালেই নম্বর নড়ে | কয়েকটি seed আর ক্রম, ছড়ানো আর জোড়া CI |
Generation-এর উত্তর থেকে label খুঁজতে কাঁচা == | “Positive” আর “positive”, বা পুরো বাক্য, ভুল গোনা হয় | Label শব্দের log-likelihood, বা লিখিত normalisation |
| Calibration-কে সব সমস্যার ওষুধ বলে | সংকেত না থাকলে কোনো সরানো কাজ করে না | আগে AUC দেখা; পরে calibration, dev set-এ |
সহায়কের কাছে কোড আর পরিকল্পনা চাওয়ার সময় যাচাইয়ের ধাপও চেয়ে নিন। গ্রাহকের আসল মন্তব্য, ফোন নম্বর বা অন্য ব্যক্তিগত তথ্য কোনো hosted সহায়কের prompt-এ দেবেন না।
Few-shot prompt চালুর আগে চেকলিস্ট
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন, তারপর “→ উত্তর” চাপুন।
প্র ০১Weight একটুও বদলায় না, তবু উদাহরণ দিলে আচরণ বদলায়। একে কি সত্যিই “শেখা” বলা যায়?
শব্দটি নিয়েই বিতর্ক। Brown ও সহকর্মীরা (২০২০) “in-context learning” নাম দিলেও লেখেন, model নতুন task শেখে নাকি pretraining-এ দেখা task চিনে নেয়, তা তাঁরা আলাদা করতে পারেননি। পরের কয়েকটি কাজ দুই দিকেই প্রমাণ জুগিয়েছে।
“চিনে নেওয়া”-র পক্ষে বড় প্রমাণ Min ও সহকর্মীদের ২০২২ সালের প্রবন্ধ (“Rethinking the Role of Demonstrations”). তাঁরা উদাহরণের সঠিক label বদলে random label দিয়ে দেখেন, অনেক classification task-এ নির্ভুলতা সামান্যই কমে। যা বেশি কাজে লাগে তা হলো label-এর জগৎ (কোন কোন শব্দ উত্তর হতে পারে), input-এর ধরন আর ফরম্যাট। অর্থাৎ উদাহরণ প্রায়ই task-টি “খুঁজে দেয়”, নতুন mapping শেখায় না। Xie ও সহকর্মীরা (২০২১) একটি তাত্ত্বিক ব্যাখ্যা দেন: pretraining-এর লেখায় লুকানো “বিষয়” থাকে, আর উদাহরণ model-কে সেই বিষয়টি অনুমানে সাহায্য করে, অনেকটা Bayesian অনুমানের মতো।
“শেখা”-র পক্ষেও প্রমাণ আছে। Wei ও সহকর্মীরা (২০২৩, “Larger language models do in-context learning differently”) দেখান, উল্টানো label দিলে বড় model-গুলো অনেক সময় সেই উল্টো নিয়মই মানে, ছোটগুলো আগের ধারণায় আটকে থাকে। খেলনা task-এ (যেমন ছোট linear regression) গবেষকেরা দেখিয়েছেন, Transformer উদাহরণ থেকে gradient descent-এর মতো একটি হিসাব প্রায় নকল করতে পারে (von Oswald ও সহকর্মী, ২০২৩)। Model-এর ভেতরে “induction head” নামের attention-এর একটি ছাঁচ (Olsson ও সহকর্মী, ২০২২) আগের অংশ খুঁজে নকল করার কাজে যুক্ত বলে প্রস্তাব করা হয়েছে।
আমাদের দুটি ছোট model দুই ছবিই দেখায়। প্রায় ৪৯ কোটি parameter-এর model-এ সঠিক, উল্টানো আর random label-এ রায় একটুও বদলায়নি; তার নিজের ঝোঁক উদাহরণের চেয়ে জোরালো। প্রায় ১৫০ কোটির model-এ (§৪) উল্টানো label নির্ভুলতাকে দৈবের নিচে নামিয়েছে, অর্থাৎ model উদাহরণের mapping কিছুটা মেনেছে, আর random label-এ পতন ছিল মাঝারি। দুটিই একটি ভাষা আর একটি task-এর মাপ, সাধারণ সিদ্ধান্ত নয়।
মূল উপলব্ধি: উদাহরণ model-কে task চেনায়, ফরম্যাট দেখায়, আর বড় model-এ কখনো নতুন নিয়মও চাপাতে পারে। কোনটি ঘটছে, তা model-এর আকার আর task-এর ওপর নির্ভর করে, তাই দাবি না করে মাপতে হয়।
প্র ০২এক পণ্যের নথি বলে “সব prompt-এ উদাহরণ দিন”, আরেকটির প্রবন্ধ বলে “few-shot ফল কমায়”। দুটিই কি ঠিক হতে পারে?
পারে, কারণ দুটি আলাদা model আর আলাদা কাজের কথা বলছে। লেখার সময়ে (নভেম্বর ২০২৬) Google-এর Gemini-র prompt design নথি সব prompt-এ few-shot উদাহরণ রাখার পরামর্শ দেয়, আর সতর্ক করে যে বেশি উদাহরণে উত্তর উদাহরণের দিকে “overfit” করতে পারে। DeepSeek-R1-এর প্রবন্ধে (২০২৫) লেখা, few-shot prompting R1-এর ফল ধারাবাহিকভাবে কমিয়েছে, আর zero-shot-এ সমস্যা আর output-এর ফরম্যাট সরাসরি লিখতে বলা হয়েছে। Anthropic-এর নথি ৩ থেকে ৫টি উদাহরণ বলে; OpenAI-এর নথি উদাহরণের সংখ্যা বলে না, বৈচিত্র্যের ওপর জোর দেয়। নথিগুলো বদলাতে পারে, তাই কাজে লাগানোর আগে বর্তমান সংস্করণ পড়ে নিন।
পার্থক্যের সম্ভাব্য কারণ কয়েকটি। এক, reasoning model নিজে লম্বা চিন্তার ধাপ লেখার জন্য প্রশিক্ষিত; উদাহরণের ছোট উত্তর সেই ধাপকে ছেঁটে দিতে পারে, বা উদাহরণের পদ্ধতি নকল করতে ঠেলে দিতে পারে। দুই, instruction-tuned model-এর কাছে ফরম্যাট আগেই অনেকটা পরিচিত; তখন উদাহরণের প্রধান কাজ ভঙ্গি আর সীমানা দেখানো। তিন, কাজের ধরন: ছোট classification-এ label শব্দ দেখানো খুব কাজের, কঠিন গণিতে কয়েকটি উত্তর দেখানো ততটা নয়। এগুলো যুক্তিসঙ্গত অনুমান, প্রবন্ধে প্রমাণিত কারণ নয়।
আমাদের নিজের মাপও এই দ্বিধার ছোট সংস্করণ দেখায়। 1.5B model-এ বাংলা label-এ 0-shot প্রায় দৈব (০.৫১০), উদাহরণে উন্নতি স্পষ্ট, অথচ ইংরেজি label-এ 0-shot-ই ০.৭৮০; কিন্তু উদাহরণ ভুল বাছলে (সব এক label) আবার দৈব। 0.5B-তে বাংলা label-এ উদাহরণে কোনো লাভই হয়নি। তাহলে “উদাহরণ দেওয়া ভালো” বা “খারাপ” কোনোটিই সর্বজনীন নয়। এটি একটি hyperparameter, যা model, ভাষা আর task ধরে মাপতে হয়।
ব্যবহারিক পথ: নথির পরামর্শকে শুরু হিসেবে নিন, সত্য হিসেবে নয়; model বদলালে dev set-এ আবার মাপুন (পর্ব ৬৬ · Prompt পরীক্ষা)।
মূল উপলব্ধি: বিভিন্ন নির্মাতার পরামর্শ তাদের নিজেদের model-এর জন্য লেখা। উদাহরণ দেবেন কি না, কয়টি, সেটি নিজের model আর task-এ মেপে ঠিক করার বিষয়।
প্র ০৩Similar উদাহরণে নির্ভুলতা অনেক বাড়ল। এটিকে কি “model ভালো বুঝছে” বলা যায়?
সাবধানে বলতে হয়। Liu ও সহকর্মীরা (২০২২) GPT-3-এ embedding দিয়ে কাছের উদাহরণ বেছে random-এর চেয়ে ভালো ফল পান, আর পরের অনেক কাজ উদাহরণ খোঁজাকে retrieval-এর সমস্যা হিসেবে দেখে। ব্যাখ্যাটি স্বাভাবিক: কাছের উদাহরণ একই ধরনের ভাষা, একই বিষয়, একই ধাঁচের label দেখায়, তাই model-এর কাজ সহজ হয়।
কিন্তু আমাদের মাপ একটি বিকল্প ব্যাখ্যা জোরালো করে। Similar 4-shot-এ 1.5B model ০.৮৭০, আর কোনো LLM ছাড়া কাছের চারটি মন্তব্যের label-এর ভোট ০.৮৯০. যেখানে চারটি প্রতিবেশীর label এক (২০০টির ১৪৮টি), model ৯৬% ক্ষেত্রে সেটিই বলেছে; যেখানে প্রতিবেশীরা বিভক্ত, নির্ভুলতা ০.৬৫-এ নেমেছে। ছোট 0.5B model-এ ব্যাপারটি আরও স্পষ্ট: random উদাহরণে AUC প্রায় ০.৫ বা তার নিচে, কোনো সংকেত নেই; similar-এ AUC প্রায় ০.৯৪, যা প্রায় পুরোটাই প্রতিবেশীদের label থেকে আসা। মন্তব্য পড়ে sentiment ধরার চেয়ে “উদাহরণে কোন label বেশি” পড়াই এখানে বড় কাজ।
এর তিনটি পরিণতি আছে। এক, তুলনা ন্যায্য করতে k-NN ভোটকে baseline হিসেবে রাখতে হয়; না রাখলে retrieval-এর কৃতিত্ব LLM-কে দেওয়া হয়। দুই, ফাঁসের ঝুঁকি বাড়ে: test-এর যমজ ভাণ্ডারে থাকলে উত্তরই উদাহরণে চলে আসে, আর নম্বর ফাঁপা হয়; আমাদের ২০০টির ২৬টির নিকটতম প্রতিবেশীর cosine ০.৮-এর ওপরে, দল ধরে ভাগ করার পরও। তিন, প্রতিবেশীর label নিজেই ভুল হলে ভুলটিও নকল হয়।
তবু similar বাছাই অকেজো নয়: যেখানে task শুধু label নয়, বা প্রতিবেশীরা বিভক্ত, সেখানে model-এর নিজের পড়া কাজে লাগে।
মূল উপলব্ধি: নির্ভুলতা বাড়লে তার উৎস খুঁজুন। LLM ছাড়া একই retrieval-এর ফল পাশে রাখলেই বোঝা যায়, লাভটি model-এর না উদাহরণ খোঁজার।
প্র ০৪বাংলা মন্তব্যের sentiment-এর জন্য few-shot LLM, fine-tuning আর TF-IDF classifier-এর মধ্যে কীভাবে বাছবেন?
তিনটি প্রশ্ন দিয়ে শুরু করুন: কত লেবেল করা ডেটা আছে, প্রতিদিন কত অনুরোধ, আর উত্তর কি শুধু একটি label? এই ডেটায় ছয় হাজারের বেশি লেবেল করা মন্তব্য ছিল। তা দিয়ে TF-IDF + logistic regression আমাদের ২০০টিতে ০.৯৪৫, CPU-তে মুহূর্তে। পর্ব ৪২-এ শূন্য থেকে শেখা neural model এটিকে হারায়নি, আর পর্ব ৪৮-এ fine-tuned Bangla BERT সমান জায়গায় থেমেছিল, অনেক বেশি খরচে। আমাদের সবচেয়ে ভালো few-shot (similar, 1.5B) প্রায় ০.৮৯, প্রতিটি অনুরোধে ৪০০ থেকে ৬০০ token খরচ করে।
Few-shot-এর জায়গা আলাদা। এক, লেবেল প্রায় নেই: নতুন একটি শ্রেণি, যেমন “ডেলিভারি দেরি নিয়ে অভিযোগ”, যার মাত্র কয়েকটি উদাহরণ আছে। দুই, task ঘন ঘন বদলায়, আর প্রতিবার নতুন model শেখানো সম্ভব নয়। তিন, উত্তর একটি label-এর বেশি: কারণসহ রায়, সারাংশ, বা পর্ব ৬২-এর মতো JSON. চার, একই model দিয়ে অনেক ছোট কাজ, যেখানে প্রতিটির জন্য আলাদা classifier রাখা ঝামেলা।
খরচ আর গোপনীয়তাও ভাবুন: hosted LLM-এ প্রতিটি অনুরোধে পুরো prompt আবার যায়, আর গ্রাহকের লেখা বাইরের সেবায় যায়। একটি যুক্তিসঙ্গত ক্রম: আগে সবচেয়ে সস্তা baseline, তারপর few-shot দিয়ে দ্রুত prototype, ডেটা জমলে fine-tuning বা classifier; প্রতিটি ধাপে একই test set আর CI. চূড়ান্ত ব্যবস্থা প্রায়ই মিশ্র: সাধারণ ক্ষেত্রে classifier, অনিশ্চিত বা নতুন ধরনের মন্তব্যে LLM.
মূল উপলব্ধি: Few-shot লেবেলহীন অবস্থার দ্রুত সমাধান, সব অবস্থার সেরা সমাধান নয়। লেবেল থাকলে পুরনো, সস্তা পদ্ধতিটি আগে মেপে দেখুন।
প্র ০৫“Calibrate Before Use” প্রবন্ধে calibration অনেক কাজে এল, আমাদের বাংলা run-এ প্রায়ই ক্ষতি করল। কেন এমন হতে পারে?
Zhao ও সহকর্মীরা (২০২১) GPT-3 আর GPT-2-এ দেখান, few-shot-এর অস্থিরতার বড় অংশ তিনটি ঝোঁক থেকে আসে: উদাহরণে বেশি থাকা label (majority label), শেষের দিকের label (recency), আর pretraining-এ বেশি দেখা শব্দ (common token). তাঁদের ধারণা ছিল, এই ঝোঁকগুলো মোটামুটি input-নিরপেক্ষ, তাই “N/A”-এর মতো অর্থহীন input-এ মাপা ঝোঁক বাদ দিলেই হয়। প্রবন্ধের অনেক task-এ এতে নির্ভুলতা বাড়ে আর prompt-ভেদে ছড়ানো কমে।
আমাদের run দেখায়, শর্তটি সব সময় খাটে না। ছোট model-এ ইংরেজি label-এ ঝোঁকটি সব input-এ প্রায় সমান ছিল, আর calibration ০.৫২৫ থেকে ০.৬৪৫ করল। কিন্তু 1.5B-এর বাংলা prompt-এ তিনটি content-free input একই prompt-এ খুব আলাদা সম্ভাবনা দিয়েছে, যেমন একটি prompt-এ ০.০৭, ০.৩১ আর ০.১৯; গড়টি আসল মন্তব্যের ঝোঁকের ভালো প্রতিনিধি নয়। ইংরেজি “N/A” বা “[MASK]” বাংলা মন্তব্যের জায়গায় বসালে model-এর কাছে সেটি হয়তো একটি অদ্ভুত, আলাদা ধরনের input, নিরপেক্ষ নয়। এটি আমাদের অনুমান; প্রমাণ করতে বাংলা content-free input দিয়ে আলাদা পরীক্ষা লাগবে।
পরের গবেষণা (§৯-এর “আরও গভীরে”) ঠিক এই দুর্বলতা সারাতে ডোমেইনের শব্দ বা লেবেলহীন আসল input দিয়ে ঝোঁক মাপার প্রস্তাব দেয়।
আর একটি মৌলিক সীমা: দুই label-এ এমন যেকোনো calibration শুধু সিদ্ধান্তের সীমা সরায়; মন্তব্যগুলোর নিজেদের ক্রম বদলায় না। ক্রমই যদি এলোমেলো হয় (AUC প্রায় ০.৫), কোনো সীমা সাহায্য করে না। তাই আগে AUC দেখুন, তারপর calibration.
মূল উপলব্ধি: Calibration একটি অনুমানের ওপর দাঁড়ায়: ঝোঁকটি স্থির আর content-free input দিয়ে মাপা যায়। নতুন ভাষা বা model-এ সেই অনুমানটি আগে যাচাই করুন।
অনুশীলন
খাতা-কলমে করুন, তারপর উত্তর মেলান। বিশ্ববিদ্যালয়, চাকরি বা ইন্টারভিউর পরীক্ষায় এই ধরনের হিসাব কাজে লাগে।
-
Calibration আর খরচের হিসাব: (ক) একটি 4-shot prompt-এ “N/A” দিলে model-এর p(ইতি) = ০.৮০. একটি আসল মন্তব্যে p(ইতি) = ০.৩০. Contextual calibration-এর পরে p(ইতি) কত, আর রায় কী? (খ) দিনে ২০,০০০টি মন্তব্য; 0-shot prompt গড়ে ১৫০ token, 8-shot ৬৫০ token. মাসে (৩০ দিন) 8-shot-এ কত বাড়তি input token লাগবে? প্রতি ১০ লাখ token-এর দাম P হলে বাড়তি খরচ কত?
(ক) সম্ভাবনাকে pcf দিয়ে ভাগ: ইতি ০.৩০ ÷ ০.৮০ = ০.৩৭৫, নেতি ০.৭০ ÷ ০.২০ = ৩.৫. আবার normalise: ০.৩৭৫ ÷ (০.৩৭৫ + ৩.৫) ≈ ০.০৯৭. Log-odds দিয়েও একই: ln(০.৩/০.৭) ≈ −০.৮৪৭, ln(০.৮/০.২) ≈ ১.৩৮৬; −০.৮৪৭ − ১.৩৮৬ = −২.২৩৩, sigmoid ≈ ০.০৯৭. রায় নেতিবাচক। Calibration-এর আগেও রায় নেতিবাচক ছিল (০.৩০ < ০.৫), তবে এখন অনেক বেশি নিশ্চিত, কারণ prompt নিজেই ইতিবাচকের দিকে জোরে টানছিল।
(খ) প্রতি অনুরোধে বাড়তি ৫০০ token; দিনে ২০,০০০ × ৫০০ = ১ কোটি; মাসে ৩০ কোটি = ৩০০ × ১০৬ token. বাড়তি খরচ = ৩০০ × P. Output token এখানে উপেক্ষা করা হয়েছে; label শব্দ বাংলায় হলে তাও কয়েক token.
-
আউটপুট অনুমান করুন: কোড না চালিয়ে দুটি লাইনের আউটপুট লিখুন।
import numpy as np m = np.array([1.2, 0.4, -0.3, 2.0]) # চারটি মন্তব্যের log-odds (ইতি − নেতি) cf = 0.9 # content-free input-এর log-odds print((m > 0).astype(int)) print(((m - cf) > 0).astype(int))[1 1 0 1] [1 0 0 1]প্রথম লাইনে শূন্যের ওপরে যেগুলো, সেগুলো ইতিবাচক। দ্বিতীয় লাইনে সীমা সরে ০.৯-এ: ০.৪ এখন নিচে, তাই দ্বিতীয় মন্তব্য নেতিবাচক হলো। দুই label-এ contextual calibration মানে শুধু এই সীমা সরানো; মন্তব্যগুলোর নিজেদের ক্রম (কোনটি বেশি ইতিবাচক) বদলায় না।
-
নকশা সমালোচনা করুন: বাজারঘরের একটি দল রিভিউ-শ্রেণিকরণের জন্য পরিকল্পনা দিল: “AI সহায়ককে বলে ৮টি উদাহরণ বানাব, সবগুলো সন্তুষ্ট গ্রাহকের, কারণ বেশিরভাগ রিভিউ ভালো। Similar উদাহরণ খুঁজব পুরো রিভিউ-ডেটা থেকে, test-সহ। একটি ক্রমে ৫০টি রিভিউয়ে চালিয়ে accuracy বেশি এলে চালু।” অন্তত পাঁচটি সমস্যা আর সমাধান বলুন।
- সব উদাহরণ এক label: Majority-label bias; আমাদের run-এ চারটি ইতিবাচক উদাহরণে ২০০টির সব রায় ইতিবাচক হয়েছিল। সমাধান: দুই label-ই, কাছাকাছি সংখ্যায়।
- বানানো উদাহরণ: আসল গ্রাহকের ভাষা, বানান, Banglish থাকে না। সমাধান: আসল ডেটা থেকে বাছা, ব্যক্তিগত তথ্য মুছে।
- Test থেকে similar: প্রশ্নের নিজের বা যমজ রিভিউ উদাহরণে চলে আসে; নম্বর ফাঁপা। সমাধান: দল ধরে আলাদা pool, সবচেয়ে কাছের cosine দেখা।
- একটি ক্রম: ক্রমই নির্ভুলতা ০.২-এর মতো সরাতে পারে। সমাধান: কয়েকটি ক্রম আর seed, ছড়ানো রিপোর্ট।
- ৫০টি রিভিউ, CI নেই, baseline নেই: ৫০টিতে CI প্রায় ±০.১৪. সমাধান: কয়েকশো রিভিউ, Wilson CI, জোড়া তুলনা, আর একটি TF-IDF বা কাছের-label baseline একই set-এ।
-
কোড লিখুন: একটি ফাংশন
balanced_similar(sim, y, k)লিখুন:simএকটি মন্তব্যের সঙ্গে ভাণ্ডারের সব মন্তব্যের cosine (NumPy array),yতাদের label (০/১), k জোড় সংখ্যা। প্রতিটি label থেকে সবচেয়ে কাছের k/২টি নিন, তারপর সব k-টি এমনভাবে সাজান যাতে সবচেয়ে কাছেরটি শেষে থাকে। Index-এর তালিকা ফেরত দিন।import numpy as np def balanced_similar(sim, y, k): pick = [] for lab in (0, 1): idx = np.where(y == lab)[0] pick += list(idx[np.argsort(-sim[idx])[:k // 2]]) pick = np.array(pick) return pick[np.argsort(sim[pick])] # ছোট থেকে বড় cosine: কাছেরটি শেষে sim = np.array([0.9, 0.1, 0.8, 0.3, 0.7, 0.2]) y = np.array([1, 0, 1, 0, 1, 0]) print(balanced_similar(sim, y, 4)) # [5 3 2 0]দুই label থেকে সমান সংখ্যক নিলে majority-label bias কমে, তবে কাছের-label নকলের সুবিধাও কিছুটা কমে; কোনটি ভালো, তা নিজের dev set-এ মেপে ঠিক করুন। এই রূপে label-এর ক্রম আর cosine জড়িয়ে যায়, তাই §৬-এর মতো কয়েকটি ক্রমেও চালিয়ে দেখুন।
নিজেকে যাচাই করুন
ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।
ক্রমএকটি few-shot classifier ন্যায্যভাবে মাপার ধাপগুলো সাজান (▲▼ চেপে সরান)
- Test আর উদাহরণের ভাণ্ডার দল ধরে আলাদা করা, যাতে যমজ মন্তব্য দুই পাশে না যায়
- 0-shot আর একটি সাধারণ baseline একই test-এ মাপা
- উদাহরণ বাছাইয়ের নিয়ম লিখে রাখা: random-এর seed, বা similar-এর মাপকাঠি
- কয়েকটি seed আর ক্রমে dev set-এ চালিয়ে ক্রম আর calibration বেছে নেওয়া
- Test-এ একবার চালিয়ে CI আর জোড়া তুলনাসহ রিপোর্ট করা
একটি ২-label sentiment task-এ 4-shot prompt-এর চারটি উদাহরণই ইতিবাচক। একটি ছোট instruction-tuned model-এ সবচেয়ে সম্ভাব্য ফল কোনটি?
- Model উদাহরণের label উপেক্ষা করে আগের মতোই রায় দেবে
- প্রায় সব মন্তব্যকে ইতিবাচক বলবে, নেতিবাচকগুলোও
- প্রায় সব মন্তব্যকে নেতিবাচক বলবে
- নির্ভুলতা নিশ্চিতভাবে বাড়বে, কারণ উদাহরণ বেশি
Content-free input “N/A”-এ একটি prompt-এর p(ইতি) = ০.৭৫. একটি মন্তব্যে p(ইতি) = ০.৬০. Contextual calibration-এর পরে p(ইতি) প্রায় কত?
- ০.৬০
- ০.৩৫
- ০.৩৩
- ০.৮০
Min ও সহকর্মীদের ২০২২ সালের প্রবন্ধে few-shot উদাহরণের সঠিক label বদলে random label দেওয়ার ফল নিয়ে প্রধান পর্যবেক্ষণ কোনটি?
- নির্ভুলতা সামান্যই কমে; ফরম্যাট, label-এর জগৎ আর input-এর ধরন বেশি কাজের
- নির্ভুলতা দৈবের নিচে নেমে যায়
- নির্ভুলতা বাড়ে, কারণ model নিয়মে বাঁধা পড়ে না
- শুধু GPT-3-এ ফল পাওয়া গেছে, অন্য model-এ পরীক্ষা হয়নি
প্রতিটি নতুন মন্তব্যের জন্য সবচেয়ে কাছের উদাহরণ বাছাই (similar selection) করলে কোন ঝুঁকিটি সবচেয়ে বড়?
- Prompt অনেক লম্বা হয়ে যায়
- Cosine হিসাব খুব ধীর
- উদাহরণের ক্রম ঠিক করা যায় না
- যমজ মন্তব্যের ফাঁস, আর model শুধু কাছের label নকল করা
২০০টি মন্তব্যে একটি prompt-এর নির্ভুলতা ০.৭০. Normal approximation-এ ৯৫% CI-এর অর্ধ-প্রস্থ প্রায় কত?
- ±০.১৩
- ±০.০৬৪
- ±০.০৩২
- ±০.০১০
একই চারটি উদাহরণ ২৪টি ভিন্ন ক্রমে দিয়ে একটি model-এর নির্ভুলতা ০.৬১ থেকে ০.৮২ পাওয়া গেল। এর সবচেয়ে যুক্তিসঙ্গত ব্যবহারিক সিদ্ধান্ত কোনটি?
- ক্রম dev set-এ বাছা বা কয়েকটি ক্রম মেলানো, আর ছড়ানো রিপোর্ট করা
- Test-এ সবচেয়ে ভালো ক্রমটি বেছে ০.৮২ রিপোর্ট করা
- Few-shot বাদ দিয়ে শুধু 0-shot ব্যবহার করা
- Temperature কমিয়ে ক্রমের প্রভাব দূর করা
শব্দকোষ
লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন, অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:
মনে রাখুন
- Few-shot মানে prompt-এ উদাহরণ, weight বদলায় না। উদাহরণ ফরম্যাট আর label-এর জগৎ দেখায়; বড় model-এ কখনো নতুন নিয়মও চাপায়, ছোটগুলোতে প্রায়ই নয়।
- কোন উদাহরণ, সেটিই বড় প্রশ্ন: একই k-তে seed বদলালে নির্ভুলতা ০.৫০ থেকে ০.৭৭. কয়েকটি seed আর ক্রমে চালিয়ে ছড়ানো আর CI লিখুন।
- Similar উদাহরণ শক্তিশালী, কিন্তু model প্রায়ই কাছের label নকল করে, আর যমজ মন্তব্য ফাঁস ঘটায়। LLM ছাড়া k-NN আর TF-IDF baseline পাশে রাখুন।
- ক্রম আর label-এর অনুপাত রায় টানে: চারটি ইতিবাচক উদাহরণে সব রায় ইতিবাচক; ক্রম বদলে ০.২১ পর্যন্ত পার্থক্য, আর দিকটি model ধরে আলাদা।
- Calibration একটি সীমা সরানো: content-free input কোথাও সাহায্য করে, কোথাও ক্ষতি; সংকেত না থাকলে কিছুই বাঁচায় না। Dev set-এ বাছুন, আর লম্বা prompt-এর token-খরচ হিসাব করুন।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পর্ব ৬২ · Structured output — JSON, schema আর যাচাইপরবর্তী পর্বmodel-এর উত্তর JSON-এ বেঁধে যাচাই করার পুরো পথ।
- ডিপ লার্নিং, NLP আর Generative AI · কোর্স হোম৯১টি পর্বপুরো কোর্সের রোডম্যাপ; পর্ব ৬২ · Structured output এখানে প্রকাশ হবে।
- পর্ব ৫৮ · LLM মূল্যায়নফিরে দেখুনLog-likelihood দিয়ে বিকল্প বাছাই, CI আর কত প্রশ্ন লাগে।
- পর্ব ৪২ · Deep learning দিয়ে text classificationফিরে দেখুনএকই মন্তব্যে TF-IDF baseline আর near-duplicate পরীক্ষা।
- পর্ব ৫২ · LLM-এর ভেতরেফিরে দেখুনChat template, logits আর calibration-এর ভিত্তি।
- মেশিন লার্নিং · পর্ব ২৬ · Probability calibrationপাশের ট্র্যাকPlatt, isotonic আর reliability diagram, লেবেলসহ calibration.
- AI-এর ভিত্তি · পর্ব ৫৭ · k-Nearest Neighborsপাশের ট্র্যাকSimilar উদাহরণের পেছনের ধারণা, NumPy-তে নিজে লেখা।