Introduction to Text Mining and NLP
CSC_52082_EP · Year 1 · Period 2
Contents
- Introduction and overview
- 0. Review: vector spaces and probabilities
- 1. The text processing pipeline
- 2. Bag of words, TF-IDF and BM25
- 3. Text classification
- 4. Word embeddings
- 5. Topic models
- 6. Sequences and relations: NER, HMM, CRF, relation extraction
- 7. Transformers for NLP
- 8. Industrial text mining
- 9. Research at DaSciM (Vazirgiannis, Buscaldi)
- Exercises
- Projects and assessment
- References
Introduction and overview
| Module | Introduction to Text Mining and NLP |
| Code | CSC_52082_EP |
| Team and workload | Head (“responsable” on the 2026–2027 sheet): Michalis Vazirgiannis (École Polytechnique) · teaching team listed on the sheet: Davide Buscaldi (Université Sorbonne Paris Nord) · 36 h in class = 18 h of lectures + 18 h of small classes (the split displayed on the sheet; its in-person total line is empty) · 4.5 ECTS · from raw text to transformers: tokenization, TF-IDF and BM25, embeddings, topic models, sequences, fine-tuning, industrial text mining — and the research of the course instructors. Extended in M2 by the Large Language Models module. |
| Period | Autumn semester · period 2 (from 04/01/2027 to 19/03/2027) · X3A session “Introduction à la Fouille de Textes et au Traitement Automatique des Langues (NLP)” (code X3A VE1); course taught in English |
| Assessment | Not displayed: the 2026–2027 sheet gives no assessment modality, and its LLGA section shows no resit rule or pass threshold (those displayed belong to other programs) |
| Status in the program | Mandatory |
Audience: an engineer who has already scraped a CSV of reviews / tickets and fitted a scikit-learn classifier — and wants to know why BM25 beats TF-IDF, or why a BERT fine-tune blows up the vocab. Empirical first: F1 dropping after aggressive stemming; a tokenizer that multiplies FR tokens vs EN — then we name BoW, embeddings, transformers.
From tokenization to industrial text mining (TF-IDF/BM25, embeddings, topics, NER, fine-tuning). Mandatory P2 foundation for the M2 module Large Language Models.
What you will be able to do
- Build a complete text processing pipeline, from raw corpus to usable features.
- Represent documents with bag of words, TF-IDF and BM25, build a search engine on these foundations (inverted index) and evaluate its rankings (MAP, nDCG).
- Train and interpret word embeddings.
- Infer latent topics in a corpus with topic models.
- Classify texts, from Naive Bayes to transformer fine-tuning.
- Label sequences (named entity recognition) with HMMs and CRFs, and extract relations between entities as knowledge-graph triples.
- Fine-tune a transformer for a given NLP task, and assemble a minimal retrieval-augmented generation (RAG) pipeline.
- Build content-based and collaborative recommenders (matrix factorization), and use text features for click prediction and social media monitoring.
- Conduct a text mining project in an industrial context, from data to production deployment.
Official objectives and syllabus (2026-2027 catalog)
The official 2026–2027 sheet (scheduled session “Introduction à la Fouille de Textes et au Traitement Automatique des Langues (NLP)”, period X-3A-P2, from 04/01/2027 to 19/03/2027, taught in English) gives a short description and nothing else: no learning objectives, no prerequisites, no assessment modality and no programme are displayed.
The description observes that text is everywhere, and that text mining, natural language processing, information retrieval and recommendation systems matter greatly in applications and are in high demand at the large web companies and across industry; it singles out a strong current industrial interest in search, web marketing and advertising, social network analysis and recommendation systems (the sentence is truncated on the sheet), a large market that has made NLP a central and visible research field.
Volume: 18 h of lectures + 18 h of small classes. Since no syllabus is published, the table pairs each field and application named by the description with the sections that teach it.
| Field or application named by the description | Course section |
|---|---|
| Text mining | Chapters 1 (processing pipeline), 2 (bag of words, TF-IDF), 3 (classification), 5 (topic models), 8.1–8.4 (summarization, keywords, deduplication, ticket case) |
| Natural language processing | Chapters 1 (tokenization, n-gram language models), 4 (word embeddings), 6 (NER, HMM, CRF, relation extraction), 7 (transformers, fine-tuning) |
| Information retrieval; search | Chapter 2: TF-IDF and BM25 (Model 2.4), section 2.1 (inverted index, Definition 2.6; ranking evaluation, Definition 2.7, Example 2.8); dense retrieval with Sentence-BERT (ch. 7); a minimal RAG pipeline (section 7.4) |
| Recommendation systems | Section 8.5 (content-based and collaborative filtering, Definition 8.2; matrix factorization, Model 8.3, Example 8.4; hybrid and two-tower models) |
| Web marketing and advertising | Section 8.6 (sponsored search and click-through-rate prediction with hashed features, Definition 8.5) |
| Social network analysis | Section 8.6 (social media text, trend detection, Definition 8.6, Example 8.7); sentiment on microblogs in ch. 9 (self-study); the graph side is in the Graph ML module |
Our extensions, beyond the official description: the refresher chapter 0 (vector spaces and probabilities) and chapter 9 (the research work of Vazirgiannis and Buscaldi, self-study).
Where this course fits in the program
Mandatory module of period 2 of M1 (36 h: 18 h of lectures + 18 h of small classes, 4.5 ECTS), of which Michalis Vazirgiannis is the official head, with Davide Buscaldi in the teaching team. Official prerequisites: not displayed on the 2026–2027 sheet. It provides the vocabulary and reflexes without which the M2 large language models would remain black boxes.
- Prerequisites — Machine Learning (Naive Bayes for classification, the EM algorithm reused by topic models), and one Deep Learning course: Deep Learning in Period 1, or Deep Learning (P2) taken in parallel with this course. Students on the second route meet attention here first: section 7.1 states the transformer block in a self-contained page.
- Downstream modules — it directly prepares Large Language Models (M2), its natural extension; the same processing pipeline applied to speech is found in Speech Technology for Conversational AI (M2); and in the same period, the module Graph Machine and Deep Learning for Generative AI crosses over with this material (a document can become a graph of words, and its embeddings join node embeddings).
Course outline
- Review: vector spaces and probabilities — the two lenses of the course: representing a document as a vector, reasoning in terms of laws and likelihood.
- The text processing pipeline — segmentation, cleaning, normalization, subword tokenization and the first language model (n-grams with Kneser–Ney smoothing): the decisive craft before any model.
- Bag of words, TF-IDF and BM25 — the classical representations, the scoring function that powers information retrieval, the inverted index and ranking metrics.
- Text classification — from Naive Bayes to neural models: the reference task of NLP.
- Word embeddings — moving from counting to prediction: word vectors that carry meaning.
- Topic models — discovering the latent topics of a corpus, with EM as the engine.
- Sequences and relations: NER, HMM, CRF, relation extraction — labeling named entities with structured sequential models, training them, and linking entities into knowledge-graph triples.
- Transformers for NLP — the transformer block, pretrained families, fine-tuning, sentence embeddings, and a minimal RAG pipeline.
- Industrial text mining — summaries, keywords, deduplication, a ticket case study, recommendation systems, web advertising and social media analysis; volumes, annotation budgets, deployment and monitoring.
- Research at DaSciM (Vazirgiannis, Buscaldi) — a tour of the research work of Vazirgiannis and Buscaldi (self-study).
- Exercises, Projects and assessment and References — systematic training, project subjects with an exam and a rubric (proposals), and sources to go further.
Session plan
36 h in class = 12 sessions of 3 h. The volume is the one of the SynapseS 2026–2027 sheet, which displays 18 h of lectures + 18 h of small classes (it leaves its in-person total line empty); the sheet publishes no session-by-session programme, so the split below is our proposal for covering these notes in that time, each session pairing a lecture half with a small-class half. Level 1 = foundations (reviews, definitions, first worked examples), 2 = core methods and their derivations; the level never goes down from one session to the next.
| Session | Hours | Level | Content | Practice |
|---|---|---|---|---|
| 1 | 3 h | 1 | ch. 0 Review: vectors, probabilities, likelihood; ch. 1.1–1.2 Unicode normalization, subword tokenization (BPE, WordPiece, Unigram) | Ex. 2 |
| 2 | 3 h | 1 | ch. 1.3 Stopwords, n-grams, collocations, the Kneser–Ney language model and perplexity; ch. 2 Bag of words, TF-IDF, IDF as pointwise mutual information | Ex. 1 |
| 3 | 3 h | 1 | ch. 2 BM25, the hashing trick, document similarities; section 2.1 inverted index and ranking evaluation | Ex. 6, 11 |
| 4 | 3 h | 2 | ch. 3 Text classification: Naive Bayes, sparse logistic regression, calibration, imbalanced classes | Ex. 7 |
| 5 | 3 h | 2 | ch. 4 Word embeddings: skip-gram, negative sampling, GloVe, fastText; ch. 4.1 evaluation, SIF sentence embeddings, bias and the WEAT test | Ex. 3, 8 |
| 6 | 3 h | 2 | ch. 5 Topic models: LDA, collapsed Gibbs sampling, perplexity and coherence, LSA | Ex. 9 |
| 7 | 3 h | 2 | ch. 6.1 Sequence labeling with HMMs: forward-backward, Viterbi, Baum–Welch training | Ex. 4 |
| 8 | 3 h | 2 | ch. 6.2–6.4 CRF and its forward algorithm, BIO decoding and entity-level evaluation, relation extraction | lab: a NER tagger and a relation extractor (lab sheet in 6.4) |
| 9 | 3 h | 2 | ch. 7.1–7.3 The transformer block; BERT, GPT, T5 and few-shot prompting; fine-tuning protocol, Sentence-BERT, French models | lab: fine-tune a small encoder (lab sheet in 7.3); Ex. 10, 12 |
| 10 | 3 h | 2 | ch. 7.4 A minimal RAG pipeline; ch. 8.1–8.3 TextRank, keyword extraction, MinHash and LSH | Ex. 5 |
| 11 | 3 h | 2 | ch. 8.4 Ticket classification case study, serving and monitoring; ch. 8.5 Recommendation systems: content-based, collaborative filtering, matrix factorization | Ex. 13 |
| 12 | 3 h | 2 | ch. 8.6 Web advertising and social media analysis; the capstone and the Year 1 team project | Ex. 14 (capstone project) |
Read ahead for the Year 1 team project (one repository shared with Graph ML and Reinforcement Learning, see the box in 8.6): section 8.5 by project week 1, because subject Y1.3 needs it before session 11 teaches it; sections 6.4 and 7.4 as soon as the project starts if your subject is Y1.1.
Self-study, outside the 36 h (about 3 h in total): ch. 9 Research at DaSciM — graph-of-words and TW-IDF, degeneracy, word sense induction, legal retrieval, knowledge graphs (≈ 3 h).
How to study this module
- Work through the review section: dot products and conditional probabilities are used explicitly in every subsequent chapter.
- Once, build a bag of words and a TF-IDF score yourself on a mini-corpus: everything that follows is understood by contrast with this baseline.
- Before each model, write down on paper what it assumes (independence, word order, latency): this is what enables practical choices.
- Hand-label a few sentences for a NER task: you will measure the cost of annotation, the central constraint of industrial NLP.
- Read section 7.1 alongside the attention chapter of Deep Learning (ch. 6) or the transformer-block section of Deep Learning (P2) (ch. 0): the two reinforce each other.
- Redo the exercises of each section before moving on to the next; they prepare the graded assignments and the bridge to the LLMs module.
independent note NLP foundations up to attention: M2 LLMs continues; the graph of words crosses Graph ML. IR, monitoring, assistants, industrial classification — cases where a badly cut pipeline costs more than a bad model.
0. Review: vector spaces and probabilities
This course reads text through two lenses: as vectors (a document is a point, similarity is an angle) and as random sequences (a document is drawn from a distribution, and learning means maximizing a likelihood). The review below recalls the tools of both lenses and points to the chapter where each one is used.
L3 background used
- Vector spaces: basis, dimension, projection; cosine similarity \cos(u, v) = \frac{u^\top v}{\|u\|\,\|v\|} — invariant under dilation (\cos(u,v)=\cos(\lambda u, v) for \lambda > 0, which “cancels out” document lengths); the \ell_2 norm will be used to normalize TF-IDF vectors;
- Linear algebra: singular value decomposition \mathbf{X} \approx \mathbf{U}_k \Sigma_k \mathbf{V}_k^\top — the engine of LSA (ch. 5) and the direct cousin of PCA (Machine Learning module);
- Conditional probabilities and Bayes: \mathbb{P}(c \mid d) \propto \mathbb{P}(d \mid c)\,\mathbb{P}(c) — the Naive Bayes classifier (ch. 3) follows directly from it; the Dirichlet distribution \mathrm{Dir}(\alpha), conjugate of the multinomial — the foundation of LDA (ch. 5);
- Markov chains (Refresher Statistics 2.7, Reinforcement Learning ch. 0) and dynamic programming (Refresher CS 6.6): forward/backward and Viterbi (ch. 6) are Bellman recursions on a chain; TextRank (ch. 8) is a Markov chain raised to a power;
- Likelihood, MLE and EM: word2vec (ch. 4), LDA (ch. 5), Naive Bayes (ch. 3) and the Unigram tokenizer (ch. 1) are all likelihood maximizations — by SGD, Gibbs, direct counting or EM;
- Entropy and perplexity: for a language model, \mathrm{PPL} = \exp\!\big(-\tfrac{1}{N}\sum_{t} \log p(x_t \mid x_{<t})\big) — the universal quality measure of a generative model of text (M2 LLMs, ch. 3).
How to read this course Each chapter follows the same triptych:
- a representation of text (counts, weights, vectors, distributions, latent topics);
- a learning algorithm with its statistical justification;
- a quantified evaluation.
The thm/prop boxes contain the proven results; the proofs come at the end of each box. References of the form “module X, chapter N” point to the other courses of the master’s program.
The natural extension of this module is the M2 “Large Language Models” course, which picks up tokenization (ch. 1), BM25 (ch. 2), sentence embeddings (ch. 7) and transformers where we leave them.
1. The text processing pipeline
Concrete scene: 50,000 support tickets in French and English. A first pipeline lowercases the text, splits it into “words” with a regular expression and feeds TF-IDF features to a logistic regression: macro-F1 0.62. Without NFKC normalization, two encodings of “café” count as two different types; with aggressive stemming, “connection” and “connector” merge and the macro-F1 drops to 0.51. This chapter fixes the pipeline before the model.
What breaks Inconsistent train/prod tokenizer (ghost vocab); normalizing too late (Unicode duplicates); judging a classifier on overall accuracy when 3 classes dominate. All three sabotage an LLM fine-tune as much as a toy BoW.
Definition 1.1 — Standard pipeline Raw text → cleaning (HTML, case, accents, Unicode) → sentence segmentation → tokenization (splitting into units: words, subwords, characters) → lexical normalization (stemming raw root / lemmatization canonical form; stopwords) → representation (ch. 2, 4, 5) → model (ch. 3, 6, 7) → evaluation. Each stage destroys information; the engineer’s craft is deciding which information is expendable for the task at hand.
1.1. Unicode normalization and “clean” text
Definition 1.2 — Unicode normal forms The same glyph admits several encodings: “é” = one codepoint U+00E9 in NFC (canonical composition), but two (e + combining accent U+0301) in NFD. NFKC goes further: ligature “fi” → “fi”, digit “²” → “2”, full-width letters → ASCII. Two strings that are visually identical but distinct in bytes break counting, deduplication and search; so we normalize before anything else (in practice NFKC, or NFC if typography and units must be preserved).
- Case:
lower()merges “Polytechnique” and “polytechnique” but also the acronym and the common word; in French, keep the accents in lowercase (“élève” ≠ “eleve”); - Sentence segmentation: rules (punctuation + capital letter) or learning (Punkt, Kiss & Strunk 2006); real pitfalls: “M.”, “etc.”, German abbreviations (“z. B.”), period before a closing quote. Bad segmentation wrecks ch. 8 (extractive summarization: the sentence is the unit being selected);
- Stemming vs lemmatization: the stemmer (Porter, Snowball) cuts off suffixes by rules — fast, crude, suited to information retrieval; the lemmatizer uses a dictionary and morphology (“sont” → “être”) — slower, better for fine-grained analysis. In industry: stemmer for search, lemmatizer for analysis.
1.2. Subword tokenization: BPE, WordPiece, Unigram, SentencePiece
Why subwords Splitting on spaces works poorly: German compounds (“Donaudampfschifffahrt”), French elisions (“l’arbre”: 1 or 2 tokens?), some Asian languages write without spaces, and any closed vocabulary runs into unknown words (typos, neologisms, product references). Subword tokenizers learn, on the corpus, a fixed-size vocabulary (~32k-128k) whose concatenation reconstructs any string: frequent words = 1 token, rare words = a sequence of pieces.
Algorithm 1.3 — BPE (Byte Pair Encoding, Sennrich et al. 2016) Initial vocabulary: characters (or bytes). Iteratively: (1) count all pairs of adjacent symbols in the corpus (weighted by word frequencies); (2) merge the most frequent pair into a new symbol; (3) repeat until the vocabulary \mathcal{V} reaches the target size |\mathcal{V}|. The result is an ordered set of merge rules; tokenizing a new text = applying the merges in the learned order.
Example 1.4 — Step-by-step BPE training Mini-corpus (words, frequencies): base×5, bases×4, basse×3, basique×2. Initial alphabet: b, a, s, e, i, q, u. We write each word as a sequence of symbols and count adjacent pairs:
| Step | Most frequent pairs | Chosen merge |
|---|---|---|
| 1 | (b,a)=14, (a,s)=14, (s,e)=12, (e,s)=4, (s,s)=3, (s,i)=(i,q)=(q,u)=(u,e)=2 | ba (14; tie with (a,s), arbitrary choice) |
| 2 | (ba,s)=14, (s,e)=12, (e,s)=4, (s,s)=3, … | bas (14) |
| 3 | (bas,e)=9, (e,s)=4, (bas,s)=3, (s,e)=3, … | base (9) |
| 4 | (base,s)=4, (bas,s)=3, (s,e)=3, … | bases (4) |
| 5 | (bas,s)=3, (s,e)=3, … | bass (3) |
| 6 | (bass,e)=3, … | basse (3) |
After these six merges, base, bases and basse are whole tokens, while basique is still bas+i+q+u+e (four more merges would make it whole); an unexpected word like “basiste” breaks down into a known prefix (bas, or basi once more merges are learned) followed by single characters: never an unknown token, at worst a longer sequence. This is exactly the mechanism that equips GPT (byte-level BPE since GPT-2, 50k tokens; about 100k for GPT-4) and Llama 3 (byte-level BPE, 128k tokens) — developed in M2 LLMs, ch. 1.
Variants 1.5 — WordPiece (BERT), Unigram (T5), SentencePiece
WordPiece: the same merge loop, but a pair’s score is \frac{f(x,y)}{f(x)\,f(y)} — we merge the pair whose relative frequency increases the most, a proxy for the likelihood gain of a unigram model (justification: merging x,y replaces two symbols with one; the gain in bits is all the greater as the collocation is over-represented relative to independence);
Unigram (Kudo, 2018): a generative model — a candidate vocabulary (characters + frequent substrings), each segment s has a probability p(s), a word is segmented by Viterbi by maximizing \sum_j \log p(s_j).
Training by EM: E — for each word, the posterior distribution over its segmentations (∝ product of the p(s_j), computable by a forward dynamic program); M — p(s) = normalized expected counts; then pruning of the segments that degrade the likelihood the least, until the target size |\mathcal{V}|.
Unlike BPE, the segmentation is probabilistic and admits several analyses (subword regularization);
SentencePiece: a language-independent layer that treats the sentence as a raw stream of Unicode characters (with an optional fallback to bytes for unseen characters), the space becoming a “▁” symbol; no pre-tokenization on spaces — essential for languages without spaces and for multilingual settings. It is the tokenizer of T5 (a Unigram model) and of Llama 1 and 2 (a 32k BPE model); Llama 3 moved to the 128k byte-level BPE of Example 1.4.
import re
from collections import Counter
# --- Toy BPE: learning merges on the mini-corpus of example 1.4 ---
words = {"b a s e": 5, "b a s e s": 4, "b a s s e": 3, "b a s i q u e": 2}
merges = []
for _ in range(8):
pairs = Counter()
for w, f in words.items():
sym = w.split()
for pair in zip(sym, sym[1:]):
pairs[pair] += f
if not pairs:
break
best = max(pairs, key=pairs.get) # most frequent adjacent pair
merges.append(best)
big = " ".join(best)
words = {re.sub(r"(?<!\S)" + re.escape(big) + r"(?!\S)", "".join(best), w): f
for w, f in words.items()}
print("merges:", merges[:6])
# tokenize a new word = replay the merges in the learned order
def encode(word, merges):
sym = list(word)
for a, b in merges:
i, out = 0, []
while i < len(sym):
if i + 1 < len(sym) and (sym[i], sym[i+1]) == (a, b):
out.append(a + b); i += 2
else:
out.append(sym[i]); i += 1
sym = out
return sym
print(encode("basiste", merges))1.3. Stopwords, n-grams, collocations and n-gram language models
- Stopwords: to be removed for classical text mining (they saturate the BoW); to be kept for transformers — negation (“ne…pas”) and syntax matter. The decision must be justified by the task, not by habit;
- N-grams: sequences of n tokens; “New York” (bigram) ≠ “New” + “York”; in classification, moving from unigrams to bigrams captures compositional polarity (“pas cher”); cost: the vocabulary explodes (potentially |\mathcal{V}|^n) — hence
ngram_range=(1,2)andmin_dfin the code of ch. 3; - Collocations: bigrams whose frequency exceeds what independence predicts, measured by mutual information \mathrm{PMI}(x,y) = \log \frac{P(x,y)}{P(x)P(y)} — a criterion reused as-is in ch. 2 to justify IDF, and in ch. 5 for topic coherence.
Counting n-grams also gives the first language model: a probability for the next word given the previous ones. It is the ancestor of the LLMs of M2, it is still the language model of classical speech recognizers (Speech Technology, ch. 1), and its central difficulty — how much probability to leave for what was never seen — never goes away.
Model 1.6 — Bigram language model with interpolated Kneser–Ney smoothing A bigram model factorizes a sentence as p(w_{1:N})=\prod_{t} p(w_t\mid w_{t-1}). The maximum-likelihood estimate c(v,w)/c(v) gives probability zero to every bigram absent from the training corpus, so a single unseen bigram makes a whole test sentence impossible.
Interpolated Kneser–Ney (Kneser & Ney, 1995; Chen & Goodman, 1999) subtracts a fixed discount D \in (0, 1], typically 0.75, from every seen count and gives the freed mass to a continuation distribution:
Key result — interpolated Kneser–Ney bigram p_{\mathrm{KN}}(w\mid v)=\frac{\max\big(c(v,w)-D,\,0\big)}{c(v)}+\lambda(v)\,p_{\mathrm{cont}}(w), \qquad \lambda(v)=\frac{D\,N_{1+}(v\,\bullet)}{c(v)}, \qquad p_{\mathrm{cont}}(w)=\frac{N_{1+}(\bullet\,w)}{N_{1+}(\bullet\,\bullet)}
Here N_{1+}(v\,\bullet) is the number of distinct words seen after v, N_{1+}(\bullet\,w) the number of distinct words seen before w, and N_{1+}(\bullet\,\bullet) the number of distinct bigram types.
Reading: the continuation probability asks “in how many contexts does w appear?”, not “how often?”. “Francisco” is frequent but appears almost only after “San”, so it receives little continuation mass and is not predicted after unrelated words.
Proof. The model is a distribution. Let c(v) count the occurrences of v followed by a word. Every seen bigram has c(v,w)\ge 1\ge D, so \sum_w \frac{\max\big(c(v,w)-D,\,0\big)}{c(v)}=\frac{c(v)-D\,N_{1+}(v\,\bullet)}{c(v)}=1-\lambda(v), and the second term adds \lambda(v)\sum_w p_{\mathrm{cont}}(w)=\lambda(v). The total is 1. ∎
Example — counts from a training corpus:
- “the” is followed by a word 10 times, by 4 distinct words, 3 times by “cat” and never by “dog”;
- the corpus has 200 bigram types; “cat” follows 5 distinct words and “dog” follows 20;
- with D=0.75, the back-off weight is \lambda(\text{the})=0.75\cdot 4/10=0.3.
Then p_{\mathrm{KN}}(\text{cat}\mid\text{the})=\frac{2.25}{10}+0.3\cdot\frac{5}{200}=0.2325, \qquad p_{\mathrm{KN}}(\text{dog}\mid\text{the})=0+0.3\cdot\frac{20}{200}=0.03 .
Definition 1.7 — Perplexity On a held-out text of N tokens, \mathrm{PPL}=\exp\Big(-\frac1N\sum_{t=1}^{N}\log p(w_t\mid w_{<t})\Big), the exponential of the average negative log-likelihood (the cross-entropy, in nats).
It reads as an effective branching factor: a model that is uniform over \mathcal{V} has perplexity |\mathcal{V}|, and a model with perplexity 50 is as uncertain, on average, as a uniform choice among 50 words. Lower is better. Two perplexities are comparable only with the same tokenizer and the same test text: a subword model and a word model do not count the same N.
Example: four test tokens predicted with probabilities 0.25, 0.5, 0.1 and 0.2 have a mean log-probability of -1.498, so \mathrm{PPL}=e^{1.498}\approx 4.47 .
2. Bag of words, TF-IDF and BM25
Most models cannot read strings: they need vectors. This chapter turns each document into a vector of word counts, reweights the counts so that informative words dominate (TF-IDF), and derives BM25, the scoring function that still powers search engines.
Definition 2.1 — Bag of words (BoW) A document = a vector of counts over the vocabulary \mathcal{V} (order lost): d \in \mathbb{N}^{|\mathcal{V}|}. Documents × terms matrix \mathbf{X} \in \mathbb{N}^{n \times |\mathcal{V}|} — extremely sparse (a few hundred non-zeros per document across tens of thousands of columns; sparse representation, cf. Refresher CS).
Definition 2.2 — TF-IDF
Key result — TF-IDF weight \mathrm{tfidf}(t, d) = \mathrm{tf}(t, d) \times \underbrace{\log\frac{n}{\mathrm{df}(t)}}_{\mathrm{idf}(t)},
\mathrm{tf} = frequency of the term in the document, \mathrm{df} = number of documents containing the term, n = number of documents. It penalizes omnipresent terms and rewards discriminative ones.
L2 weighting: we post-normalize \tilde d = d / \|d\|_2, so that the dot product is directly the cosine similarity — this is what TfidfVectorizer does by default.
Proposition 2.3 — IDF = pointwise mutual information Let us choose a document D uniformly among the n, and let T denote the event “D contains the term t”.
Then for any document d containing t: \mathrm{PMI}(T\,;D=d) \;=\; \log\frac{\mathbb{P}(T,\,D=d)}{\mathbb{P}(T)\,\mathbb{P}(D=d)} \;=\; \log\frac{n}{\mathrm{df}(t)} \;=\; \mathrm{idf}(t).
In other words: IDF is exactly the pointwise mutual information between “the event t occurs” and the choice of this particular document. A term present everywhere identifies no document (zero PMI); a rare term strongly identifies the documents that contain it.
Proof. \mathbb{P}(D=d)=1/n and \mathbb{P}(T)=\mathrm{df}(t)/n, so \mathbb{P}(T,D=d)=\frac{1}{n}\,\mathbf{1}[t\in d]. Substituting: \mathrm{PMI} = \log\frac{\mathbf{1}[t\in d]/n}{(\mathrm{df}/n)(1/n)} = \log\frac{n\,\mathbf{1}[t\in d]}{\mathrm{df}}, which equals \mathrm{idf}(t) if t \in d (and -\infty otherwise). ∎
Common variants (all useful in practice)
- Sublinear TF: 1+\log \mathrm{tf} — “3 occurrences do not signal the topic 3× more than a single one”;
- Boolean TF: \mathbf{1}[\mathrm{tf}>0] — robust to highly repetitive documents (spam, bots);
- Smoothed IDF: \log\frac{1+n}{1+\mathrm{df}}+1 (the scikit-learn variant) — avoids blow-ups for \mathrm{df}=n;
- Composite schemes (SMART nomenclature): different weighting on the document side (e.g. L2 of log-tf × idf) and on the query side (e.g. plain cosine); the performance of a search engine is often tuned here, before any model.
Model 2.4 — BM25 (Robertson & Zaragoza) and its probabilistic reading A direct heir of probabilistic information retrieval (the Robertson–Sparck Jones 2-Poisson framework): a document is a mixture of “informative / non-informative” for the query.
The number of occurrences x of the term follows a Poisson law of intensity \mu_1 in the documents that are really about the term (“elite” documents) and of intensity \mu_0 \ll \mu_1 in the others, and relevance is only correlated with eliteness.
The resulting weight of x is the log-odds of relevance under this mixture: it is 0 at x = 0, increasing, and saturating as x grows (for a single pair of Poisson laws, the log-likelihood ratio \;x\log\frac{\mu_1}{\mu_0}-(\mu_1-\mu_0)\; would grow linearly; it is the mixture that bounds it).
BM25 approximates this shape:
Key result — the BM25 score \mathrm{BM25}(q,d)=\sum_{t\in q}\mathrm{idf}_{25}(t)\cdot \frac{\mathrm{tf}(t,d)\,(k_1+1)}{\mathrm{tf}(t,d)+k_1\!\left(1-b+b\,\frac{|d|}{\mathrm{avgdl}}\right)},\qquad \mathrm{idf}_{25}(t)=\log\frac{n-\mathrm{df}(t)+0.5}{\mathrm{df}(t)+0.5},
where |d| is the length of d in tokens, \mathrm{avgdl} the average length over the corpus, and k_1 \in [1.2, 2], b = 0.75 the usual defaults of the two tuning parameters.
Proof. Two limits to know by heart.
- Saturation: as \mathrm{tf}\to\infty, the factor tends to k_1+1 (bounded); at \mathrm{tf}=0 it equals 0.
- Half-saturation: it reaches half of its maximum when \mathrm{tf}=k_1(1-b+b|d|/\mathrm{avgdl}) — k_1 tunes the saturation speed, b the length penalty (b=0: no normalization; b=1: proportional).
These are exactly the two flaws of raw TF-IDF that BM25 corrects: unbounded linear growth on the tf side, and no handling of document length. ∎
| TF-IDF + cosine | BM25 | Set similarities | WMD | |
|---|---|---|---|---|
| Formula | \mathrm{tf}\cdot\mathrm{idf}, normalized dot product | probabilistic weighting, saturating tf | Jaccard \frac{|A\cap B|}{|A\cup B|} | transport distance between embeddings |
| What matters | weighted presence | presence and saturated density | set overlap | semantic alignment of words |
| Typical use | classification features (ch. 3) | search / retrieval (ch. 8, M2 ch. 7) | fast deduplication (ch. 8) | fine-grained similarity of short sentences |
| Cost | linear, sparse | linear, sparse | linear | linear program (Optimal Transport module) |
Proposition 2.5 — Hashing trick for giant vocabularies For huge or a priori unbounded |\mathcal{V}| (tweet streams, logs): hash each term h(t) \in \{1,\dots,D\} with a random sign s(t)\in\{\pm1\}, and set \tilde x_i = \sum_{t:\,h(t)=i} s(t)\,x_t. Then \mathbb{E}\,\langle \tilde x,\tilde y\rangle = \langle x,y\rangle — collisions cancel out in expectation.
Proof. We have \tilde x^\top\tilde y = \sum_{t,t'} s(t)s(t')\,x_t y_{t'}\,\mathbf{1}[h(t)=h(t')] and \mathbb{E}[s(t)s(t')]=\mathbf{1}[t=t'] (independent signs); what remains is \sum_t x_t y_t.
The standard deviation of the collision term decreases like 1/\sqrt{D}: with D\sim 2^{20}, the approximation is excellent for classification. ∎
Geometry of documents Each document becomes a point in \mathbb{R}^{|\mathcal{V}|}; we measure similarities (cosine), classify (Naive Bayes, SVM), cluster (k-means). The limitation of BoW: bag = no order and no semantics; “the cat eats the mouse” ≈ “the mouse eats the cat”.
Embeddings (ch. 4) and transformers (ch. 7) answer this. BM25 remains the baseline of any retrieval system — including RAG (M2 LLMs, ch. 7, where it serves as a reference point for dense retrievers).
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
from rank_bm25 import BM25Okapi
corpus = ["graphe de connaissances entreprise",
"réseau de neurones profond",
"graphe neuronal et réseau d'entreprise"]
X = TfidfVectorizer().fit_transform(corpus) # sparse matrix (3, vocabulary size), L2-normalized
print(cosine_similarity(X).round(2)) # docs 0 and 2 are the closest
toks = [d.split() for d in corpus]
bm25 = BM25Okapi(toks)
print(bm25.get_scores("réseau entreprise".split())) # BM25 score per document2.1. Search engines: inverted index and ranking evaluation
Information retrieval, named first among the applications of the official description, needs two more ingredients than a scoring function: a data structure that avoids scoring every document, and a way to measure whether the ranking is good.
Definition 2.6 — Inverted index For each term t, the index stores a posting list of pairs (\text{doc id}, \mathrm{tf}(t, d)) sorted by document id, together with \mathrm{df}(t) and the document lengths |d|.
A query q reads only the posting lists of its own terms, at cost \sum_{t \in q} \mathrm{df}(t) instead of n\,|q|; scores (TF-IDF, BM25) are accumulated per document and the top k kept in a heap.
Because the BM25 term factor is bounded by k_1 + 1 (Model 2.4), each term has an upper bound on its contribution, and dynamic pruning (MaxScore, WAND) skips documents that cannot enter the current top k.
Posting lists store the gaps between consecutive ids with variable-length codes; by Zipf’s law most terms are rare, so most lists are short.
Definition 2.7 — Ranking evaluation For a query with R relevant documents and a ranked list:
- Precision@k = \#\{\text{relevant in the top } k\}/k;
- Recall@k = \#\{\text{relevant in the top } k\}/R;
- average precision \mathrm{AP} = \frac{1}{R}\sum_{k\,:\,\text{doc at rank } k \text{ relevant}} \mathrm{P@}k, and MAP its mean over queries;
- reciprocal rank 1/\text{rank of the first relevant document} (MRR over queries).
With graded relevance \mathrm{rel}_i: \mathrm{DCG@}k = \sum_{i=1}^{k} \frac{2^{\mathrm{rel}_i} - 1}{\log_2(i + 1)}, \qquad \mathrm{nDCG@}k = \frac{\mathrm{DCG@}k}{\mathrm{IDCG@}k} \in [0, 1], where IDCG is the DCG of the ideal ordering. These are also the metrics of the retrievers of RAG systems (M2 LLMs, ch. 7) and of the recommenders of section 8.5.
Example 2.8 — Evaluating one ranked list A collection has R = 3 relevant documents for a query, and the engine returns five documents judged (relevant, not, relevant, not, relevant).
- Precision: \mathrm{P@}1 = 1, \mathrm{P@}3 = 2/3, \mathrm{P@}5 = 3/5.
- Average precision: \mathrm{AP} = \frac13\big(1 + \frac23 + \frac35\big) \approx 0.756 ; the reciprocal rank is 1.
- With graded judgments (3, 0, 2, 0, 1): \mathrm{DCG@}5 = \frac{7}{1} + \frac{3}{\log_2 4} + \frac{1}{\log_2 6} \approx 7 + 1.5 + 0.387 = 8.887 ;
- the ideal order (3, 2, 1, 0, 0) gives \mathrm{IDCG@}5 = 7 + \frac{3}{\log_2 3} + \frac{1}{2} \approx 9.393 .
So \mathrm{nDCG@}5 \approx 0.946.
Swapping the documents at ranks 2 and 3 gives (3, 2, 0, 0, 1) and \mathrm{nDCG@}5 \approx 9.280/9.393 \approx 0.988, the best single swap but not yet the ideal list: the grade-1 document at rank 5 must also move up to rank 3, which takes a second swap.
3. Text classification
Deciding which category a document belongs to — spam or not, which team should handle a ticket, positive or negative review — is the most common NLP task in industry. This chapter builds the two reference classifiers on the bag-of-words vectors of ch. 2, Naive Bayes and regularized logistic regression, together with the evaluation practice that goes with them.
Theorem 3.1 — Multinomial Naive Bayes, derived With the (false!) assumption of word independence given the class, \mathbb{P}(d\mid c)=\prod_{t\in d}\mathbb{P}(t\mid c)^{\mathrm{tf}(t,d)}, and Bayes: \hat c = \arg\max_c \Big[\log \mathbb{P}(c) + \sum_{t\in d}\mathrm{tf}(t,d)\log \mathbb{P}(t\mid c)\Big].
MLE of the parameters: \mathbb{P}(t\mid c)=\frac{n_{t,c}}{n_c}, where n_{t,c} is the number of occurrences of t in the documents of class c and n_c = \sum_t n_{t,c}, and \mathbb{P}(c)=\frac{N_c}{N} (N_c documents of class c among N).
Laplace smoothing: \mathbb{P}(t\mid c)=\frac{n_{t,c}+1}{n_c+|\mathcal{V}|}.
Proof.
- The MLE comes from maximizing the multinomial log-likelihood under the constraint \sum_t \mathbb{P}(t\mid c)=1 (Lagrange multipliers — relative counts).
- Problem: a word seen at test time but never in class c gives \log 0 = -\infty — a single rare word wipes out the whole class, and on small corpora this happens constantly.
- Laplace smoothing is the posterior mean under a uniform Dirichlet(1,\dots,1) prior: the posterior density \propto \prod_t \pi_t^{n_{t,c}}\cdot\prod_t\pi_t^{1-1} is that of a Dirichlet(n_{1,c}+1, \dots, n_{|\mathcal{V}|,c}+1), whose mean is \frac{n_{t,c}+1}{n_c+|\mathcal{V}|} (equivalently, it is the MAP under a Dirichlet(2,\dots,2) prior) — the exact Bayesian link of ch. 0. ∎
Why NB works despite an absurd assumption Conditional independence is massively violated (“New” predicts “York”). But the decision (argmax) is often correct even when the probabilities are badly calibrated: it is enough for the right candidate to win, not for its score to be right (the theory of Domingos & Pazzani). Hence NB’s status: bad probabilities, good baseline — always the first one in a text project, because it trains in seconds and sets the performance floor.
Sparse logistic regression: why it works in high dimension On TF-IDF, \#\text{features} \gg \#\text{docs} (10⁵ features for 10³ documents): the risk of overfitting seems maximal, yet the regularized linear model (L2, or L1 to select) generalizes very well. Three reasons:
- in high dimension the vectors are almost orthogonal — examples are naturally separable, and regularization suffices to pick a “sober” separator;
- IDF weighting has already done a large share of the statistical work (prop. 2.3);
- discriminative unigrams/bigrams are exactly the features a linear model weights well.
State of the art of the “classical” era until 2018 (Joulin et al., fastText); still formidable below 1,000 labeled examples.
- Calibration: when the probability is consumed (business thresholds, ticket routing), recalibrate — Platt (logistic regression on the scores) or isotonic; diagnostic: reliability curve (predicted vs observed reliability);
- Imbalanced classes: class weighting (
class_weight="balanced"), optimal threshold on the PR curve (not ROC); metric: macro-F1 (per-class average — every class counts equally) rather than accuracy (which flatters the majority); per-intent confusion matrix for chatbots; - Networks: sentence CNNs (Kim, 2014) and BiLSTMs over the word embeddings of ch. 4; then transformer fine-tuning (ch. 7). Empirical learning curves: linear+TF-IDF wins below ~10²-10³ examples, the transformer above;
- Zero-shot / few-shot with an LLM: zero labeled examples, or k examples in the prompt; the mechanism is stated in the box of section 7.2 and studied in depth in M2 LLMs (ch. 4.0, prompting and in-context learning). An excellent exploratory starting point and a help for labeling (active learning), rarely the final solution in production (cost, latency, confidentiality).
from sklearn.pipeline import make_pipeline
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.naive_bayes import MultinomialNB
from sklearn.datasets import fetch_20newsgroups
from sklearn.metrics import f1_score, classification_report
train = fetch_20newsgroups(subset="train", remove=("headers","footers","quotes"))
test = fetch_20newsgroups(subset="test", remove=("headers","footers","quotes"))
pipe = make_pipeline(TfidfVectorizer(min_df=3, ngram_range=(1,2), sublinear_tf=True),
LogisticRegression(C=10, max_iter=2000, class_weight="balanced"))
pipe.fit(train.data, train.target)
pred = pipe.predict(test.data)
print("macro-F1:", f1_score(test.target, pred, average="macro"))
print(classification_report(test.target, pred, labels=[0, 1, 2], # first 3 of the 20 classes
target_names=test.target_names[:3]))4. Word embeddings
In a bag of words, “car” and “automobile” are as different as “car” and “banana”: every word is its own orthogonal axis. Word embeddings replace these axes by dense vectors of a few hundred dimensions, learned from the contexts in which words appear, so that words used in similar contexts get similar vectors.
word2vec (Mikolov et al., 2013): distributional hypothesis “A word is characterized by the company it keeps” (Firth, 1957). Each word has two vectors: a center vector v_w, used when w sits at the current position, and a context vector u_c, used when it appears in the window of another word.
Skip-gram: for each position t with center word w_t, maximize the log-likelihood of the context words c within a window, \sum_{t}\sum_{c\in \mathrm{window}(t)} \log p(c\mid w_t), \qquad p(c\mid w)=\frac{\exp(u_c^\top v_w)}{\sum_{c'\in \mathcal{V}}\exp(u_{c'}^\top v_w)} — a softmax over the |\mathcal{V}| words of the vocabulary at each position: \mathcal{O}(|\mathcal{V}|) per example, prohibitive. CBOW: symmetric (predict the word from the average of its context).
Theorem 4.1 — Negative sampling: the derived loss For one observed pair (center w, context c), we draw k “negatives” n_1,\dots,n_k \sim p_n,\qquad p_n(x)\propto \mathrm{freq}(x)^{3/4} (the unigram distribution raised to the power 3/4) and replace the softmax with k+1 binary classifications “is this (center, word) pair a true context pair?”. The loss, to be minimized, is \mathcal{L}_{\mathrm{neg}} = -\log\sigma(u_c^\top v_w) - \sum_{i=1}^{k}\log\sigma(-u_{n_i}^\top v_w), at a cost of \mathcal{O}(k) instead of \mathcal{O}(|\mathcal{V}|). Averaged over the draws, the sum over negatives becomes k\,\mathbb{E}_{n\sim p_n}\big[\log\sigma(-u_n^\top v_w)\big].
The gradient in v_w: \nabla_{v_w}\mathcal{L}_{\mathrm{neg}} = -\big(1-\sigma(u_c^\top v_w)\big)\,u_c \;+\; \sum_{i=1}^{k}\sigma(u_{n_i}^\top v_w)\,u_{n_i}.
Reading: a descent step moves v_w toward the context vector u_c, with a force 1-\sigma that vanishes once the pair is well predicted, and away from each negative, with a force equal to its current score \sigma — a negative that the model wrongly scores high (often a semantically close word!) receives the largest correction.
After training, the center vectors are kept as the word embeddings. The rest of the chapter writes z_w for the embedding of w whatever the method (here z_w = v_w).
Theoretical interpretation: negative sampling is a form of NCE (noise contrastive estimation, Gutmann & Hyvärinen 2010; cf. Goldberg & Levy 2014).
Two settings that matter (and why)
- Frequency subsampling: very frequent words (“the”, “of”) drown the signal; they are discarded with probability p_{\mathrm{discard}}(w)=1-\sqrt{t/f(w)} (threshold t\sim10^{-5} to 10^{-3}) — the signal per pair stays intact and the computation is sped up;
- The 3/4 exponent: flattening the frequencies boosts rare negatives, which are the most informative ones (frequent negatives are trivial to repel). The same exponent reappears in the weighting function of GloVe below: an empirical compromise between signal and coverage.
GloVe (Pennington et al., 2014): least squares on cooccurrences Let X_{ij} be the number of cooccurrences (words i,j) in the corpus. GloVe factorizes \log X_{ij} with a weighted bilinear model: J=\sum_{i,j} f\!\left(X_{ij}\right)\big(z_i^\top \tilde z_j + b_i + \tilde b_j - \log X_{ij}\big)^2,\qquad f(x)=\min\!\Big[\big(x/x_{\max}\big)^{3/4},\,1\Big], where f cuts the weight of rare cooccurrences (noisy, possibly zero; one cannot take \log 0) and saturates for frequent ones. The biases b_i,\tilde b_j absorb the marginal frequencies.
Deep connection: skip-gram with negative sampling is an implicit factorization of a shifted PMI matrix (Levy & Goldberg, NeurIPS 2014). When the dot products are unconstrained, the optimum of the expected loss of Theorem 4.1 is u_c^\top v_w=\mathrm{PMI}(w,c)-\log k, where the PMI uses the noise distribution p_n(c) in place of the context frequency P(c). GloVe does it explicitly, and globally (the whole matrix at once) rather than locally (sampled windows).
fastText (Bojanowski et al., 2017): subwords A word = the sum of the vectors of its character n-grams (3 to 6): z_w = \sum_{g\in G_w} z_g. Consequences: an out-of-vocabulary word still receives a vector (the sum of its n-grams), and typos and rich morphology (German: compounds; French: conjugations) are absorbed. The same team shows that “fastText + bigrams” is a formidable classification baseline (cf. ch. 3).
4.1. Evaluating embeddings
- Lexical similarity: rate word pairs (SimLex-999, WordSim-353), correlate with the cosine — metric: Spearman correlation;
- Analogies: precision@1 on z_b - z_a + z_c \approx z_d excluding \{a,b,c\} from the search (the Mikolov protocol): “king − man + woman ≈ queen”. Caution: analogy accuracy is sensitive to word frequency;
- Downstream: the real evaluation is the final task (ch. 3).
Proposition 4.2 — SIF sentence embeddings (Arora et al., TACL 2017) Sentence = weighted average with a(w)=\frac{\alpha}{\alpha+p(w)}, where p(w) is the relative frequency of w in the corpus (an anti-frequency weight; \alpha\sim10^{-3}), then removal of the first principal component of the corpus: \bar v(S)=\frac{1}{|S|}\sum_{w\in S}\frac{\alpha}{\alpha+p(w)}\,z_w,\qquad v(S) = \bar v(S) - u_1 u_1^\top \bar v(S), with |S| the number of words of S and u_1 the first singular vector of the matrix whose rows are the \bar v(S) of all the sentences of the corpus.
Proof. Why remove u_1: in the generative model of Arora et al., each sentence is emitted around a “discourse vector” c_S, but a common vector c_0 (syntax, function words) biases all the sentences of the corpus — that is exactly the direction of greatest variance, hence u_1.
The orthogonal projection removes this shared nuisance term; on Semantic Textual Similarity (STS), this single removal gains several correlation points and makes this baseline “simple but hard to beat” without a trained encoder. It is the direct ancestor of SBERT embeddings (ch. 7). ∎
Bias in embeddings — the WEAT test (Caliskan et al., 2017) Two sets of target words X,Y (e.g. professions) and two attributes A,B (e.g. male/female first names). Association score s(w)=\frac{1}{|A|}\sum_{a\in A}\cos(z_w,z_a)-\frac{1}{|B|}\sum_{b\in B}\cos(z_w,z_b); test statistic t = \frac{\mathrm{mean}_{x\in X}\,s(x)-\mathrm{mean}_{y\in Y}\,s(y)} {\mathrm{sd}_{w\in X\cup Y}\,s(w)}, significance by permutations of the targets.
On GloVe/word2vec: scientific professions associate with the male attribute, artistic ones with the female — the corpus contains these stereotypes, and the geometry encodes them.
Mitigation (Bolukbasi et al., 2016): estimate the bias direction (PCA of the “he/she” pairs…), neutralize neutral words (remove their projection onto this direction) and equalize the pairs — we will see the “representation → bias → correction” pattern again in M2 (LLM safety, ch. 9 of the LLMs module).
Text ↔︎ graphs, the other LLGA bridge word2vec on random walks yields DeepWalk/node2vec (Graph ML module, ch. 3); conversely, a Graph of Words (nodes = words, edges = cooccurrence within a window) enables text mining with graph tools — this is a research axis of the course’s professor, detailed in ch. 9: the words ↔︎ graphs loop is a signature of the master’s program.
import gensim.downloader as api
wv = api.load("glove-wiki-gigaword-100") # pretrained embeddings
def analogy(a, b, c): # a - b + c ≈ ?
v = wv[a] - wv[b] + wv[c]
return wv.most_similar(v, topn=3)
print(analogy("king", "man", "woman"))
# quick evaluation: do the neighbors share the context?
for w in ["graph", "court", "ticket"]:
print(w, "->", [x for x, _ in wv.most_similar(w, topn=3)])5. Topic models
A corpus of thousands of documents is too large to read, but it is usually about a few dozen themes. Topic models recover these themes without any labels: each topic is a probability distribution over words, and each document a mixture of topics.
Model 5.1 — LDA (Blei, Ng & Jordan, 2003): the full generative model For each document d and each position i of the corpus: \theta_d \sim \mathrm{Dir}(\alpha_{\mathrm{LDA}}),\quad z_{d,i}\mid\theta_d \sim \theta_d,\quad \varphi_k\sim\mathrm{Dir}(\beta_{\mathrm{LDA}}),\quad w_{d,i}\mid z_{d,i},\varphi \sim \varphi_{z_{d,i}}. A document is a mixture of K topics; each word is drawn from the topic of its position. The hyperparameters carry the subscript LDA because \alpha_t and \beta_t denote the forward and backward variables of the HMM in ch. 6.
The likelihood p(\mathbf{w}) sums over all assignments z — intractable (K^{\#\mathrm{words}} terms): hence the variational Bayes inference (original paper) or Gibbs sampling (practical usage).
Connected reminders: EM from the ML module (variational inference is its Bayesian version); Markov chains (Refresher Statistics 2.7, Reinforcement Learning ch. 0 — the sampler is a chain whose stationary law is the posterior; geometric convergence under conditions).
Theorem 5.2 — Collapsed Gibbs sampling: the update equation By integrating out \theta,\varphi (Dirichlet–multinomial conjugacy), the law of an assignment z_i given everything else depends only on counts:
Key result — collapsed Gibbs update for LDA \mathbb{P}(z_i = k \mid z_{-i},\, w) \;\propto\; \underbrace{\frac{n_{k,w_i}^{-i}+\beta_{\mathrm{LDA}}}{n_k^{-i}+|\mathcal{V}|\beta_{\mathrm{LDA}}}}_{\text{does topic \(k\) like word \(w_i\)?}}\;\cdot\; \underbrace{\frac{n_{d,k}^{-i}+\alpha_{\mathrm{LDA}}}{n_d^{-i}+K\alpha_{\mathrm{LDA}}}}_{\text{does document \(d\) like topic \(k\)?}}
where n_{k,w} = number of times topic k has emitted w, n_{d,k} = topic k in d.
The exponent -i means “without the current position”.
Each z_i is sampled sequentially, over thousands of passes; the topics emerge by reinforcement (the rich-get-richer property of Dirichlets).
Proof. By conjugacy, the marginal of the corpus factorizes into multivariate beta functions: p(w,z\mid\alpha_{\mathrm{LDA}},\beta_{\mathrm{LDA}})=\prod_k \frac{B(n_{k,\cdot}+\beta_{\mathrm{LDA}})}{B(\beta_{\mathrm{LDA}})} \prod_d \frac{B(n_{d,\cdot}+\alpha_{\mathrm{LDA}})}{B(\alpha_{\mathrm{LDA}})}.
The conditional \mathbb{P}(z_i=k\mid\cdot) is the ratio p(w,z_i=k,z_{-i})/p(z_{-i},w_{-i}): all the factors not touching position i cancel out, by a property of beta ratios: \frac{B(u+e_k)}{B(u)}=\frac{u_k}{\sum_j u_j} . This leaves the product of the two predictive factors above. ∎
Choosing the hyperparameters and K Small \alpha_{\mathrm{LDA}} = pure documents (few topics per document); small \beta_{\mathrm{LDA}} = pure topics (distinctive words). The asymmetric version (a non-uniform vector \alpha_{\mathrm{LDA}}) lets a “noise” topic emerge. K is chosen by validation (held-out perplexity) or by coherence — see below; the two criteria do not rank models in the same order, an important result of text mining.
Evaluation 5.3 — Perplexity vs coherence Perplexity (held-out): \mathrm{PPL}=\exp\big(-\frac{1}{N_{\mathrm{test}}}\sum \log p(w_{\mathrm{test}})\big) with p(w\mid d)=\sum_k \theta_{d,k}\varphi_{k,w} — but it correlates poorly with human judgment (Chang et al., 2009: models with lower perplexity may produce less interpretable topics).
NPMI coherence: for the M most probable words of each topic, average \mathrm{NPMI}(u,v)=\frac{\log\dfrac{P(u,v)}{P(u)P(v)}}{-\log P(u,v)} \in [-1,1] over all pairs (probabilities estimated from document cooccurrences): it measures the actual collocation of the topic’s words — well correlated with humans.
The engineer’s rule: perplexity for predictive capacity, NPMI/C_v for interpretability.
Proposition 5.4 — LSA: truncated SVD as the PCA of text On the TF-IDF matrix \mathbf{X}: \mathbf{X}\approx\mathbf{U}_k\Sigma_k\mathbf{V}_k^\top ; each row of \mathbf{U}_k\Sigma_k gives one document’s coordinates in the latent space (the rows of \mathbf{X} are the documents). The k dimensions are the directions of maximal second moment — not of variance, since \mathbf{X} is not centered — and the coordinate columns are orthogonal, which makes them uncorrelated only after centering. The columns of \mathbf{V}_k give the topics as signed word loadings (unlike LDA’s distributions, they can be negative).
Key differences: LSA is linear, deterministic, fast; LDA is generative, models the counts, yields interpretable mixtures — but LSA captures weighted cooccurrence and is often sufficient for document similarity.
Link with PCA: PCA = SVD of the centered-scaled matrix (ML module); LSA = SVD of the TF-IDF matrix (no centering: the “mean” of text makes no sense).
- After LDA: BERTopic (embeddings + clustering + c-TF-IDF) for topics on contemporary corpora — consistent with the “embeddings, ch. 4” pipeline; for the industrial use of topics: monitoring, compliance, e-discovery, detection of emerging themes;
- Word Sense Induction: applying clustering to all the occurrences of a single word (BERT contexts) reveals its senses — the joint Vazirgiannis–Buscaldi paper of ch. 9 does exactly that, with mutual information maximization;
- Topic models on graphs (TopSBM, Gerlach et al., 2018): the idea extended to networks (see the Graph ML module).
6. Sequences and relations: NER, HMM, CRF, relation extraction
Some tasks need a label for every word rather than for the whole document: finding the names of persons and companies in a sentence, or the grammatical category of each word. Neighboring labels depend on each other (an entity that begins must continue), so this chapter uses models of the whole label sequence: hidden Markov models, then conditional random fields. It ends by linking the entities it finds into relations: the triples of a knowledge graph.
Definition 6.1 — Sequence labeling Assign a label to each token: POS (grammatical category) or NER (named entities: PER, ORG, LOC…) in BIO (“Begin/Inside/Outside”): “Kim” = B-PER, “Noel” = I-PER. NER is the gateway to building knowledge graphs (entity + relation extraction, section 6.4).
6.1. Hidden Markov models
HMM: forward, backward, Viterbi — the recurrences derived HMM: hidden states z_t (labels), emissions \mathbb{P}(w_t\mid z_t), transitions \mathbb{P}(z_t\mid z_{t-1}). Notation: \alpha_t(z)=\mathbb{P}(w_1,\dots,w_t,\,z_t=z) (forward) and \beta_t(z)=\mathbb{P}(w_{t+1},\dots,w_T\mid z_t=z) (backward): \alpha_t(z)=\mathbb{P}(w_t\mid z)\sum_{z'}\alpha_{t-1}(z')\,\mathbb{P}(z\mid z'), \qquad \beta_t(z)=\sum_{z'}\mathbb{P}(z'\mid z)\,\mathbb{P}(w_{t+1}\mid z')\,\beta_{t+1}(z').
Proof.
- Forward: condition on z_{t-1}. \alpha_t(z)=\sum_{z'}\mathbb{P}(w_{1:t},z_{t-1}=z',z_t=z) =\sum_{z'}\underbrace{\mathbb{P}(w_{1:t-1},z_{t-1}=z')}_{\alpha_{t-1}(z')} \,\mathbb{P}(z\mid z')\,\mathbb{P}(w_t\mid z) — by the Markov property, given z_{t-1} the pair (z_t, w_t) does not depend on the earlier observations.
- Backward: symmetric, conditioning on z_{t+1}.
Uses: likelihood \mathbb{P}(w_{1:T})=\sum_z \alpha_T(z); marginal posteriors \mathbb{P}(z_t\mid w)=\alpha_t(z)\beta_t(z)/\mathbb{P}(w) — this is the E-step of an EM to train the HMM (ML module). All in \mathcal{O}(T K^2). ∎
Algorithm 6.2 — Viterbi: optimality by substructure The most likely label path satisfies the recursion \delta_t(z) = \max_{z'} \big[\delta_{t-1}(z')\, \mathbb{P}(z \mid z')\big]\ \mathbb{P}(w_t \mid z),\qquad \delta_1(z)=\mathbb{P}(z)\mathbb{P}(w_1\mid z), and the optimal labeling is read off by backtracking the argmaxes — \mathcal{O}(T K^2) instead of \mathcal{O}(K^T).
Proof. Optimality: any optimal path arriving at (t,z) has an optimal prefix up to (t-1,z') — otherwise replacing the prefix with a better one increases the total probability (exchange argument: the future factors depend only on z, Markovian). So it suffices to follow the best predecessor: this is Bellman (RL module, ch. 2) on a Markov chain, with max instead of expectation. ∎
Algorithm 6.3 — Baum–Welch: training an HMM without labels When only the words are observed (no tagged corpus), the initial law \pi(z)=\mathbb{P}(z_1=z) and the tables \mathbb{P}(z\mid z') and \mathbb{P}(w\mid z) are learned by EM, with forward-backward as the E-step.
E-step — with the current parameters, compute \alpha_t, \beta_t and the likelihood \mathbb{P}(w_{1:T}), then the posterior of each state and of each transition: \gamma_t(z)=\frac{\alpha_t(z)\,\beta_t(z)}{\mathbb{P}(w_{1:T})}, \qquad \xi_t(z',z)=\frac{\alpha_{t-1}(z')\,\mathbb{P}(z\mid z')\,\mathbb{P}(w_t\mid z)\,\beta_t(z)}{\mathbb{P}(w_{1:T})}.
M-step — re-estimate each table by its expected relative counts: \hat\pi(z)=\gamma_1(z), \qquad \hat{\mathbb{P}}(z\mid z')=\frac{\sum_{t=2}^{T}\xi_t(z',z)}{\sum_{t=2}^{T}\gamma_{t-1}(z')}, \qquad \hat{\mathbb{P}}(w\mid z)=\frac{\sum_{t}\gamma_t(z)\,\mathbf{1}[w_t=w]}{\sum_{t}\gamma_t(z)}. With several sentences, the numerators and the denominators are summed over the sentences.
Proof. The M-step is the maximum-likelihood estimate of a tagged corpus — relative counts, as for Naive Bayes in Theorem 3.1 — with each hard count \mathbf{1}[z_t=z] replaced by its posterior expectation \gamma_t(z), and each transition count by \xi_t(z',z).
This is the EM recipe of the ML module: maximize the expected complete-data log-likelihood under the posterior of the hidden states. EM never decreases \mathbb{P}(w_{1:T}), but it reaches only a local maximum, so initialize from a small tagged corpus when one exists. Each iteration costs \mathcal{O}(TK^2). ∎
In practice, compute in log space or rescale \alpha_t at each step: the probabilities underflow after a few hundred words. The Speech Technology module (ch. 1) keeps z_t for the hidden states but writes x_t for the observed acoustic frames, a_{ij} for the transitions and b_j(x_t) for the emissions; the recursions are the same.
# Toy Viterbi: 2-state POS tagging (N noun, V verb), 4-word vocabulary
import numpy as np
W = ["le", "chat", "mange", "souris"]
p_z0 = np.array([.9, .1]) # P(z1)
A = np.array([[.8,.2],[.3,.7]]) # P(z_t | z_{t-1}) rows=prev
B = np.array([[.6,.3,.02,.08],
[.0,.02,.9,.08]]) # P(w | z) columns=words
seq = [0,1,2,3] # "le chat mange souris"
delta = B[:, seq[0]] * p_z0 # initialization
back = []
for w in seq[1:]:
m = delta[:, None] * A * B[:, w][None, :] # (prev, cur)
back.append(m.argmax(0)); delta = m.max(0)
z = [delta.argmax()]
for bp in reversed(back): z.append(bp[z[-1]])
print("labels:", [["N","V"][i] for i in reversed(z)])6.2. Conditional random fields
CRF (Lafferty et al., 2001): the discriminative approach An HMM models \mathbb{P}(w,z) jointly (generative); a CRF models \mathbb{P}(z\mid w) directly: \mathbb{P}(z\mid w)=\frac{\exp\big(\sum_{t}\theta^\top f(z_{t-1},z_t,w,t)\big)}{Z(w)}, \qquad \nabla_\theta \log\mathbb{P}(z^\star\mid w) = F(z^\star, w)-\mathbb{E}_{p(z\mid w)}\big[F(z, w)\big] (with z^\star the gold labeling and F(z, w) = \sum_t f(z_{t-1}, z_t, w, t) the summed features) — arbitrary features over the whole sequence: word identity, suffixes, capitalization, shape of the neighbor, hyphen, position…, plus transition features z_{t-1}\to z_t (whose learned weights make O→I-PER very unlikely: an entity start must be B).
Computing \log Z(w): the forward algorithm. The partition function sums over the K^T labelings, but it factorizes along the chain. Write the potential of one transition, with a start state z_0 before t=1, as \psi_t(z',z)=\exp\big(\theta^\top f(z',z,w,t)\big). Then \alpha_1(z)=\psi_1(z_0,z),\qquad \alpha_t(z)=\sum_{z'}\alpha_{t-1}(z')\,\psi_t(z',z),\qquad Z(w)=\sum_{z}\alpha_T(z), the HMM forward recursion with potentials in place of probabilities, in \mathcal{O}(TK^2). In practice it runs in log space, which avoids overflow: \log\alpha_t(z)=\operatorname{logsumexp}_{z'}\big[\log\alpha_{t-1}(z')+\theta^\top f(z',z,w,t)\big].
A backward pass \beta_t, defined in the same way from t=T down, gives the pairwise marginals \mathbb{P}(z_{t-1}=z',\,z_t=z\mid w)=\frac{\alpha_{t-1}(z')\,\psi_t(z',z)\,\beta_t(z)}{Z(w)}, from which the expectation \mathbb{E}_{p(z\mid w)}[F(z,w)] in the gradient is a sum over t, z' and z. Viterbi with the same potentials gives the best labeling.
The gain over HMM: no “waste” in modeling the words, rich features, arbitrary interactions — long the state of the art for NER (CoNLL-2003).
6.3. Decoding and evaluating entities
BIO decoding and entity-level NER evaluation Per-token predictions must be converted into spans: an entity = a B-X (I-X)* sequence. Entity evaluation (not token): an entity is correct iff both type and exact boundaries match; \mathrm{P}=\frac{\#\text{correct}}{\#\text{predicted}},\qquad \mathrm{R}=\frac{\#\text{correct}}{\#\text{gold}},\qquad F_1=\frac{2PR}{P+R}.
Token-level F1 (lenient about boundaries) usually overestimates entity-level F1, but not always. If the gold has a 10-token entity and a 1-token entity and the system finds only the short one, entity-level F1 is 0.67 while token-level F1 is 0.17. Always report entity-level F1 (the conlleval standard).
Industrial reflex: audit boundary errors (“Banque de France” truncated) separately from type errors (PER vs ORG).
Today Transformers label token by token (per-token softmax + BIO decoding; the head is often a linear-chain CRF or a simple softmax with BIO constraints in post-processing); the spaCy and transformers libraries (the ner pipeline) deliver the state of the art in a few lines. The lab of section 6.4 turns the tagged entities into relations that feed the GraphRAG lab of the Graph ML module (ch. 10); ch. 8 of this course assembles the full pipeline.
6.4. Relation extraction
NER finds the entities of a text; relation extraction decides which relation, if any, links two of them. The output is a set of triples (head, relation, tail): the edges of a knowledge graph, which the GraphRAG of the Graph ML module (ch. 10) then searches.
Definition 6.4 — Relation extraction Given a passage and two entity mentions e_1, e_2 found by NER, predict a relation r \in \mathcal{R}\cup\{\text{none}\} from a fixed inventory \mathcal{R} (place of birth, director, employer…).
Each positive decision yields a directed triple (e_1, r, e_2) — head, relation, tail — stored with its source passage. The triples (e_1, r, e_2) and (e_2, r, e_1) are different.
Example: “Marie Curie was born in Warsaw” gives (Marie Curie, place of birth, Warsaw).
Pipeline vs joint. A pipeline runs NER, then classifies every ordered pair of mentions of a sentence (m(m-1) candidates for m mentions). It is modular and easy to debug, but NER errors propagate: a missed entity is a missed triple.
A joint model predicts entities and relations together — by table filling, or by a sequence-to-sequence model that generates the linearized triples (REBEL, Huguet Cabot & Navigli, 2021). It removes the propagation but is harder to train and to audit.
Entity markers on an encoder (Baldini Soares et al., 2019; Zhong & Chen, 2021). Wrap the two mentions in marker tokens, “[E1] Marie Curie [/E1] was born in [E2] Warsaw [/E2]”, encode the sentence with a BERT-type model (ch. 7), concatenate the output vectors at the two opening markers and classify: p(r\mid s,e_1,e_2)=\mathrm{softmax}\big(W\,[h_{[E1]};\,h_{[E2]}]+b\big). Typed markers such as [E1:PER] add the NER type for free. Training follows the fine-tuning Protocol 7.1.
Distant supervision (Mintz et al., 2009): labels without annotators. Align a knowledge base such as Wikidata with the text, and label every sentence that mentions both entities of a known triple with that relation.
The labels are noisy in both directions: “Obama visited Hawaii” is labeled place of birth (a false positive), and true facts missing from the base become false negatives. Multi-instance learning (Riedel et al., 2010) only assumes that at least one sentence of each bag expresses the relation. A small hand-checked test set remains necessary.
Few-shot LLM extraction with a JSON schema. Prompt an instruction-tuned LLM with the relation inventory, two to five annotated examples and the passage (the mechanism of the few-shot box in section 7.2), and require an answer that validates against a schema:
{"type": "object", "required": ["triples"], "properties": {"triples": {"type": "array", "items": { "type": "object", "required": ["head", "relation", "tail", "evidence"], "properties": {"head": {"type": "string"}, "tail": {"type": "string"}, "relation": {"enum": ["place of birth", "director", "employer"]}, "evidence": {"type": "string"}}}}}}Validate every answer (re-ask on invalid JSON or an unknown relation) and drop the triples whose head or tail does not occur in the passage, a cheap guard against invented entities. No training data is needed, but every passage costs tokens; on a fixed schema with a few thousand labeled examples, a fine-tuned extractor is usually more accurate and far cheaper.
Definition 6.5 — Triple evaluation: strict and relaxed micro-F1 Pool the predicted and the gold triples of all documents (micro-averaging), then \mathrm{P}=\frac{\#\text{correct}}{\#\text{predicted}},\qquad \mathrm{R}=\frac{\#\text{correct}}{\#\text{gold}},\qquad F_1=\frac{2PR}{P+R}.
Under the strict criterion, a predicted triple is correct when its head, relation and tail all match a gold triple after light normalization (case, spaces, punctuation).
Under the relaxed criterion, the relation must match, and the head and the tail need only refer to the same entity: the same knowledge-base identifier after entity resolution, or one string contained in the other (“Curie” for “Marie Curie”).
The gap between the two scores measures boundary and alias errors, as the token/entity gap does for NER.
Example 6.6 — Scoring an extractor A passage has 4 gold triples. The extractor outputs 5: 2 match exactly, and 1 more matches after alias resolution (“M. Curie”).
- Strict: P=2/5=0.4, R=2/4=0.5, F_1\approx 0.444.
- Relaxed: P=3/5=0.6, R=3/4=0.75, F_1\approx 0.667.
The extractor finds the right facts more often than its strict score says: the next fix is entity resolution, not the relation classifier.
Lab sheet — session 8: from tagged entities to triples
- NER. Train a CRF with hand-crafted features (
sklearn-crfsuite) and run a pretrained transformer tagger on CoNLL-2003 (Tjong Kim Sang & De Meulder, 2003). Report entity-level F1 withseqeval, and sort 20 errors into boundary and type errors. - Relations. Take 200 development questions of 2WikiMultiHopQA (Ho et al., COLING 2020): each comes with its supporting Wikipedia paragraphs and gold evidence triples. Run the few-shot JSON extractor on the supporting paragraphs, restricted to the relations that occur in the evidences.
- Score. Report strict and relaxed triple micro-F1 against the evidence triples (Definition 6.5), and read 10 false positives.
- Export. Write the triples to a CSV file (head, relation, tail, source paragraph). It is the input of the GraphRAG lab of Graph ML (ch. 10); Exercise 12 adds a supervised extractor to this sheet.
7. Transformers for NLP
The models of the previous chapters give each word one vector whatever its context, and read a sentence through a short window at best. Transformers compute for each token a representation that depends on the whole sentence; pretrained once on a large corpus, they are then adapted to each task with little labeled data. This chapter states the architecture in one page, then applies it to text: pretrained families, fine-tuning, sentence embeddings and a first retrieval-augmented generator.
7.1. The transformer block in one page
The transformer block, self-contained Input. A sentence of n tokens becomes a matrix X \in \mathbb{R}^{n \times d}, one row per token: the token’s embedding (a row of a learned table with |\mathcal{V}| rows) plus a position vector. Positions are learned vectors (BERT) or fixed sinusoids, P_{t,2i}=\sin\big(t/10000^{2i/d}\big),\qquad P_{t,2i+1}=\cos\big(t/10000^{2i/d}\big). Without them, self-attention is permutation-equivariant: the sentence would be read as a bag of words again (ch. 2). Recent LLMs rotate queries and keys instead (RoPE).
One attention head. With W_Q, W_K, W_V \in \mathbb{R}^{d\times d_k}, Q=XW_Q,\quad K=XW_K,\quad V=XW_V,\qquad \mathrm{Attn}(X)=\mathrm{softmax}\Big(\frac{QK^\top}{\sqrt{d_k}}+M\Big)V, with the softmax taken row by row. Row i of the output is a weighted average of the value vectors, weighted by how well query i matches each key. The scale \sqrt{d_k} keeps the logits of order one: if the entries of a query and a key are independent, with mean zero and variance one, their dot product has variance d_k.
Mask. With M=0 every token sees the whole sentence (encoder, BERT). The causal mask, M_{ij}=-\infty for j>i and 0 otherwise, lets token i see only the past (decoder, GPT), so the model learns to predict every next token of a sentence in one pass.
Multi-head. h heads with d_k = d/h run in parallel; their outputs are concatenated and mixed by W_O\in\mathbb{R}^{d\times d}: \mathrm{MHA}(X)=\big[\mathrm{head}_1,\dots,\mathrm{head}_h\big]\,W_O . Each head can follow a different relation (syntax, coreference, position).
Block. Each of the L blocks adds two sublayers to a residual stream, with a LayerNorm before each (pre-LN, the modern choice; BERT and the original transformer normalize after the sum): H=X+\mathrm{MHA}\big(\mathrm{LN}(X)\big),\qquad Y=H+\mathrm{FFN}\big(\mathrm{LN}(H)\big). The feed-forward network acts on each token separately, \mathrm{FFN}(x)=W_2\,\mathrm{GELU}(W_1x+b_1)+b_2, with a hidden width of about 4d. The residual sums let the gradient cross dozens of blocks.
Families and cost. Encoder only (BERT, no mask) for understanding tasks; decoder only (GPT, causal mask) for generation; encoder–decoder (T5), where the decoder’s queries also attend to the encoder’s outputs (cross-attention). Attention costs \mathcal{O}(n^2 d) per layer and the FFN \mathcal{O}(n d^2): long inputs are expensive, which is one reason why RAG (section 7.4) sends only a few retrieved passages to the model.
Going deeper. Proofs and a PyTorch block: Deep Learning, ch. 6. The same block from the systems side: Deep Learning (P2), ch. 0. Modern variants (RoPE, GQA, MoE): M2 LLMs, ch. 2.
7.2. Pretrained families: BERT, GPT, T5
BERT (Devlin et al., 2019): MLM + NSP in detail Bidirectional encoder, pretrained on two tasks.
- Masked LM: 15 % of tokens drawn; among them 80 % replaced by
[MASK], 10 % by a random word, 10 % unchanged; the original token is predicted (output: per-position classification). The mixing avoids a pretraining/fine-tuning mismatch (the model will never see[MASK]downstream again) and forces a robust representation. - Next Sentence Prediction: classify whether two sentences follow each other (the pair
[CLS]A[SEP]B) — a weak task, abandoned by RoBERTa in favor of more data.
Result: [CLS] = sentence representation; one model, dozens of tasks via a simple head layer.
GPT (Radford et al.) and T5 (Raffel et al., 2019) GPT: causal decoder — \mathcal{L}=-\sum_t\log p(x_t\mid x_{<t}), pretraining = predicting the next token; generative by construction, zero task-specific architecture (this is the family extended in M2).
T5: everything in text-to-text — span corruption (masking continuous fragments and regenerating them), every task (classification, translation, QA…) formulated as textual input→output; it unifies MLM and CLM.
Zero- and few-shot classification with a causal LM A decoder can classify text without any gradient step.
- Write a prompt: an instruction, k labeled examples (“Review: … Sentiment: positive”), then the test input followed by “Sentiment:”. With k=0 it is zero-shot.
- Score each label by the model’s probability of the label’s tokens after the prompt, and take the argmax — or let the model generate and parse its answer.
- Accuracy moves by several points with the choice and the order of the examples and with the label words. Dividing each label’s probability by its probability after a content-free input such as “N/A” removes part of this bias (Zhao et al., 2021).
- Compare with fine-tuning (Protocol 7.1) on the same test split before choosing (ch. 3).
- M2 LLMs (ch. 4.0) studies in-context learning in depth; Graph ML (ch. 10.2) applies the same mechanism to graphs written as text.
7.3. Fine-tuning and sentence embeddings
Protocol 7.1 — Full fine-tuning (the stable recipe)
- Head: a linear layer \mathrm{Linear}(d, K) on
[CLS](classification) or per position (NER, POS); - Optimizer: AdamW, learning rate \{2\times10^{-5}, 3\times10^{-5}, 5\times10^{-5}\} — a short grid, fine-tuning is sensitive but flat around the optimum; linear warmup for 10 % then linear decay;
- Epochs: 2 to 4 (beyond that: brutal overfitting on small corpora — watch the dev set); batch 16-32;
- Small corpora (<1k): freeze the lower layers, layer-wise decay (layer-wise lr decay), or adapters/LoRA (added parameters << 1 %; the mathematics in Deep Learning 7.3, the LLM practice in M2 LLMs 4.3);
- Cost: distillation (DistilBERT: 40 % fewer parameters, 60 % faster at inference, ~97 % of the performance of BERT), int8 quantization — the performance/cost trade-off is an engineering criterion, deepened in M2 (LLMs 4.3 for distillation and 6.4 for quantization; ML Ops).
Lab sheet — session 9: fine-tuning a small encoder by hand The loop below implements Protocol 7.1 without the Trainer class, so that every step is visible: tokenization, padding per batch, AdamW with 10 % warmup and linear decay, gradient clipping, evaluation on the dev set after each epoch, and keeping the best epoch. It fine-tunes DistilBERT (66M parameters) on SST-2 (binary sentiment) on a free GPU tier.
- Run it, and plot the dev macro-F1 per epoch for two learning rates of the protocol’s grid.
- Swap in a French encoder and dataset (CamemBERT on the Allociné reviews, for instance): change only the model name, the dataset and its text column (
review), and keep the loop as it is. - Exercise 10 then compares this model with the TF-IDF baselines of ch. 3 as the training set grows.
import torch
from torch.utils.data import DataLoader
from datasets import load_dataset
from transformers import (AutoTokenizer, AutoModelForSequenceClassification,
DataCollatorWithPadding, get_linear_schedule_with_warmup)
from sklearn.metrics import f1_score
name = "distilbert-base-uncased" # small encoder, 66M parameters
tok = AutoTokenizer.from_pretrained(name)
ds = load_dataset("nyu-mll/glue", "sst2") # columns: sentence, label, idx
ds = ds.map(lambda b: tok(b["sentence"], truncation=True, max_length=128),
batched=True, remove_columns=["sentence", "idx"])
collate = DataCollatorWithPadding(tok) # pads per batch, renames label -> labels
train = DataLoader(ds["train"], batch_size=32, shuffle=True, collate_fn=collate)
dev = DataLoader(ds["validation"], batch_size=64, collate_fn=collate)
torch.manual_seed(0)
device = "cuda" if torch.cuda.is_available() else "cpu"
model = AutoModelForSequenceClassification.from_pretrained(name, num_labels=2).to(device)
epochs = 3
opt = torch.optim.AdamW(model.parameters(), lr=2e-5, weight_decay=0.01)
steps = epochs * len(train)
sched = get_linear_schedule_with_warmup(opt, int(0.1 * steps), steps) # 10 % warmup, linear decay
def evaluate():
model.eval(); ys, ps = [], []
with torch.no_grad():
for b in dev:
b = {k: v.to(device) for k, v in b.items()}
ps += model(**b).logits.argmax(-1).tolist(); ys += b["labels"].tolist()
model.train()
return f1_score(ys, ps, average="macro")
best = 0.0
for epoch in range(epochs):
for b in train:
b = {k: v.to(device) for k, v in b.items()}
loss = model(**b).loss # cross-entropy of the head on [CLS]
loss.backward()
torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)
opt.step(); sched.step(); opt.zero_grad()
f1 = evaluate()
print(f"epoch {epoch}: dev macro-F1 {f1:.3f}")
if f1 > best: # keep the best epoch only
best = f1; model.save_pretrained("best"); tok.save_pretrained("best")Sentence-BERT (Reimers & Gurevych, 2019): siamese training objectives To encode sentences in a comparable space (search, clustering, RAG), two copies of BERT with shared weights encode the two sentences of a pair, and mean pooling of the output vectors gives u and v. The paper uses the objective that fits the data at hand:
- classification on NLI pairs (SNLI and MultiNLI: entailment, contradiction, neutral), for its main models, with a cross-entropy on \hat y=\mathrm{softmax}\big(W_t\,[u;\,v;\,|u-v|]\big);
- regression on STS pairs: the cosine of u and v is fitted to the gold similarity score with a squared loss;
- triplet, for its Wikipedia-sections data: with an anchor a, a positive p and a negative n, \mathcal{L}=\max\big(0,\ d(a,p)-d(a,n)+\varepsilon\big).
Proof. Triplet loss. If the margin is respected (d(a,p)+\varepsilon\le d(a,n)), the loss is zero: nothing to learn. Otherwise, the gradient \nabla = \nabla d(a,p)-\nabla d(a,n) pulls the anchor toward the positive and pushes it away from the negative; with this hinge loss, the size of the update does not depend on how much the margin is violated. ∎
Later sentence-transformers models are mostly trained on (query, positive) pairs with the multiple negatives ranking loss (Henderson et al., 2017). In a batch of B pairs (a_i, p_i), the other positives p_j, j\ne i, serve as negatives: \mathcal{L}=-\frac1B\sum_{i=1}^{B}\log\frac{\exp\big(\cos(a_i,p_i)/\tau\big)}{\sum_{j=1}^{B}\exp\big(\cos(a_i,p_j)/\tau\big)}, with a temperature \tau of about 0.05. These in-batch negatives are mostly random, hence easy. Hard negatives — passages that BM25 ranks high but that are not relevant — are mined and added explicitly, and they are what sharpens the space. Such embeddings index the corpora of RAG systems (section 7.4; M2 LLMs ch. 7 for dense retrieval and reranking).
French: CamemBERT, FlauBERT, JuriBERT CamemBERT (Martin et al., 2020): RoBERTa retrained on 138 GB of French text — the reference French model; FlauBERT: an academic French BERT; JuriBERT (Douka et al., 2021 — research from this course, ch. 9): an adaptation to legal French, where the vocabulary (doctrine, grievances, appeal) confuses general models. Multilingual: mBERT, XLM-R (100+ languages, shared embeddings — at the price of capacity diluted per language).
from transformers import pipeline
classifier = pipeline("text-classification",
model="distilbert-base-uncased-finetuned-sst-2-english")
print(classifier("Graph RAG is a game changer for enterprise search."))
ner = pipeline("ner", aggregation_strategy="simple")
print(ner("Michalis Vazirgiannis teaches at Ecole Polytechnique."))
# sentence embeddings for RAG (cf. section 7.4 and M2 LLMs ch. 7)
from sentence_transformers import SentenceTransformer
enc = SentenceTransformer("paraphrase-multilingual-MiniLM-L12-v2")
print(enc.encode(["résumé automatique", "automatic summarization"]).shape)7.4. A minimal RAG pipeline
A language model answers from what it memorized during pretraining: it does not know a company’s documents, and it can state wrong facts fluently. Retrieval-augmented generation (RAG; Lewis et al., 2020) first retrieves passages from a corpus, then asks the model to answer from them. This section builds the minimal version from pieces of this course: BM25 (ch. 2), Sentence-BERT (7.3) and the ranking metrics of section 2.1.
M2 LLMs (ch. 7) goes in depth (reranking, evaluation at scale). The GraphRAG of Graph ML (ch. 10) and the LLM agents of Reinforcement Learning (ch. 7) start from this pipeline.
Definition 7.2 — Retrieve-then-read
- Chunking. Split each document into passages of about 100 to 300 words, overlapping by 10 to 20 % so that a sentence cut at a boundary survives whole in one chunk. Keep the document and the position of each chunk, for citations. Paragraphs or sections, when the documents have them, beat fixed windows.
- Indexing. Index the chunks twice: an inverted index scored by BM25 (Definition 2.6, Model 2.4), and a matrix of normalized Sentence-BERT vectors, in which the cosine is a dot product.
- Retrieval. For a query, take the top k chunks of each retriever (k from 3 to 10). Hybrid search fuses the two rankings by reciprocal rank fusion (Cormack et al., 2009), which needs no calibration between the two kinds of score: \mathrm{RRF}(c)=\sum_{r\,\in\,\{\text{sparse},\ \text{dense}\}}\frac{1}{60+\mathrm{rank}_r(c)}, where a chunk absent from a ranking gets no term from it.
- Reading. Put the k chunks, numbered, into a prompt that asks for an answer from these passages only, with citations [n], and for “not in the passages” when they do not contain it.
- Sparse or dense? BM25 wins on rare exact strings — product codes, names, article numbers, the tickets of 8.4 — that a sentence encoder blurs. Dense retrieval wins on paraphrases and synonyms (“car” for “automobile”, ch. 4), and across languages with a multilingual encoder. Hybrid fusion is the safe default; measure before choosing.
- How many chunks? A larger k raises recall but lengthens the prompt (cost, latency), and models use the middle of a long context less well than its ends.
Evaluation 7.3 — Retrieval recall and faithfulness Evaluate the two stages separately.
- Retrieval: on questions whose supporting passages are known, Recall@k (Definition 2.7) is the share of the supporting chunks found in the top k, and MRR scores the first one. A passage that is not retrieved cannot be used by any generator.
- Answer: exact match or token F1 against a reference answer, when one exists.
- Faithfulness spot-check: on a sample of 20 to 50 answers, check by hand that each claim is supported by a cited chunk. Report the share of supported claims and the share of answers that cite nothing. An answer can be right but unsupported (memorized), or supported but wrong (a misleading chunk).
Example 7.4 — Recall@5 before and after fusion A two-hop question (“Where was the director of The Last Emperor born?”) has two supporting chunks: s_1 about the film, s_2 about its director.
- BM25 returns (s_1, a, b, c, d): Recall@5 is 1/2.
- The dense retriever returns (e, s_2, f, a, g), with s_1 only at rank 7: Recall@5 is 1/2.
- Fuse the top 7 of each list, in which only a and s_1 appear twice. The four best RRF scores are a:\ \tfrac{1}{62}+\tfrac{1}{64}\approx 0.0318,\qquad s_1:\ \tfrac{1}{61}+\tfrac{1}{67}\approx 0.0313,\qquad e:\ \tfrac{1}{61}\approx 0.0164,\qquad s_2:\ \tfrac{1}{62}\approx 0.0161, and every other chunk scores less.
Both supporting chunks are in the fused top 4, so the fused Recall@5 is 1: each retriever found the hop that the other missed.
import numpy as np
from rank_bm25 import BM25Okapi
from sentence_transformers import SentenceTransformer
corpus = ["..."] # list of document strings
def chunk(text, size=150, overlap=30): # windows of `size` words
w = text.split()
return [" ".join(w[i:i + size]) for i in range(0, max(len(w) - overlap, 1), size - overlap)]
chunks = [c for doc in corpus for c in chunk(doc)]
bm25 = BM25Okapi([c.lower().split() for c in chunks]) # sparse index (ch. 2)
enc = SentenceTransformer("paraphrase-multilingual-MiniLM-L12-v2")
E = enc.encode(chunks, normalize_embeddings=True) # dense index (7.3)
def retrieve(q, k=5):
sparse = np.argsort(-bm25.get_scores(q.lower().split()))[:k]
dense = np.argsort(-(E @ enc.encode(q, normalize_embeddings=True)))[:k]
fused = {}
for ranking in (sparse, dense): # reciprocal rank fusion
for r, i in enumerate(ranking):
fused[int(i)] = fused.get(int(i), 0.0) + 1 / (60 + r + 1)
return sorted(fused, key=fused.get, reverse=True)[:k]
def prompt(q, ids):
passages = "\n".join(f"[{n + 1}] {chunks[i]}" for n, i in enumerate(ids))
return ("Answer the question using only the passages below, and cite them as [n]. "
"If they do not contain the answer, say so.\n\n"
f"{passages}\n\nQuestion: {q}\nAnswer:")
def recall_at_k(ids, gold): # gold: set of supporting chunk ids
return len(set(ids) & gold) / len(gold)8. Industrial text mining
This chapter assembles the building blocks of ch. 1-7 into products: summaries, keywords, deduplication, ticket classification — the real workloads of NLP in industry, together with their engineering pitfalls.
8.1. TextRank: extractive summarization by PageRank
TextRank (Mihalcea & Tarau, 2004)
- Sentence → node; similarity between sentences S_i,S_j (overlap of filtered words): w_{ij}=\frac{|\{t\in S_i\}\cap\{t\in S_j\}|}{\log|S_i|+\log|S_j|} (|S_i| = number of words of S_i);
- symmetric weights → random walk;
- score: \mathrm{TR}(u)=\frac{\alpha}{N}+(1-\alpha)\sum_{v\to u}\frac{w_{vu}}{\sum_{v'}w_{vv'}}\,\mathrm{TR}(v), with the teleport probability \alpha\approx 0.15 (the paper writes d=1-\alpha=0.85, the damping factor; this page follows the PageRank convention of the Graph ML module), iterated from the uniform distribution (matrix power); geometric convergence to the unique stationary distribution (Perron–Frobenius: primitive stochastic matrix — a Markov chain reminder, ch. 0);
- the k top-scoring sentences = the summary (reordered chronologically).
The same algorithm on the graph of words (cooccurrence window) yields keyword extraction — “PageRank for text”.
Proof. The recursion reads \pi^{(k+1)}=\alpha\,\tfrac{\mathbb{1}}{N} +(1-\alpha)\,M\pi^{(k)} with M the column-stochastic weighted transition matrix: the map is a contraction in the \ell_1 norm (factor 1-\alpha<1), hence geometric convergence at rate 1-\alpha — typically settling in ~20-30 iterations for \alpha=0.15. ∎
8.2. Keyword extraction: RAKE, YAKE, KeyBERT
- RAKE (Rose et al., 2010): split on stopwords/punctuation → candidate phrases; a word’s score = \deg(w)/\mathrm{freq}(w) (degree in the cooccurrence graph within the candidates) + bigram frequency; a phrase’s score = the sum of its words. Fast, no external corpus, sensitive to stopwords;
- YAKE (Campos et al., 2020): unsupervised statistical features per word — frequency, dispersion of positions (a keyword appears everywhere), case (a capital letter mid-sentence = signal), redundancy of variants (edit distance) — an aggregated score, with left/right windows for context; robust and multilingual;
- KeyBERT (Grootendorst, 2020): extract candidates (n-grams), embed them and the document with a sentence encoder (Sentence-BERT, section 7.3; word vectors in ch. 4), keep the ones closest to the document — and diversify with MMR: \mathrm{MMR}=\arg\max_{c\,\in\,C\setminus S}\ \Big[\lambda\cos(c,d)-(1-\lambda)\max_{s\in S}\cos(c,s)\Big], which adds to the set S the candidate that is relevant and not very redundant; the same “embeddings + MMR” pattern returns in RAG (M2, ch. 7).
Extractive vs abstractive Extractive (TextRank; BERT: ranking sentences): attributable, hallucination-free, but redundant and choppy. Abstractive (generating): fluent, but requires a generative model and a faithfulness evaluation — this is the territory of M2 (LLMs ch. 7-8) and of the M2 instructor’s research (meeting summarization, cf. ch. 9). In industry: extractive remains the trusted solution when every sentence must be traceable to its source.
8.3. Deduplication at scale: MinHash + LSH
Proposition 8.1 — MinHash estimates the Jaccard similarity For uniform h,
Key result — MinHash collision probability \mathbb{P}\big(\min_{x\in A} h(x)=\min_{y\in B} h(y)\big) = J(A,B)=\frac{|A\cap B|}{|A\cup B|}.
Stacking m hashings → a signature \mathrm{sig}(A)\in\{0,\dots,2^{64}\}^m, and the collision frequency estimates J.
Proof. Let z be the element of A\cup B minimizing h (a.s. unique for uniform h). Then \min h(A)=\min h(B) iff z\in A\cap B.
Now z is uniform over A\cup B (permutation invariance of hashings), hence the probability \frac{|A\cap B|}{|A\cup B|}. ∎
LSH (Locality-Sensitive Hashing): bands and rows The signature is split into b bands of r rows; two documents are candidates if an entire band coincides. Detection probability: \mathbb{P}_{\mathrm{detect}}(J)=1-\big(1-J^{\,r}\big)^{b} — a steep sigmoid: with r=5,\ b=20: J=0.5\to 47\,\%, J=0.8\to 99.96\,\%.
The accepted/rejected boundary is “chosen” through (r,b) — this is the exact deduplication mechanism used on LLM pretraining corpora (M2 LLMs, ch. 3, where it is detailed with scale figures; lab implementation: datasketch).
8.4. Complete case: support ticket classification
Case study — 50,000 tickets, 40 categories, 3 languages
- Data: tickets (subject + body), heavily imbalanced categories (software ~30 %, licensing ~0.2 %); fragmentary annotation, noisy history;
- Preprocessing: NFKC (ch. 1), language detection, replacement of product references/numbers with generic tokens (
<REF>,<DATE>) — the highest-impact step: tickets are 30 % codes; - Baseline: TF-IDF (unigrams, sublinear) + weighted logistic regression → macro-F1 ≈ 0.72 — the bar to beat;
- Model: fine-tuned CamemBERT/multilingual (protocol 7.1) → macro-F1 ≈ 0.82; the main gain is on rare classes;
- Errors: confusion matrix — “login” vs “password” systematically confused (a fuzzy semantic boundary for humans too); solution: business-class merging or a rejection threshold (confidence below the threshold → human queue);
- Production: drift (new products → OOV): input distribution monitoring, quarterly retraining, active learning on rejected tickets (the most uncertain = the most informative).
Serving and monitoring the ticket classifier Steps 4–6 become a service only after three more decisions; the operations view is in MLOps (ch. 5).
- Packaging. Ship the tokenizer, the weights, the label map, the preprocessing rules of step 2 and the rejection threshold as one versioned artifact, so that training and serving cannot drift apart (the “ghost vocabulary” of ch. 1). Export it to ONNX or TorchScript, and record the dev macro-F1 of that exact artifact.
- Latency budget. Write the budget before choosing the model. If routing must answer within 100 ms at the 95th percentile on a CPU, measure each stage: tokenization takes about a millisecond, a distilled encoder on 128 tokens tens of milliseconds. Batching, int8 quantization or distillation (Protocol 7.1, point 5) buy the rest; the TF-IDF baseline answers in under a millisecond and stays as the fallback.
- Drift check. Each week, compare inputs and outputs with the training period: share of
<REF>tokens and of unknown product names, distribution of the predicted classes, mean confidence, share of tickets sent to the human queue. Alert when one of them moves beyond a set tolerance — for instance when the human-queue share doubles — and label a sample of the new tickets before retraining.
- Question answering and RAG: retriever (BM25 — the direct descendant of ch. 2 — and/or dense; hybrid search) + generator, built in section 7.4 and deepened in M2 LLMs (ch. 7); the capstone exports triples to the graph version of it (Graph ML, ch. 10);
- Monitoring: stream → MinHash dedup → topic model (ch. 5) → keywords (8.2) → classification → alerts;
- French and multilingual: corpora, multilingual models (mBERT, XLM-R); legal/French = specific difficulties — JuriBERT (ch. 9) answers on the model side, Buscaldi’s research (ch. 9) on the information retrieval side.
8.5. Recommendation systems
The official description names recommendation systems next to retrieval as a major industrial use. A recommender is a search engine without a query: it ranks items for a user, and text is one of its two sources of signal — the other being the behaviour of other users.
Definition 8.2 — Content-based and collaborative recommendation Users u, items i, and a very sparse interaction matrix R \in \mathbb{R}^{|U| \times |I|} (ratings, clicks, purchases).
Content-based: represent each item by a text vector x_i (TF-IDF of ch. 2, or a sentence embedding of ch. 7), build the user profile p_u = \sum_{i \in I_u} r_{ui}\, x_i \big/ \sum_{i \in I_u} r_{ui} from the items the user liked, and score \cos(p_u, x_i). It handles new items (their text exists before any click) but over-specializes.
Collaborative filtering ignores content and exploits the agreement between users: user-based neighbours predict \hat r_{ui} = \bar r_u + \frac{\sum_v \mathrm{sim}(u, v)(r_{vi} - \bar r_v)}{\sum_v |\mathrm{sim}(u, v)|} over the most similar users v who rated i (item-based neighbours are symmetric and more stable in practice).
Model 8.3 — Matrix factorization (Koren, Bell & Volinsky, 2009) Model \hat r_{ui} = \mu + b_u + b_i + p_u^\top q_i with latent factors p_u, q_i \in \mathbb{R}^k, and fit only the observed pairs \Omega: \min \sum_{(u,i) \in \Omega} \big(r_{ui} - \hat r_{ui}\big)^2 + \lambda\big(\|p_u\|^2 + \|q_i\|^2 + b_u^2 + b_i^2\big).
SGD update for one observed pair, with error e_{ui} = r_{ui} - \hat r_{ui}:
Key result — SGD step of matrix factorization p_u \leftarrow p_u + \eta\,(e_{ui}\, q_i - \lambda\, p_u), \qquad q_i \leftarrow q_i + \eta\,(e_{ui}\, p_u - \lambda\, q_i).
Proof. The loss of one pair is \ell = e_{ui}^2 + \lambda\|p_u\|^2 + \lambda\|q_i\|^2 (biases treated the same way). Since \partial \hat r_{ui}/\partial p_u = q_i, \nabla_{p_u}\ell = -2\,e_{ui}\,q_i + 2\lambda\,p_u, \qquad \nabla_{q_i}\ell = -2\,e_{ui}\,p_u + 2\lambda\,q_i (symmetrically); a gradient step with the factor 2 absorbed into \eta gives the updates.
ALS alternative: with Q fixed, the problem in p_u is a ridge regression on the items rated by u, solved in closed form p_u = (Q_u^\top Q_u + \lambda I)^{-1} Q_u^\top r_u — independently and in parallel for all users, then the roles swap. ∎
The model is the truncated SVD of LSA (ch. 5) adapted to a matrix with missing entries — a plain SVD would treat them as zeros. Implicit feedback (clicks) uses confidence weights on all entries (Hu, Koren & Volinsky, 2008).
Hybrid models tie the item factor to its text, q_i = W x_i + \varepsilon_i, which gives a factor to items nobody has interacted with yet; industrial two-tower retrievers push this further, with a user encoder and an item text encoder whose dot product is searched by approximate nearest neighbours.
Example 8.4 — One SGD step, computed Setting:
- k = 2, \mu = 3.5, b_u = 0.2, b_i = -0.1;
- p_u = (0.5, 0.1), q_i = (0.4, 0.3);
- an observed rating r_{ui} = 5, \eta = 0.1, \lambda = 0.05.
Prediction: p_u^\top q_i = 0.23, so \hat r_{ui} = 3.83 and e_{ui} = 1.17.
Updates (each using the old values): \begin{aligned} p_u &\leftarrow (0.5, 0.1) + 0.1\,(0.443, 0.346) = (0.544, 0.135),\\ q_i &\leftarrow (0.4, 0.3) + 0.1\,(0.565, 0.102) = (0.457, 0.310),\\ b_u &\leftarrow 0.2 + 0.1\,(1.17 - 0.01) = 0.316,\\ b_i &\leftarrow -0.1 + 0.1\,(1.17 + 0.005) \approx 0.018. \end{aligned}
New prediction: 3.5 + 0.316 + 0.018 + 0.290 \approx 4.12 — the error went from 1.17 to about 0.88 in one step.
Recommenders are evaluated offline with the ranking metrics of Definition 2.7 (Recall@k, nDCG@k) on a temporal split, watching the popularity bias; the user–item graph view (PinSage) is in the Graph ML module.
The Year 1 project Y1.3 (cold-start news recommendation on the MIND dataset, end-of-year projects) builds its text tower on Definition 8.2 and on the hybrid of Model 8.3: read this section by project week 1.
8.6. Web advertising and social media analysis
The other two industrial markets named by the description — web marketing/advertising and social network analysis — are text problems at their core: matching queries to ads, and reading short, noisy posts at scale.
Definition 8.5 — Sponsored search and click-through-rate prediction For a search query q, the engine retrieves the ads whose advertiser keywords match q — exact, phrase or broad match, the last one relying on query rewriting and embeddings (ch. 4, 7) — then ranks them by expected value \mathrm{bid} \times \hat p(\text{click} \mid q, \text{ad}, \text{context}).
The click model is typically a logistic regression \hat p = \sigma(w^\top \phi(q, \text{ad}, \text{user})) over billions of sparse features — query terms, ad terms and their crosses — mapped by the hashing trick (Proposition 2.5) and trained online with L1 regularization (FTRL-Proximal, McMahan et al., 2013).
Because \hat p multiplies a price, calibration (ch. 3) is a business requirement, not a refinement.
Example: ad A bids 2.0 with \hat p = 0.02, ad B bids 1.2 with \hat p = 0.05; expected values 0.04 and 0.06 — B is shown first despite the lower bid.
Definition 8.6 — Social media text and trend detection Posts are short, noisy and multilingual, full of hashtags, mentions, emojis and URLs. Normalization (ch. 1) replaces mentions and URLs by placeholders, splits hashtags (#GenoaFlood → “genoa flood”) and keeps emojis as tokens, since they carry sentiment.
Typical tasks are sentiment and emotion classification (ch. 3, or a tweet-pretrained encoder, ch. 7), stance and rumour detection, and event or trend detection: for a term t with counts c_t(\tau) per time window, flag a burst when z = \big(c_t(\tau) - \bar c_t\big)/s_t exceeds a threshold, with \bar c_t, s_t the mean and standard deviation over past windows (Poisson or Kleinberg burst models refine this for small counts).
Joining the text with the follower or retweet graph — communities, influence by PageRank — is social network analysis proper, developed in the Graph ML module; Buscaldi’s flood-tweet study (ch. 9) is a research instance.
Example 8.7 — Detecting a burst A hashtag was used 12, 9, 11, 10, 8, 10 times in the last six hours: mean \bar c = 10, sample variance \frac{4 + 1 + 1 + 0 + 4 + 0}{5} = 2, s \approx 1.41.
In the current hour it appears 31 times: z = 21 / 1.41 \approx 14.8, far above a threshold of 3 — a burst, which the monitoring pipeline then hands to keyword extraction (8.2) and classification to describe the event.
Capstone project Full monitoring pipeline: corpus of 500 articles → cleaning/tokenization → TF-IDF + LDA (topics) → fine-tuned supervised classification → NER + relation extraction (section 6.4) → export of the triples to the GraphRAG of the Graph ML module (ch. 10); evaluation at every stage (perplexity, coherence, macro-F1, entity-level F1, triple F1). It is Exercise 14, which we propose as the graded NLP deliverable.
Team project — Year 1 (proposal) We propose that Graph ML, Reinforcement Learning and this course share one team repository with three graded work packages: the graph package is the Graph ML team project, the RL package is the RL course project, and the NLP package is graded as this course’s capstone (Exercise 14). The subjects Y1.1–Y1.5 are on the end-of-year projects page; in each one, the NLP package is:
- Y1.1 — relation extraction (6.4) that feeds the GraphRAG of Graph ML ch. 10;
- Y1.2 — a parser of natural-language bookings (ch. 6 tagging, 7.3 fine-tuning);
- Y1.3 — the text tower of a news recommender (7.3, 8.5);
- Y1.4 — a text encoder aligned with molecule graphs (ch. 1 tokenization, 7.3);
- Y1.5 — a parser that turns questions about a scene into programs (ch. 6, 7.3).
The read-ahead line of the session plan says which sections to read before they are taught.
9. Research at DaSciM (Vazirgiannis, Buscaldi)
This module is backed by a laboratory (DaSciM, LIX, École Polytechnique — M. Vazirgiannis; LIPN, Sorbonne Paris Nord — D. Buscaldi): here is the actual research of the two instructors, each positioned with respect to the chapters of the course. A methodological lesson: every building block of the course (TF-IDF, clustering, graphs, embeddings) is a living research argument.
9.1. Michalis Vazirgiannis: text mining through graphs
Graph-of-Word and TW-IDF — F. Rousseau & M. Vazirgiannis, Graph-of-word and TW-IDF: new approach to ad hoc IR, CIKM 2013 (doi); overview: Graph of Words: Boosting Text Mining Tasks with Graphs, WWW 2017 (doi).
The idea: represent each document as a graph of words (nodes = terms, edges = cooccurrence within a window), and replace the tf(t,d) of TF-IDF (ch. 2) with the centrality of the term — the sum of the weights of its edges (weighted degree). The weight captures the local cohesion of the term in the discourse, not just its frequency; TW-IDF improves ad hoc retrieval on reference collections.
Position: directly extends ch. 2 — “counting becomes a graph score”; it is also the gateway to the Graph ML module (motifs, communities, k-cores).
Keywords by degeneracy — Main Core Retention on Graph-of-Words for Single-Document Keyword Extraction, ECIR 2015 (doi); Tixier, Malliaros & Vazirgiannis, A Graph Degeneracy-based Approach to Keyword Extraction, EMNLP 2016 (aclanthology). k-core decomposition of the graph-of-words: the main core (the maximal subgraph in which every word cooccurs with at least k neighbors) isolates the words that carry the document — an unsupervised, noise-robust method that rivals supervised approaches.
Position: the “graph” competitor of RAKE/YAKE in ch. 8; GoWvis demo (ACL 2016, aclanthology); real-time version for conversations: EACL 2017 (aclanthology).
Clustering — Giatsidis, Malliaros, Thilikos & Vazirgiannis, CoreCluster: A Degeneracy Based Graph Clustering Framework, AAAI 2014 (doi); Skianis, Rousseau & Vazirgiannis, Regularizing Text Categorization with Clusters of Words, EMNLP 2016 (aclanthology): we cluster the words (communities of the cooccurrence graph) and classify the documents on these clusters — a regularization in small dimension, interpretable, that foreshadows the “topics” logic of ch. 5; Position: ch. 3 and ch. 5 (clustering in the service of classification).
Word sense induction by neural clustering — Abdine, Kamal Eddine, Buscaldi & Vazirgiannis, Word Sense Induction with Hierarchical Clustering and Mutual Information Maximization, AI Open 2023 (arXiv:2210.05422) — a paper co-signed by the two instructors of the module: clustering the occurrences of a word by their contextual embeddings (BERT), with a mutual information criterion that is maximized — the exact dual of the “coherence” NPMI of ch. 5; Position: a merger of ch. 4 (embeddings) + ch. 5 (topics/clustering) + ch. 7 (BERT).
JuriBERT — Douka, Abdine, Vazirgiannis, El Hamdani & Restrepo Amariles, NLLP@EMNLP 2021 (arXiv:2110.01485): adapting the masked LM to legal French — cf. ch. 7; it paves the way for Buscaldi’s work in legal IR (below).
Open extension: TF-IDF × LLMs The TF-IDF of ch. 2 selects the terms that identify a document; a current research question is to weight in the same way the examples shown to an LLM (in-context learning, M2) — the loop “classical weights in the service of modern models” starts from TW-IDF. A possible capstone project topic: comparing TF-IDF, graph-based TF-IDF (TW-IDF) and dense embeddings for ordering the examples of a prompt.
9.2. Davide Buscaldi: QA, legal, sentiment, knowledge graphs
- Question answering by passage retrieval — Gómez-Soriano, Buscaldi et al., A Multilingual Question Answering System using an n-grams based Passage Retrieval Engine, IICAI 2005, and journal version (Answering questions with an n-gram based passage retrieval engine, JIIS 2011): ranking passages by query-passage n-gram overlap (the direct ancestor of the BM25 scoring of ch. 2), evaluated in multilingual settings (CLEF QA) and on spoken questions (QAST). Position: ch. 2 (n-grams, retrieval) and ch. 8 (the retriever before RAG — the “R” of RAG in M2, ch. 7, has this history).
- Legal information retrieval — Rosso, Correa & Buscaldi, Passage retrieval in legal texts, Journal of Logic and Algebraic Programming 2011 (doi): retrieving the relevant passages in court decisions — long texts, technical vocabulary, cross-references: exactly the “legal French” difficulties of ch. 8, on the retrieval side (JuriBERT, above, handles them on the model side).
- Sentiment for crisis management — Buscaldi & Hernandez-Farias, Sentiment Analysis on Microblogs for Natural Disasters Management: a Study on the 2014 Genoa Floodings, WWW Companion 2015 (doi): classifying the emotion of tweets during a flood — classification (ch. 3) on short, noisy text, with subtle classes (worry vs alert); natural follow-up: troll detection (TexTrolls, arXiv:1910.01340).
- Scientific knowledge graphs — Dessì, Osborne, Reforgiato Recupero, Buscaldi et al., AI-KG (ISWC 2020) and CS-KG (ISWC 2022): NLP pipelines (entity extraction, relation extraction — ch. 6) that turn millions of articles into a knowledge graph; Position: the exact outlet of the NER of ch. 6; these graphs feed the GraphRAG of the Graph ML module; the group’s LLM-KG article series connects the module to M2.
- In the LLM era: detection and memorization — with Liyanage & Nazarenko, a benchmark for detecting generated academic text (LREC 2022, arXiv:2202.02013); with Dentan, Shabou & Vanier: Predicting memorization within fine-tuned Large Language Models (ECAI 2025, arXiv:2409.18858) and the multilingual hallucination benchmark MUCH (LREC 2026, arXiv:2511.17081). Position: this research structures the “evaluation and safety” ch. 9 of the M2 LLMs module — the pedagogical continuity of the master’s program.
Common thread Vazirgiannis: text as a graph (ch. 2, 5, 8 → Graph ML, GraphRAG); Buscaldi: finding information and making it reliable (ch. 2, 3, 8 → RAG, M2 safety). Their joint paper (WSI) is the crossroads: contextual embeddings + clustering + mutual information — that is, ch. 4, 5 and 7 of this module.
Exercises
★ TF-IDF on paper, and IDF as PMI. On 3 given documents, compute by hand the TF-IDF matrix (natural log) of the reduced vocabulary, then the cosine similarity of each pair; verify with
TfidfVectorizer(watch out for L2 normalization). Then rederive Proposition 2.3 in the cases \mathrm{df}(t)=n (term everywhere) and \mathrm{df}(t)=1 (unique term), and deduce why L2 weighting alone is not enough to squash omnipresent words.Proof. Solution (method):
- count tf(t,d);
- df(t) over the 3 documents, then \mathrm{idf}=\log(3/\mathrm{df}) (0 for a term present everywhere — it disappears);
- multiply;
- normalize each row \tilde d=d/\|d\|_2, so that \cos(d_i,d_j)=\tilde d_i^\top \tilde d_j — this is what sklearn returns;
- classic pitfall: sklearn uses the smoothed IDF \log\frac{1+n}{1+\mathrm{df}}+1; pass
smooth_idf=Falseto recover the formula from the course.
IDF as PMI:
- \mathrm{df}=n \Rightarrow \mathrm{idf}=\log 1=0 — the term discriminates no document (zero PMI);
- \mathrm{df}=1 \Rightarrow \mathrm{idf}=\log n — the term perfectly identifies its document.
The L2 norm rescales documents, not columns: a frequent word keeps a high tf in all documents — only IDF (a per-column weight) squashes it. ∎
★ BPE. Redo example 1.4 with the corpus
stage×3,stages×2,stand×4 and list the 5 first merges; what happens if we addstand×40?Proof. Solution (start): initial pairs (s,t)=9, (t,a)=9, (a,g)=5, (a,n)=4… — the initial (s,t)/(t,a) tie is broken arbitrarily; with
stand×40, the pair (a,n) reaches 44 and stand becomes a token before the other roots — this is BPE’s lesson: the vocabulary encodes the corpus frequencies, not linguistics. ∎★ Analogies and bias. With pretrained embeddings (GloVe fr), test 10 analogies and measure the success rate; compute the WEAT statistic on two sets of professions × two lists of first names; implement neutralization (projection removal) and measure the effect on both scores.
★ Viterbi. Implement Viterbi for a toy POS tagger (2 labels, 5-word vocabulary); verify optimality against exhaustive enumeration; complexity \mathcal{O}(TK^2); modify the proof of Algorithm 6.2 for the case of paths with zero weights.
★ MinHash/LSH. For r=5, b=20, plot \mathbb{P}_{\mathrm{detect}}(J)=1-(1-J^r)^b and locate the “threshold”; which pair (r,b) at m=256 gives a threshold close to J=0.7?
Proof. Solution: the sigmoid goes from ~0.1 to ~0.9 between J\approx0.35 and J\approx0.65 — threshold \approx(1/b)^{1/r}\approx 0.55.
To target 0.7 one needs b \approx 0.7^{-r} with rb \le 256.
Then r=9, b=25 gives (1/25)^{1/9}\approx 0.70 with 225 of the 256 hashes (while r=8, b=32 uses all 256 but puts the threshold near 0.65).
Keep the rule of thumb: threshold \approx (1/b)^{1/r}, and a larger m makes the curve steeper. ∎
★★ BM25. Show that the tf factor of BM25 is increasing, bounded by k_1+1, and reaches half its value at \mathrm{tf}=k_1(1-b+b|d|/\mathrm{avgdl}); comment on the effect of b=0.9 on a corpus of documents with widely varying lengths.
Proof. Solution: set g(x)=\frac{x(k_1+1)}{x+c} with c=k_1(1-b+b|d|/\mathrm{avgdl})>0. Then g'(x)=\frac{c(k_1+1)}{(x+c)^2}>0, \qquad g\to k_1+1, \qquad g(x)=\frac{k_1+1}{2} \Leftrightarrow x=c .
High b: long documents see their c increase → slower saturation and a stronger penalty — suited when length signals richness; dangerous on heterogeneous mixtures of short/long documents. ∎
★★ Naive Bayes. Derive the MLE estimator of \mathbb{P}(t \mid c), show the problem of zero probabilities and justify Laplace smoothing as the posterior mean under Dirichlet(1,…,1) (theorem 3.1); implement and compare against
MultinomialNBon 20 Newsgroups; test the effect of α on calibration.Proof. Solution (core): Lagrangians → relative counts; a test word absent from the class → \log 0: the class is eliminated; the uniform prior adds a “pseudo-count” of 1 to every term → the smoothed formula; α>1 squashes differences (less overconfident), α<1 sharpens them (more discriminative, less calibrated). ∎
★★ Skip-gram. Write the negative-sampling loss of Theorem 4.1 for one pair (center w, context c) and k negatives n_1,\dots,n_k, \mathcal{L}_{\mathrm{neg}} = -\log \sigma(u_c^\top v_w) - \sum_{i=1}^{k}\log \sigma(-u_{n_i}^\top v_w), a loss to minimize (its negative is the objective that skip-gram maximizes). Compute the gradient in v_w and interpret it (who is attracted, who is repelled, with what force); implement on a small corpus and check that words with similar contexts have close embeddings.
Proof. Solution: since the derivative of -\log\sigma(x) is -(1-\sigma(x)) and that of -\log\sigma(-x) is \sigma(x), \nabla_{v_w}\mathcal{L}_{\mathrm{neg}}=-\big(1-\sigma(u_c^\top v_w)\big)\,u_c+\sum_{i=1}^{k}\sigma(u_{n_i}^\top v_w)\,u_{n_i} (Theorem 4.1). A descent step moves v_w toward u_c with weight 1-\sigma and away from each u_{n_i} with weight \sigma; check: cosine neighborhood of “graphe” ≈ {réseau, nœud, arête}. ∎
★★ LDA. Write the joint law of model 5.1, integrate out \theta_d and \varphi_k and recover the Gibbs equation of theorem 5.2 in the case K=2, \alpha_{\mathrm{LDA}}=\beta_{\mathrm{LDA}}=1 (the multivariate betas reduce to generalized factorials); verify numerically the “rich-get-richer” reinforcement on 200 words.
★★ Comparison. On a classification task from your own corpus: Naive Bayes / TF-IDF+SVM / fine-tuned CamemBERT — plot accuracy vs training size (50, 200, 1000, all) and comment on the crossover.
★★ Ranking metrics. For a query with R = 4 relevant documents, an engine returns the ten-document list (rel, rel, not, rel, not, not, not, rel, not, not). Compute P@5, Recall@5, AP and the reciprocal rank; then, with graded judgments (2, 3, 0, 1, 0, 0, 0, 2, 0, 0), compute nDCG@5. Which single swap of two documents increases nDCG@5 the most?
★★ Relation extraction, scored on 2WikiMultiHopQA. Extend the lab sheet of section 6.4. On the training split of 2WikiMultiHopQA (Ho et al., 2020), label by distant supervision: a sentence of a supporting paragraph that contains the head and the tail of an evidence triple gets its relation, other entity pairs get “none”. Fine-tune the entity-marker classifier on these examples (Protocol 7.1). Compare it with the few-shot JSON extractor on 200 development questions: strict and relaxed triple micro-F1 (Definition 6.5), per relation type. Finally, read 20 distant labels and count the wrong ones.
Proof. Solution (what to expect and to check):
- candidate pairs are taken within a sentence and in both orders, since a relation is directed;
- relaxed F1 exceeds strict F1 mostly through dates and aliases (“1934” vs “3 June 1934”, “Bertolucci” vs “Bernardo Bertolucci”): normalize dates before scoring;
- a distant label is wrong when a sentence names both entities without stating the relation (the director and an actor of the same film); evidence triples whose head and tail never share a sentence give no training example at all — report how many;
- report the number of training pairs, the seeds, and the gap between the two extractors with a bootstrap interval over questions. ∎
★★ Matrix factorization. Implement Model 8.3 with SGD on the MovieLens-100k ratings (temporal split), with k \in \{5, 20, 50\} and \lambda \in \{0.01, 0.1\}; report RMSE and Recall@10, compare with a content-based recommender on the movie text (TF-IDF profiles of the titles and genres of
u.item, or of plot summaries if you join them; Definition 8.2), and measure both on movies with fewer than five training ratings.★★★ Capstone (project). Carry out the project of ch. 8 (box in 8.6), with its relation stage built as in section 6.4; each stage must report ITS metric (NPMI coherence for LDA, macro-F1 for classification, entity-level F1 for NER, strict and relaxed triple F1 for relations) and an error analysis on 10 examples.
Projects and assessment
Official assessment: not displayed — the 2026–2027 sheet gives no assessment modality (see the fiche); the proposals below are ours. We propose Exercise 14, the capstone, as the graded NLP deliverable: taken with Graph ML and Reinforcement Learning, it is the NLP work package of the Year 1 team project (box in 8.6), and the course is used again by the Year 2 projects Y2.1 to Y2.4 (Y2.2 for tokenization only). The projects exercise the master objectives O3 (tokenization, transformers, fine-tuning, retrieval), O5 (text turned into a knowledge graph for GraphRAG) and O7 (pipelines measured at every stage).
Solo projects
- [Solo · ≈ 20 h] Tokenizer fertility in French and English. Does a subword tokenizer make French more expensive than English, and does the choice change accuracy?
- Implement: BPE and Unigram tokenizers trained with SentencePiece at 8k, 16k and 32k tokens on the French–English Europarl corpus (Koehn, 2005); fertility (tokens per word) on held-out parallel sentences, compared with the CamemBERT and GPT-2 tokenizers.
- Downstream: macro-F1 of TF-IDF + logistic regression on subword tokens, on the Allociné (French) and IMDb (English; Maas et al., 2011) sentiment reviews.
- Deliverables: code, a 4-page report, a 10-minute talk. Chapters: ch. 1, 3, 7.
- Success: a fertility table with bootstrap intervals, and an F1 effect stated against the seed-to-seed spread.
- [Solo · ≈ 25 h] Paper study: keywords from graphs of words. Reproduce Tixier, Malliaros & Vazirgiannis (EMNLP 2016), “A Graph Degeneracy-based Approach to Keyword Extraction”, and test it against the methods of ch. 8.
- Implement: graph-of-words with k-core and main-core extraction (ch. 9,
networkx), TextRank (8.1), RAKE, YAKE and KeyBERT with MMR (8.2). - Data: the Hulth (2003) Inspec abstracts with their gold keywords, one of the datasets of the paper.
- Deliverables: code, a 6-page report, a 10-minute talk. Chapters: ch. 2, 8, 9.
- Success: precision, recall and F1 within about 2 points of the paper’s figures, or a documented reason for the gap; a paired bootstrap between the best graph method and KeyBERT.
- Implement: graph-of-words with k-core and main-core extraction (ch. 9,
- [Solo · ≈ 20 h] Text-aware cold start on MovieLens. Can item text rescue the items that matrix factorization cannot score? This is the solo version of the text tower of Y1.3.
- Implement: Model 8.3 by SGD and by ALS on MovieLens-25M with a temporal split; a content-based recommender on the user tags (TF-IDF and Sentence-BERT profiles, Definition 8.2); the hybrid q_i = W x_i fitted by ridge regression on the warm items.
- Deliverables: code, a 4-page report. Chapters: ch. 2, 7, 8.
- Success: Recall@10 and nDCG@10 overall and on the items with fewer than 5 training ratings, where the hybrid should beat MF with a bootstrap interval that excludes zero.
Group projects
- [Group of 3 · ≈ 30 h each] From paragraphs to a knowledge graph. Which extractor gives the GraphRAG of Graph ML (ch. 10) the most useful graph, and at what cost? This is the NLP package of Y1.1.
- Member A — entities: a CRF with hand-crafted features vs a fine-tuned encoder on CoNLL-2003, scored by entity-level F1 (ch. 6).
- Member B — relations: the entity-marker classifier trained by distant supervision vs the few-shot JSON extractor, on the evidence triples of 2WikiMultiHopQA (Ho et al., 2020; section 6.4).
- Member C — graph and use: entity resolution, MinHash deduplication of near-identical paragraphs (8.3), export to the Graph ML GraphRAG lab, and answers to 200 questions compared with the RAG of section 7.4.
- Deliverables: one repository, a 6-page report, a 15-minute talk. Chapters: ch. 6, 7, 8.
- Success: a metric at every stage (entity F1, strict and relaxed triple F1, answer F1), and a GraphRAG gain over 7.4 on two-hop questions — or a documented reason why there is none.
- [Group of 3 · ≈ 30 h each] Paper study: hybrid French legal search on BSARD. Reproduce and extend Louis & Spanakis (ACL 2022), “A Statutory Article Retrieval Dataset in French”: more than 1,100 legal questions labeled by jurists with the relevant articles among about 22,600 Belgian law articles.
- Member A: a hand-built inverted index scored by BM25 (section 2.1), with k_1 and b tuned on the training questions.
- Member B: dense retrieval with a French sentence encoder, then fine-tuned on the training questions with in-batch negatives (7.3).
- Member C: reciprocal rank fusion (7.4); Recall@100, MAP and MRR (Definition 2.7); failure analysis on legal vocabulary (the legal-IR work of ch. 9). Optional: a LinUCB bandit (Reinforcement Learning, ch. 4) that chooses sparse or dense per query.
- Deliverables: code, a 6-page report, a 15-minute talk. Chapters: ch. 2, 7, 9.
- Success: BM25 within a few points of the paper’s BM25 baseline, and a paired test of fusion against each retriever.
Written exam (proposal)
Format: 2 hours, one handwritten A4 sheet allowed, no electronic devices; four questions, 20 points.
Question (5 points). (a) Name the two flaws of TF-IDF scoring that BM25 corrects, and the parameter that controls each. (b) In the RAG pipeline of section 7.4, give one query on which BM25 beats a Sentence-BERT retriever and one on which it loses, and say what reciprocal rank fusion does.
Expected: (a) unbounded growth in tf, replaced by saturation toward k_1+1 at a speed set by k_1; no length normalization, added by b (Model 2.4). (b) BM25 wins on rare exact strings (a product code, an article number) and loses on paraphrases (“car” for “automobile”). RRF sums reciprocal ranks, so a chunk found by either retriever can reach the fused top k without calibrating the two scores.
Question (5 points). A two-state HMM (N noun, V verb) has \pi=\begin{pmatrix}0.9\\0.1\end{pmatrix},\qquad \mathbb{P}(z_t\mid z_{t-1})=\begin{pmatrix}0.8&0.2\\0.3&0.7\end{pmatrix},\qquad \begin{array}{c|ccc} & \text{le} & \text{chat} & \text{mange}\\\hline \text{N} & 0.6 & 0.3 & 0.02\\ \text{V} & 0 & 0.02 & 0.9\end{array} (rows of the transition matrix: previous state N, then V; the table gives the emission probabilities). For “le chat mange”: (a) run Viterbi and give the best labeling and its joint probability; (b) run the forward algorithm and give the probability of the sentence; (c) deduce the posterior probability of the best labeling.
Expected: (a) the Viterbi scores for (N, V) are \delta_1=(0.54,\,0),\qquad \delta_2=(0.1296,\,0.00216),\qquad \delta_3=(0.00207,\,0.0233), so the best labeling is N N V, with joint probability 0.0233. (b) \alpha_3=(0.00209,\,0.0247), so the sentence has probability 0.0268. (c) The posterior is 0.0233/0.0268\approx 0.87.
Question (4 points). A relation extractor is run on two documents. Document A has 3 gold triples; the system predicts 2, both correct. Document B has 2 gold triples; the system predicts 4, one of them correct. (a) Compute the micro-averaged precision, recall and F1 (Definition 6.5). (b) Compute the average of the per-document F1 scores. (c) Which average would you report for a corpus with a few very long documents, and why?
Expected: (a) P=3/6=0.5, R=3/5=0.6, F_1\approx 0.545. (b) A has F1 0.8 and B has F1 0.333, so the average is about 0.567. (c) The micro average weights every triple equally, so long documents dominate it; it measures the graph that will actually be used. Report it, with per-document scores to show that short documents are not neglected.
Question (6 points). In skip-gram with negative sampling (Theorem 4.1), let \#(w,c) count the (center, context) pairs, \#(w) and \#(c) be its margins and |D| the number of pairs; the noise law is p_n(c)=\#(c)/|D|. As a function of x=u_c^\top v_w, the expected loss of the pair is \ell(x)=-\#(w,c)\,\log\sigma(x)-k\,\#(w)\,\frac{\#(c)}{|D|}\,\log\sigma(-x). Show that, for \#(w,c)>0 and x free, the minimum is reached at x^\star=\mathrm{PMI}(w,c)-\log k,\qquad \mathrm{PMI}(w,c)=\log\frac{\#(w,c)\,|D|}{\#(w)\,\#(c)}.
Expected: both terms are convex, since -\log\sigma(x)=\log(1+e^{-x}) and -\log\sigma(-x)=\log(1+e^{x}). Setting the derivative to zero gives \#(w,c)\,\big(1-\sigma(x)\big)=k\,\frac{\#(w)\,\#(c)}{|D|}\,\sigma(x)\iff e^{x}=\frac{\sigma(x)}{1-\sigma(x)}=\frac{\#(w,c)\,|D|}{k\,\#(w)\,\#(c)}, hence x^\star. Comment: the embeddings factorize a shifted PMI matrix (Levy & Goldberg, 2014), the link with GloVe in ch. 4.
Grading rubric (proposal)
| Criterion | Weight | What earns the marks |
|---|---|---|
| Framing and baselines | 15 % | A precise question; the simple baseline (TF-IDF + logistic regression, BM25, Naive Bayes) run first and reported |
| Method and correctness | 25 % | The methods of the chapters implemented correctly; code checked against toy cases (brute force, gradient checks) |
| Evaluation rigour | 25 % | The right metric at each stage (macro-F1, entity-level F1, triple F1, Recall@k, nDCG); clean splits (temporal when time matters); several seeds and bootstrap intervals |
| Error analysis and honesty | 15 % | At least 10 errors read per stage and sorted into types; negative results reported |
| Reproducibility | 10 % | One command rebuilds the tables; pinned versions, fixed seeds, a data-download script |
| Communication | 10 % | A 4–6 page report and a talk that state the question, the answer and its limits |
References
- Textbooks: D. Jurafsky, J. Martin, Speech and Language Processing, 3rd ed. (draft) — free online (the module’s textbook); C. Manning, H. Schütze, Foundations of Statistical Natural Language Processing, MIT Press, 1999 (HMM, CRF, collocations).
- Tokenization: R. Sennrich et al., Neural Machine Translation of Rare Words with Subword Units (BPE), ACL 2016; T. Kudo, J. Richardson, SentencePiece, EMNLP 2018; T. Kudo, Subword Regularization (Unigram), ACL 2018.
- Weighting and retrieval: S. Robertson, H. Zaragoza, The Probabilistic Relevance Framework: BM25 and Beyond, Foundations and Trends in IR, 2009 — doi; A. Broder, Min-wise Permutations (MinHash), 1998.
- Language models and HMMs (sections 1.3, 6.1): R. Kneser, H. Ney, “Improved backing-off for M-gram language modeling”, ICASSP 1995; S. F. Chen, J. Goodman, “An empirical study of smoothing techniques for language modeling”, Computer Speech & Language, 1999; L. R. Rabiner, “A Tutorial on Hidden Markov Models and Selected Applications in Speech Recognition”, Proceedings of the IEEE, 1989 (forward-backward, Baum–Welch).
- Embeddings: T. Mikolov et al., Efficient Estimation of Word Representations in Vector Space, 2013; Y. Goldberg, O. Levy, word2vec Explained: deriving Mikolov et al.’s negative-sampling word-embedding method, 2014; O. Levy, Y. Goldberg, Neural Word Embedding as Implicit Matrix Factorization, NeurIPS 2014 (the shifted-PMI result of ch. 4); J. Pennington et al., GloVe, EMNLP 2014; P. Bojanowski et al., Enriching Word Vectors with Subword Information (fastText), TACL 2017; S. Arora, Y. Liang, T. Ma, A Simple but Tough-to-Beat Baseline for Sentence Embeddings, TACL 2017; A. Caliskan et al., Semantics derived automatically from language corpora contain human-like biases, Science 2017; T. Bolukbasi et al., Man is to Computer Programmer as Woman is to Homemaker, NeurIPS 2016.
- Topic models: D. Blei, A. Ng, M. Jordan, Latent Dirichlet Allocation, JMLR 2003; T. Griffiths, M. Steyvers, Finding scientific topics, PNAS 2004 (Gibbs); J. Chang et al., Reading Tea Leaves: How Humans Interpret Topic Models, NeurIPS 2009.
- Classification, sequences, transformers: A. Joulin et al., Bag of Tricks for Efficient Text Classification, EACL 2017; Y. Kim, Convolutional Neural Networks for Sentence Classification, EMNLP 2014; J. Lafferty et al., Conditional Random Fields, ICML 2001; J. Devlin et al., BERT, NAACL 2019; Y. Liu et al., RoBERTa, 2019; C. Raffel et al., T5, JMLR 2020; N. Reimers, I. Gurevych, Sentence-BERT, EMNLP 2019; L. Martin et al., CamemBERT, ACL 2020; H. Le et al., FlauBERT, ACL 2020.
- Relation extraction (section 6.4): E. F. Tjong Kim Sang, F. De Meulder, “Introduction to the CoNLL-2003 Shared Task: Language-Independent Named Entity Recognition”, CoNLL 2003; M. Mintz, S. Bills, R. Snow, D. Jurafsky, “Distant supervision for relation extraction without labeled data”, ACL-IJCNLP 2009; S. Riedel, L. Yao, A. McCallum, “Modeling Relations and Their Mentions without Labeled Text”, ECML PKDD 2010; L. Baldini Soares, N. FitzGerald, J. Ling, T. Kwiatkowski, Matching the Blanks: Distributional Similarity for Relation Learning, ACL 2019; Z. Zhong, D. Chen, A Frustratingly Easy Approach for Entity and Relation Extraction, NAACL 2021; P.-L. Huguet Cabot, R. Navigli, “REBEL: Relation Extraction By End-to-end Language generation”, Findings of EMNLP 2021; X. Ho, A.-K. Duong Nguyen, S. Sugawara, A. Aizawa, Constructing A Multi-hop QA Dataset for Comprehensive Evaluation of Reasoning Steps (2WikiMultiHopQA), COLING 2020.
- Transformers, prompting and RAG (ch. 7): A. Vaswani et al., Attention Is All You Need, NeurIPS 2017; V. Sanh et al., DistilBERT, 2019; T. Brown et al., Language Models are Few-Shot Learners, NeurIPS 2020; T. Z. Zhao, E. Wallace, S. Feng, D. Klein, S. Singh, Calibrate Before Use: Improving Few-Shot Performance of Language Models, ICML 2021; M. Henderson et al., Efficient Natural Language Response Suggestion for Smart Reply, 2017 (in-batch negatives); P. Lewis et al., Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks, NeurIPS 2020; V. Karpukhin et al., Dense Passage Retrieval for Open-Domain Question Answering, EMNLP 2020; G. V. Cormack, C. L. A. Clarke, S. Büttcher, “Reciprocal Rank Fusion Outperforms Condorcet and Individual Rank Learning Methods”, SIGIR 2009; N. F. Liu et al., Lost in the Middle: How Language Models Use Long Contexts, TACL 2024.
- Industrial text mining: R. Mihalcea, P. Tarau, TextRank, 2004; S. Rose et al., Automatic Keyword Extraction from Individual Documents (RAKE), 2010; R. Campos et al., YAKE!, Information Processing & Management 2020 (code).
- Retrieval engines and evaluation (section 2.1): C. Manning, P. Raghavan, H. Schütze, Introduction to Information Retrieval, Cambridge University Press, 2008 — free online (inverted index, MAP); K. Järvelin, J. Kekäläinen, “Cumulated Gain-Based Evaluation of IR Techniques” (nDCG), ACM TOIS, 2002.
- Recommendation, advertising, social media (sections 8.5–8.6): Y. Koren, R. Bell, C. Volinsky, “Matrix Factorization Techniques for Recommender Systems”, IEEE Computer, 2009; Y. Hu, Y. Koren, C. Volinsky, “Collaborative Filtering for Implicit Feedback Datasets”, ICDM 2008; H. B. McMahan et al., “Ad Click Prediction: a View from the Trenches”, KDD 2013; J. Kleinberg, “Bursty and Hierarchical Structure in Streams”, KDD 2002.
- Research at DaSciM (Vazirgiannis, Buscaldi) (ch. 9): Rousseau & Vazirgiannis (TW-IDF, CIKM 2013); Tixier, Malliaros & Vazirgiannis (degeneracy, EMNLP 2016); Skianis et al. (EMNLP 2016); Giatsidis et al. (CoreCluster, AAAI 2014); Abdine, Buscaldi et Vazirgiannis (WSI, AI Open 2023); Douka et al. (JuriBERT, 2021); Buscaldi et al. (JIIS 2011; WWW 2015; TexTrolls; generated-text detection; memorization; MUCH).
- Data and papers of the projects: P. Koehn, “Europarl: A Parallel Corpus for Statistical Machine Translation”, MT Summit 2005; A. Maas et al., “Learning Word Vectors for Sentiment Analysis” (IMDb reviews), ACL 2011; A. Hulth, “Improved Automatic Keyword Extraction Given More Linguistic Knowledge”, EMNLP 2003; F. M. Harper, J. A. Konstan, “The MovieLens Datasets: History and Context”, ACM TiiS, 2015; A. Louis, G. Spanakis, A Statutory Article Retrieval Dataset in French (BSARD), ACL 2022.
- Tools: HuggingFace Course (the labs follow this curriculum); spaCy; gensim; rank_bm25; datasketch (MinHash LSH).