BRAGA

02 Writing02-02 Notes02-02-397

Categorical Distribution (1 trial, K outcomes)

Published 26 Oct 20266 min read
Contents
  1. 01Deep Breakdown
  2. 02Flowchart
  3. 03Real-world use
  4. 04The formula, piece by piece
  5. 05The formula in words
  6. 06Critical Concepts
  7. 07Step-by-step calculation (tiny example)
  8. 08Code examples
P(X=k)=pk=∏j=1Kpj[x=j]P(X=k) = p_k = \prod_{j=1}^{K} p_j^{[x=j]}
(1)

, where pk≥0p_k \ge 0, ∑k=1Kpk=1\sum_{k=1}^{K} p_k = 1, and [x=j][x=j] is 1 if x=jx=j and 0 otherwise

Deep Breakdown

What it tells me (Situation Awareness): The Categorical distribution models one single draw that lands in exactly one of KK classes, with class kk having probability pkp_k. It is the multi-class generalisation of the Bernoulli (K=2K=2) and the one-trial special case of the Multinomial (n=1n=1). The product form ∏jpj[x=j]\prod_j p_j^{[x=j]} looks odd but simply "switches on" the probability of the observed class, exactly like px(1−p)1−xp^x(1-p)^{1-x} does for Bernoulli. Its negative log-likelihood for one observation is −log⁡py-\log p_y, which is precisely the cross-entropy loss. In DA/DS: every softmax output of a multiclass classifier is a Categorical distribution over labels; LLM next-token prediction is a Categorical over the vocabulary (sampling with temperature, top-k and top-p all reshape pp before drawing); multinomial logistic regression, Naive Bayes class priors, customer segment assignment, ticket routing, and the "which plan will this user pick" question are all Categorical models.

Flowchart

Model logits z_1... z_KSoftmax: p_k =exp(z_k) / sumexp(z_j)Categorical(p_1... p_K)Draw one labelor take argmaxTrue label yobservedLikelihood = p_yCross-entropyloss = -log p_y

Real-world use

Where it is used

Multiclass classification (softmax layer, multinomial logistic regression), language-model token sampling, recommendation of one item among KK, routing a support ticket to one of KK teams, modelling which product category a shopper buys, and topic or cluster assignment in mixture models.

Problem it solves

Gives a valid probability for each of KK mutually exclusive outcomes of one event, so a model can express uncertainty across classes instead of just outputting a single label, and so that model can be trained by maximum likelihood.

How it solves the problem

The model produces KK non-negative numbers that sum to 1 (softmax guarantees this). The observed class yy receives likelihood pyp_y; maximising ∑ilog⁡pyi\sum_i \log p_{y_i} over the training set is the same as minimising average cross-entropy. At prediction time I either take arg⁡max⁡kpk\arg\max_k p_k (classification) or sample from pp (generation).

Example in a business

A support-ticket router outputs p=(0.7,0.2,0.1)p = (0.7, 0.2, 0.1) for (Billing, Tech, Sales). If the ticket really is Billing, the loss is −log⁡0.7=0.3567-\log 0.7 = 0.3567; if it is really Sales, the loss is −log⁡0.1=2.3026-\log 0.1 = 2.3026, more than six times larger. That asymmetry is what pushes the model to put mass on the right class, and calibrated pkp_k let the operations team auto-route only tickets with pmax⁡≥0.8p_{\max} \ge 0.8 and send the rest to a human.

The formula, piece by piece

  • XX: the outcome of one trial, taking a value in {1,…,K}\{1, \dots, K\}.
  • KK: number of possible classes or categories.
  • pkp_k: probability of class kk; the parameter vector p=(p1,…,pK)p = (p_1, \dots, p_K) lives on the probability simplex.
  • ∑kpk=1\sum_k p_k = 1: exactly one class happens.
  • [x=j][x=j]: indicator (one-hot encoding) that the outcome is class jj.
  • ∏jpj[x=j]\prod_j p_j^{[x=j]}: every factor is pj0=1p_j^0 = 1 except the observed class, so the product equals pxp_x.
  • E[ [X=k] ]=pkE\left[\,[X=k]\,\right] = p_k and Var([X=k])=pk(1−pk)Var([X=k]) = p_k(1-p_k): each one-hot component is a Bernoulli.
  • −log⁡py-\log p_y: the negative log-likelihood, i.e. the cross-entropy between the one-hot label and pp.

The formula in words

"One trial, KK possible outcomes: the probability of seeing class kk is just pkp_k, and the probabilities over all classes add to one." Tiny example: a shopper buys from Electronics, Fashion, or Home with probabilities 0.5,0.3,0.20.5, 0.3, 0.2. P(Fashion)=0.50×0.31×0.20=0.3P(\text{Fashion}) = 0.5^0 \times 0.3^1 \times 0.2^0 = 0.3.

