Course contents 14 / 27

14 / 27 · Linear Classification

Multiclass and multilabel classification

Classification with more than two classes and with several labels per example: one-vs-rest and one-vs-one with their costs and pitfalls, multinomial logistic regression with the softmax, the cross-entropy and its gradient p − y and the invariance to shifting the scores, micro and macro averages of the metrics, independent sigmoids for multilabel problems and their metrics, and a brief look at hierarchical and extreme classification.

On this page 11

Every classifier so far in this section, from logistic regression to the kernel SVM, separates two classes. Most real problems have more: ten digits, a few dozen product categories, a vocabulary of tens of thousands of words for a language model. Others attach several labels to the same object: a news article can be about both politics and the economy. This note covers the three ways to handle K>2K \gt 2 classes with linear models: split the problem into binary ones, or extend logistic regression to a single model with KK outputs, the softmax, which is the output layer of nearly every neural classifier. It then adapts the metrics of the classification metrics note to many classes, and treats the case of several labels per example.

Notation. Classes 1,…,K1, \dots, K; a training set (xi,yi)(x_i, y_i), i=1,…,ni = 1, \dots, n, with xi∈Rdx_i \in \mathbb R^d and yi∈{1,…,K}y_i \in \{1, \dots, K\}. The one-hot vector of a label is y∈{0,1}K\mathbf y \in \{0, 1\}^K with a single 1 in position yy. A linear multiclass model has a weight matrix WW with rows w1,…,wKw_1, \dots, w_K and biases bkb_k; the scores (logits) are zk=⟨wk,x⟩+bkz_k = \langle w_k, x\rangle + b_k, and p=(p1,…,pK)p = (p_1, \dots, p_K) is the vector of predicted class probabilities. In the multilabel case the target is a vector y∈{0,1}K\mathbf y \in \{0, 1\}^K with any number of ones. TPk\mathrm{TP}_k, FPk\mathrm{FP}_k and FNk\mathrm{FN}_k count the true positives, false positives and false negatives of class kk against the rest.

Reducing to binary problems#

One-vs-rest#

Train KK binary classifiers; classifier kk separates class kk (label +1+1) from all the others (label −1-1) and outputs a score fk(x)f_k(x). Predict the class with the highest score, y^=arg⁡max⁡kfk(x)\hat y = \arg\max_k f_k(x). The cost is KK binary trainings on all nn examples. Taking the sign of each classifier instead of the argmax leaves regions where no classifier, or several, claim the point (Bishop, 2006, §4.1.2); the argmax removes the ambiguity but brings its own problems:

  • Scores on different scales. Each classifier is trained alone, so nothing makes f3(x)=2f_3(x) = 2 comparable with f7(x)=2f_7(x) = 2. For SVMs, whose scores are not probabilities, this is a real concern; calibrated probabilities help.
  • Imbalance by construction. With ten balanced classes every binary problem is 1 against 9.
  • A class between others. A linear score for “class kk against the rest” cannot be high in a band and low on both sides of it, so the binary model of a middle class is misspecified. The argmax of several linear scores can still carve out the band; the trouble is that each score is fitted alone, to its own binary problem.

The last pitfall is not a matter of data size. Take three classes on a line, with xx normal of variance 1 around −2-2, 00 and 22, and fit both approaches to the distribution itself:

Figure

One-vs-rest against softmax on three classes

