রোডম্যাপ
PHASE 1 · অধ্যায় 6

স্টেমিং

Stemming

Word এর base root form খুঁজে বের করা।

ভূমিকা

'play', 'playing', 'played', 'plays' — চারটা আলাদা word? নাকি একটাই word এর চারটা রূপ? Computer যদি প্রতিটা কে আলাদা ধরে, তাহলে তার vocabulary বিশাল বড় হয়ে যাবে। Stemming এই সমস্যার সবচেয়ে সহজ সমাধান।

ধারণা

Stemming হলো একটা word এর শেষ suffix কেটে base/root form বের করার rule-based process। যেমন 'playing' → 'play', 'caring' → 'car' (notice — সবসময় meaningful হয় না, এটাই stemming এর limitation)। এটা fast কিন্তু crude — শুধু string chopping।

সহজ ব্যাখ্যা

Stemming হলো একজন কুড়াল-হাতে কাঠুরে। সে গাছের ডালপালা কাটে দ্রুত, কিন্তু কখনো একটু বেশি কেটে ফেলে। 'studies' → 'studi' (real word না), 'better' → 'better' (কাটতে পারে না)। তাই stemming এর output সবসময় valid dictionary word হবে না — এটা শুধু matching/grouping এর জন্য ব্যবহৃত হয়।

বাস্তব ব্যবহার

  • Search engine — 'running shoes' search করলে 'run shoe' এর সাথেও match করে।
  • TF-IDF, BoW — feature space ছোট রাখার জন্য stemming করা হয়।
  • Document clustering — সম্পর্কিত words কে এক group এ আনতে।
  • Information Retrieval — query expansion এ।

ধাপে ধাপে বিশ্লেষণ

1
Step 1 — Stemmer choose করুন
PorterStemmer (most popular, English), SnowballStemmer (multi-language), LancasterStemmer (aggressive)।
2
Step 2 — Tokenize করুন
Word-level tokenization আগে।
3
Step 3 — প্রতিটা word stem করুন
stemmer.stem(word) — প্রতিটা token এর উপর।
4
Step 4 — Result review করুন
কোনটা valid word হল, কোনটা না — analyze করুন।

Python কোড

from nltk.stem import PorterStemmer, SnowballStemmer, LancasterStemmer
from nltk.tokenize import word_tokenize
import nltk
nltk.download("punkt", quiet=True)
nltk.download("punkt_tab", quiet=True)

words = ["playing", "played", "plays", "player",
         "studies", "studying", "studied",
         "caring", "cared", "running", "ran",
         "better", "happily", "fairly"]

porter = PorterStemmer()
snowball = SnowballStemmer("english")
lancaster = LancasterStemmer()

print(f"{'Word':<12}{'Porter':<12}{'Snowball':<12}{'Lancaster':<12}")
print("-" * 48)
for w in words:
    print(f"{w:<12}{porter.stem(w):<12}{snowball.stem(w):<12}{lancaster.stem(w):<12}")

# In real pipeline
text = "The boys are playing football happily in the studied field."
tokens = word_tokenize(text.lower())
stemmed = [porter.stem(t) for t in tokens]
print("\nStemmed sentence:", stemmed)
ব্যাখ্যা

তিনটা stemmer একই word এ আলাদা result দেয় — Porter conservative, Snowball balanced, Lancaster aggressive (কখনো একদম root টা ও কেটে ফেলে)। 'studies' → 'studi', 'happily' → 'happili' — notice এগুলো actual English word না। এটাই stemming এর nature। 'better' → 'better' (irregular word handle করতে পারে না, সেজন্য পরের chapter এ Lemmatization এ যাব)।

সাধারণ ভুল

  • Stem output কে real word ধরে নেওয়া — 'studi' English word না।
  • Display এর জন্য stemming use করা — backend processing এর জন্য, user কে দেখানোর জন্য না।
  • Bangla এ English stemmer use করা — কাজ করে না, language-specific দরকার।
  • Irregular form expect করা — 'went' → 'went', 'better' → 'better', stemmer change করে না।

অনুশীলন

  1. 'I am running, you were ran, he runs' — Porter এ stem করুন। 'ran' কী হলো?
  2. তিনটা stemmer compare করুন এই word গুলো দিয়ে: 'beautiful', 'happily', 'organization'।
  3. একটা paragraph নিন, stem করুন, এবং দেখুন unique word count কতটা কমলো।

ছোট প্রজেক্ট

Mini Project: Search Query Normalizer

একটা mini search system বানান — ১০টা document এর list থাকবে। User একটা query দিবে। আপনি query এবং সব document কে stem করে compare করবেন। যে document এর stemmed words এর সাথে query এর stemmed word সবচেয়ে বেশি match — সেটা return করবেন। দেখবেন 'run' search করলে 'running' আছে এমন document ও match হচ্ছে।

সারাংশ

  • Stemming = suffix কেটে base form বের করা (rule-based, fast)।
  • Result সবসময় valid word না — 'studies' → 'studi'।
  • Porter (popular), Snowball (multi-lang), Lancaster (aggressive)।
  • Search, IR, clustering এ useful — display এ না।