Critical Concepts

  • Bernoulli and Multinomial relatives: K=2K=2 gives the Bernoulli; nn independent Categorical draws, counted per class, give the Multinomial.
  • Softmax output is a Categorical: pk=ezk/∑jezjp_k = e^{z_k}/\sum_j e^{z_j}. Compute it with the log-sum-exp trick so large logits do not overflow.
  • Cross-entropy = Categorical NLL: training any softmax classifier with cross-entropy is maximum-likelihood estimation of a Categorical model.
  • MLE from data: with no features, p^k=nk/n\hat{p}_k = n_k / n, the class frequencies (class priors).
  • Argmax vs sampling: classification uses arg⁡max⁡kpk\arg\max_k p_k; LLMs sample, and temperature TT rescales logits as z/Tz/T to make pp sharper (TT less than 1) or flatter (TT greater than 1).
  • Calibration: a model can rank classes well yet output over-confident pkp_k; check reliability diagrams before using pkp_k as real probabilities in business rules.

Step-by-step calculation (tiny example)

Step 1: Model output Router probabilities p=(0.7,0.2,0.1)p = (0.7, 0.2, 0.1) for (Billing, Tech, Sales). Check: 0.7+0.2+0.1=10.7 + 0.2 + 0.1 = 1.

Step 2: Probability of the true label True label is Billing, so the one-hot is (1,0,0)(1, 0, 0) and P(X=Billing)=0.71×0.20×0.10=0.7P(X=\text{Billing}) = 0.7^1 \times 0.2^0 \times 0.1^0 = 0.7.

Step 3: Loss for this ticket −log⁡0.7=0.3567-\log 0.7 = 0.3567.

Step 4: Compare with a wrong-but-possible label If the true label were Tech: −log⁡0.2=1.6094-\log 0.2 = 1.6094. If Sales: −log⁡0.1=2.3026-\log 0.1 = 2.3026.

Step 5: Interpretation The less probability the model gave to the truth, the larger the loss; averaging these over all tickets gives the training cross-entropy.

Code examples

Beginner example (Python)

python
import numpy as np

labels = ["Billing", "Tech", "Sales"]
p = np.array([0.7, 0.2, 0.1])
print(f"Sum of p = {p.sum():.2f}")   # 1.00
for name, pk in zip(labels, p):
    print(f"P({name}) = {pk:.1f} | loss if true = {-np.log(pk):.4f}")
# Billing 0.3567, Tech 1.6094, Sales 2.3026

rng = np.random.default_rng(42)
draws = rng.choice(len(p), size=100_000, p=p)
print("Empirical frequencies:", np.round(np.bincount(draws) / draws.size, 3))   # about [0.7 0.2 0.1]

Beginner example (R)

r
p <- c(Billing = 0.7, Tech = 0.2, Sales = 0.1)
print(-log(p))   # 0.3567 1.6094 2.3026
set.seed(42)
draws <- sample(names(p), size = 100000, replace = TRUE, prob = p)
print(round(table(draws) / length(draws), 3))

Professional example (Python)

python
import numpy as np
from scipy.special import logsumexp
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import log_loss
from sklearn.model_selection import train_test_split


def categorical_nll(logits: np.ndarray, y: np.ndarray) -> float:
    """Mean negative log-likelihood of a Categorical(softmax(logits)) model.

    log p_y = z_y - logsumexp(z), computed stably.
    """
    log_probs = logits - logsumexp(logits, axis=1, keepdims=True)
    return float(-log_probs[np.arange(len(y)), y].mean())


X, y = make_classification(
    n_samples=3000, n_features=8, n_informative=5, n_classes=3, random_state=42
)
X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.3, random_state=42)
clf = LogisticRegression(max_iter=1000).fit(X_tr, y_tr)

logits = clf.decision_function(X_te)        # z_1..z_K per ticket
probs = clf.predict_proba(X_te)             # softmax(z) = Categorical parameters
print(f"Rows sum to 1: {np.allclose(probs.sum(axis=1), 1.0)}")
print(f"Manual Categorical NLL: {categorical_nll(logits, y_te):.4f}")
print(f"sklearn log_loss:       {log_loss(y_te, probs):.4f}")   # identical

# Business rule: auto-route only confident predictions
confident = probs.max(axis=1) >= 0.8
acc_conf = (probs.argmax(axis=1)[confident] == y_te[confident]).mean()
print(f"Auto-routed share: {confident.mean():.1%} | accuracy there: {acc_conf:.1%}")

Source: domain knowledge

#probability-statistics#statistical-operations-and-random-variables#common-discrete-distributions

Keyboard shortcuts

Single keys, ignored while typing in a field or with Cmd, Ctrl or Alt held.

0
Home
1 2 3 4
Work, Writing, Tools, About
j / k
Next / previous section on this page
n / p
Next / previous project or essay
u
Up one level
l
Deutsch
t
Light or dark theme
?
This list
Esc
Close