انتقل إلى المحتوى الرئيسي

الوحدة 2 — التقطيع: الكلمات، الوحدات الجزئية، BPE، SentencePiece

بعد أن أصبح النصّ نظيفًا ومطبَّعًا، تأتي الخطوة التي تُحوّله من سلسلة أحرف إلى قائمة كائنات يستطيع النموذج معالجتها: التقطيع. الاختيار هنا ليس شكليًّا. فهو يحدّد حجم المفردات، وكيف يُعالَج المجهول، وكم يكلّف نصّ عربي بالجُذاذات مقارنة بنصّ إنجليزي، وهو رقم يُدفَع مباشرة في فواتير الاستدلال.

سنستأنف مراجعات العملاء العربية: 10 000 مراجعة، متوسّط طولها 40 كلمة، ومفردات إجمالية بعد التطبيع تناهز 30 000 كلمة.

التقطيع الكلمي وحدوده الصارمة

أبسط استراتيجية هي القطع عند الفراغات وعلامات الترقيم. وينتج عن ذلك «كلمات كاملة» تمثّل كلّ واحدة منها بمعرِّف عددي.

import re

def qatti3_kalimi(nass: str) -> list[str]:
return re.findall(r"\w+|[^\w\s]", nass, flags=re.UNICODE)

print(qatti3_kalimi("المنتج رائع جدا!!"))
# ['المنتج', 'رائع', 'جدا', '!', '!']

الميزة: كلّ جُذاذة كلمة كاملة، سهلة القراءة وسهلة التفسير. أمّا العيوب فثلاثة، وكلّها ثقيلة على العربية.

  • انفجار المفردات: كلّ اشتقاق يُنتج كلمة جديدة. يذهب ويذهبون وذاهب ومذهب أربع مداخل مختلفة.
  • الكلمات المجهولة (OOV): كلمة لم تظهر في التدريب لا يمكن تمثيلها. المراجعات الحقيقية مليئة بأسماء علامات وأخطاء إملاء ومصطلحات جديدة.
  • الالتصاق: العربية تلصق الضمائر وحروف الجرّ بالكلمات (وبالمنتج، فسنشتريه). هذه صيغ فريدة لا تشترك في أيّ رمز مع «المنتج» أو «شراء».

على مراجعاتنا، حجم المفردات الكلمية يقارب 30 000، ومعدّل الكلمات المجهولة على جسم اختبار مستقلّ يتجاوز 6 بالمئة. النموذج يفقد بذلك سياقًا كبيرًا من دون أن يعلم.

البديل: الوحدات الجزئية (subwords)

الفكرة الرئيسة للوحدات الجزئية: الحفاظ على الكلمات الشائعة كاملة، وتفكيك النادرة إلى أجزاء أعرف. هكذا لا يبقى شيء «مجهولًا» تمامًا، لأنّ كلّ كلمة يمكن على الأقلّ تفكيكها إلى أحرف.

كلمة فسنشتريه تصبح مثلًا ف + سن + شتر + يه. لا يعرف النموذج معناها كوحدة، لكنّه يعرف الأجزاء ويستفيد من تكرارها في كلمات أخرى. وعلى مراجعاتنا، ينهار معدّل المجهول إلى الصفر، ويهبط حجم المفردات إلى نحو 30 000 وحدة جزئية بدل 30 000 كلمة كاملة، مع تغطية أوسع للاشتقاقات.

ثلاث خوارزميات تهيمن على هذا المجال: BPE (Byte Pair Encoding) وWordPiece وSentencePiece.

BPE خطوة بخطوة على 20 كلمة

خوارزمية BPE بسيطة إلى حدّ يستحقّ التنفيذ يدويًّا. تنطلق من مفردات مبدئية هي الأحرف، ثمّ تدمج الزوج الأكثر تكرارًا في كلّ تكرار، حتّى بلوغ حجم المفردات المستهدف.

from collections import Counter

corpus = ["منتج", "منتجات", "المنتج", "منتوج", "جيد", "الجيد", "جيدا", "جيدون"]

def hasseb_azwaj(kalimat: list[list[str]]) -> Counter:
azwaj = Counter()
for kalimah in kalimat:
for i in range(len(kalimah) - 1):
azwaj[(kalimah[i], kalimah[i + 1])] += 1
return azwaj

def damj_zawj(kalimat: list[list[str]], zawj: tuple[str, str]) -> list[list[str]]:
a, b = zawj
natija = []
for kalimah in kalimat:
jadid, i = [], 0
while i < len(kalimah):
if i < len(kalimah) - 1 and kalimah[i] == a and kalimah[i + 1] == b:
jadid.append(a + b)
i += 2
else:
jadid.append(kalimah[i])
i += 1
natija.append(jadid)
return natija

kalimat = [list(k) for k in corpus]
for step in range(6):
azwaj = hasseb_azwaj(kalimat)
if not azwaj:
break
afdal = azwaj.most_common(1)[0][0]
kalimat = damj_zawj(kalimat, afdal)
print(f"دمج {step + 1}: {afdal}")

خلال ست خطوات، ينشئ الخوارزم وحدات ثابتة مثل منت وجيد وال. هذه هي الجُذاذات النهائية. كلمة جديدة مثل منتوجات ستقطع إلى منت + و + جات بلا كلفة مفاجئة.