Class probabilities of two modelsTwo panels with three probability curves each. On the left the blue curve falls, the red one rises, and the amber one is a horizontal line at 1/3; the strip below gives class 2 a narrow interval. On the right the amber curve is a bump peaking at zero, and class 2 wins between −1 and 1.class 1, μ = −2class 2, μ = 0class 3, μ = 2one-vs-rest: three separate models00.51class 2 vs rest: 1/3 everywhere−0.700.70accuracy 0.774, recall of class 2 0.51softmax: one multinomial model00.51−11accuracy 0.788, recall of class 2 0.68Class probabilities of two modelsTwo panels with three probability curves each. On the left the blue curve falls, the red one rises, and the amber one is a horizontal line at 1/3; the strip below gives class 2 a narrow interval. On the right the amber curve is a bump peaking at zero, and class 2 wins between −1 and 1.class 1, μ = −2class 2, μ = 0class 3, μ = 2one-vs-rest: three separate models00.51class 2 vs rest: 1/3 everywhere−0.700.70accuracy 0.774, recall of class 2 0.51softmax: one multinomial model00.51−11accuracy 0.788, recall of class 2 0.68
Three classes on a line: x is normal with mean −2, 0 or 2 and variance 1, and the classes are equally likely. Both models are fitted to the distribution itself, free of sampling noise. Left: three logistic regressions, each separating one class from the rest. The middle class is a band between the other two, and a line in the logits cannot separate a band from both of its sides: the best such model is constant at 1/3. Class 2 wins only where both outer models have dropped below 1/3, for |x| < 0.70: the argmax does form a band, but the separate binary fits put its edges in the wrong place. Right: multinomial logistic regression, whose solution is the Bayes posterior, with boundaries at ±1; the recall of class 2 is 0.68 instead of 0.51 and the accuracy 0.788 instead of 0.774. The probabilities on the left do not sum to 1.

The best linear logit for the middle class is constant, so its one-vs-rest model predicts 1/31/3 everywhere, and class 2 wins only where both outer models fall below 1/31/3, for ∣x∣<0.70\lvert x\rvert \lt 0.70 instead of the optimal ∣x∣<1\lvert x\rvert \lt 1. Its recall drops from 0.680.68 to 0.510.51, and the accuracy from the optimal 0.7880.788 to 0.7740.774. In high dimension such configurations are less common, and with well-regularized binary classifiers one-vs-rest is often as accurate as anything else (Rifkin and Klautau, 2004); but the example shows what the reduction gets wrong. It is not a matter of representation: the argmax of the one-vs-rest scores does form a band, and the same family of three linear scores contains the optimal rule, since the argmax of (−2x−2, 0, 2x−2)(-2x - 2,\ 0,\ 2x - 2) picks class 2 exactly for ∣x∣<1\lvert x\rvert \lt 1. What fails is the training. Each binary logistic model is fitted alone to a posterior that is not logistic in xx (for the middle class it rises and falls), and the three misspecified fits do not combine into the optimal boundaries.

One-vs-one#

Train a classifier for every pair of classes, K(K−1)/2K(K-1)/2 of them, each on the examples of its two classes only; predict by majority vote, with ties broken by summed scores. Each problem is small and balanced, about 2n/K2n/K examples for balanced classes. If training on mm examples costs mam^a, one-vs-rest costs KnaK n^a and one-vs-one costs K(K−1)2(2n/K)a\tfrac{K(K-1)}{2}(2n/K)^a. For a linear-time learner, a=1a = 1, both cost about KnKn; for kernel SVMs, with aa around 2, one-vs-one costs about 2n22n^2 against Kn2Kn^2, five times less for ten classes. This is why LIBSVM, and scikit-learn’s SVC on top of it, use one-vs-one (Hsu and Lin, 2002). The price is at prediction time, K(K−1)/2K(K-1)/2 evaluations, 45 for ten classes, and each pairwise classifier also votes on points from the other K−2K - 2 classes, which it never saw.

On the ten digits of scikit-learn (1,797 images of 8×88 \times 8 pixels, half for testing) with L2-regularized logistic regression as the binary learner, one-vs-rest with 10 models reaches a test accuracy of 0.9530.953 and one-vs-one with 45 models 0.9660.966. A single multinomial model, the subject of the next section, reaches 0.9630.963. Reductions are not limited to these two schemes: error-correcting output codes assign each class a binary code word and train one classifier per bit (Dietterich and Bakiri, 1995), and joint formulations such as the multiclass SVM of Crammer and Singer (2001) train all KK score functions in one optimization problem.

Multinomial logistic regression#

One model with KK linear scores, turned into a probability distribution, avoids all three pitfalls: the scores are trained together, on one scale, against one likelihood.

Why a softmax of linear functions. Bayes’ formula gives the form of the posterior. Suppose the classes have prior probabilities πk\pi_k and Gaussian class-conditional densities N(μk,Σ)N(\mu_k, \Sigma) with a shared covariance. By Bayes’ formula, P(y=k∣x)∝πkexp⁡(−12(x−μk)⊤Σ−1(x−μk))P(y = k \mid x) \propto \pi_k \exp\big(-\tfrac12 (x - \mu_k)^\top \Sigma^{-1} (x - \mu_k)\big). Expanding the quadratic form, the term −12x⊤Σ−1x-\tfrac12 x^\top \Sigma^{-1} x is the same for every class and cancels in the normalization, which leaves

