* interview cheat-sheet — preprocessing → representation → embeddings → pipeline
Goal: strip noise, shrink vocabulary, normalize text into a form a model can actually learn from — every step below trades signal loss for less noise / smaller vocab, so skip a step whenever the thing it removes is actually meaningful for your task.
When to use which: stemming for speed at scale — search engines, large-scale IR, quick baselines where crude matching is fine. Lemmatization when the actual word meaning matters downstream — feeding into embeddings, chatbots, anything sensitive to semantic accuracy.
Bag of Words: represent each document as a vector of raw word counts (or just presence/absence), order thrown away entirely. Simple, but treats every word as equally important — "the" ends up with a huge count and drowns out words that actually distinguish documents.
TF-IDF fixes that by weighting each word by how discriminative it is:
Why it's better than BoW: a word appearing in almost every document (low IDF) gets downweighted automatically — no need to hand-pick a stopword list. A word that's rare across the corpus but frequent in one document (high TF, high IDF) gets boosted — it's genuinely informative for that document.
Still a bag — no word order, no semantics, and vectors are high-dimensional and sparse (mostly zeros). That gap is exactly what embeddings solve next.
Why embeddings capture meaning: built on the distributional hypothesis — "you shall know a word by the company it keeps." Words that show up in similar contexts get pushed to similar points in vector space during training. No one tells the model "king" and "queen" are related — it falls out of the fact that both words appear near similar neighboring words across millions of sentences.
Result: dense, low-dimensional vectors (e.g. 100–300 numbers per word, vs tens of thousands for BoW) where distance and direction mean something — the classic example being vector("king") − vector("man") + vector("woman") ≈ vector("queen").
GloVe takes a different route to the same kind of vectors: instead of predicting words from context (a neural, local-window approach like Word2Vec), it builds a global word-word co-occurrence matrix over the whole corpus and factorizes it directly. Both land on dense vectors that capture similar relationships — Word2Vec learns them predictively and locally, GloVe learns them from global counts.
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import f1_score
X_train, X_test, y_train, y_test = train_test_split(
texts, labels, test_size=0.2, random_state=42
)
vectorizer = TfidfVectorizer(stop_words="english", max_features=5000)
X_train_tfidf = vectorizer.fit_transform(X_train) # fit only on train
X_test_tfidf = vectorizer.transform(X_test) # reuse the same vocab
clf = LogisticRegression(max_iter=1000)
clf.fit(X_train_tfidf, y_train)
preds = clf.predict(X_test_tfidf)
print(f1_score(y_test, preds, average="weighted"))