أخذ عينات Top-k
حصر الاختيار في الرموز k الأكثر احتمالًا وتأثير ذلك في تنوع المخرجات
أخذ عينات Top-k درس مجاني في AI Prompt Engineering على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في AI Prompt Engineering، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة AI Prompt Engineering 4 دروس في المجموع.
ما المقصود بأخذ العينات باستخدام top-k؟
يقيّد أخذ العينات باستخدام top-k النموذجَ بأخذ العينات من الرموز k الأكثر احتمالًا في كل خطوة. وتُسند إلى جميع الرموز خارج top-k احتمالية تساوي صفرًا، ولا يمكن اختيارها.
يمثل k=1 فك الترميز الجشع (أي الرمز الوحيد الأكثر احتمالًا). وتُعد k=50 قيمة شائعة للنطاق الإبداعي. أما k=vocabulary_size فيعادل أخذ العينات بلا قيود.
خوارزمية top-k
الخوارزمية أبسط من خوارزمية top-p:
- احسب احتمالات softmax على كامل المفردات
- رتّب الرموز تنازليًا حسب الاحتمال
- أبقِ على الرموز k الأولى فقط، واضبط قيمة جميع الرموز الأخرى على 0
- أعد تطبيع احتمالات top-k ليكون مجموعها 1
- خذ العينات من التوزيع بعد إعادة تطبيعه
import numpy as np
def softmax(logits, temperature=1.0):
scaled = logits / temperature
e = np.exp(scaled - np.max(scaled))
return e / e.sum()
def top_k_sample(logits, k=50, temperature=1.0):
probs = softmax(logits, temperature)
# Find top-k indices
top_k_indices = np.argsort(probs)[::-1][:k]
top_k_probs = probs[top_k_indices]
# Renormalize
top_k_probs = top_k_probs / top_k_probs.sum()
# Sample
chosen = np.random.choice(top_k_indices, p=top_k_probs)
return chosen
# With a 10-token vocabulary:
logits = np.random.randn(10)
print('Chosen token:', top_k_sample(logits, k=3))k=1: فك الترميز الجشع
عندما تكون k=1، لا يوجد في مجموعة المرشحين إلا الرمز الوحيد الأكثر احتمالًا. ويكون أخذ العينات من مجموعة حجمها 1 حتميًا، إذ يختار النموذج ذلك الرمز دائمًا. وهذا مطابق لفك الترميز الجشع (temperature=0).
logits = np.array([3.0, 2.0, 1.0, 0.5, -1.0])
# k=1: greedy
top_1 = top_k_sample(logits, k=1)
print(f'k=1 always picks: {np.argmax(logits)}') # index 0, the highest logit
print(f'top_k_sample result: {top_1}') # always 0
# Multiple runs
for _ in range(5):
print(top_k_sample(logits, k=1), end=' ')
# Output: 0 0 0 0 0 — perfectly deterministicالنطاق الإبداعي الشائع: k=50
تُعد k=50 قيمة افتراضية شائعة لتوليد النصوص الإبداعية. فهي تتيح الاستكشاف بين 50 رمزًا في كل خطوة، مع منع النموذج من اختيار الرموز التي لا يملك ثقة كبيرة بها.
مع مفردات تضم 50,000 رمز، تعني k=50 أن النموذج لا يأخذ في الحسبان إلا أعلى 0.1% من الرموز في كل خطوة. وهذا تقييد كبير، إذ تُستبعد معظم المفردات.
import openai
client = openai.OpenAI(api_key='sk-...')
# Note: OpenAI API does not expose top_k directly in chat completions.
# Top-k is primarily a parameter in Hugging Face Transformers and Anthropic's API.
# Hugging Face example:
from transformers import pipeline
generator = pipeline('text-generation', model='gpt2')
output = generator(
'Once upon a time',
max_new_tokens=100,
do_sample=True,
top_k=50,
temperature=1.0
)
print(output[0]['generated_text'])top-k في Anthropic's Claude API
تتيح واجهة Claude API من Anthropic استخدام top_k بوصفه معاملًا مباشرًا. وهذا يسهل تجربة تأثير الاقتطاع الثابت للمفردات في مخرجات Claude.
import anthropic
claude = anthropic.Anthropic(api_key='sk-ant-...')
# top_k limits the number of tokens considered
message = claude.messages.create(
model='claude-opus-4-5',
max_tokens=256,
temperature=1.0,
top_k=50, # sample from top 50 most probable tokens
messages=[{
'role': 'user',
'content': 'Write a short poem about debugging code.'
}]
)
print(message.content[0].text)مشكلة k الثابت
القيد الأساسي في top-k هو أن قيمة k ثابتة بغض النظر عن درجة ثقة النموذج في تلك الخطوة.
عندما يكون النموذج واثقًا جدًا (إذ يملك رمز واحد احتمالًا قدره 95%)، يظل k=50 يضم 49 رمزًا غير ذي صلة إلى حد كبير. وعندما يكون النموذج غير متأكد جدًا (إذ يملك كل رمز من 50 احتمالًا يقارب 2%)، فقد تكون k=50 مناسبة فعلًا.
المشكلة هي أن k=50 قد يكون مقيّدًا جدًا ومتساهلًا جدًا في الوقت نفسه، حسب السياق. ويعالج top-p ذلك من خلال تغيير حجم النواة ديناميكيًا.
# Illustrating the fixed-k problem
logits_confident = np.array([5.0] + [0.1] * 9) # model is very sure
logits_uncertain = np.array([1.0] * 10) # model has no idea
probs_conf = softmax(logits_confident)
probs_unc = softmax(logits_uncertain)
print('Confident — top 3 tokens cover:', np.sort(probs_conf)[::-1][:3].sum().round(3))
# ~0.998 — k=50 is extremely wasteful, includes near-zero probability tokens
print('Uncertain — top 3 tokens cover:', np.sort(probs_unc)[::-1][:3].sum().round(3))
# ~0.30 — k=50 may actually be needed to cover a reasonable nucleustop-k عند ذيول التوزيع
يختلف top-k عن top-p اختلافًا أكبر عند ذيول التوزيع:
- مع top-k=50، قد يملك الرمز الخمسون احتمالًا قدره 0.001% (أي احتمالًا ضعيفًا جدًا، لكنه يظل ضمن مجموعة المرشحين)
- مع top-p=0.9، يُستبعد أي رمز خارج نواة الـ90%، بما في ذلك الرموز التي كانت ستدخل ضمن top-k
يتعامل top-p مع سلوك الذيل بطريقة أكثر استنادًا إلى المبادئ، إذ يستبعد الرموز ضعيفة الاحتمال بناءً على الاحتمال لا على موضعها في الترتيب.
# Tail behavior comparison
import numpy as np
# Highly skewed distribution (one dominant token)
skewed_logits = np.array([4.0, 2.0, 1.5, 1.0, 0.5,
0.1, 0.0, -0.1, -0.5, -1.0])
probs = softmax(skewed_logits)
print('Probability of tokens 6-9 (tail):')
for i in range(6, 10):
print(f' Token {i}: {probs[i]:.4%}')
# These tokens are very unlikely but are included in top-k=10
# Top-p=0.9 would exclude them entirelyالجمع بين top-k وtop-p
تطبّق بعض عمليات التنفيذ كلاً من top-k وtop-p: فتقتطع أولًا إلى top-k، ثم تطبّق أخذ عينات النواة باستخدام top-p ضمن تلك المجموعة. ويوفر ذلك حدًا أقصى صارمًا لحجم المفردات (top-k)، مع تطبيق تصفية تعتمد على الاحتمال (top-p) أيضًا.
def top_k_top_p_sample(logits, k=50, p=0.9, temperature=1.0):
probs = softmax(logits, temperature)
# First apply top-k
top_k_indices = np.argsort(probs)[::-1][:k]
top_k_probs = probs[top_k_indices]
# Then apply top-p within top-k
sorted_k = np.sort(top_k_probs)[::-1]
cumulative = np.cumsum(sorted_k)
nucleus_size = np.searchsorted(cumulative, p) + 1
final_indices = top_k_indices[:nucleus_size]
final_probs = top_k_probs[:nucleus_size]
final_probs = final_probs / final_probs.sum()
return np.random.choice(final_indices, p=final_probs)متى يُفضَّل top-k على top-p
على الرغم من المزايا النظرية لـ top-p، يُفضَّل top-k في بعض الحالات:
- مهام المفردات المقيّدة: عندما ينبغي للنموذج أن يخرج من مجموعة ثابتة فقط (مثل الاختيار من متعدد A/B/C/D)، يفرض top-k صغير (4) ذلك مباشرةً
- قابلية إعادة الإنتاج: يسهل فهم سلوك top-k، إذ يعني «ضع في الحسبان 50 رمزًا بالضبط دائمًا»
- عمليات التنفيذ المحسّنة للأجهزة: تنفّذ بعض محركات الاستدلال top-k بكفاءة أعلى من top-p
# Constrained output with top-k=4
# For a multiple choice task (A, B, C, D)
# If A/B/C/D tokens have indices 32, 33, 34, 35
# top-k=4 with those as the top-4 logits forces selection from those 4 only
multiple_choice_prompt = (
'Answer with only A, B, C, or D.\n'
'What is the capital of France?\n'
'A) Berlin\n'
'B) Paris\n'
'C) Rome\n'
'D) Madrid\n'
'Answer:'
)
# With temperature=0, top_k=1: always picks the highest logit tokenإرشادات عملية بشأن top-k
متى تستخدم top-k، وما القيم التي تختارها:
- k=1: المهام الجشعة / الواقعية
- k=5–20: المهام الإبداعية المركزة، مع أقل قدر من التنوع
- k=40–100: النطاق الإبداعي القياسي في معظم نماذج اللغة
- k=500+: استكشاف مفتوح جدًا (نادرًا ما تكون هناك حاجة إليه؛ استخدم top-p بدلًا منه)
في معظم واجهات API الحديثة لنماذج اللغة الكبيرة، يُعد top-p المعامل المفضّل. استخدم top-k عندما تحتاج إلى حد أقصى صارم للمفردات، أو عندما تتيح واجهة API استخدامه ولا تتيح top-p.
TOP_K_GUIDELINES = {
'factual_qa': 1, # greedy
'code_generation': 10, # near-greedy, correct syntax
'summarization': 20, # slightly varied but focused
'chat': 50, # natural variation
'creative_writing': 100, # wider vocabulary exploration
'poetry': 200, # unusual word choices encouraged
}
def call_with_top_k(task, prompt, model='claude-opus-4-5'):
k = TOP_K_GUIDELINES.get(task, 50)
claude = anthropic.Anthropic(api_key='sk-ant-...')
return claude.messages.create(
model=model,
max_tokens=512,
top_k=k,
messages=[{'role': 'user', 'content': prompt}]
)Top-k ودرجة الحرارة معًا
يُطبَّق كلٌّ من Top-k ودرجة الحرارة بالتتابع: تُعيد درجة الحرارة تشكيل توزيع القيم اللوغاريتمية أولًا، ثم يقتطع Top-k التوزيع ليحتفظ بأكثر k رموز احتمالًا. ويُعد استخدامهما معًا شائعًا في مسارات Hugging Face Transformers.
التركيبة المعتادة: temperature=0.9 (تنوع متوسط) + top_k=50 (حد صارم للمفردات). ويمنع ذلك كلاً من التسطيح الناتج عن استخدام درجة حرارة مرتفعة وحدها، ومشكلة أخذ العينات من ذيل التوزيع.
from transformers import pipeline
generator = pipeline('text-generation', model='gpt2')
# Combined top-k + temperature
output = generator(
'The future of AI is',
max_new_tokens=80,
do_sample=True,
top_k=50,
temperature=0.9
)
print(output[0]['generated_text'])
# Compare: top-k=1 (greedy)
greedy_output = generator(
'The future of AI is',
max_new_tokens=80,
do_sample=False # greedy, equivalent to top_k=1
)
print(greedy_output[0]['generated_text'])اختبار المعرفة
في أخذ عينات top-k، ما السلوك الذي يُظهره النموذج عند ضبط k=1؟
مراجعة سريعة: أخذ عينات Top-k
يقتطع أخذ عينات Top-k المفردات ليحتفظ بالرموز k الأكثر احتمالًا قبل أخذ العينة:
- k=1: فك الترميز الجشع — حتمي، ويختار دائمًا الرمز الأعلى احتمالًا
- k=50: نطاق إبداعي معتاد — توازن بين التنوع والترابط
- القيد الأساسي: قيمة k ثابتة بغض النظر عن ثقة النموذج — وقد تكون متساهلة جدًا أو مقيِّدة جدًا
- مقارنةً بـ top-p: تتكيف نواة top-p الديناميكية مع مستوى الثقة، أما top-k فلا يفعل ذلك
استخدم Top-k عندما تحتاج إلى حد صارم للمفردات. وفضّل top-p في معظم تطبيقات الإنتاج. الدرس التالي: اختيار المعلمات لحالة الاستخدام الخاصة بك.
الأسئلة الشائعة
هل درس «أخذ عينات Top-k» مجاني؟
نعم — نص درس «أخذ عينات Top-k» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة AI Prompt Engineering، انتقل إلى CoddyKit PRO. تتضمن دورة AI Prompt Engineering 4 دروس في المجموع.
ماذا ستتعلم في «أخذ عينات Top-k»؟
حصر الاختيار في الرموز k الأكثر احتمالًا وتأثير ذلك في تنوع المخرجات تتمرن على AI Prompt Engineering مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ AI Prompt Engineering؟
لا تُشترط خبرة سابقة. AI Prompt Engineering على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.
كم من الوقت يستغرق درس «أخذ عينات Top-k»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس AI Prompt Engineering هذا؟
نعم. كل درس في AI Prompt Engineering يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.