P(y=k∣x)=ezk∑jezj,zk=⟨Σ−1μk, x⟩−12μk⊤Σ−1μk+log⁡πk,P(y = k \mid x) = \frac{e^{z_k}}{\sum_{j} e^{z_j}}, \qquad z_k = \langle \Sigma^{-1}\mu_k,\ x\rangle - \tfrac12 \mu_k^\top \Sigma^{-1}\mu_k + \log \pi_k ,

a normalized exponential of linear functions of xx (see the multivariate Gaussian; Bishop, 2006, §4.2). Multinomial logistic regression keeps this form and fits the weights directly, without assuming Gaussians. For the three classes of the figure, zk=μkx−μk2/2=(−2x−2, 0, 2x−2)z_k = \mu_k x - \mu_k^2/2 = (-2x - 2,\ 0,\ 2x - 2), and the fitted model reproduces exactly this posterior.

The model and its loss. The softmax maps a score vector to a probability vector:

pk=softmax⁡(z)k=ezk∑j=1Kezj.p_k = \operatorname{softmax}(z)_k = \frac{e^{z_k}}{\sum_{j=1}^K e^{z_j}} .

The exponential makes every entry positive and the division makes them sum to 1; the largest score gets the largest probability, and a score far above the others takes almost all of it, hence the name, a soft version of the argmax. The model is fitted by maximum likelihood under a categorical distribution: the negative log-likelihood of one example is

L=−log⁡py=−∑kyklog⁡pk=−zy+log⁡∑jezj,L = -\log p_{y} = -\sum_{k} \mathbf y_k \log p_k = -z_y + \log \sum_{j} e^{z_j} ,

the cross-entropy between the one-hot label and the predicted distribution, in the sense of the entropy note of the generative models course. For K=2K = 2 it is the logistic loss.

Figure

Softmax, cross-entropy and the gradient p − y

One example through multinomial logistic regressionLeft to right: the input x, the weight matrix W, the score vector z, a softmax block, the probability vector p, a minus-log block and the loss L. Below p lies the one-hot label y, to its left the gradient vector p − y, from which a dashed arrow returns to W.21xW3 × 22.01.00.1zsoftmax0.6590.2420.099p−log p₁L = 0.417100y−0.3410.2420.099p − y∂L/∂W = (p − y)xᵀ1234inputstateweights, gatesoutputOne example through multinomial logistic regressionTop to bottom: the input x, the weights W, the scores z, a softmax block, the probabilities p, the label y, a minus-log block and the loss L; at the bottom the gradient vector p − y, from which a dashed arrow rises to W.21xW3 × 22.01.00.1zsoftmax0.6590.2420.099p100y−log p₁L = 0.417−0.3410.2420.099p − y∂L/∂W = (p − y)xᵀ1234inputstateweights, gatesoutput
Multinomial logistic regression on one example (green: input, amber: weights, blue: scores, red: probabilities and loss). (1) A linear layer gives one score per class, z = Wx. (2) The softmax turns scores into probabilities: the exponential makes them positive, dividing by the sum normalizes them. (3) The loss is minus the log-probability of the true class, 0.417. (4) Its gradient with respect to the scores is the difference p − y between the predicted distribution and the one-hot label: the true class is pushed up by 0.341, the others down by their probabilities. Adding one constant to all scores leaves p unchanged.
  1. The linear layer gives one score per class: with x=(2,1)x = (2, 1) and the weights of the figure, z=(2.0,1.0,0.1)z = (2.0, 1.0, 0.1).
  2. The softmax: ez=(7.389,2.718,1.105)e^{z} = (7.389, 2.718, 1.105), which sum to 11.21211.212, so p=(0.659,0.242,0.099)p = (0.659, 0.242, 0.099).
  3. The true class is 1, and the loss is −log⁡0.659=0.417-\log 0.659 = 0.417.
  4. The gradient with respect to the scores is p−y=(−0.341,0.242,0.099)p - \mathbf y = (-0.341, 0.242, 0.099).

