فن تقسيم النص (Tokenization) في معالجة اللغة الطبيعية
حققت تقنيات معالجة اللغة الطبيعية (NLP) إنجازات كبيرة منذ ظهور نماذج المحولات (Transformer Models). وتُعد تقسيم النص (Tokenization)، بعد تنظيف البيانات، أول خطوة في أي مهمة تتعلق بـ NLP.
لقد قطعت تقنيات تقسيم النص شوطًا طويلاً؛ بدءًا من التقنيات البدائية مثل التقسيم باستخدام المسافات البيضاء وعلامات الترقيم، وصولًا إلى التقسيم السياقي والبنيوي الحديث المستخدم في نماذج الذكاء الاصطناعي التوليدي مثل BERT وChatGPT وClaude. في هذا الدليل، نستعرض تطور آليات تقسيم النص وكيف تُستخدم اليوم ضمن أحدث النماذج اللغوية الضخمة (LLMs).
رحلة تطور تقنيات تقسيم النص
يشير تقسيم النص (Tokenization) إلى عملية تقسيم البيانات النصية إلى أجزاء أصغر (Tokens) باستخدام تقنيات مختلفة، لتمكين النماذج من فهم وتحليل البيانات بشكل أفضل. التقنيات الأساسية شملت تقسيم الجمل، وتقسيم الكلمات، والتقسيم عبر المسافات البيضاء. لكن هذه الأساليب واجهت قيودًا مثل فقدان السياق، أو تضخم حجم المفردات.
بالتالي، ظهرت تقنيات مثل N-Gram، BPE (Byte Pair Encoding)، SentencePiece والتي تُستخدم على نطاق واسع في النماذج الحديثة، كونها تحافظ على السياق البنيوي واللغوي.
الأساليب الأساسية في تقسيم النص
1. تقسيم المسافات البيضاء (Whitespace Tokenization)
تُقسّم الكلمات استنادًا إلى المسافات، مثل الفراغات وعلامات التبويب (tab) والأسطر الجديدة. ومع أن هذه الطريقة بسيطة، فإنها تُهمل الجوانب السياقية واللغوية للكلمات.
text = "He left the room on the left side."
tokens = text.split()
print(tokens)
- الكلمة “left” تظهر مرتين لكن تُعتبر توكن واحدة دون تمييز سياقي لمعناها المختلف في كل مرة.
- علامات الترقيم مثل النقطة (.) لا تُفصل عن الكلمة المجاورة، مما يُضعف فهم الجملة نحويًا.
2. تقسيم الكلمات (Word Tokenization)
تقنية تعتمد على تقسيم النص إلى كلمات مفصولة باستخدام خوارزميات محسنة تأخذ بعين الاعتبار علامات الترقيم وتُعالج فصلها بشكل دقيق.
from nltk.tokenize import word_tokenize
text = "He left the room on the left side."
tokens = word_tokenize(text)
print(tokens)
- ما زالت لا تميز بين المعاني المختلفة للكلمات المتشابهة.
- يتم فصل علامات الترقيم عن الكلمات المجاورة، مما يحسن فهم تركيب الجملة.
- تُعامل كل كلمة كتوكِن مستقل مما يؤدي إلى تضخم حجم القاموس.
3. تقسيم الجمل (Sentence Tokenization)
يُستخدم هذا الأسلوب لتقسيم النص إلى جمل كاملة، اعتمادًا على علامات الترقيم مثل النقطة (.)، وعلامة الاستفهام (?)، وبعض القواعد الخاصة بكل لغة.
from nltk.tokenize import sent_tokenize
text = "He left the room on the left side. Was it intentional?"
tokens = sent_tokenize(text)
print(tokens)
مفيد في مهام مثل الترجمة الآلية، ولكنه ما يزال يعتمد على تقسيم الكلمات داخليًا، وبالتالي يرث جميع قيودها المتعلقة بالسياق والمعنى.
التقنيات المتقدمة في تقسيم النص
1. N-Grams
▪ تقوم بتقسيم النص باستخدام نافذة منزلقة (sliding window) لإنشاء مجموعات من الكلمات بطول محدد N.
▪ تمكّن من فهم العلاقة بين الكلمات المتجاورة.
💡 تُستخدم هذه التقنية في مهام مثل التعرف على الكلام (Speech Recognition)، وتكميل النص (Text Completion).
⚠️ تلتقط العلاقة مع الكلمات المتجاورة فقط، مما يفقد المعنى السياقي في الجمل الطويلة.
2. Byte Pair Encoding (BPE)
▪ تبدأ ببناء قاموس أولي من كل الحروف (Bytes) الموجودة في النص.
▪ ثم تقوم بدمج أكثر الأزواج تكرارًا بشكل متكرر لتكوين مفردات جديدة.
▪ عند الوصول إلى الحد الأقصى للدمج، يتم تقسيم النص الجديد بناءً على القاموس الناتج.
▪ يُمكنها التعامل مع الكلمات خارج المفردات (OOV) دون تضخم في حجم القاموس.
💡 تُستخدم في نماذج مثل RoBERTa وGPT-2
- ⚠️ حجم القاموس ثابت أثناء التدريب، ما قد يسبب مشاكل مع كلمات جديدة.
- لا تأخذ في الاعتبار البنية الصرفية أو السياق المعنوي.
كود BPE
from tokenizers import ByteLevelBPETokenizer
model_path = 'path_to_save_model'
BPE_tokenizer = ByteLevelBPETokenizer()
BPE_tokenizer.train(files=['path_to_txt_file_for_training'], vocab_size=1000, min_frequency=2)
BPE_tokenizer.save_model(model_path)
BPE_tokenizer = ByteLevelBPETokenizer.from_file(
f"{model_path}/vocab.json", f"{model_path}/merges.txt")
text = "I would love to see a lion!"
encoded = BPE_tokenizer.encode(text)
print("Original text:", text)
print("Encoded tokens:", encoded.tokens)
3. SentencePiece
▪ مكتبة تقسيم النص على مستوى ما دون الكلمة (sub-word) وتدعم نماذج Unigram وBPE مع برمجة ديناميكية.
▪ تُعالج النص كنص Unicode خام، دون الحاجة لتقسيم مبدئي إلى كلمات.
▪ تدعم لغات متعددة بنموذج واحد.
▪ تُسهل عملية tokenization وdetokenization في وقت واحد.
💡 تُستخدم في BERT، T5، XLNet، والعديد من نماذج HuggingFace.
- ⚠️ الأداء يختلف حسب اللغة المستخدمة.
- لا تراعي السياق البنيوي مثل الفقرة أو القسم.
كود SentencePiece
import sentencepiece as spm
spm.SentencePieceTrainer.train(
input='path_to_txt_file_for_training', model_prefix='path_to_save_model', vocab_size=1000)
sp = spm.SentencePieceProcessor(model_file='path_to_save_model.model')
text = "I would love to see a lion when we reach the zoo!"
tokens_subword = sp.encode_as_pieces(text)
tokens_ids = sp.encode_as_ids(text)
decoded_text = sp.decode_pieces(tokens_subword)
print("Original text:", text)
print("Tokenized text:", tokens_subword)
print("Decoded text:", decoded_text)
الخلاصة
- التقنيات الأساسية مفيدة كبداية لكنها تعاني من قيود كبيرة.
- تقنيات مثل BPE وSentencePiece تسمح بفهم أعمق للسياق والبنية.
- يتم استخدام هذه التوكنات لاحقًا لتحويلها إلى Embeddings داخل نماذج اللغة الحديثة.