Bag of Words ও TF-IDF: প্রথম যুগের NLP (এখনও কাজের)

Project P5 — TF-IDF text classifier (Series 07, Episode 02)

🟢 BEGINNER Series 07 — NLP, Transformers ও LLM Episode 02 / 08

📑 এই পর্বে যা যা আছে

🧩 ১. গল্প: token তো পেলাম, এখন সংখ্যা কই?

গত পর্বে Rahim শিখল কীভাবে CV থেকে token বের করতে হয়। কিন্তু এবার সে আটকে গেল — তার কাছে এখন ["python", "django", "sql"]-এর মতো token আছে, কিন্তু LogisticRegression-এ (S05E04-এ শেখা) এই list পাঠাতেই error!

Rahim: "আপা, আমার তো token আছে। কিন্তু model বলছে সে string নেয় না, শুধু সংখ্যা নেয়। এখন কী করব?"

Nila: "এটাই তো NLP-র মূল প্রশ্ন — text-কে সংখ্যায় রূপান্তর করা। এই প্রক্রিয়ার নাম text vectorization বা feature extraction। সবচেয়ে পুরনো কিন্তু এখনো অসম্ভব কাজের দুটো পদ্ধতি হলো Bag of Words আর TF-IDF। মজার ব্যাপার — অনেক production system আজও এগুলোই ব্যবহার করে, কারণ এরা দ্রুত, সস্তা আর ব্যাখ্যাযোগ্য।"

২. সমস্যা: model তো token খায় না, সংখ্যা খায়

S05-এ আমরা দেখেছি প্রতিটা ML model আসলে সংখ্যার matrix-এর উপর গণিত করে। text-এর ক্ষেত্রে আমাদের প্রতিটা document (একটা review, একটা CV, একটা JD)-কে একটা সংখ্যার vector-এ রূপান্তর করতে হবে।

মূল ধারণা: প্রতিটা document → একটা row, প্রতিটা unique শব্দ → একটা column। সেই cell-এ থাকবে সংখ্যা (শব্দটা কতবার এল, বা কতটা গুরুত্বপূর্ণ)। এই বড় সংখ্যার টেবিলটাকেই বলে document-term matrix

🎒 ৩. Bag of Words কী (intuition)

নামটাই ইঙ্গিত দেয় — একটা "ব্যাগ ভর্তি শব্দ"। আমরা document-টাকে একটা ব্যাগ ধরে নিই যেখানে শুধু কোন শব্দ কতবার আছে সেটা গুনি, কিন্তু শব্দের ক্রম (order) ভুলে যাই

তিনটা ছোট document ধরুন:

D1: "python python job" D2: "sql job" D3: "python sql" Vocabulary: [python, job, sql] Bag of Words matrix (count): python job sql D1 2 1 0 D2 0 1 1 D3 1 0 1

এখন D1, D2, D3 প্রত্যেকেই একটা সংখ্যার vector — model-এ পাঠানোর জন্য প্রস্তুত!

⚖️ ৪. Bag of Words-এর সমস্যা → TF-IDF-এর জন্ম

BoW-এর একটা বড় দুর্বলতা: সে শুধু গোনে। কিন্তু "job", "the", "and" — এই শব্দগুলো তো প্রায় সব document-এই থাকে। এগুলো অনেকবার এলেও আসলে কোন document-কে অন্যটা থেকে আলাদা করতে সাহায্য করে না।

আমরা চাই এমন একটা measure যা বলবে: এই শব্দটা কি এই document-এ common, কিন্তু বাকি সব document-এ rare? তাহলে সেটাই এই document-এর জন্য গুরুত্বপূর্ণ। এই ধারণাই TF-IDF

TF (Term Frequency): একটা document-এ শব্দটা কতবার এল (যত বেশি, তত গুরুত্বপূর্ণ — এই document-এ)।

IDF (Inverse Document Frequency): শব্দটা কত কম document-এ আছে (যত rare, তত গুরুত্বপূর্ণ — কারণ সে আলাদা করে)।

TF-IDF = TF × IDF। ফলে "python" (rare, তথ্যবহুল) বেশি score পায়, আর "job" (সব জায়গায় আছে) কম score পায়।