The gradient p−yp - \mathbf y. Differentiate L=−zy+log⁡∑jezjL = -z_y + \log\sum_j e^{z_j} with respect to zkz_k: the first term gives −[k=y]-[k = y], the second ezk/∑jezj=pke^{z_k}/\sum_j e^{z_j} = p_k. So

∂L∂z=p−y,∂L∂W=(p−y) x⊤,∂L∂b=p−y,\frac{\partial L}{\partial z} = p - \mathbf y, \qquad \frac{\partial L}{\partial W} = (p - \mathbf y)\, x^\top, \qquad \frac{\partial L}{\partial b} = p - \mathbf y ,

where the second form follows from z=Wx+bz = Wx + b by the chain rule. The gradient is “predicted minus observed”, the same pattern as the residual of least squares and the p−yp - y of binary logistic regression. A gradient step raises the score of the true class in proportion to 1−py1 - p_y and lowers every other score in proportion to its probability; an example the model already gets right with confidence contributes almost nothing.

The loss is convex in the scores. The second derivatives are ∂pk/∂zj=pk([k=j]−pj)\partial p_k / \partial z_j = p_k([k = j] - p_j), so the Hessian is H=diag⁡(p)−pp⊤H = \operatorname{diag}(p) - pp^\top, and for any vector vv

v⊤Hv=∑kpkvk2−(∑kpkvk)2=Var⁡(vY),Y∼Categorical(p),v^\top H v = \sum_k p_k v_k^2 - \Big(\sum_k p_k v_k\Big)^2 = \operatorname{Var}(v_Y), \qquad Y \sim \text{Categorical}(p) ,

a variance, hence non-negative. The scores are linear in WW and bb, so the training loss is convex in the parameters too, and gradient descent or Newton’s method finds its minimum.

Invariance to shifting the scores. The Hessian has one direction of zero curvature: v=(1,…,1)v = (1, \dots, 1), for which vY=1v_Y = 1 always and the variance is 0. Adding the same constant cc to every score multiplies numerator and denominator of the softmax by ece^c:

softmax⁡(z+c1)=softmax⁡(z).\operatorname{softmax}(z + c\mathbf 1) = \operatorname{softmax}(z) .

Three consequences follow. First, the parameters are not identifiable: adding the same vector vv to every wkw_k and the same number to every bkb_k shifts all scores by ⟨v,x⟩+c\langle v, x\rangle + c and changes no probability. One class can therefore serve as a reference with wK=0w_K = 0, bK=0b_K = 0; for K=2K = 2 this gives p1=ez1/(ez1+ez2)=σ(z1−z2)p_1 = e^{z_1}/(e^{z_1} + e^{z_2}) = \sigma(z_1 - z_2), binary logistic regression. With an L2 penalty the weights become unique: of all equivalent weight sets, the penalty picks the one with the smallest norm, in which the class weights sum to zero. scikit-learn does not penalize the intercepts, so they remain defined only up to a common shift, and its solvers return the representative whose intercepts sum to zero: L-BFGS starts from zero, and the gradient with respect to the intercepts, a sum of vectors p−yp - \mathbf y over the examples, always has components summing to zero, so the iterates never leave that set. That is why the fitted intercepts of the figure are (−0.667,1.333,−0.667)(-0.667, 1.333, -0.667) rather than (−2,0,−2)(-2, 0, -2): the same posterior, shifted by 4/34/3. Second, the shift is the standard numerical safeguard. For z=(1000,999)z = (1000, 999), e1000e^{1000} overflows and the naive formula returns undefined values; subtracting the maximum first gives softmax⁡(0,−1)=(0.731,0.269)\operatorname{softmax}(0, -1) = (0.731, 0.269), and the loss is computed as −zy+max⁡jzj+log⁡∑jezj−max⁡jzj-z_y + \max_j z_j + \log\sum_j e^{z_j - \max_j z_j}. Third, only differences of scores matter, which is why the Gaussian term x⊤Σ−1xx^\top\Sigma^{-1}x could be dropped above.

Softmax regression is the output layer of neural classifiers and of language models. A language model is a classifier whose KK classes are the tokens of the vocabulary: the n-gram language models note estimates the next-token probabilities by counting, and word2vec computes them with this softmax over dot products, where KK in the hundreds of thousands makes the normalization the bottleneck.

