Natural Language Processingপড়তে ৯ মিনিট লাগবে

টোকেনাইজেশন (Tokenization)

যেকোনো বাক্যকে ছোট ছোট টুকরোতে ভাগ করে নেওয়া
scope:কোর কনসেপ্ট (মূল ধারণা)difficulty:বিগিনার (Beginner)

পিজ্জা যেভাবে কাটা হয় (Cutting the Pizza)

একটি ল্যাঙ্গুয়েজ মডেল (Language model) কোনো বাক্য পড়ার আগেই, সেটিকে ছোট ছোট টুকরোতে ভাগ করে নিতে হয়। আর এই কাজটির নামই হলো টোকেনাইজেশন (tokenization) — আর আপনি কীভাবে এই ভাগটি করছেন, সেটিও অনেক বড় একটি ভূমিকা পালন করে।

ধরা যাক, একটি পিজ্জার কথা। এই পিজ্জাটিকে আপনি কয়েকভাবে কেটে ভাগ করতে পারেন:

  • আস্ত এক পিস বা স্লাইস (ওয়ার্ড টোকেনাইজেশন) — এখানে প্রতিটি শব্দই হলো একেকটি টোকেন। যেমন: "I love pizza" বাক্যটি হবে ["I", "love", "pizza"]। এটি দেখতে বেশ সাধারণ বা ক্লিন (clean) মনে হলেও, প্রশ্ন হলো "don't"-এর মতো শব্দগুলোর কী হবে? এটি কি একটি টোকেন নাকি দুটি? আর "GPT-4o"-এর মতো যেসব শব্দ মডেলটি কখনোই দেখেনি, সেগুলোর কী হবে?
  • ছোট ছোট বাইট-সাইজ টুকরো (সাবওয়ার্ড টোকেনাইজেশন) — যেকোনো শব্দকে ছোট ছোট অর্থপূর্ণ অংশে ভাগ করা। যেমন: "unhappiness" হয়ে যায় ["un", "happiness"], আবার "playing" হয়ে যায় ["play", "ing"]। এই পদ্ধতিতে মডেলটি না-দেখা বা একেবারে নতুন শব্দগুলোকেও পরিচিত টুকরোগুলোর সাথে জোড়া লাগিয়ে খুব সহজেই বুঝতে পারে।
  • একদম আলাদা আলাদা টপিং (ক্যারেক্টার টোকেনাইজেশন) — এখানে প্রতিটি অক্ষরের একটি নিজস্ব টোকেন থাকে। যেমন: "cat" হয়ে যায় ["c", "a", "t"]। এটি খুব ফ্লেক্সিবল (flexible) হলেও, মডেলটিকে নিজেই বুঝে নিতে হয় যে "c-a-t" মানে হলো লোমশ একটি প্রাণী। যা সত্যিই বেশ কঠিন কাজ।

আধুনিক সময়কার এআই (AI) মডেলগুলো প্রায় বেশিরভাগ ক্ষেত্রেই সাবওয়ার্ড টোকেনাইজেশন (subword tokenization) ব্যবহার করে — এটি ফ্লেক্সিবিলিটি বা নমনীয়তা এবং অর্থের একদম সঠিক ভারসাম্য বজায় রাখতে পারে।

বিপিই (BPE): মডার্ন টোকেনাইজার কীভাবে কাজ করে

বাইট-পেয়ার এনকোডিং (Byte-Pair Encoding বা BPE) হলো টোকেনাইজেশনের সবচেয়ে জনপ্রিয় একটি অ্যালগরিদম। এটি মূলত ডেটা কম্প্রেশন (Data compression) বা সংকুচিত করার একটি কৌশল ছিল, যা ২০১৫ সালে এডিনবার্গ বিশ্ববিদ্যালয়ের গবেষকেরা এনএলপি (NLP)-এর জন্য নতুন করে তৈরি করেছিলেন।

BPE যেভাবে এর শব্দভাণ্ডার বা ভোকাবুলারি তৈরি করে:

  1. প্রাথমিক টোকেন হিসেবে শুরুতে প্রতিটি আলাদা ক্যারেক্টার বা অক্ষরকে নেওয়া হয়।
  2. এরপর ট্রেইনিং ডেটাতে পাশাপাশি থাকা কোন জোড় বা পেয়ার সবচেয়ে বেশিবার এসেছে তা গণনা করা হয়।
  3. সবচেয়ে বেশি আসা ওই জোড়টিকে একসাথে যুক্ত করে একটি নতুন টোকেন তৈরি করা হয়।
  4. আপনার কাঙ্ক্ষিত ভোকাবুলারি সাইজ বা আকার না হওয়া পর্যন্ত এটি বারবার রিপিট বা পুনরাবৃত্তি করা হয়।