BPE بهذه الصيغة يستعمله GPT-2 وGPT-3 وGPT-4 وLLaMA. الفرق الوحيد أنّه يعمل على البايتات لا على الأحرف، ما يجعله عالميًّا بشكل حرفيّ: يستطيع تمثيل أيّ نصّ بأيّ لغة.

WordPiece وSentencePiece

WordPiece (يستعمله BERT وأخواته) يشبه BPE، مع فرق واحد جوهري: بدل دمج الزوج الأكثر تكرارًا، يدمج الزوج الذي يعظّم احتمالية الجسم تحت نموذج لغة أحاديّ الغرام. النتيجة قريبة عمليًّا، لكن المفردات تميل إلى وحدات ذات محتوى لغويّ أوضح. يُعلَّم الجزء الداخلي من الكلمة بـ## في المخرجات: المنتجاتالمنتج, ##ات.

SentencePiece (يستعمله T5 وXLNet وAraELECTRA) يذهب أبعد. لا يفترض أنّ الفراغات تفصل الكلمات، بل يعتبر الفراغ نفسه محرفًا عاديًّا (يُرمَز إليه بـ). هذا يحلّ مشكلتين. أوّلًا، اللغات التي لا تستعمل الفراغات (اليابانية والصينية) لا تحتاج معالجة خاصّة. ثانيًا، إعادة بناء النصّ الأصلي من الجُذاذات عملية عكسية دقيقة، دون أن يُحتَاج إلى معرفة كيف نضع الفراغات.

على العربية، SentencePiece هو الاختيار الأكثر شيوعًا في النماذج الحديثة، لأنّه يعامل الالتصاق بمرونة: وبالمنتج تُقطع إلى ▁و + ب + المنتج بشكل قابل للعكس تلقائيًّا.

كلفة الجُذاذات: لماذا العربية تكلّف ضِعف الإنجليزية

الرقم الأهمّ عمليًّا: كم جُذاذة يستهلك النصّ الواحد؟ هذا يحدّد كلفة الاستدلال (تُفوترها كلّ مزوّدي الـAPI بالجُذاذة)، وطول السياق المتاح، وسرعة الاستجابة.

قارِن الجملة نفسها بالعربية والإنجليزية على مقطِّع GPT-4:

  • «المنتج جيّد جدًّا، سأشتريه مرّة أخرى» تنقسم إلى نحو 14 جُذاذة.
  • «The product is very good, I will buy it again» تنقسم إلى نحو 11 جُذاذة.

الفرق يبدو محدودًا هنا، لكنّه يبلغ الضعف أو الثلاثة أضعاف في المتوسّط على المراجعات الطويلة. السبب: مقطّعات GPT دُرِّبت أساسًا على الإنجليزية، فتوجد وحدات جزئية غنيّة في الإنجليزية، وقليلة في العربية. النتيجة: نصّ عربي بمقدار 1000 حرف يستهلك 700 جُذاذة، بينما نظيره الإنجليزي 250 جُذاذة فقط.

هذا يُترجَم مباشرة إلى الفاتورة، ويشرح لماذا اختيار نموذج مدرَّب مسبقًا على العربية (AraBERT، AraT5) يوفّر مالًا ووقتًا: مقطّعه يعرف عربية كافية ليختصر الوحدات الشائعة إلى جُذاذات كبرى.

قِس كلفة الجُذاذات قبل اختيار المزوّد
from transformers import AutoTokenizer

for chatra in ["gpt2", "aubmindlab/bert-base-arabertv02"]:
tok = AutoTokenizer.from_pretrained(chatra)
ida = tok.encode("المنتج جيد جدا وسأشتريه مرة أخرى")
print(f"{chatra}: {len(ida)} جذاذة")

جرّبها على عيّنة تمثيلية من نصوصك قبل اعتماد نموذج معيّن؛ الفرق قد يصل إلى ثلاثة أضعاف الكلفة.

في الخلاصة

  • التقطيع الكلمي يعاني في العربية من انفجار المفردات ومن نسبة عالية للكلمات المجهولة، خصوصًا مع الالتصاق: وبالمنتج لا يشترك في أيّ رمز مع المنتج.
  • الوحدات الجزئية تُلغي عمليًّا فكرة «المجهول»، لأنّ كلّ كلمة يمكن تفكيكها إلى أجزاء أعرف، مع مفردات معتدلة الحجم.
  • BPE يدمج الزوج الأكثر تكرارًا، WordPiece يدمج الزوج الأكثر احتمالًا تحت نموذج لغة، SentencePiece يعامل الفراغ محرفًا ويعمل مباشرة على النصّ الخام.
  • كلفة الجُذاذات على العربية ضعف ما هي عليه في الإنجليزية على المقطّعات المدرَّبة أساسًا على الإنجليزية. اختيار نموذج مدرَّب على العربية يخفّض هذه الكلفة إلى النصف أو الثلث.

الوحدة التالية: نموذج مرجعي بسيط لكنّه فعّال يجب أن نُبنيَه قبل أيّ تعقيد — TF-IDF متبوعًا بانحدار لوجستي.