Multiclass metrics: micro and macro averages#

Precision, recall and F1F_1 are defined for one class against the rest. With KK classes there are KK such tables, and two ways to combine them (Manning, Raghavan and Schütze, 2008, §13.6):

  • Macro averaging computes the metric per class and averages the KK numbers: every class counts equally, however rare.
  • Micro averaging sums TPk\mathrm{TP}_k, FPk\mathrm{FP}_k and FNk\mathrm{FN}_k over the classes and computes the metric once from the totals: every example counts equally.
  • Weighted averaging averages the per-class metrics with weights proportional to the class sizes.

For single-label classification, micro averaging adds nothing: every wrong prediction is one false positive (for the predicted class) and one false negative (for the true class), so ∑kFPk=∑kFNk\sum_k \mathrm{FP}_k = \sum_k \mathrm{FN}_k equals the number of errors and ∑kTPk\sum_k \mathrm{TP}_k the number of correct answers. Micro precision, micro recall and micro F1F_1 all equal the accuracy.

Worked example. A toy classifier on 100 examples with classes of 80, 15 and 5 (rows: true class, columns: prediction):

true \ predictedABC
A (80)7631
B (15)690
C (5)302

The accuracy, and so the micro F1F_1, is 87/100=0.8787/100 = 0.87. Per class, F1=2TP/(2TP+FP+FN)F_1 = 2\mathrm{TP}/(2\mathrm{TP} + \mathrm{FP} + \mathrm{FN}) is 152/165=0.921152/165 = 0.921 for A, 18/27=0.66718/27 = 0.667 for B and 4/8=0.54/8 = 0.5 for C. The macro F1F_1 is (0.921+0.667+0.5)/3=0.696(0.921 + 0.667 + 0.5)/3 = 0.696; the weighted F1F_1, 0.8⋅0.921+0.15⋅0.667+0.05⋅0.5=0.8620.8 \cdot 0.921 + 0.15 \cdot 0.667 + 0.05 \cdot 0.5 = 0.862, sits close to the accuracy because the large class dominates both. Which number to report is a question about the task: if finding the 5 examples of class C matters as much as the 80 of class A, the macro average says the classifier is mediocre, and the micro average hides it. The NLP evaluation note works through a three-topic text example of the same effect. Ranking metrics generalize too: a ROC curve and its AUC can be computed per class against the rest and macro-averaged.

Multilabel classification#

In multilabel problems each example carries a set of labels: the tags of a photo, the topics of an article, the diagnoses of a patient. The standard model treats each label as its own binary problem with its own sigmoid:

P(y∣x)=∏k=1Kpkyk(1−pk)1−yk,pk=σ(⟨wk,x⟩+bk).P(\mathbf y \mid x) = \prod_{k=1}^K p_k^{\mathbf y_k} (1 - p_k)^{1 - \mathbf y_k}, \qquad p_k = \sigma(\langle w_k, x\rangle + b_k) .

The product says that the labels are conditionally independent given xx, and its negative logarithm is the sum of KK binary cross-entropies, one per label. The difference from the multiclass model is the normalization: the softmax makes the classes compete for one unit of probability, while independent sigmoids let any number of labels be likely at once, or none. Each label gets its own decision threshold, tuned on validation data to the metric that matters, because a label present in 2% of examples rarely deserves the default threshold of 0.5. This approach is called binary relevance. It still reflects labels that co-occur because they depend on the same features of xx, but it ignores any dependence that remains once xx is known (“economy” making “politics” more likely for the same article). Classifier chains feed the predictions for the first labels as extra features into the classifiers for the next ones (Read et al., 2011); a network with a shared hidden layer and KK sigmoid outputs shares a representation between the labels, which helps when they depend on the same features (Zhang and Zhou, 2014). Its output is still the product above, so given xx the labels remain independent; dependence that remains given xx needs chains or a model of the joint distribution of the label vector.