উদাহরণস্বরূপ, যদি "th" শব্দটি ১০০০ বার এবং "he" শব্দটি ৮০০ বার আসে, তবে প্রথমে "th" একটি টোকেন হিসেবে যুক্ত হবে। তারপর হয়তো "the" যুক্ত হতে পারে। এভাবে "the"-এর মতো সাধারণ শব্দগুলো একটিমাত্র টোকেনে পরিণত হয়। আবার বিরল শব্দগুলোকে ছোট ছোট সাবওয়ার্ডে ভাগ করা হয়।

GPT-4 প্রায় ১০০,০০০ টোকেনের একটি ভোকাবুলারি বা শব্দভাণ্ডার ব্যবহার করে। ইংরেজি ভাষার পরিচিত শব্দগুলো হলো সিঙ্গেল টোকেন। আর এর বাইরের বিরল শব্দ, টেকনিক্যাল জার্গন (technical jargon) বা অন্য কোনো ভাষার শব্দগুলোকে ছোট ছোট টুকরোতে ভাগ করা হয়।

টোকেনাইজেশন কেন আপনার ভাবনার চেয়েও বেশি গুরুত্বপূর্ণ

টোকেনাইজেশন একটি ল্যাঙ্গুয়েজ মডেলের প্রায় প্রতিটি বিষয়কেই প্রভাবিত করে:

  • খরচ (Cost) — এপিআই (API)-গুলো টোকেন অনুযায়ী চার্জ করে বা বিল নেয়। যার মানে হলো এফিশিয়েন্ট বা দক্ষ টোকেনাইজেশনের কারণে ইনফারেন্স (inference)-এর খরচ কমে যায়।
  • কনটেক্সট লেংথ (Context length) — প্রতিটি মডেলেরই একটি টোকেন লিমিট থাকে (যেমন ১২৮ হাজার টোকেন)। তাই ছোট ছোট অনেকগুলো টোকেন ব্যবহার করলে আপনি খুব বেশি লেখাও জায়গা দিতে পারবেন না।
  • মাল্টিলিঙ্গুয়াল অ্যাবিলিটি (Multilingual ability) — কেবল ইংরেজি ভাষার চর্চা বেশি হয় এমন টোকেনাইজারগুলো অন্যান্য ভাষার জন্য অনেকটাই অপচয়। যেমন: একটি ইংরেজি বাক্যের সমান একটি হিন্দি বা বাংলা বাক্য লিখতে প্রায় ৩ গুণের বেশি টোকেন লাগতে পারে।

প্র্যাকটিক্যালি টোকেনাইজেশন (Tokenization in Practice)

# সাধারণ ওয়ার্ড এবং সাবওয়ার্ড টোকেনাইজেশন
def word_tokenize(text):
"""যেকোনো স্পেস এবং পাংচুয়েশন ব্যবহার করে ভাগ করা।"""
import re
return re.findall(r"\w+|[^\w\s]", text)
def simple_bpe_demo(text, num_merges=5):
"""বিপিই (BPE)-এর মতো মার্জিং দেখানো।"""
# ক্যারেক্টার দিয়ে শুরু করা
tokens = list(text.replace(" ", "_"))
print(f"প্রাথমিক (Initial): {tokens}")
for step in range(num_merges):
# পাশাপাশি থাকা জোড়গুলো গোনা
pairs = {}
for i in range(len(tokens) - 1):
pair = (tokens[i], tokens[i+1])
pairs[pair] = pairs.get(pair, 0) + 1
if not pairs:
break
# সবচেয়ে বেশিবার আসা জোড়টিকে একসাথে যুক্ত করা
best = max(pairs, key=pairs.get)
merged = best[0] + best[1]
new_tokens = []
i = 0
while i < len(tokens):
if i < len(tokens)-1 and (tokens[i], tokens[i+1]) == best:
new_tokens.append(merged)
i += 2
else:
new_tokens.append(tokens[i])
i += 1
tokens = new_tokens
print(f"মার্জ (Merge) {step+1}: '{best[0]}'+'{best[1]}' → '{merged}' → {tokens}")
return tokens
text = "the cat and the car"
print("ওয়ার্ড টোকেনাইজেশন:")
print(f" {word_tokenize(text)}\n")
print("বিপিই (BPE)-স্টাইল মার্জিং:")
simple_bpe_demo(text, num_merges=4)
Output
ওয়ার্ড টোকেনাইজেশন:
  ['the', 'cat', 'and', 'the', 'car']