🪜 ৫. তিন স্তরে TF-IDF

Level 1 — সহজ intuition:
একটা ক্লাসে সবাই যদি "স্যার" শব্দটা বলে, তাহলে "স্যার" শুনে আপনি কাউকে চিনতে পারবেন না। কিন্তু কেউ যদি "quantum" শব্দটা বারবার বলে আর বাকিরা না বলে — তাহলে "quantum" ওই লোকটার signature। TF-IDF ঠিক এভাবে signature শব্দ খুঁজে বের করে।

Level 2 — technical:
tf(t,d) = document d-তে term t-এর frequency। idf(t) = log(মোট document / যত document-এ t আছে)। TF-IDF weight = tf × idf। rare + local শব্দ high weight, global common শব্দ low weight।

Level 3 — AI Engineer perspective:
TF-IDF এখনো industry-তে ভীষণ কাজের — কারণ এটা দ্রুত, GPU লাগে না, ব্যাখ্যাযোগ্য (কোন শব্দে বেশি weight দেখা যায়), আর ছোট dataset-এ প্রায়ই deep model-এর সমান বা ভালো করে। তাই সবসময় LLM লাগে না — একজন engineer আগে সস্তা baseline (TF-IDF) দিয়ে শুরু করে।
গুরুত্বপূর্ণ: TF-IDF কিন্তু শব্দের অর্থ বোঝে না — "চাকরি" আর "job" তার কাছে সম্পূর্ণ আলাদা দুটো column। শব্দের অর্থ ও মিল ধরতে লাগে embeddings — যেটা পরের পর্বের (S07E03) বিষয়।

🖼️ ৬. Visual: text → matrix

Documents Tokenize TF-IDF Vectorizer Matrix "python job" --> [python,job] --> fit + transform --> [0.7, 0.7, 0.0] "sql job" --> [sql,job] --> --> [0.0, 0.5, 0.8] ^col: python job sql এই matrix এখন সরাসরি LogisticRegression / SVM-এ পাঠানো যায়

💻 ৭. Code: sklearn দিয়ে TF-IDF

কেন scikit-learn? — কারণ এর TfidfVectorizer preprocessing, vocabulary building আর weighting একসাথে করে দেয়, আর সরাসরি sklearn model-এর সাথে খাপ খায়।

# pip install scikit-learn from sklearn.feature_extraction.text import TfidfVectorizer docs = [ "python developer needed with django", "sql database administrator role", "python and sql for data science", ] vectorizer = TfidfVectorizer() X = vectorizer.fit_transform(docs) # sparse matrix print(vectorizer.get_feature_names_out()) # ['administrator' 'and' 'database' 'data' 'developer' 'django' # 'for' 'needed' 'python' 'role' 'science' 'sql' 'with'] print(X.shape) # (3, 13) -> 3 document, 13 unique word print(X.toarray().round(2)[0]) # প্রথম document-এর TF-IDF vector

দরকারি প্যারামিটার, যেগুলো production-এ প্রায়ই লাগে:

vectorizer = TfidfVectorizer( lowercase=True, stop_words="english", # common ইংরেজি শব্দ বাদ ngram_range=(1, 2), # unigram + bigram ("data science" ধরবে) max_features=5000, # শুধু top 5000 শব্দ, memory বাঁচে min_df=2, # অন্তত 2 document-এ থাকতে হবে )

🛠️ ৮. Project P5: NLP Text Classifier

এবার একটা পূর্ণাঙ্গ classifier — job description থেকে বলা যে এটা কোন category (এখানে উদাহরণ: tech vs non-tech)। এটাই আমাদের Project P5-এর ভিত্তি।

from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.linear_model import LogisticRegression from sklearn.pipeline import Pipeline from sklearn.model_selection import train_test_split from sklearn.metrics import classification_report # ছোট demo dataset (বাস্তবে bdjobs থেকে scrape করা যায়) texts = [ "python django backend developer", "machine learning engineer pytorch", "sales executive fmcg field marketing", "customer support call center agent", "data scientist sql tensorflow", "hr recruitment officer payroll", ] labels = ["tech", "tech", "non-tech", "non-tech", "tech", "non-tech"] X_tr, X_te, y_tr, y_te = train_test_split( texts, labels, test_size=0.34, random_state=42 ) # Pipeline: vectorizer + classifier একসাথে (train/inference এ একই preprocessing) clf = Pipeline([ ("tfidf", TfidfVectorizer(ngram_range=(1, 2))), ("model", LogisticRegression(max_iter=1000)), ]) clf.fit(X_tr, y_tr) print(clf.predict(["senior python engineer with fastapi"])) # ['tech']
কেন Pipeline? কারণ এটা নিশ্চিত করে training আর inference-এ হুবহু একই preprocessing হচ্ছে। এটা S03E08-এ শেখা data leakage এড়ানোরও চাবিকাঠি — vectorizer শুধু training data দিয়ে fit হয়, test data দিয়ে নয়।

🔬 ৯. Experiment: কোন শব্দ বেশি গুরুত্বপূর্ণ

TF-IDF-এর সবচেয়ে সুন্দর দিক — এটা ব্যাখ্যাযোগ্য। model কোন শব্দকে "tech"-এর ইঙ্গিত ধরছে দেখুন:

import numpy as np feat = clf.named_steps["tfidf"].get_feature_names_out() coef = clf.named_steps["model"].coef_[0] top = np.argsort(coef)[-5:] # সবচেয়ে "tech"-ঘেঁষা শব্দ for i in reversed(top): print(f"{feat[i]:20} weight={coef[i]:.3f}")
যা লক্ষ্য করবেন: "python", "pytorch", "sql"-এর মতো শব্দ high positive weight পায়। এই ব্যাখ্যাযোগ্যতা (interpretability) interview-তে আর business stakeholder-দের বোঝাতে অসম্ভব কাজের — একটা black-box deep model এত সহজে "কেন" বলতে পারে না।

🇧🇩 ১০. বাস্তব উদাহরণ ও AI Engineer perspective

Must Know: BoW ও TF-IDF-এর পার্থক্য, sklearn দিয়ে vectorize + classify, Pipeline।
Good to Know: n-gram, max_features/min_df tuning, sparse matrix।
Learn Later: BM25, hashing vectorizer, বড় scale text search।

💼 ১১. Boss Question

Boss: "সবাই তো এখন ChatGPT-র কথা বলে। তুমি এই পুরনো TF-IDF কেন শেখাচ্ছ?"

উত্তর: কারণ আমাদের ৫০,০০০ product review classify করতে TF-IDF লাগে মাত্র কয়েক সেকেন্ড আর প্রায় শূন্য টাকা — কোনো GPU বা API খরচ নেই। একই কাজ LLM দিয়ে করলে খরচ হাজার গুণ বেশি আর ধীর। একজন ভালো engineer আগে সস্তা baseline বানায়, তারপর দরকার হলে দামি solution-এ যায়। এটাই সঠিক business সিদ্ধান্ত।

🔎 ১২. Job Requirement Decoder: "TF-IDF / Feature Extraction"

JD-তে: "Familiarity with text feature extraction (Bag of Words, TF-IDF)."
প্রশ্নউত্তর
কী বোঝায়?text-কে সংখ্যার vector-এ রূপান্তর করে ML model-এ দিতে পারা।
কেন চায়?classical NLP task (classification, search) এর ভিত্তি; সস্তা ও নির্ভরযোগ্য baseline।
কোন সমস্যা সমাধান করে?string data → numeric feature, যা model process করতে পারে।
junior-এর কী জানা লাগে?TfidfVectorizer ব্যবহার, Pipeline, একটা text classifier train ও evaluate করা।
এখনই কী master লাগে না?IDF-এর গাণিতিক variant, custom weighting scheme।
GitHub-এ কীভাবে দেখাবেন?একটা text classifier repo — dataset, pipeline, metrics ও top-feature ব্যাখ্যা।
Interview-তে?"BoW vs TF-IDF?", "IDF কেন দরকার?", "TF-IDF কি অর্থ বোঝে?"

⚠️ ১৩. সাধারণ ভুল

ভুল ১: পুরো dataset (train+test) দিয়ে vectorizer fit করা। → data leakage! শুধু train দিয়ে fit, test শুধু transform।

ভুল ২: TF-IDF থেকে semantic similarity আশা করা। → সে অর্থ বোঝে না; "job" ≠ "চাকরি" তার কাছে।

ভুল ৩: max_features/min_df ছাড়া বিশাল vocabulary → memory ও overfitting সমস্যা।

ভুল ৪: বাংলা text-এ ইংরেজি stopword list ব্যবহার — কাজ করবে না, বাংলার জন্য আলাদা list লাগে।

🎤 ১৪. Interview Prep

প্রশ্ন ১: Bag of Words আর TF-IDF-এর পার্থক্য?
উত্তর: BoW শুধু count রাখে; TF-IDF সেই count-কে "শব্দটা কত rare" দিয়ে weight করে, ফলে common শব্দের গুরুত্ব কমে, তথ্যবহুল শব্দের বাড়ে।

প্রশ্ন ২: IDF না থাকলে কী সমস্যা?
উত্তর: "the", "job"-এর মতো সব জায়গায় থাকা শব্দ বেশি weight পেয়ে model-কে বিভ্রান্ত করত।

প্রশ্ন ৩: TF-IDF-এর সীমাবদ্ধতা কী?
উত্তর: শব্দের ক্রম আর অর্থ ধরে না; synonym বোঝে না; খুব বড় sparse matrix তৈরি করে। এসব সমাধানে লাগে embeddings।

✍️ ১৫. হাতে-কলমে

১. উপরের P5 classifier-এ আরও কয়েকটা example যোগ করে classification_report দিয়ে precision/recall দেখুন (S05E05 recall করুন)।
২. ngram_range=(1,1) বনাম (1,2) — accuracy-তে পার্থক্য দেখুন।
৩. একটা document জোড়ার cosine similarity বের করুন sklearn.metrics.pairwise.cosine_similarity দিয়ে, আর ভাবুন কেন synonym থাকলেও similarity কম আসতে পারে।

🚀 ১৬. Project Connection

flagship "Bangladesh Tech Career Assistant"-এ এখন আমরা JD text-কে TF-IDF vector-এ রূপান্তর করে দুটো নতুন feature যোগ করছি: (১) JD auto-categorize করা, (২) দুটো JD-র মধ্যে similarity মাপা।

এটাই আমাদের standalone Project P5 (NLP Text Classifier)-এরও ভিত্তি — portfolio-তে এটা আপনার প্রথম "NLP" project হিসেবে দেখাবেন। তবে মনে রাখুন: এই TF-IDF similarity "python"≈"পাইথন" ধরতে পারবে না — সেই সীমা টপকাতেই পরের পর্বে embeddings আসছে।

📌 ১৭. সারসংক্ষেপ ও পরবর্তী পর্ব

এই পর্বে শিখলাম:

✓ Text vectorization = text-কে সংখ্যার vector বানানো, model-এ দেওয়ার জন্য
✓ Bag of Words = শুধু count; order ভুলে যায়
✓ TF-IDF = count × rarity; তথ্যবহুল শব্দকে বেশি weight দেয়
✓ sklearn Pipeline দিয়ে leakage-free text classifier (Project P5) বানানো
✓ TF-IDF দ্রুত, সস্তা, ব্যাখ্যাযোগ্য — সবসময় LLM লাগে না
✓ কিন্তু TF-IDF অর্থ/synonym বোঝে না — এটাই তার বড় সীমা
পরবর্তী পর্ব (S07E03): TF-IDF-এর কাছে "job" আর "চাকরি" সম্পূর্ণ অচেনা দুটো শব্দ। কিন্তু আমরা তো জানি এদের অর্থ এক! computer-কে এই "অর্থ" শেখাব কীভাবে? পরের পর্বে Word Embeddings — শব্দ কীভাবে vector space-এ meaning সহ বসে, আর কীভাবে semantic similarity মাপা যায়।
© 2025 Sheikh Thanbir Alam. All Rights Reserved. thanbirtamim.github.io
এই লেখা মূল লেখকের সম্পত্তি — লিখিত অনুমতি ছাড়া কপি করে অন্য কোনো ওয়েবসাইট, ব্লগ, বই বা প্ল্যাটফর্মে প্রকাশ/বিতরণ করা কঠোরভাবে নিষিদ্ধ। Content may not be copied or republished without permission.