Multilabel metrics compare a predicted set with a true set. With true sets YiY_i and predicted sets ZiZ_i:

  • Hamming loss: the share of wrong label decisions, 1nK∑i∣Yi △ Zi∣\frac{1}{nK}\sum_i \lvert Y_i \,\triangle\, Z_i\rvert, where △\triangle is the symmetric difference;
  • subset accuracy (exact match): the share of examples whose whole set is right, a harsh metric for large KK;
  • example-based metrics, averaged over examples: the Jaccard index ∣Yi∩Zi∣/∣Yi∪Zi∣\lvert Y_i \cap Z_i\rvert / \lvert Y_i \cup Z_i\rvert, or F1F_1 per example;
  • micro and macro averages over labels, as in the multiclass case. Micro F1F_1 no longer equals any accuracy, since one example can contribute several true positives.

Worked example. Four examples and three labels, with true sets {1,3},{2},{1,2},{3}\{1, 3\}, \{2\}, \{1, 2\}, \{3\} and predicted sets {1},{2},{1,2,3},{2,3}\{1\}, \{2\}, \{1, 2, 3\}, \{2, 3\}. Three of the 12 label decisions are wrong, so the Hamming loss is 0.250.25; only the second example is exactly right, so the subset accuracy is 0.250.25 too. The Jaccard indices are 1/2,1,2/3,1/21/2, 1, 2/3, 1/2, with mean 0.6670.667. Summed over labels, TP=5\mathrm{TP} = 5, FP=2\mathrm{FP} = 2, FN=1\mathrm{FN} = 1, so micro F1=10/13=0.769F_1 = 10/13 = 0.769; per label F1F_1 is 11, 0.80.8 and 0.50.5, and the macro average is 0.7670.767. On a synthetic problem with 5 labels, about two per example, independent logistic regressions have a Hamming loss of 0.2160.216 but get the whole label set right for only 0.3510.351 of the test examples: the two metrics measure very different things.

The text classification note of the NLP course lists the binary, multiclass and multilabel variants side by side with their losses.

Hierarchical and extreme classification#

Hierarchical classification. Classes often form a taxonomy: product categories, the topics of a library catalogue, biological species. A flat classifier ignores the tree; a top-down approach trains a classifier at each internal node to choose among its children, which keeps each problem small but propagates an error at the top to everything below it. Errors can be weighted by their distance in the tree, so that confusing two breeds of dog costs less than confusing a dog with a car (Silla and Freitas, 2011). The same tree gives a fast softmax: if the classes are leaves of a binary tree, the probability of a leaf is the product of the binary decisions on its path, which costs log⁡2K\log_2 K sigmoids instead of a sum over KK classes. This hierarchical softmax was introduced for language models (Morin and Bengio, 2005) and is used by word2vec.

Extreme classification. When KK reaches 10510^5 to 10710^7 (all Wikipedia categories, all products of a shop, all tokens of a vocabulary), the softmax costs O(Kd)O(Kd) per example for both the scores and the gradient, and most labels have only a handful of examples. Training then approximates the normalization by sampling a few negative classes per example (sampled softmax, Jean et al., 2015; negative sampling in the word2vec note) or uses label trees, and evaluation switches to ranking metrics such as precision at kk: the share of correct labels among the kk top-scored ones.

What changed#

Binary classificationMulticlass and multilabel
Outputone score, its signKK scores: an argmax, or a set of labels
Probability modelBernoulli, σ(z)\sigma(z)categorical, softmax⁡(z)\operatorname{softmax}(z); or KK independent Bernoullis
Losslogistic losscross-entropy −log⁡py-\log p_y; or a sum of KK binary cross-entropies
Gradient in the scoresp−yp - yp−yp - \mathbf y, a vector
Reductionsnone neededone-vs-rest (KK models), one-vs-one (K(K−1)/2K(K-1)/2 models)
Identifiabilityunique weightsscores defined up to a common shift; fix a reference class or use L2
Metricsprecision, recall, F1F_1per class, then micro, macro or weighted averages; Hamming loss and exact match for label sets