বিপিই (BPE)-স্টাইল মার্জিং:
প্রাথমিক (Initial): ['t', 'h', 'e', '_', 'c', 'a', 't', '_', 'a', 'n', 'd', '_', 't', 'h', 'e', '_', 'c', 'a', 'r']
মার্জ (Merge) 1: 't'+'h' → 'th'  →  ['th', 'e', '_', 'c', 'a', 't', '_', 'a', 'n', 'd', '_', 'th', 'e', '_', 'c', 'a', 'r']
মার্জ (Merge) 2: 'th'+'e' → 'the'  →  ['the', '_', 'c', 'a', 't', '_', 'a', 'n', 'd', '_', 'the', '_', 'c', 'a', 'r']
মার্জ (Merge) 3: 'c'+'a' → 'ca'  →  ['the', '_', 'ca', 't', '_', 'a', 'n', 'd', '_', 'the', '_', 'ca', 'r']
মার্জ (Merge) 4: 'the'+'_' → 'the_'  →  ['the_', 'ca', 't', '_', 'a', 'n', 'd', '_', 'the_', 'ca', 'r']
Note: ফলাফলের ওপর ভাষার প্রভাব (The token tax on non-English languages): সাধারণত বেশির ভাগ টোকেনাইজারকে ইংরেজি ভাষার ডেটা দিয়ে ট্রেন বা প্রশিক্ষণ দেওয়া হয়, ফলে ইংরেজি ভাষার শব্দগুলো খুব সহজেই সিঙ্গেল বা একক টোকেন হিসেবে কাজ করতে পারে। কিন্তু চীনা, জাপানি, আরবি, হিন্দি এমনকি বাংলা ভাষার ক্ষেত্রে একই অর্থের জন্য অনেক বেশি টোকেনের প্রয়োজন হয়। এর মানে হলো, ইংরেজি ব্যতীত অন্য ভাষার ব্যবহারকারী এপিআই কল (API call)-এর জন্য অনেক বেশি খরচ করে এবং খুব দ্রুত এর লিমিটও শেষ করে ফেলে — যা এআই (AI) জগতে সমতার জন্য সত্যিই একটি চিন্তার বিষয়।

টোকেনাইজেশনের কিছু সমস্যা (Tokenization Gotchas)

টোকেনাইজেশনের কারণে অনেক সময় ল্যাঙ্গুয়েজ মডেলগুলো বেশ অদ্ভুত আচরণ করে থাকে:

  • অক্ষর গোনা: আপনি যদি GPT-কে জিজ্ঞেস করেন "strawberry শব্দটিতে কতগুলো r আছে?" তখন এটি অনেক সময়ই ভুল উত্তর দিয়ে থাকে। কিন্তু কেন? কারণ "strawberry" শব্দটি নিজেই একটি সম্পূর্ণ বা সিঙ্গেল টোকেন — মডেলটি কখনোই এর ভেতরের প্রতিটি আলাদা অক্ষর দেখতে পায় না।
  • অঙ্ক বা ম্যাথ (Math): যেমন "12345" সংখ্যাটিকে হয়তো ["123", "45"] হিসেবে টোকেনাইজ করা হতে পারে, যার ফলে মডেলটির জন্য গাণিতিক হিসাব-নিকাশ করা আরও কঠিন হয়ে যায়।
  • কোড (Code): পাইথনে ইনডেন্টেশনের (indentation) সময় স্পেসগুলো একেকটি আলাদা টোকেন হয়ে যায়, যার ফলে এগুলো খুব দ্রুতই পুরো জায়গাটি দখল করে ফেলে বা কনটেক্সট উইন্ডো খেয়ে ফেলে।

এই টোকেনাইজেশন প্রক্রিয়াটি ঠিকমতো বুঝতে পারলেই আপনি আসলে ধরতে পারবেন যে কেন ল্যাঙ্গুয়েজ মডেল মাঝে মাঝে এমন অদ্ভুত আচরণ করে। এদের এই সমস্ত অদ্ভুত কার্যকলাপ মডেলটির কোনো বাগ (bug) বা সমস্যা নয় — বরং এগুলো মডেলের কাছে শব্দগুলোকে যেভাবে কেটে টুকরো করে পাঠানো হয়, মূলত তারই ফলাফল।

ছোট কুইজ

কেন ওয়ার্ড-লেভেল টোকেনাইজেশনের চেয়ে সাবওয়ার্ড টোকেনাইজেশনকে বেশি ভালো ধরা হয়?
Challenge

পড়া চালিয়ে যান