Chapter 3: Classification
Learn to predict discrete categories with machine learning. Master logistic regression for binary classification, understand the sigmoid function and cross-entropy loss, extend to multiclass problems with softmax, and use feature engineering to handle non-linear patterns.
Chapter Overview
Classification is the task of predicting which category an input belongs to. Unlike regression which outputs continuous values, classification outputs discrete class labels: spam or not spam, cat or dog or bird, malignant or benign.
The foundational algorithm is logistic regression, which despite its name is a classification method. It works by computing a linear combination of features, then passing the result through the sigmoid function to produce a probability between 0 and 1. If this probability exceeds a threshold (typically 0.5), we predict the positive class.
The key to understanding logistic regression is the loss function. We can't use mean squared error because sigmoid creates a non-convex loss surface. Instead, we use cross-entropy (log loss), which heavily penalizes confident wrong predictions and creates a smooth, convex optimization landscape.
The decision boundary in logistic regression is a hyperplane—the set of points where the predicted probability equals 0.5. Points on one side are classified as positive, points on the other as negative. This boundary is linear in the original feature space, but we can create non-linear boundaries through feature engineering.
For problems with more than two classes, we extend to multiclass classification using techniques like one-vs-rest (train K binary classifiers) or softmax regression (directly model probabilities for all K classes).
This chapter covers:
- Binary Classification: The sigmoid function, decision thresholds, and linear decision boundaries
- Logistic Regression: Maximum likelihood, cross-entropy loss, and why it works
- Multiclass: One-vs-rest, one-vs-one, and softmax approaches
- Naive Bayes: A probabilistic classifier based on Bayes' theorem
- Class Imbalance: Handling datasets where classes have very different frequencies
- Feature Engineering: Polynomial features and transformations to handle non-linear patterns
Chapter Roadmap
Click any topic to jump in
Binary Classification
The core task — separate inputs into two classes using sigmoid probabilities and decision thresholds.
Discriminative vs. generative classifiers for binary problems
Logistic Regression
The workhorse classifier — maximum likelihood estimation with cross-entropy loss and linear decision boundaries.
Naive Bayes
A probabilistic approach using Bayes' theorem with conditional independence — fast, interpretable, strong baseline.
Multiclass Classification
Extend binary methods to K classes with one-vs-rest, one-vs-one, or softmax regression.
Handling imbalanced data and engineering better features
Class Imbalance
Handle skewed class distributions with resampling, class weights, threshold tuning, and proper metrics.
Feature Engineering
Transform raw inputs into informative features — encoding, scaling, selection, and dimensionality reduction.
A bank must decide whether to approve a loan, a hospital whether a scan shows a tumor, an email service whether a message is spam. Each question has exactly two answers, and getting it wrong in one direction usually costs far more than the other. The previous chapter, Linear Regression, predicted continuous numbers such as prices. Its straight-line output is unbounded, so it cannot directly say how likely a yes is, and a number like 1.7 or minus 0.4 is not a probability.
This chapter, Classification, adapts the linear model to discrete outcomes, and this first topic sets up the two-class case. We begin by separating classification from regression. We then introduce the sigmoid function, which squashes any score into the range 0 to 1, and study its symmetry and saturation. Next we turn probabilities into decisions with a threshold, see that a linear score defines a flat decision boundary, and finish by choosing the threshold from the real costs of each kind of mistake rather than defaulting to 0.5.
Definition
Binary classification is the task of learning a function that maps an input feature vector to one of two classes, usually labeled 0 and 1. A probabilistic binary classifier outputs an estimate of the probability that the label is 1, and a decision threshold converts that probability into a hard prediction.
In this topic
Classification vs Regression
The first modeling decision is what kind of output the target is, because it fixes the loss, the metrics, and the final layer of the model. Regression predicts a continuous quantity, such as a price or a temperature, and errors are measured as distances. Classification predicts a discrete category, such as yes or no, or cat, dog, or bird, and errors are counted as right or wrong. Most classifiers first produce a probability for each class and then pick one. A common trap is treating ordered categories, such as ratings from 1 to 5, as regression or as nominal classes without thinking about which errors matter.
Regression models — a continuous conditional expectation. Classification models for discrete — a probability distribution over categories. Using MSE for classification creates a loss surface with flat regions (gradient ) where the sigmoid saturates, stalling gradient descent. Cross-entropy fixes this because has gradient , which remains large even when is near 0 or 1.
Predict house price vs predict if house sells within 30 days. Which is regression, which is classification?
Sigmoid Function
Linear regression gives a score anywhere on the real line, but a probability must lie between 0 and 1. The sigmoid fixes this by mapping to . Large positive scores give outputs near 1, large negative scores give outputs near 0, and gives exactly 0.5. The output is read as the probability that the label is 1. Its derivative has the convenient form , which peaks at 0.25 when . That form makes gradients cheap to compute, and it is why the sigmoid pairs so neatly with cross-entropy loss later in this chapter.
The sigmoid maps . Its derivative is , which peaks at (value ) and vanishes exponentially as . The sigmoid is the canonical link function for Bernoulli-distributed responses in generalized linear models. It arises naturally from the log-odds: if (a linear function of features), then solving for gives exactly the sigmoid. The inverse is the logit function: .
Calculate σ(0) and σ(2).
Sigmoid Properties
Three properties of the sigmoid shape how classifiers behave. First, its range: outputs approach 0 and 1 but never reach them, so a logistic model never claims total certainty. Second, symmetry: , so flipping the sign of the score swaps the two class probabilities, and the two classes are treated alike. Third, saturation: for scores beyond about plus or minus 5, the curve is almost flat and its gradient is near zero. Saturation is harmless with cross-entropy loss, which cancels it, but with squared-error loss it stalls learning on badly wrong examples, which is one reason logistic regression does not use MSE.
The symmetry means the sigmoid is symmetric about the point . This implies that if the linear score flips sign, the predicted probability for class 1 and class 0 swap. Saturation at the extremes ( for and for ) means the function is approximately linear only in a narrow band around where . Outside this band, changes in barely affect the output.
If σ(z) = 0.73, what is σ(-z)?
Decision Threshold
A classifier's probability is not yet a decision. The threshold converts it: predict class 1 when the probability is at least , otherwise class 0. Because the sigmoid is monotonic, this is the same as comparing the raw score with the logit of , which is . The default corresponds to and minimizes error count only when both mistakes cost the same and probabilities are calibrated. Lowering labels more examples positive, raising recall and lowering precision, and raising it does the reverse. The threshold is chosen after training, on validation data, without retraining the model.
The decision rule if is equivalent to if (the logit of ). At , the boundary is . Lowering to 0.1 shifts the boundary to , dramatically expanding the positive prediction region. The optimal threshold minimizes expected cost: , where and are the costs of false positives and false negatives respectively.
Probabilities: [0.3, 0.6, 0.45, 0.8]. Predictions at t=0.5? At t=0.4?
Linear Decision Boundary
The set of points where the classifier is undecided is its decision boundary. For a linear score , the boundary is where , which is a line in two dimensions, a plane in three, and a hyperplane in general. The weight vector is perpendicular to it and points toward class 1. The value of divided by the length of is the signed distance to the boundary, so points far from it get confident probabilities. The limitation is that a single hyperplane cannot separate classes arranged in rings or in XOR patterns, which motivates the feature engineering at the end of this chapter.
The decision boundary is a hyperplane in with normal vector . The signed distance from any point to this hyperplane is , which is proportional to the log-odds. Points farther from the boundary have higher confidence. The margin (distance between the nearest points of each class and the boundary) determines how robust the classifier is to small perturbations in the input.
Boundary: 2x₁ + 3x₂ - 6 = 0. Is point (1, 2) class 0 or 1?
Threshold Tuning
The right threshold comes from the cost of each mistake, not from habit. If a false positive costs and a false negative costs , and the probabilities are calibrated, predicting positive is cheaper on average whenever the probability exceeds . Equal costs give 0.5. In cancer screening a miss is far worse than a false alarm, so the threshold drops sharply. For a spam filter, losing a real email is worse, so it rises. When costs are hard to price, teams pick the threshold that meets a recall or precision target on validation data. This only works if the model's probabilities are calibrated.
The ROC curve plots true positive rate against false positive rate as the threshold varies from 0 to 1. The area under this curve (AUC) measures discrimination ability independent of threshold. The precision-recall curve is more informative for imbalanced data: precision and recall directly reflect performance on the minority class. The score summarizes the tradeoff as a single number.
Cancer detection: missing cancer costs 1,000,000 dollars, a false alarm costs 1,000 dollars. How to set threshold?
Theory Exercise
Problem:
A medical test has P(positive|disease) = 0.95 and P(positive|healthy) = 0.05. If 1% of people have the disease, what is P(disease|positive)?
Hints:
- This is Bayes' theorem
- P(disease) = 0.01, P(healthy) = 0.99
- Calculate P(positive) using total probability
Coding Exercise
Problem:
Implement the sigmoid function in numpy, fit a LogisticRegression on the breast cancer dataset, then sweep the decision threshold from 0.5 down to 0.3 and report how precision and recall trade off.
Hints:
- sigmoid(z) = 1 / (1 + np.exp(-z)); verify sigmoid(0)==0.5.
- Use clf.predict_proba(X_test)[:, 1] to get positive-class probabilities, then apply (probs >= t).astype(int) for each threshold t.
- Use precision_score and recall_score from sklearn.metrics and observe that lowering the threshold raises recall but lowers precision.
Related Problems on PixelBank
The previous topic, Binary Classification, gave us a sigmoid that turns a linear score into a probability, but it left the weights unspecified. How do we find weights that make the probabilities match the data? The obvious idea is to reuse mean squared error from linear regression, but squared error on a sigmoid output gives a non-convex loss with flat regions, where gradient descent stalls on confidently wrong examples.
This topic, Logistic Regression, replaces squared error with a loss built from probability itself. We start with the model, a sigmoid applied to a linear score. We then derive cross-entropy loss and show it is exactly the negative log-likelihood of the labels, which connects training to maximum likelihood estimation. Next comes the gradient, which turns out to have the same error-times-feature form as linear regression. We then read the model through odds and log-odds, add L2 regularization to stop weights from blowing up on separable data, and finish by interpreting each weight as a multiplier on the odds.
Definition
Logistic regression is a linear classifier that models the probability of the positive class as the sigmoid of a weighted sum of the features plus a bias. Its weights are fitted by maximum likelihood, which is equivalent to minimizing binary cross-entropy, and its log-odds are a linear function of the inputs.
In this topic
Logistic Model
Logistic regression combines the two pieces from the previous topic into one model. It computes a linear score , exactly as linear regression does, and passes it through the sigmoid to get the probability that the label is 1. Each weight says how strongly feature pushes the score up or down, and the bias sets the baseline when all features are zero. This is a discriminative model: it learns the conditional probability of the label given the features directly, rather than modeling how the features themselves are distributed, as Naive Bayes does later in this chapter.
The model is a discriminative classifier — it directly models the posterior without modeling the joint distribution . The weight vector is perpendicular to the decision boundary, and is the signed distance from the origin to the boundary. Each weight represents the change in log-odds per unit change in feature : .
w=[0.5, -0.3], b=0.1, x=[2, 1]. What's P(y=1)?
Cross-Entropy Loss
Training needs a loss that rewards assigning high probability to the true label. Binary cross-entropy does this: for each example it charges when the label is 1 and when it is 0, then averages over the examples. A confident correct prediction costs almost nothing, an unsure one costs about 0.69, and a confident wrong one costs a lot, growing without bound as the probability of the true label approaches 0. Unlike squared error on a sigmoid, this loss is convex in the weights, so gradient descent cannot get trapped in a local minimum.
The loss is derived from the negative log-likelihood of the Bernoulli distribution. For , the loss is , which goes to infinity as (confident wrong prediction). The loss surface is convex in when the model is , guaranteeing a unique global minimum. Information-theoretically, cross-entropy measures the expected number of bits needed to encode events from distribution using a code optimized for distribution .
True y=1, model predicts ŷ=0.9 vs ŷ=0.1. Compare losses.
MLE Connection
Cross-entropy is not an arbitrary choice; it falls out of maximum likelihood estimation. Treat each label as a coin flip whose probability of heads is the model's output . The likelihood of the whole dataset is the product of the probabilities the model gave to the labels that actually occurred. Products of many small numbers are awkward, so we take logs, which turns the product into a sum, and negate it so we can minimize. The result is exactly the cross-entropy loss. Minimizing cross-entropy therefore finds the weights under which the observed labels were most probable.
Maximum likelihood seeks . Taking the log and negating converts the product to a sum and max to min: , which is exactly cross-entropy. This means minimizing cross-entropy is equivalent to finding the parameters that make the observed labels most probable under the model. The MLE has desirable statistical properties: it is consistent (converges to true parameters as ) and asymptotically efficient (lowest variance among unbiased estimators).
3 samples: (y=1,ŷ=0.8), (y=0,ŷ=0.3), (y=1,ŷ=0.6). What's the likelihood?
Gradient for Logistic Regression
To minimize cross-entropy with gradient descent we need its gradient, and it comes out remarkably simple. The sigmoid's derivative cancels against the logarithm in the loss, leaving the gradient for each weight as the average of prediction error times feature value, . This is the same form as linear regression's gradient, except that is now a sigmoid output. When the model predicts too low for a positive example, the error is negative, so the gradient step raises the weights of that example's active features. Examples that are already predicted confidently and correctly contribute almost nothing.
The gradient has the same form as linear regression's gradient — the sigmoid's derivative cancels neatly with the log in cross-entropy. This is not a coincidence: both are members of the exponential family, and the gradient of the negative log-likelihood always takes the form . This elegant form means the same gradient descent code works for both linear and logistic regression with only the loss function changed.
Sample: x=[1,2], y=1, ŷ=0.7. What's the gradient for w?
Odds and Log-Odds
Probabilities are bounded, but odds are not, which makes them a natural scale for a linear model. The odds of an event are its probability divided by the probability that it does not happen, ranging from 0 to infinity. Taking the logarithm gives the log-odds, or logit, which ranges over the whole real line. Logistic regression is exactly the assumption that the log-odds are a linear function of the features. This is why it counts as a linear classifier even though its output curve is S-shaped, and why the score can be read directly as evidence measured in log-odds.
The odds ratio is the exponential of the linear predictor. The log-odds (logit) is linear in the features, which is why logistic regression is a linear classifier despite having a nonlinear output. A unit increase in multiplies the odds by : if , the odds double (). This multiplicative interpretation makes logistic regression highly interpretable in domains like medicine and social science.
P(y=1) = 0.8. What are the odds? What are the log-odds?
Regularized Logistic Regression
When the training classes can be separated perfectly, plain logistic regression has no finite best solution. Scaling the weights up always makes the sigmoid steeper and the likelihood higher, so the weights grow without bound and the model becomes overconfident. Adding an L2 penalty to the loss charges for large weights, giving a finite, smoother solution that generalizes better. A larger means stronger shrinkage. Scikit-learn uses the inverse, , so a smaller C means more regularization. L1 regularization instead drives some weights exactly to zero, which performs feature selection.
Adding L2 penalty gives . The penalty prevents weights from growing to infinity when classes are perfectly separable — without regularization, the optimizer keeps increasing to make the sigmoid steeper, approaching a hard step function. Regularization caps this growth, maintaining a smooth probability transition and better generalization. In scikit-learn, the parameter inverts the convention: larger means less regularization.
sklearn C=0.1 vs C=10. Which has more regularization?
Weight Interpretation
Logistic weights have a precise meaning on the odds scale. Increasing feature by one unit, holding the others fixed, adds to the log-odds, which multiplies the odds by , called the odds ratio. A weight of 0.7 roughly doubles the odds, and a negative weight shrinks them. This reading holds in the feature's own units, scaled or not. Standardizing matters only when comparing weights, since a one-unit change in age and a one-unit change in income are not comparable. Correlated features also split credit unpredictably between them, so individual weights should not be read as causal effects.
For a binary feature , the weight equals the log odds-ratio: . For a continuous feature, represents the change in log-odds per unit increase. After standardization, the magnitude indicates relative feature importance. Confidence intervals for can be computed from the Fisher information matrix , giving .
Weight for 'years of experience' = 0.3. Current odds = 2:1. What happens if experience increases by 1?
Theory Exercise
Problem:
Why does logistic regression use cross-entropy loss instead of MSE? What would happen if we used MSE?
Hints:
- Think about the gradient when sigmoid output is near 0 or 1
- Consider the shape of the loss surface
- What about confident wrong predictions?
Coding Exercise
Problem:
Implement binary cross-entropy loss in numpy and verify it decreases as predicted probabilities move toward the true labels. Then fit a LogisticRegression and interpret one coefficient as a change in log-odds.
Hints:
- BCE = -mean(y*log(p) + (1-y)*log(1-p)); clip p to [eps, 1-eps] to avoid log(0).
- Compare BCE for predictions that are far from the labels vs close to them; the closer set should have lower loss.
- A LogisticRegression coefficient is the change in log-odds per unit increase of that (standardized) feature; exp(coef) is the odds ratio.
Related Problems on PixelBank
Many real problems have more than two answers. A digit recognizer must choose among 10 digits, a news classifier among dozens of topics, and an image model among a thousand object categories. The previous topic, Logistic Regression, produces one probability for one yes-or-no question, so it cannot directly say which of K classes is most likely or give a distribution that sums to one.
This topic, Multiclass Classification, extends binary classifiers to many classes in two ways. The first reduces the problem to several binary ones: One-vs-Rest trains one classifier per class, and One-vs-One trains one per pair of classes and lets them vote. The second generalizes the model itself: softmax regression produces a full probability distribution over all K classes in one shot. We study softmax's properties, including temperature, then the multiclass cross-entropy loss that trains it. We close by separating multiclass problems, where exactly one label applies, from multilabel problems, where any number of labels can apply at once.
Definition
Multiclass classification is the task of assigning each input to exactly one of K mutually exclusive classes, where K is greater than 2. It is solved either by combining several binary classifiers, as in One-vs-Rest and One-vs-One, or by a single model, such as softmax regression, that outputs a probability distribution over all K classes.
In this topic
One-vs-Rest (OvR)
One-vs-Rest is the simplest way to reuse a binary classifier for K classes. Train K separate classifiers, where classifier treats class as positive and every other class as negative. At prediction time, run all K and pick the class whose classifier is most confident. It costs only K training runs and works with any binary model. Its weaknesses: each classifier sees an imbalanced problem, one class against all the rest, and the K scores come from independently trained models, so they are not calibrated against each other and need not sum to one. Rifkin and Klautau showed that, well tuned, OvR is often as accurate as fancier schemes.
OvR trains binary classifiers , each treating class as positive and all others as negative. Prediction assigns the class with the highest score: . Training cost is times a single binary classifier. The key limitation: each classifier sees a different class imbalance (1 class vs. ), which biases probability estimates. Platt scaling (fitting a sigmoid on the scores) can calibrate the outputs, but fundamentally the classifiers are not jointly optimized.
3 classes (A,B,C). Classifiers output: P(A vs rest)=0.6, P(B vs rest)=0.3, P(C vs rest)=0.8. Prediction?
One-vs-One (OvO)
classifiers
One-vs-One trains a separate classifier for every pair of classes, in all, and each one learns to tell just two classes apart using only their examples. To predict, every pairwise classifier votes for one of its two classes, and the class with the most votes wins, with ties broken by confidence. Each subproblem is small and balanced, which suits SVMs, whose training cost grows faster than linearly in the number of examples. The drawback is the quadratic count: 10 classes need 45 classifiers and 100 classes need 4,950, so prediction becomes slow for large K.
OvO trains classifiers, one per class pair. Prediction uses majority voting: each classifier casts a vote, and the class with the most votes wins. For , this means 45 classifiers, but each trains on only 2 classes (smaller subsets). OvO is preferred for kernel methods like SVMs where training cost is superlinear in — training 45 small classifiers is faster than 10 large ones. The drawback: prediction time grows as since every classifier must be evaluated.
4 classes. OvO: A beats B, A beats C, A beats D, B beats C, B beats D, C beats D. Prediction?
Softmax (Multinomial)
Softmax regression handles all K classes in one model. It computes a score for each class, each from its own weight vector, then exponentiates every score and divides by the sum of the exponentials. Exponentiating makes every value positive, and dividing makes them sum to 1, so the result is a proper probability distribution. Larger scores get disproportionately more mass, because the exponential grows quickly. With two classes, softmax reduces exactly to the sigmoid of the score difference, so it is the natural generalization of logistic regression. It is also the output layer of almost every neural network classifier.
Softmax converts raw scores into a probability distribution: where . This requires weight parameters (a weight vector per class). The softmax function is the multi-class generalization of the sigmoid: for , softmax reduces to sigmoid. The temperature parameter controls confidence: — as , the distribution becomes one-hot; as , it becomes uniform.
z = [2, 1, 0] for 3 classes. Calculate softmax probabilities.
Softmax Properties
Two properties of softmax matter in practice. First, shift invariance: adding the same constant to every score leaves the output unchanged. Implementations exploit this by subtracting the largest score before exponentiating, which prevents overflow without changing the answer. Second, temperature: dividing the scores by before softmax controls how peaked the distribution is. Low temperatures sharpen it toward a one-hot argmax, and high temperatures flatten it toward uniform. Temperature is used to sample text from language models and, in knowledge distillation, to soften a teacher model's outputs so a student can learn from the relative scores of the wrong classes.
Softmax is invariant to constant shifts: for any scalar . This is exploited for numerical stability by subtracting before exponentiating, preventing overflow. The Jacobian has the same form as the sigmoid derivative when . Softmax outputs are calibrated probabilities only when trained with cross-entropy loss — otherwise the outputs may be overconfident or underconfident and require temperature scaling.
z=[3,1]. Softmax at T=1? At T=0.5?
Cross-Entropy (Multiclass)
Training softmax uses the multiclass version of cross-entropy. The labels are one-hot vectors, with a 1 for the true class and 0 elsewhere, so the double sum over samples and classes collapses: each sample contributes only minus the log probability assigned to its true class. This is again the negative log-likelihood, now of a categorical distribution. The gradient with respect to each score is simply the predicted probability minus the one-hot label, the same elegant form as the binary case. Minimizing this loss pushes up the true class's score and pushes down every other class's score in proportion to the probability it stole.
The multiclass cross-entropy loss uses one-hot encoded labels where if sample belongs to class . This simplifies to where is the true class. The gradient has the same elegant form as the binary case. Cross-entropy is the KL divergence between the true label distribution and the model's predicted distribution, plus the entropy of the true distribution (which is constant).
True class=B. Predicted: P(A)=0.1, P(B)=0.7, P(C)=0.2. Cross-entropy loss?
Multiclass vs Multilabel
Multiclass and multilabel problems look similar but need different output layers. In multiclass classification, exactly one label applies to each example, so a softmax distributes one unit of probability across mutually exclusive classes. In multilabel classification, any subset of labels can apply, such as a photo tagged both outdoor and sunset. That calls for K independent sigmoids, one per label, each trained with its own binary cross-entropy, and each thresholded separately. Using softmax for a multilabel task is a common bug: it forces the labels to compete, so a photo that is both cute and fluffy can never score high on both.
Multiclass: each sample belongs to exactly one of mutually exclusive classes — outputs sum to 1 via softmax. Multilabel: each sample can belong to multiple classes simultaneously — each output is an independent sigmoid producing independent probabilities. The loss for multilabel is the sum of binary cross-entropies. A photo can be tagged "cat" AND "outdoor" (multilabel) but a tumor can only be "benign" OR "malignant" (multiclass). The distinction determines the output activation (softmax vs. independent sigmoids) and loss function.
Classify animal photo: (a) cat/dog/bird, (b) cute/scary/fluffy. Which is multiclass vs multilabel?
Theory Exercise
Problem:
You have a 5-class classification problem. Compare OvR vs OvO: how many classifiers are needed? When might you prefer each?
Hints:
- OvR: one classifier per class
- OvO: one classifier per pair
- Think about training data balance
Coding Exercise
Problem:
Implement a numerically-stable softmax in numpy (subtract the row max), verify each output row sums to 1, then fit a LogisticRegression on the iris dataset (multinomial is the default).
Hints:
- Subtract the per-row max before np.exp to prevent overflow: exp(z - z.max(axis=1, keepdims=True)).
- Normalize by the row sum with keepdims=True so broadcasting works; check np.allclose(rows.sum(axis=1), 1).
- Fit LogisticRegression(max_iter=...) directly on iris X, y — do NOT pass multi_class= (deprecated).
Related Problems on PixelBank
Suppose you need a spam filter by tomorrow, with only a few thousand labeled emails and a vocabulary of 50,000 words. The discriminative models from the previous topics, Logistic Regression and Multiclass Classification, learn a weight for every word by iterative optimization and can overfit on so little data. A different strategy is to model how each class generates its features, then flip the question around with probability theory.
This topic, Naive Bayes, takes that generative route. We start from Bayes' theorem, which turns the probability of the features given a class into the probability of the class given the features. We then make the naive assumption that features are independent within each class, which reduces the estimation problem to simple counting. Next comes the classification rule and why it is computed in log space. We then cover the two most common variants, Gaussian Naive Bayes for continuous features and Multinomial Naive Bayes for word counts, and finish with Laplace smoothing, which stops a single unseen word from zeroing out an entire prediction.
Definition
Naive Bayes is a family of generative classifiers that apply Bayes' theorem under the assumption that features are conditionally independent given the class. Each class-conditional feature distribution is estimated separately, and the prediction is the class that maximizes the prior probability times the product of the per-feature likelihoods.
In this topic
Bayes' Theorem
Bayes' theorem lets us compute the probability we want from probabilities that are easy to estimate. We want the posterior, the probability of class given features . The theorem writes it as the likelihood, the probability of seeing in class , times the prior, how common is, divided by the evidence, the overall probability of . Likelihoods and priors can be counted from labeled data. The evidence is the same for every class, so it only normalizes. A frequent mistake is confusing the likelihood with the posterior: a word common in spam is not automatically strong evidence of spam if it is also common elsewhere.
Bayes' theorem inverts the direction of conditioning. The prior encodes class frequency in the training data. The likelihood captures the distribution of features within each class. The evidence is a normalizing constant. Since we only need , we can ignore and compare numerators directly. This makes Naive Bayes a generative classifier — it models the joint rather than the posterior directly.
P(spam)=0.3, P('free'|spam)=0.8, P('free'|not spam)=0.1. Email contains 'free'. P(spam|'free')?
Naive Independence Assumption
Estimating the joint likelihood of all features within each class is hopeless: with 50,000 binary word features there are combinations. The naive assumption is that features are conditionally independent once the class is known, so the joint likelihood factors into a product of one-feature terms. Each term needs only a simple count, and the parameter count grows linearly with the number of features. The assumption is almost always false, since words such as 'free' and 'money' co-occur. It still works for classification because only the ranking of classes matters, even when the probabilities themselves become badly overconfident.
The "naive" assumption factorizes the joint likelihood into a product of marginals. This reduces the number of parameters from (full joint) to (marginals), making estimation feasible with limited data. The assumption is almost always violated in practice — features like "word A" and "word B" co-occur in spam emails. Despite this, Naive Bayes often works well because classification only requires getting the ranking of correct, not the exact probabilities. The decision boundary is still correct even when probability estimates are poorly calibrated.
Spam email: P('free'|spam)=0.8, P('money'|spam)=0.7. What's P('free','money'|spam) under naive assumption?
Classification Rule
To classify, Naive Bayes picks the class with the largest posterior. The evidence term is shared by every class, so it can be dropped, leaving the prior times the product of feature likelihoods. In practice we compare sums of log probabilities instead of products. Multiplying hundreds of small probabilities underflows floating point to exactly zero, which makes every class tie. Because the logarithm is monotonic, taking logs never changes which class wins. Writing the rule in log space also exposes its structure: for multinomial and Bernoulli models it is a linear function of the features, so Naive Bayes is a linear classifier, just fitted by counting instead of by optimization.
The decision rule avoids computing the denominator . In practice, we work with log-probabilities: to avoid numerical underflow from multiplying many small probabilities. The decision boundary is linear in the log-probability space: defines a hyperplane when the class-conditional distributions are Gaussian with equal covariance.
P(A)×P(x|A)=0.0002, P(B)×P(x|B)=0.00015. Prediction? Why use log?
Gaussian Naive Bayes
For continuous features, Gaussian Naive Bayes assumes each feature follows a normal distribution within each class. Training is just computing a mean and a variance for every feature-class pair, numbers for features and classes. To classify, evaluate each feature's normal density under each class, multiply them with the prior, and pick the largest. Because each class has its own variance, the boundary between classes is quadratic, not linear. The method fails when a feature is strongly non-normal, such as bimodal or heavily skewed, so transforming or binning such features first often helps.
Assumes — each feature follows a Gaussian distribution within each class, with class-specific mean and variance . This requires estimating parameters ( and for each feature-class pair). The log-likelihood for feature given class is . The decision boundary between classes depends on the quadratic vs. terms.
Height|Male: μ=175, σ=10. Height|Female: μ=162, σ=8. Person is 170cm. Which is more likely?
Multinomial Naive Bayes
Multinomial Naive Bayes is the standard variant for text. It models a document as a bag of word counts and gives each class its own probability of producing each word, estimated as the word's count in that class divided by the total words in the class. A document's log-likelihood is the sum, over words, of count times log word probability, so repeated words add evidence. Training takes one pass of counting over the corpus. It remains a strong baseline for spam filtering and topic classification, especially with small datasets, though it ignores word order and needs smoothing for rare words.
For text classification with word counts, where is the probability of word appearing in class . Given a document with word counts for vocabulary of size , the likelihood is . Parameters are estimated by counting: . This is the maximum likelihood estimate for the multinomial distribution.
In spam corpus: 'free' appears 500 times out of 10,000 words. P('free'|spam)?
Laplace Smoothing
Counting has a fatal flaw: a word that never appeared with a class in training gets probability zero for it, and one zero in the product wipes out all other evidence. Laplace smoothing adds a pseudocount , usually 1, to every word count, and adds times the vocabulary size to the denominator so the probabilities still sum to one. Unseen words now get a small positive probability, and estimates for frequent words barely change. Smaller values of , such as 0.1, smooth less and are often tuned by cross-validation. It is a simple form of Bayesian prior on word frequencies.
Adding a pseudocount to every word-class count: where is vocabulary size. Without smoothing, a word never seen in class gives , zeroing out the entire posterior regardless of other features. With (Laplace), unseen words get probability instead of 0. This is equivalent to placing a uniform Dirichlet prior on the multinomial parameters — a Bayesian approach where the prior regularizes the maximum likelihood estimate.
Word 'cryptocurrency' never seen in training. Without smoothing, P('cryptocurrency'|spam)=0. Problem?
Theory Exercise
Problem:
Why does Naive Bayes work well for spam detection even though the independence assumption is violated (words like 'Nigerian' and 'prince' are correlated)?
Hints:
- Think about what we're actually trying to do
- We need ranking, not exact probabilities
- Consider the bias-variance tradeoff
Coding Exercise
Problem:
Fit a GaussianNB on the continuous iris features and report accuracy. Then, on small integer count data, show how the Laplace smoothing parameter alpha in MultinomialNB changes the predicted class probabilities.
Hints:
- GaussianNB assumes each feature is Gaussian per class — fit it directly on iris X, y.
- Build a tiny MultinomialNB count matrix with some zero counts so smoothing matters.
- Compare predict_proba with a small alpha (e.g. 1e-10, near no smoothing) vs alpha=1.0 (Laplace); larger alpha pulls probabilities toward uniform.
Related Problems on PixelBank
Fraud makes up about 0.1 percent of card transactions, and a rare disease may affect 1 patient in 1,000. A classifier trained naively on such data can reach 99.9 percent accuracy by always predicting the common class, while missing every case we actually care about. The models from the previous topics, Logistic Regression and Naive Bayes, minimize average loss, so with this much imbalance the majority class dominates the gradient and the priors.
This topic, Class Imbalance, covers the problem and the standard fixes. We start by showing why accuracy fails as a metric. We then cover the data-level fixes: oversampling the minority class, including the synthetic SMOTE method, and undersampling the majority class. Next come the algorithm-level fixes: class weights that make each minority mistake count more, and threshold adjustment that trades precision for recall after training. We finish with the metrics that tell the truth on imbalanced data, especially precision, recall, F1, and the area under the precision-recall curve.
Definition
Class imbalance is a classification setting in which one class has far fewer examples than the others, so a model that minimizes average loss can largely ignore it. Remedies include resampling the training data, weighting the loss by class, moving the decision threshold, and evaluating with metrics such as recall and precision-recall AUC instead of accuracy.
In this topic
The Problem
Imbalance breaks training and evaluation at once. In training, a loss averaged over examples is dominated by the majority class, so the cheapest way to lower it is to push every prediction toward the common label. In evaluation, accuracy rewards exactly that: if 99 percent of examples are negative, predicting negative for everything scores 99 percent while finding no positives. The rare class is usually the one that matters, such as fraud, disease, or defects. The first step is always to compute the majority-class baseline, and then judge models by recall and precision on the minority class.
With class ratio 1:100, a model predicting the majority class always achieves 99% accuracy but 0% recall on the minority class. The loss function is dominated by the majority class: , and since , the gradient points almost entirely toward minimizing majority class errors. The decision threshold at is miscalibrated — the model's estimated is biased toward the prior , so even samples that are truly positive often get probabilities below 0.5.
Fraud detection: 9,900 legit, 100 fraud. Model predicts ALL legit. Accuracy?
Resampling: Oversampling
Oversampling rebalances the training set by adding minority examples. Random oversampling duplicates existing minority points, which is simple but encourages the model to memorize those exact points. SMOTE instead creates synthetic points: for a minority example, pick one of its nearest minority neighbors and place a new point at a random position on the segment between them. This fills in the minority region rather than stacking copies. Risks remain: SMOTE can create points inside majority territory when classes overlap. Resample only the training folds, never before splitting, or synthetic copies of test points leak into training.
Random oversampling duplicates minority class examples, creating a balanced training set. SMOTE (Synthetic Minority Over-sampling TEchnique) generates synthetic examples by interpolating between nearest neighbors: where . This expands the minority class region in feature space rather than just duplicating points. The risk is generating noisy synthetic points in overlapping regions between classes, which can blur the decision boundary.
100 fraud, 9900 legit. Apply SMOTE to make 5000 fraud. How?
Resampling: Undersampling
Undersampling rebalances by removing majority examples. Random undersampling keeps a random subset of the majority class, which makes training fast and balanced but throws away information, sometimes most of the dataset. Informed methods remove examples more selectively. Tomek links remove majority points that sit right next to a minority point, cleaning the boundary, and Edited Nearest Neighbors removes majority points misclassified by their neighbors. Another option is to train several models on different random majority subsets and combine them, as in EasyEnsemble, so all the data is used. Undersampling suits huge datasets where the majority class is highly redundant.
Random undersampling discards majority class examples to match minority count. This is simple but throws away potentially useful data — if the minority class has 100 samples, we keep only 100 of 10,000 majority samples. Informed undersampling methods like Tomek Links remove majority samples that are nearest neighbors of minority samples (cleaning the boundary region). Ensemble approaches like EasyEnsemble train multiple classifiers on different random subsets of the majority class, then combine predictions via voting.
100 fraud, 9900 legit. Random undersample to 100 legit. Issue?
Class Weights
Class weights change the loss instead of the data. Each example's loss is multiplied by a weight for its class, so mistakes on the minority class cost more and pull the gradient harder. The common balanced scheme sets , where is the total count, the number of classes, and the size of class . Each class then contributes equally to the total loss. This matches oversampling in expectation, without enlarging the dataset or creating duplicates. In scikit-learn, set class_weight='balanced'. Weighting shifts predicted probabilities upward for the minority class, so they are no longer calibrated.
Weighted loss assigns weight to class , so each class contributes equally to the total loss regardless of size. With 100:1 ratio, minority samples get weight 100. This is equivalent to oversampling without actually duplicating data. In scikit-learn, class_weight='balanced' computes . The gradient for a minority sample becomes 100 larger, forcing the model to pay attention to minority class errors during optimization.
100 fraud, 9900 legit (n=10000, K=2). What are balanced class weights?
Threshold Adjustment
The cheapest fix for imbalance needs no retraining: move the decision threshold. A model trained on imbalanced data often ranks examples well but rarely pushes minority probabilities above 0.5, so lowering the threshold recovers many missed positives. The tradeoff is more false alarms, so recall rises while precision falls. Choose the threshold on a validation set, never the test set, using the F1 score, a recall target, or expected cost. It combines well with class weights or resampling, and it is the right first step whenever the model's ranking, measured by ROC or precision-recall AUC, is already good.
Even with balanced training, the default threshold of 0.5 may not be optimal. For imbalanced problems, the optimal threshold is often lower than 0.5 because we want to catch more minority class instances. The precision-recall curve directly shows the tradeoff for each threshold. The optimal threshold can be selected to maximize score: , where weighs recall higher (appropriate when missing positives is costly).
At t=0.5: precision=80%, recall=20%. At t=0.2: precision=30%, recall=85%. Which for fraud?
Metrics for Imbalanced Data
Metrics for imbalanced problems must focus on the minority class. Precision is the share of predicted positives that are real, and recall is the share of real positives that are found. F1 is their harmonic mean, which stays low if either is low. ROC-AUC measures ranking across all thresholds but uses the false positive rate, whose denominator is the huge negative class, so thousands of false alarms barely move it. Precision-recall AUC uses precision instead, so it exposes those false alarms. Its random baseline equals the positive rate, which is why it is the preferred summary for rare-event problems.
Accuracy is misleading for imbalanced data — always predict majority class for 99% accuracy with 0% minority recall. Better metrics: precision (of those predicted positive, how many are correct), recall (of those actually positive, how many did we find), and (harmonic mean — low if either is low). Matthews Correlation Coefficient uses all four confusion matrix entries and ranges from -1 to +1.
1% positive rate. Model A: ROC-AUC=0.95. Model B: ROC-AUC=0.93, PR-AUC=0.60 vs 0.40. Which is better?
Theory Exercise
Problem:
A fraud detection model has: 99.5% accuracy, 40% precision, 80% recall. Is this a good model? What do these metrics tell you?
Hints:
- Think about what precision and recall mean
- Consider the base rate of fraud
- Calculate how many false positives vs true positives
Coding Exercise
Problem:
Use make_classification with weights=[0.95, 0.05] to build an imbalanced dataset. Show that high accuracy is misleading versus a majority-class baseline, then retrain LogisticRegression with class_weight='balanced' and report the improvement in minority recall and F1.
Hints:
- Pass weights=[0.95, 0.05] to make_classification and use stratify=y in the split.
- Compare model accuracy to the trivial baseline of always predicting the majority class (~0.95).
- Refit with class_weight='balanced' and compare recall_score / f1_score on the minority class.
Related Problems on PixelBank
A linear classifier draws one flat boundary, yet many real patterns are curved, involve interactions, or arrive as text categories rather than numbers. The classifiers from the earlier topics, such as Logistic Regression and Naive Bayes, can only learn what their input features let them express. Feed them raw city names, features on wildly different scales, or an XOR pattern, and they either fail outright or train badly.
This topic, Feature Engineering, closes the chapter by transforming the inputs instead of the model. We start with polynomial features, which let a linear model learn curved boundaries and even solve XOR. We then cover feature scaling, which makes gradient descent and regularization behave. Next come three ways to encode categorical variables: one-hot encoding, label encoding, and target encoding, each with its own pitfalls. We then cover feature selection, contrasting fast filter methods with accurate but expensive wrapper methods, and finish with dimensionality reduction, which builds a few compact features out of many correlated ones.
Definition
Feature engineering is the process of transforming raw input variables into representations that make patterns easier for a model to learn. It includes creating new features such as polynomials and interactions, scaling numeric features, encoding categorical variables as numbers, selecting informative subsets of features, and compressing many features into fewer ones.
In this topic
Polynomial Features
A linear model can learn curved boundaries if we give it curved features. Polynomial expansion adds powers of each feature, such as , and interaction terms, such as . The model stays linear in its weights, so training is unchanged, but its boundary in the original space becomes a curve: a circle, an ellipse, or a saddle. The cost is rapid growth: degree 2 on 100 features produces 5,150 features, and degree 3 produces 176,850. That invites overfitting, so polynomial features are almost always paired with regularization, and kernels offer a way to get the same effect without building the features explicitly.
Adding polynomial terms and interaction terms enables linear classifiers to learn nonlinear decision boundaries. The decision boundary is linear in the transformed space but nonlinear in the original space . For example, defines a circle or ellipse in space. The number of degree- features for inputs is , which grows rapidly.
XOR problem: (0,0)→0, (1,1)→0, (0,1)→1, (1,0)→1. Not linearly separable. Add x₁x₂. Now?
Feature Scaling
Features measured in different units can distort training. If income ranges into the hundreds of thousands while age ranges up to about 90, the loss surface becomes a long narrow valley, and gradient descent zigzags across it instead of heading to the minimum. Regularization also penalizes weights unevenly, because a feature's weight size depends on its units. Standardization subtracts the mean and divides by the standard deviation , giving zero mean and unit variance. Min-max scaling instead maps values to the range 0 to 1. Fit the scaler on training data only and reuse those numbers on test data. Tree models are unaffected by scaling.
Gradient-based optimizers converge faster when features have similar scales. Standardization () centers at zero with unit variance; normalization () maps to . For logistic regression, unscaled features cause the loss landscape to have elongated contours — gradient descent zigzags instead of heading straight to the minimum. Distance-based methods (KNN, SVM) are particularly sensitive: a feature ranging 0-1000 will dominate Euclidean distance over a feature ranging 0-1.
Age: μ=35, σ=10. Person age=55. Standardized value?
One-Hot Encoding
Models need numbers, but many features are nominal categories with no order, such as city or color. One-hot encoding creates one binary column per category, with a 1 in the column for the example's category and 0 elsewhere. No false ordering is introduced, and a linear model learns a separate effect for each category. For an unregularized linear model with an intercept, keep only of the columns, because the full set always sums to 1 and duplicates the intercept, the dummy variable trap. Regularized models and trees can keep all . High-cardinality features, such as zip codes, produce thousands of sparse columns.
Converts a categorical variable with levels into binary columns: category maps to a vector with 1 in position and 0 elsewhere. For linear models, use columns (drop one as reference) to avoid perfect multicollinearity with the intercept — the dropped category's effect is absorbed into the intercept. One-hot encoding preserves the categorical nature: the model can learn a different coefficient for each level. The cost is dimensionality — a feature with 1000 categories adds 999 dimensions.
City: [NYC, LA, Chicago]. One-hot encode 'LA'. Why drop one column?
Label Encoding
Label encoding replaces each category with an integer, such as 0, 1, and 2. That is correct for ordinal categories, where the order means something, such as small, medium, and large. For nominal categories it invents a false order and false spacing: a linear model would treat green as twice as far from red as blue is, which is meaningless. Tree-based models are more forgiving, because they split on thresholds and can isolate any integer value with a few splits, so label encoding is often acceptable there. For linear models and neural networks, use one-hot encoding or learned embeddings for nominal features.
Maps each category to an integer: . This implicitly assumes an ordinal relationship (dog is "between" cat and bird), which is incorrect for nominal categories. For tree-based models (decision trees, random forests), label encoding works fine because splits like can isolate any subset of categories. For linear models, the imposed ordering introduces spurious linear relationships — always use one-hot encoding for nominal features with linear classifiers.
Size: [S, M, L] → [0, 1, 2]. Color: [Red, Blue, Green] → [0, 1, 2]. Which encoding is valid?
Target Encoding
High-cardinality categories, such as zip codes with tens of thousands of values, make one-hot encoding unwieldy. Target encoding replaces each category with the mean target value observed for it, producing a single numeric column. Two dangers come with it. Rare categories get noisy means, so we shrink them toward the global mean, weighting by sample size. And computing the encoding from the same rows the model trains on leaks the label into the feature, so encodings must be computed out-of-fold, using only other folds' data. Scikit-learn's TargetEncoder does that cross-fitting automatically.
Replaces each category level with the mean of the target variable for that level: . This reduces a high-cardinality feature (e.g., zip code with 40,000 levels) to a single numeric column while preserving predictive information. The risk is target leakage: the encoding uses values from the training set, which can overfit — rare categories with few samples get noisy estimates. Regularization strategies include adding noise, using leave-one-out encoding (exclude the current sample's ), or Bayesian shrinkage toward the global mean.
City NYC: 80% churn rate (40 samples). City Smalltown: 90% churn (2 samples). Target encode both?
Feature Selection: Filter Methods
Filter methods score each feature by itself against the target, then keep the top scorers, without training the final model. Common scores are correlation for linear relationships, mutual information for any dependence, the chi-squared statistic for categorical features, and the ANOVA F-test. They are fast, scaling to thousands of features, and reduce overfitting and training time. Their blind spot is interactions: a feature useless alone, but powerful in combination, gets discarded, and two redundant copies of the same signal are both kept. They are best used as a quick first pass before a more careful method.
Filter methods rank features by statistical association with the target, independent of the model. Common scores: mutual information (captures nonlinear dependencies), chi-squared (for categorical features), and ANOVA F-statistic (ratio of between-group to within-group variance). Filter methods are fast () but evaluate features independently — they miss redundant features and informative feature combinations.
100 features. Correlation with target: X₁=0.8, X₂=0.7, X₃=0.01. Keep which?
Feature Selection: Wrapper Methods
Wrapper methods judge feature subsets by actually training and validating the model on them, so they capture interactions and redundancy that filters miss. Forward selection starts empty and repeatedly adds the feature that most improves the validation score. Backward elimination starts with everything and repeatedly removes the least useful feature. Recursive feature elimination drops the features with the smallest model weights or importances in each round. The price is compute: every candidate subset costs a full training run, ideally with cross-validation. Searching too many subsets also overfits the validation set, so confirm the final choice on held-out data.
Wrapper methods evaluate feature subsets by training and testing the actual model. Forward selection starts with zero features and greedily adds the best one at each step ( model fits). Backward elimination starts with all features and removes the least useful ( fits). Exhaustive search over all subsets is optimal but intractable for . Recursive Feature Elimination (RFE) trains the model, ranks features by importance (e.g., weight magnitude), removes the weakest, and repeats — a practical approximation to backward elimination.
Forward selection: start empty. Add features one by one, keeping best. 50 features, want 5. How many models trained?
Dimensionality Reduction
Instead of choosing a subset of the original features, dimensionality reduction builds a few new ones from all of them. PCA finds orthogonal directions of maximum variance and projects the data onto the top , usually enough to keep about 95 percent of the variance. It removes multicollinearity, cuts training time, and can reduce overfitting. LDA instead uses the labels to find directions that separate the classes best, and autoencoders learn nonlinear compressions. The costs: the new features are mixtures that are hard to interpret, and PCA ignores the labels, so a low-variance direction it discards may be the one that predicts the target.
PCA finds directions of maximum variance: the first principal component captures the most variance, and subsequent components are orthogonal. The eigenvalues of the covariance matrix measure variance along each component. Retaining components that explain 95% of total variance () is a common heuristic. Unlike feature selection, PCA creates new features that are linear combinations of originals, making interpretation harder but often capturing more information in fewer dimensions.
100 correlated features. PCA keeps 95% variance with 10 components. Trade-off?
Theory Exercise
Problem:
You have a classification problem with 10,000 samples and 500 features. You suspect many features are irrelevant. What preprocessing steps would you take?
Hints:
- Consider feature selection methods
- Think about regularization
- What about feature correlations?
Coding Exercise
Problem:
Build a scikit-learn Pipeline that standardizes features before LogisticRegression (preventing leakage via cross-validation), and compare its cross-validated accuracy against a SelectKBest filter that keeps only the top features.
Hints:
- Wrap StandardScaler and LogisticRegression in a Pipeline so scaling is fit only on training folds inside cross_val_score.
- Run cross_val_score on the full-feature pipeline to get a leakage-free baseline.
- Insert SelectKBest(f_classif, k=...) between the scaler and classifier to do filter-based feature selection and compare scores.