Limitations#

  • Reductions do not see the whole problem. One-vs-rest fits each linear score alone, so a class between others gets a misspecified binary model and suboptimal boundaries, even though the argmax can still form a band; one-vs-one asks classifiers about classes they never saw. Their scores are not calibrated probabilities.
  • The softmax forces a choice. Probabilities sum to 1 over the known classes, so an input from none of them is still spread over them. The output may be overconfident, or close to uniform: being forced to choose a known class and being confident are different things; detecting such inputs is the subject of the anomaly detection note.
  • Independent sigmoids ignore label dependence given xx, even with a shared hidden layer, and exact-match accuracy falls quickly as the number of labels grows.
  • Cost grows with KK. Scores and gradients cost O(Kd)O(Kd) per example; for very large KK the normalization must be approximated.
  • Still linear. Every score zkz_k is linear in xx, so the decision regions are convex polytopes; a class made of two separate clusters cannot be one region.

What you should remember#

  • One-vs-rest trains KK classifiers on all data; one-vs-one trains K(K−1)/2K(K-1)/2 on pairs, cheaper for superlinear learners such as kernel SVMs. Their scores are not on a common scale.
  • Multinomial logistic regression: p=softmax⁡(Wx+b)p = \operatorname{softmax}(Wx + b), loss −log⁡py-\log p_y, the categorical negative log-likelihood. It is the exact posterior for Gaussian classes with a shared covariance.
  • The gradient in the scores is p−yp - \mathbf y, and in the weights (p−y)x⊤(p - \mathbf y)x^\top. The Hessian diag⁡(p)−pp⊤\operatorname{diag}(p) - pp^\top is a covariance matrix, so the loss is convex.
  • Adding a constant to all scores changes nothing: fix a reference class or regularize, and subtract the maximum score before exponentiating.
  • Single-label micro F1F_1 equals accuracy; macro averages weight classes equally and expose rare classes. Multilabel: independent sigmoids, per-label thresholds, Hamming loss, exact match, micro and macro F1F_1.

Code#

The softmax and its gradient, one-vs-rest against the multinomial model on three classes, the three strategies on the digits, and the multiclass and multilabel metrics:

import numpy as np
from scipy.stats import norm
from sklearn.datasets import load_digits, make_multilabel_classification
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.multiclass import OneVsRestClassifier, OneVsOneClassifier
from sklearn.metrics import f1_score, accuracy_score, hamming_loss, jaccard_score

# softmax, cross-entropy and its gradient for the scores z = (2, 1, 0.1), true class 1
def softmax(z):
    e = np.exp(z - z.max())            # subtracting the maximum changes nothing and prevents overflow
    return e / e.sum()
z = np.array([2.0, 1.0, 0.1]); y = np.array([1, 0, 0])
p = softmax(z)
print(p.round(3), round(-np.log(p[0]), 3), (p - y).round(3))   # [0.659 0.242 0.099] 0.417 [-0.341  0.242  0.099]
print(softmax(z + 100).round(3))                                # [0.659 0.242 0.099]: adding a constant changes nothing
with np.errstate(over='ignore', invalid='ignore'):
    big = np.array([1000.0, 999.0])
    print(np.exp(big) / np.exp(big).sum(), softmax(big).round(3))   # [nan nan] [0.731 0.269]
eps = 1e-6; L = lambda z: -np.log(softmax(z)[0])
print(np.array([(L(z + eps * np.eye(3)[k]) - L(z - eps * np.eye(3)[k])) / (2 * eps) for k in range(3)]).round(3))   # [-0.341  0.242  0.099]

# three classes on a line, N(-2, 1), N(0, 1), N(2, 1): one-vs-rest and multinomial fitted to the population (a fine weighted grid)
x = np.arange(-8, 8.0001, 0.01); X = np.tile(x, 3)[:, None]; c = np.repeat([0, 1, 2], len(x))
w = np.concatenate([norm.pdf(x, m) for m in (-2, 0, 2)])
fit = lambda target: LogisticRegression(C=1e8, tol=1e-12, max_iter=10000).fit(X, target, sample_weight=w)
ovr = [fit((c == k).astype(int)) for k in range(3)]
print([(round(float(m.coef_[0, 0]), 3), round(float(m.intercept_[0]), 3)) for m in ovr])   # [(-2.114, -2.169), (0.0, -0.693), (2.114, -2.169)]
t = (np.log(1 / 2) - ovr[0].intercept_[0]) / ovr[0].coef_[0, 0]            # where the left model drops to 1/3
print(round(-t, 3), round((2 * norm.cdf(2 + t) + 2 * norm.cdf(-t) - 1) / 3, 3), round(2 * norm.cdf(-t) - 1, 3))   # 0.698 0.774 0.515
mn = fit(c)
print(mn.coef_.ravel().round(3), mn.intercept_.round(3), round((4 * norm.cdf(1) - 1) / 3, 3), round(2 * norm.cdf(1) - 1, 3))
# [-2.  0.  2.] [-0.667  1.333 -0.667] 0.788 0.683: the Bayes posterior, shifted so that the intercepts sum to zero

# ten digits: one-vs-rest, one-vs-one and multinomial logistic regression
Xd, yd = load_digits(return_X_y=True)
Xtr, Xte, ytr, yte = train_test_split(Xd, yd, test_size=0.5, random_state=0, stratify=yd)
sc = StandardScaler().fit(Xtr); Xtr, Xte = sc.transform(Xtr), sc.transform(Xte)
base = LogisticRegression(C=0.1, max_iter=5000)
for name, m in (('ovr', OneVsRestClassifier(base)), ('ovo', OneVsOneClassifier(base)), ('multinomial', base)):
    m.fit(Xtr, ytr)
    n_models = len(m.estimators_) if hasattr(m, 'estimators_') else 1
    print(name, n_models, round(m.score(Xte, yte), 3))
# ovr 10 0.953 | ovo 45 0.966 | multinomial 1 0.963
print(np.abs(base.coef_.sum(axis=0)).max() < 1e-6)   # True: with an L2 penalty the class weights sum to zero

# micro and macro averages: 100 examples, classes of 80, 15 and 5
cm = np.array([[76, 3, 1], [6, 9, 0], [3, 0, 2]])     # rows: true class, columns: prediction
yt = np.repeat(np.repeat([0, 1, 2], 3), cm.ravel()); yp = np.tile([0, 1, 2], 3).repeat(cm.ravel())
print(accuracy_score(yt, yp), f1_score(yt, yp, average=None).round(3), [round(f1_score(yt, yp, average=a), 3) for a in ('micro', 'macro', 'weighted')])
# 0.87 [0.921 0.667 0.5  ] [0.87, 0.696, 0.862]

# multilabel: four examples, three labels
Yt = np.array([[1, 0, 1], [0, 1, 0], [1, 1, 0], [0, 0, 1]]); Yp = np.array([[1, 0, 0], [0, 1, 0], [1, 1, 1], [0, 1, 1]])
print(hamming_loss(Yt, Yp), accuracy_score(Yt, Yp), round(jaccard_score(Yt, Yp, average='samples'), 3),
      [round(f1_score(Yt, Yp, average=a), 3) for a in ('micro', 'macro')], f1_score(Yt, Yp, average=None).round(3))
# 0.25 0.25 0.667 [0.769, 0.767] [1.  0.8 0.5]

# independent sigmoids on a synthetic multilabel problem (5 labels)
Xm, Ym = make_multilabel_classification(n_samples=2000, n_features=20, n_classes=5, n_labels=2, random_state=0)
Xtr, Xte, Ytr, Yte = train_test_split(Xm, Ym, test_size=0.5, random_state=0)
P = OneVsRestClassifier(LogisticRegression(max_iter=5000)).fit(Xtr, Ytr).predict_proba(Xte)
Yhat = (P >= 0.5).astype(int)
print(Ytr.mean(axis=0).round(2), round(hamming_loss(Yte, Yhat), 3), round(accuracy_score(Yte, Yhat), 3),
      [round(f1_score(Yte, Yhat, average=a), 3) for a in ('micro', 'macro')], round(f1_score(Yte, Yhat, average='samples', zero_division=0), 3))
# [0.38 0.43 0.39 0.36 0.33] 0.216 0.351 [0.695, 0.695] 0.619: label shares, Hamming loss, exact match, micro, macro and per-example F1

Next#

Every model of this section, binary or multiclass, scores an input by a linear function of its features, or of features fixed in advance by a kernel. A linear score cannot express interactions on its own: if a loan is risky when the income is low and the debt is high, but not when only one of them holds, the effect of income depends on debt, and no weighted sum of the two captures it. The next section starts from models that are built out of such conditions. The decision trees note splits the feature space by a sequence of yes-or-no questions, handles any number of classes at its leaves directly, and needs no scaling of the features.

References#