Part of Language AI Handbook
Covers linear classifiers, from weighted dot products and decision boundary geometry to softmax for multiclass problems, gradient descent training.
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
Linear Classifiers
Before studying the complex architectures of modern neural networks, it pays to understand their fundamental building block: the linear classifier. Every neuron in a deep network applies a linear classifier followed by a nonlinearity. Understanding linear classifiers thoroughly means that when you later study multilayer perceptrons and backpropagation, the mechanics will feel natural rather than mysterious.
Linear classifiers make predictions by computing a weighted sum of input features and comparing the result against a threshold. They draw straight lines (or, in higher dimensions, hyperplanes) to separate data into categories. This simplicity limits what they can model, but it also makes them fast, interpretable, and mathematically tractable. Most of the machinery for training neural networks was developed in the context of linear classifiers first, including gradient descent, the concept of a loss function, and regularization. A solid grip on these ideas at the linear level pays dividends throughout the rest of this book.
The story of linear classifiers is in many ways the story of how machine learning learned to learn. Before statistical learning, classifiers were hand-coded: a programmer would read documents and write rules like "if the word 'free' appears more than twice, flag as spam." These rules broke as soon as the world changed. Learning-based classifiers replaced hand-crafted rules with a process that adjusts parameters automatically from labeled examples. The linear classifier is the simplest instantiation of this idea, and it is still the right tool for many practical problems today.
In this chapter, you will build linear classifiers from scratch. You will learn how weights and biases define decision boundaries, why the dot product is the central operation, and how logistic regression turns a raw score into a probability. We will extend to multiclass problems with the softmax function, apply these ideas to text classification, and train a complete model with gradient descent. We then examine regularization, the perceptron as a historical precursor, the connection to maximum likelihood estimation, and what linear classifiers fundamentally cannot do. These limitations motivate the nonlinear architectures in the chapters ahead.
The Core Idea: Weighted Voting
At its heart, a linear classifier is a voting system. Each input feature casts a vote, weighted by its importance, and the votes are summed to produce a decision score. Consider spam detection: words like "free" and "winner" should push the score toward spam, while words like "meeting" and "quarterly" should push it toward legitimate email. The classifier does not think about these words in the way a human reader does. It simply accumulates a numerical score, and the accumulated value determines the outcome.
This weighted voting metaphor reveals something important about the nature of linear models: they treat features independently. The contribution of "free" to the spam score does not depend on what other words are present in the email. The classifier cannot detect that "free" is less suspicious when it appears in "free of charge for your order confirmation" (a transactional email) versus "claim your FREE prize now" (spam). That kind of contextual reasoning requires feature interactions that linear classifiers cannot represent, a point we return to in the limitations section. But for many problems, independent feature voting works remarkably well.
A linear classifier predicts a class based on a linear combination of input features. For an input vector , a weight vector , and a bias scalar , the classifier computes the score and predicts the positive class if , otherwise the negative class.
The computation is a dot product plus a bias term. Given input and weights , the score is:
where:
- : the dimensionality of the input (number of features)
- : the -th input feature value
- : the weight assigned to feature , determining its contribution
- : the bias term, which shifts the decision threshold away from zero
- : the resulting score, which can be any real number
Let us make this concrete with a movie review example. We represent each review as a vector of word counts, and define weights that express our prior belief about which words indicate sentiment.
import numpy as np
# Features: [count of "great", count of "terrible", count of "loved", count of "boring"]
# Positive sentiment words get positive weights; negative words get negative weights
weights = np.array([0.8, -0.9, 0.7, -0.6])
bias = -0.2
# Three example reviews represented as feature vectors
review_1 = np.array([3, 0, 2, 0]) # "great" 3x, "loved" 2x
review_2 = np.array([0, 2, 0, 3]) # "terrible" 2x, "boring" 3x
review_3 = np.array([1, 1, 1, 1]) # one of each word
def classify(x, w, b):
"""Return (score, label) for a feature vector x."""
score = np.dot(w, x) + b
label = "positive" if score > 0 else "negative"
return score, labelReview 1 (enthusiastic): score = 3.60 -> positive Review 2 (disappointed): score = -3.80 -> negative Review 3 (mixed): score = -0.20 -> negative
Review 1, dominated by positive words, scores high and is classified as positive. Review 2, dominated by negative words, scores below zero and is classified as negative. Review 3 is close to zero, sitting near the decision boundary, which reflects its mixed sentiment. The weights encode both which features matter and in which direction they push the decision.
Notice how the bias term creates a slight skepticism in the classifier: a review needs some positive signal before it gets a positive label, rather than defaulting to positive on a neutral input. You can think of the bias as encoding the prior: how likely is positive sentiment before looking at any evidence?
The Dot Product as Similarity
The dot product has a geometric interpretation that becomes central as we progress through this book. It measures how aligned the input vector is with the weight vector . More precisely, for vectors of unit length, , where is the angle between them. When the two vectors point in similar directions ( small), the dot product is large and positive. When they point in opposite directions ( near ), the dot product is large and negative. When they are orthogonal (), the dot product is zero.
You can think of the weight vector as encoding the "ideal positive example" for the classifier. An input that closely resembles this ideal template scores high. An input that is the opposite scores low. This template-matching interpretation carries through to the attention mechanism in transformers: the query-key dot product in self-attention performs the same similarity computation, scaled up across thousands of dimensions and computed in parallel across all token pairs. Linear classifiers and attention heads are, at their computational core, doing the same basic thing.
The dot product is also the operation at the heart of linear regression, support vector machines, and word embedding comparisons like cosine similarity. Understanding it at the level of linear classifiers creates an intuition that transfers across all of these tools.
Why the Weighted Sum Works
It may seem surprising that such a simple formula, a weighted sum of features, works well for tasks as complex as language classification. Several reasons explain its effectiveness.
First, in many real-world problems, a small number of features carry most of the predictive signal, and these features act roughly independently. For spam detection, the presence of certain words is highly predictive regardless of context, because spammers reliably use the same vocabulary. A weighted sum over a bag-of-words representation can capture this pattern very effectively.
Second, with enough features, even linear classifiers can approximate nonlinear decision surfaces in the original input space. TF-IDF weighting, n-grams, and other feature engineering transformations implicitly create features that make problems more linearly separable. Before the deep learning era, practitioners spent enormous effort designing feature sets that would make linear models competitive with more complex alternatives. These efforts succeeded often enough that logistic regression remained a strong baseline well into the era of neural networks.
Third, linear classifiers have strong theoretical guarantees. They converge to a global optimum when the training objective is convex (as cross-entropy loss is for logistic regression). They generalize well when regularized, with formal bounds on the gap between training and test performance. And they are interpretable: you can read off the weights to understand what the model learned. These properties make them valuable as baselines and as deployed models in high-stakes settings where transparency matters.
The Geometry: Decision Boundaries
Understanding linear classifiers geometrically reveals both their power and their limitations. In two dimensions, the decision boundary is a line. In three dimensions, it is a plane. In dimensions, it is a -dimensional hyperplane. The critical insight is that this boundary is always flat.
The decision boundary is defined by the equation:
where:
- : the weight vector (the normal to the hyperplane)
- : a point on the boundary
- : the bias, which shifts the boundary parallel to itself (without , the boundary must pass through the origin)
On one side of this hyperplane, and the classifier predicts the positive class. On the other side, and it predicts the negative class.
The weight vector is always perpendicular to the decision boundary and points toward the positive region. To see why: for any two points and that both lie on the decision boundary (so both satisfy ), their difference satisfies:
where:
- : any vector lying in the decision boundary hyperplane
- The equation shows this vector is orthogonal to , confirming is the normal direction

The score gives more than just a class label: it also provides a measure of confidence. Points far from the boundary have large absolute scores, indicating the classifier is confident. Points close to the boundary have scores near zero, indicating uncertainty. This magnitude becomes important when we convert scores to probabilities.
The distance from a point to the decision boundary has a precise geometric meaning. It equals , the absolute score divided by the norm of the weight vector. A point with a high absolute score is geometrically far from the boundary, explaining why large scores correspond to high confidence. This distance interpretation connects linear classifiers to support vector machines (SVMs), which find the linear boundary that maximizes the minimum distance to any training point. SVMs are essentially linear classifiers with a specific training objective (maximum margin) rather than cross-entropy loss.
Changing the Boundary Through Weight Changes
Training a linear classifier means finding the weight vector and bias that place the decision boundary in a good location, separating the training classes as cleanly as possible. As changes direction, the hyperplane rotates. As changes, the hyperplane translates parallel to itself. Together, these degrees of freedom (one per feature plus the bias) determine the full family of linear boundaries.
An important observation is that scaling and by the same constant does not change the decision boundary at all. Multiplying and by 2 produces the same hyperplane, but the raw scores are twice as large, and the sigmoid transformation of those scores produces more extreme probability estimates. This means the norm controls model confidence while the direction controls the boundary location. Regularization, which we discuss later, constrains to prevent the model from becoming overconfident.
Weights and Bias: What They Encode
The weight vector has a direct interpretation. Each element tells the classifier how much feature contributes to the positive class decision. A large positive means feature strongly indicates the positive class. A large negative means feature strongly indicates the negative class. A near zero means feature is irrelevant for this decision.
For text classification with a bag-of-words representation (which you encountered in the Bag of Words chapter), the weights are word-level indicators. After training, you can inspect the top-weighted words to understand what the classifier has learned. For sentiment analysis, words like "excellent," "outstanding," and "recommend" will have large positive weights, while "awful," "disappointing," and "refund" will have large negative weights. This interpretability is one of the most practically valuable properties of linear classifiers. When a model makes an error, you can trace the error back to which features were responsible and understand whether the model's reasoning is coherent or whether the training data contains a misleading pattern.
The bias sets the base rate for the classifier. If you set to a large positive value, the classifier will predict the positive class for almost every input, regardless of features. This is appropriate when the positive class is very common in the training data and the prior probability is high. Conversely, a large negative bias makes the classifier predict the negative class by default unless features strongly push it positive. In a well-trained model, the bias adjusts to reflect class imbalance in the training set, effectively encoding a prior probability before any evidence is considered.
Sparse vs. Dense Features
The behavior of linear classifiers changes significantly depending on whether the feature space is sparse or dense. With bag-of-words representations in NLP, feature vectors are typically very sparse: a document might contain only a few hundred unique words out of a vocabulary of tens of thousands. Most entries in are zero. The dot product then only involves the non-zero entries, and the classifier effectively sums votes only from words present in the document.
Dense feature representations, such as averaged word embeddings or sentence vectors from a pretrained encoder, give every dimension a non-zero value. The classifier must consider the full vector, and every dimension can affect the decision. Logistic regression on top of dense embeddings is a common pattern in modern NLP, used as a lightweight classification head on top of a frozen pretrained model. The embeddings provide rich features; the linear classifier provides a trainable decision layer. This separation of feature extraction from classification is a recurring architectural pattern throughout this book.
Logistic Regression: From Score to Probability
The raw score can be any real number, from negative infinity to positive infinity. This makes it hard to interpret as a probability, since probabilities must lie between 0 and 1. Logistic regression solves this by passing the score through the sigmoid function.
To convert into a probability, we need a function that maps to . The sigmoid function does exactly this:
where:
- : the raw linear score , any real number
- : the exponential of ; this quantity is large when is negative and small when is positive
- : the denominator, which normalizes the output
- : the resulting probability, always strictly between 0 and 1
The sigmoid function has three key properties:
- When : , so (confident positive prediction)
- When : , so (confident negative prediction)
- When : (maximum uncertainty, on the decision boundary)
The function is smooth and differentiable everywhere, a requirement for gradient descent. Its derivative also has a convenient form:
where:
- : the sigmoid output at
- : one minus the sigmoid, since
This derivative is easy to compute once you have the forward pass value, which makes backpropagation through the sigmoid efficient. You compute on the forward pass and store it; on the backward pass, you compute without any additional expensive operations.
Logistic regression applies the sigmoid function to the linear score to produce a probability estimate. It predicts , where is the sigmoid function. Despite the name "regression," it is used for classification.
def sigmoid(z):
"""Map a real-valued score to the interval (0, 1)."""
return 1.0 / (1.0 + np.exp(-z))
def logistic_predict_proba(x, w, b):
"""Return the probability of the positive class."""
z = np.dot(w, x) + b
return sigmoid(z)Review 1 (enthusiastic): Linear score: 3.60 P(positive): 0.973 Review 2 (disappointed): Linear score: -3.80 P(positive): 0.022 Review 3 (mixed): Linear score: -0.20 P(positive): 0.450
Review 1 gets a high probability of being positive. Review 2 gets a low probability. Review 3, near the decision boundary, gets a probability close to 0.5. These probabilities are more informative than a hard yes/no decision because they communicate the model's confidence. A downstream system can decide how to act based on these probabilities: it might automatically file a very high-confidence prediction but route uncertain ones to a human reviewer.
The Sigmoid Curve
Visualizing the sigmoid function helps build intuition about how it compresses scores into probabilities.

Notice how the sigmoid "saturates" in the tails: for or , the function barely changes. This saturation has consequences for training. When the classifier is very confident but wrong, the gradient of the sigmoid is tiny, meaning learning happens slowly. This is the vanishing gradient problem in its simplest form, and it is one reason why alternative activations like ReLU (covered in the Activation Functions chapter) were developed for hidden layers of deep networks. For output layers producing probability estimates, however, sigmoid and softmax remain standard.
The Log-Odds Connection
The sigmoid function has a natural probabilistic interpretation through log-odds. If , then the odds in favor of the positive class are , and the log-odds (also called the logit) are . Inverting the sigmoid relationship shows that:
This means logistic regression is modeling the log-odds of the positive class as a linear function of the input features. A unit increase in feature multiplies the odds of the positive class by . This multiplicative relationship in odds space corresponds to an additive relationship in log-odds space, which is what makes the math tractable. The log-odds framing also connects logistic regression to Naive Bayes classifiers: under a specific set of distributional assumptions (that features are conditionally independent given the class), Naive Bayes produces a classifier with the same logistic regression form, with weights determined by feature likelihood ratios.
Multiclass Classification: Softmax
Binary classification (two classes) covers many problems, but NLP is full of multiclass problems: classifying documents into dozens of topics, assigning one of hundreds of part-of-speech tags, or selecting the next word from a vocabulary of 50,000 tokens. Logistic regression extends to multiple classes through the softmax function.
For classes, we define weight vectors and biases . The model computes one score per class. For class and input :
where:
- : the weight vector for class , one per class
- : the bias for class
- : the logit (raw score) for class
The resulting score vector is called the vector of logits. To convert logits into a probability distribution, we apply the softmax function. For class :
where:
- : the exponential of the -th class logit, which ensures all values are positive
- : the sum of exponentials across all classes, the normalizing constant
- : the resulting probability for class
The softmax output is a valid probability distribution: all values are positive (because exponentials are always positive) and they sum to exactly 1 (by construction). The class with the highest logit always receives the highest probability. The exponential function amplifies differences: if class has a logit 2 units above class , then receives times the unnormalized probability mass of .
Softmax converts a vector of real-valued logits into a probability distribution over classes. It is the multiclass generalization of the sigmoid function. When , softmax with two outputs is equivalent to using a single sigmoid.
The softmax function is ubiquitous in modern deep learning. Every language model that predicts the next token applies softmax over a vocabulary of tens of thousands of entries to produce a distribution over what comes next. Every classification network ends with a softmax layer. Understanding how softmax works at the scale of logistic regression gives you the intuition to understand what is happening at vastly larger scale in transformer models.
Numerical Stability with Log-Sum-Exp
Computing directly causes overflow when logits are large (for example, when , exceeds the floating-point limit). The standard fix is to subtract the maximum logit before exponentiating. This does not change the result because, for any constant :
where:
- : the constant we subtract (chosen as the maximum so that the largest exponential is )
- All other values : avoiding overflow
Setting ensures the numerically largest exponential equals 1 and all others are at most 1. This technique appears in every modern framework, including NumPy, PyTorch, and TensorFlow. If you ever implement softmax from scratch and forget this step, your code will silently produce NaN values on inputs with large logits.
def softmax(z):
"""Convert a logit vector to a probability distribution (numerically stable)."""
z_shifted = z - np.max(z) # Subtract max for stability
exp_z = np.exp(z_shifted)
return exp_z / exp_z.sum()
# Multiclass text classifier: 3 classes (sports, politics, technology)
# Features: word count vector for 5 key words
# ["game", "election", "server", "team", "vote"]
W = np.array(
[
[0.9, -0.3, 0.1, 0.8, -0.2], # sports
[-0.1, 0.9, -0.2, -0.1, 0.8], # politics
[0.1, -0.1, 0.9, 0.1, -0.1], # technology
]
)
b_multi = np.array([0.0, 0.1, -0.1])
doc_1 = np.array([1, 0, 1, 1, 0]) # "game server crashed during finals"
doc_2 = np.array([0, 1, 0, 0, 1]) # "election results shocked the nation"Sports+Tech: 'game server crashed during finals' sports : logit=1.80 P=0.636 ############ politics : logit=-0.30 P=0.078 # technology : logit=1.00 P=0.286 ##### Predicted: sports Politics: 'election results shocked nation' sports : logit=-0.50 P=0.082 # politics : logit=1.80 P=0.818 ################ technology : logit=-0.30 P=0.100 ## Predicted: politics
The first document, mentioning "game," "server," and "team," gets split probability between sports and technology because it matches both class templates. The second document, mentioning "election" and "vote," is confidently classified as politics. This ambiguity in the first document reflects semantic ambiguity: "game server crashed during finals" could plausibly come from either a gaming article or a sports one. The model's uncertainty is well-calibrated.
The Weight Matrix View
When we have classes, the individual weight vectors can be stacked as rows of a weight matrix . The logit vector becomes:
This is a matrix-vector product: each row of computes a dot product with , producing one score per class. This operation is the first linear layer of any neural network. In a deep network, you stack many such transformations, but each individual transformation has exactly this form. Recognizing this pattern across different scales of complexity is key to understanding neural network architecture.
Feature Representation for Text
The linear classifier expects a fixed-length numerical vector. Text is not naturally numerical, so we need a representation strategy. As you learned in the Bag of Words and TF-IDF chapters, there are several options.
The simplest is binary bag-of-words: a vector of 0s and 1s indicating whether each vocabulary word appears in the document. A richer option is TF-IDF weighting, which downweights common words and upweights rare ones. The representation choice directly affects what the classifier can learn.
For a vocabulary of size , each document becomes a vector in . The classifier applies a weight to each vocabulary position. After training, the weight for word in class reflects how much seeing word increases the probability of class . This is interpretable: you can look at the highest-weighted words for each class and understand the classifier's reasoning.
The key insight is that the choice of text representation and the linear classifier are not independent decisions. They are two sides of the same coin. A TF-IDF representation is designed to make the signal for a linear classifier as strong as possible by reducing the noise from high-frequency stopwords. Feature engineering and model design are deeply intertwined for linear classifiers in a way that is less true for deep neural networks, which can learn their own representations.
from sklearn.feature_extraction.text import TfidfVectorizer
documents = [
# Sports (label 0)
"The team won the championship with a decisive victory in the final game",
"Baseball scores improved as the pitcher dominated the field all season long",
"Soccer players celebrated after winning the league title with stunning goals",
# Politics (label 1)
"The senator voted against the new healthcare legislation in congress",
"Presidential candidates debated economic policy and foreign affairs last week",
"Government officials announced new regulations for environmental protection",
# Technology (label 2)
"The new machine learning framework outperforms previous models on benchmarks",
"Software engineers deployed the neural network to the cloud computing platform",
"Deep learning algorithms process natural language with impressive accuracy",
]
labels = [0, 0, 0, 1, 1, 1, 2, 2, 2]
class_names_str = ["sports", "politics", "technology"]
vectorizer = TfidfVectorizer(max_features=30, stop_words="english")
X = vectorizer.fit_transform(documents).toarray()
vocab = vectorizer.get_feature_names_out()Vocabulary size: 30 Feature matrix shape: (9, 30) Sample vocabulary: ['learning', 'long', 'machine', 'models', 'natural', 'network', 'neural', 'new', 'officials', 'outperforms']
With 9 documents and a vocabulary of 30 words, each document becomes a 30-dimensional TF-IDF vector. The classifier will learn one weight per vocabulary word per class. In a real application, the vocabulary would be much larger, typically tens of thousands of words, and the weight matrix would have millions of entries. This is one reason why linear classifiers trained on bag-of-words features can be computationally intensive: not because of the classifier itself, but because of the high-dimensional sparse feature vectors they operate on.
Training with Gradient Descent
So far, we have assumed the weights and bias are given. In practice, we learn them from labeled training data by minimizing a loss function. The loss function quantifies how wrong the model's predictions are, and gradient descent iteratively adjusts the parameters to reduce that wrongness.
The Cross-Entropy Loss
For binary classification, the standard loss function for logistic regression is the binary cross-entropy. Given a training example where and the model predicts , the loss is:
where:
- : the true label
- : the model's predicted probability for the positive class
- : the active term when ; this approaches 0 as and approaches as
- : the active term when ; this approaches 0 as and approaches as
The cross-entropy loss has an important property: it penalizes confident wrong predictions much more severely than uncertain ones. If the model assigns probability 0.01 to the true class, the loss is . If it assigns 0.9, the loss is only .
For multiclass problems with classes, the cross-entropy generalizes. The true label is represented as a one-hot vector where if is the true class and otherwise. The multiclass cross-entropy is:
where:
- : the one-hot indicator for class
- : the softmax probability for class
- Since exactly one , this simplifies to : only the true class probability is penalized
Why Cross-Entropy and Not Mean Squared Error?
You might wonder why we use cross-entropy loss instead of mean squared error (MSE). After all, MSE is simpler and widely used in regression. The issue is that MSE applied to probability outputs produces gradients that vanish when the model is very wrong. Consider a training example where the true label is but the model predicts (extremely wrong). The MSE gradient is proportional to , which is tiny because is tiny near 0. The model would learn almost nothing from this catastrophically wrong prediction. Cross-entropy avoids this: its gradient is , which is large, producing a strong learning signal even when the model is very wrong.
This is one of the most important practical lessons in designing learning systems: the choice of loss function matters for what it measures and for the quality of the learning signal it provides. Cross-entropy is the natural loss for models that produce probability estimates, both because of its probabilistic derivation (negative log-likelihood) and because of its favorable gradient properties.
Computing Gradients
To minimize the loss, we need the gradient of with respect to the weights and bias . A key result of differentiating through the sigmoid and logarithm is that the gradient has a remarkably simple form. For a single training example :
where:
- : the prediction error, the difference between the model's predicted probability and the true label
- : the input features, which scale the gradient for each individual weight dimension
The gradient formula has an elegant structure: it is exactly the prediction error times the input. If the model predicts but the true label is (error = 0.9), the gradient is large and pushes the weights to reduce the score for this input. If the prediction is correct and confident (, , error = 0.05), the gradient is small and the update is tiny. We only learn substantially from mistakes.
Deriving this gradient is a good exercise. Starting from with , and using the chain rule together with , the derivatives of the logarithms cancel beautifully with the derivative of the sigmoid, yielding exactly . This cancellation is not accidental: it is the reason that cross-entropy is the "right" loss for sigmoid outputs, a pairing that produces clean gradients and fast learning.
Stochastic Gradient Descent
Gradient descent updates parameters iteratively:
where:
- : the learning rate, controlling step size
- : the gradient pointing uphill; subtracting it moves downhill toward lower loss
For large datasets, computing gradients over the full training set is expensive. Stochastic gradient descent (SGD) uses a single random example or a small mini-batch per update, which is much faster and introduces useful noise that can help escape shallow local minima. The Stochastic Gradient Descent chapter covers SGD in depth.
def binary_cross_entropy(y_true, y_pred_proba):
"""Compute binary cross-entropy loss for a batch."""
eps = 1e-15 # Prevent log(0)
p = np.clip(y_pred_proba, eps, 1 - eps)
return -np.mean(y_true * np.log(p) + (1 - y_true) * np.log(1 - p))
def train_logistic_regression(
X, y, learning_rate=0.1, n_epochs=100, random_state=42
):
"""Train logistic regression with full-batch gradient descent."""
n_samples, n_features = X.shape
w = np.zeros(n_features)
b = 0.0
losses = []
for epoch in range(n_epochs):
# Forward pass
z = X @ w + b
p_hat = sigmoid(z)
# Loss
loss = binary_cross_entropy(y, p_hat)
losses.append(loss)
# Gradients (averaged over the batch)
error = p_hat - y
grad_w = (X.T @ error) / n_samples
grad_b = error.mean()
# Parameter update
w -= learning_rate * grad_w
b -= learning_rate * grad_b
return w, b, losses# Binary classification: sports vs. politics (first 6 documents)
X_binary = X[:6]
y_binary = np.array([0, 0, 0, 1, 1, 1]) # 0=sports, 1=politics
w_trained, b_trained, losses = train_logistic_regression(
X_binary, y_binary, learning_rate=0.5, n_epochs=200
)Training progress:
Epoch Loss Accuracy
1 0.6931 1.000
11 0.5130 1.000
51 0.2208 1.000
101 0.1204 1.000
200 0.0612 1.000
Final training accuracy: 1.000The loss decreases steadily and accuracy reaches a high level as the model learns which TF-IDF features distinguish sports from politics articles.

The Convexity Advantage
One of the most important theoretical properties of logistic regression is that the cross-entropy loss is a convex function of the parameters and . Convexity means that the loss surface has no local minima: any local minimum is guaranteed to be the global minimum. Gradient descent on a convex function will always find the optimal solution, provided the learning rate is small enough and training runs long enough.
This guarantee does not hold for neural networks with hidden layers, which have non-convex loss surfaces with many local minima. Practitioners working with deep networks must worry about initialization, learning rate schedules, and optimization methods suited to these surfaces. With logistic regression, the optimization is straightforward. This makes logistic regression a reliable baseline and a sanity check: if your neural network performs worse than logistic regression on the same features, something has gone wrong with the training procedure.
The convexity also means that the solution is unique (assuming the data is not linearly separable with a finite margin). There is a single global optimum that all gradient descent trajectories converge to, regardless of initialization. This uniqueness is valuable for reproducibility and for understanding what the model has learned.
Regularization
Logistic regression can overfit when the number of features is large relative to the number of training examples. With TF-IDF features, the vocabulary can easily contain tens of thousands of words, yet training data may be limited. In such settings, the model can memorize the training set by assigning extreme weights to rare words that appear in certain training documents but are not informative for the task.
The intuition for why this happens is straightforward. If a word appears in only one training document and that document belongs to class A, the model can drive its weight toward positive infinity, making the presence of that word nearly deterministic evidence for class A. This works perfectly on the training set but fails on new documents because the word's appearance was coincidental, not predictive.
Regularization adds a penalty term to the loss function that discourages large weights. The two most common forms are:
L2 regularization (ridge): adds the squared weight norm, penalizing all large weights proportionally:
L1 regularization (Lasso): adds the sum of absolute weights, encouraging sparsity:
where:
- : the regularization strength hyperparameter; larger values apply stronger shrinkage
- : the squared L2 norm
- : the L1 norm, which can drive weights exactly to zero
The gradient of the L2 penalty with respect to is , adding a term proportional to the current weight magnitude. This gives a modified update rule:
where:
- : the decay factor, slightly less than 1, shrinking weights by a fraction each step
- This is why L2 regularization is also called "weight decay": weights are decayed toward zero at each update
L1 regularization can drive some weights exactly to zero, effectively performing automatic feature selection. In NLP, where the vocabulary is large and most words are uninformative for a given task, L1 can produce sparse weight vectors that are easier to inspect and interpret. A sparse model trained on a 50,000-word vocabulary might only use 500 non-zero weights, making the classifier's reasoning highly transparent.
The choice between L1 and L2 regularization involves a tradeoff between sparsity and stability. L2 shrinks all weights smoothly and produces stable, dense weight vectors. L1 sets many weights exactly to zero but can be unstable when many features are correlated, because any one of several correlated features can serve the same purpose and L1 arbitrarily zeros out some of them. Elastic net regularization combines both, which offers a smooth interpolation between the two extremes.
def train_logistic_regression_l2(
X, y, learning_rate=0.1, n_epochs=100, lambda_l2=0.01, random_state=42
):
"""Train logistic regression with L2 regularization."""
n_samples, n_features = X.shape
w = np.zeros(n_features)
b = 0.0
losses = []
for epoch in range(n_epochs):
z = X @ w + b
p_hat = sigmoid(z)
base_loss = binary_cross_entropy(y, p_hat)
l2_penalty = (lambda_l2 / 2.0) * np.dot(w, w)
losses.append(base_loss + l2_penalty)
error = p_hat - y
grad_w = (X.T @ error) / n_samples + lambda_l2 * w
grad_b = error.mean()
w -= learning_rate * grad_w
b -= learning_rate * grad_b
return w, b, losseslambdas = [0.0, 0.01, 0.1, 1.0]
results_reg = {}
for lam in lambdas:
w_reg, b_reg, losses_reg = train_logistic_regression_l2(
X_binary, y_binary, learning_rate=0.5, n_epochs=200, lambda_l2=lam
)
preds_reg = (sigmoid(X_binary @ w_reg + b_reg) >= 0.5).astype(int)
acc_reg = (preds_reg == y_binary).mean()
results_reg[lam] = {
"w": w_reg,
"b": b_reg,
"losses": losses_reg,
"accuracy": acc_reg,
"weight_norm": np.linalg.norm(w_reg),
}Lambda Accuracy Weight L2 Norm -------------------------------------- 0.000 1.000 6.5942 0.010 1.000 4.6584 0.100 1.000 1.4709 1.000 1.000 0.2012
As increases, the weight norm decreases: regularization is working. On this tiny dataset, all settings achieve the same accuracy, but on a larger dataset with more features, differences in weight norm translate into differences in generalization.

Choosing the Regularization Strength
The regularization hyperparameter (or equivalently, scikit-learn's ) is one of the most important decisions when training logistic regression. Too little regularization and the model overfits; too much and the model underfits, being unable to capture any real signal. The right value depends on the dataset size, the number of features, and the noise level.
Cross-validation is the standard approach to choosing . You train models with a range of values, evaluate each on a held-out validation set, and pick the value that produces the best validation performance. In scikit-learn, LogisticRegressionCV automates this process. In practice, it is worth checking whether regularization substantially changes your results: if it does, you are in a high-variance regime where more training data or stronger regularization would help. If it does not, you are likely in a high-bias regime where the model architecture itself is the limiting factor.
Scikit-learn Implementation
In practice, you will use scikit-learn's LogisticRegression for most tasks. It handles numerical stability, supports multiple solvers, and provides utilities for cross-validation and pipeline composition. Implementing gradient descent from scratch (as we did above) builds understanding, but scikit-learn's implementation uses more sophisticated optimization algorithms like L-BFGS that converge faster and more reliably.
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
pipeline = Pipeline(
[
("tfidf", TfidfVectorizer(max_features=50, stop_words="english")),
("clf", LogisticRegression(C=1.0, max_iter=500, random_state=42)),
]
)
X_docs = documents
y_docs = np.array([0, 0, 0, 1, 1, 1, 2, 2, 2])
pipeline.fit(X_docs, y_docs)Scikit-learn LogisticRegression - Training Results
==================================================
precision recall f1-score support
sports 1.00 1.00 1.00 3
politics 1.00 1.00 1.00 3
technology 1.00 1.00 1.00 3
accuracy 1.00 9
macro avg 1.00 1.00 1.00 9
weighted avg 1.00 1.00 1.00 9Inspecting the Learned Weights
One advantage of linear classifiers over black-box models is interpretability. You can inspect which words (features) the model weighted most highly for each class.
clf_sk = pipeline.named_steps["clf"]
tfidf_sk = pipeline.named_steps["tfidf"]
feature_names_sk = tfidf_sk.get_feature_names_out()
top_n = 5Top weighted features per class: ============================================= SPORTS victory : +0.2421 team : +0.2421 decisive : +0.2421 championship : +0.2421 winning : +0.1977 POLITICS new : +0.2580 senator : +0.2272 officials : +0.2272 legislation : +0.2272 protection : +0.2272 TECHNOLOGY learning : +0.3217 outperforms : +0.1966 previous : +0.1966 benchmarks : +0.1966 models : +0.1966
The top-weighted words for each class match intuition. Sports-related words dominate the sports class, political vocabulary the politics class, and technical terms the technology class. When the model makes an error, inspecting the weights reveals which features drove the wrong decision. This level of transparency is a key advantage of linear classifiers in regulated domains where decisions must be explainable.
Visualizing the weight magnitudes across classes helps compare which features are most discriminative.

Key Parameters
The key parameters for sklearn.linear_model.LogisticRegression are:
- C: Inverse regularization strength (). Smaller values apply stronger regularization. Defaults to 1.0.
- penalty: Regularization type.
'l2'(default),'l1','elasticnet', or'none'. - solver: Optimization algorithm.
'lbfgs'works well for most cases;'saga'supports L1 and is faster for large datasets. - max_iter: Maximum number of optimization iterations. Increase if the solver does not converge.
- multi_class:
'ovr'(one-vs-rest) or'multinomial'(softmax).'multinomial'is usually better for multiclass tasks.
The Perceptron: The Simplest Linear Classifier
Before logistic regression, the perceptron was the first trainable linear classifier, proposed by Frank Rosenblatt in 1958. The perceptron algorithm is simpler than gradient descent: it only updates weights when it makes a mistake.
The perceptron uses labels (rather than ) and predicts . When the prediction is wrong (i.e., ), it applies the update:
where:
- : the true class label
- : the input feature vector
- Adding to : when , moves closer to , increasing the score; when , moves away from , decreasing the score
The perceptron convergence theorem states that if the training data is linearly separable, the perceptron finds a separating hyperplane in a finite number of steps. The bound on the number of mistakes is , where is the radius of the smallest sphere containing all training points and is the margin (the distance from the closest training point to the optimal hyperplane). A larger margin means faster convergence. When there is no separating hyperplane, however, the perceptron loops indefinitely.
Logistic regression with gradient descent is strictly more powerful: it produces probability estimates rather than hard labels, converges to the best linear fit even on non-separable data, and minimizes a smooth convex loss function. The perceptron is primarily of historical and pedagogical interest today, but understanding it helps connect the update rules of modern neural network training to their historical roots. The perceptron's mistake-driven update rule also reappears in online learning settings where data arrives sequentially and one cannot afford to store the full training set.
The perceptron's announcement in 1958 generated enormous excitement. The New York Times ran a story about a machine that could learn. There was widespread belief that general artificial intelligence was imminent. Then, in 1969, Marvin Minsky and Seymour Papert published a thorough mathematical analysis showing that the perceptron could not solve XOR and other non-linearly-separable problems. The result was devastating to the field's optimism and contributed to the first "AI winter," a period of reduced funding and interest in neural network research. The solution, stacking perceptrons in multiple layers with nonlinear activations, was known even at the time, but efficient training algorithms for multilayer networks were not developed until the 1986 popularization of backpropagation. The lesson: architectural expressiveness without a training algorithm is not enough.
Maximum Likelihood Estimation and Cross-Entropy
The cross-entropy loss is not an arbitrary choice. It arises naturally from maximum likelihood estimation (MLE), a foundational principle in statistics. Understanding this connection grounds the training process in probability theory and explains why cross-entropy is the "correct" objective.
Suppose we model the conditional probability . Given a training dataset of independent examples, the likelihood of observing this dataset under our model is:
For binary labels, this becomes . Taking the log (which turns the product into a sum and is monotonically increasing, so maximizing log-likelihood is equivalent to maximizing likelihood):
Minimizing the negative log-likelihood is exactly minimizing the average cross-entropy loss. Maximum likelihood estimation tells us that the cross-entropy loss is the principled objective for logistic regression: we are finding the parameters that make the observed training labels as likely as possible under our model. This connection is fundamental: it means that training logistic regression produces well-calibrated probability estimates, not just good rankings.
Well-calibrated probabilities are practically important. If your sentiment classifier says 90% probability of positive for a particular review, and it is well-calibrated, then roughly 90% of similar reviews with that predicted probability will indeed be positive. This means you can use the raw probability outputs as decision inputs, alongside the hard class predictions. Poor calibration, often seen in models trained with mean squared error or in overconfident deep networks, can lead to systematic errors in downstream systems that rely on probability values.
One-vs-Rest Multiclass Strategy
Before softmax became standard, and still useful in some settings, the one-vs-rest (OvR) strategy handles multiclass problems by training separate binary classifiers. Classifier is trained to distinguish class from all other classes. At prediction time, all classifiers produce a score, and the class with the highest score is predicted.
OvR is simple to implement: you just train logistic regression models independently, one for each class. Each classifier sees the full training set, with the positive class being the -th class and the negative class being all other examples combined. This works well when the classes are well-separated and the models' output scores are on comparable scales.
The disadvantage of OvR is that the classifiers are not jointly trained to produce a coherent probability distribution. The scores from different classifiers are not comparable, and they do not necessarily sum to 1. Softmax (multinomial logistic regression) avoids this by training all weight vectors jointly and normalizing the outputs. In practice, multinomial logistic regression with softmax outperforms OvR, especially when classes are similar and the probability estimates need to be well-calibrated. Scikit-learn's multi_class='multinomial' parameter enables this.
Limitations of Linear Classifiers
The defining constraint of linear classifiers is that they can only learn linear decision boundaries. In two dimensions, the boundary is a line. In three dimensions, a plane. In dimensions, a hyperplane. This is a fundamental limitation, not a matter of insufficient parameters. Adding more features to a linear classifier does not change the functional form of its decision boundary; it only adds dimensions to the space in which that flat boundary lives.
The classic example is XOR: four points labeled such that the pattern forms a checkerboard. No straight line can separate the positive from the negative examples correctly. The pattern requires a nonlinear boundary.

Logistic regression accuracy on XOR: 0.520 Baseline (predict majority class): 0.500 The linear classifier performs near chance on XOR. It cannot capture the diagonal separation pattern.
The linear classifier achieves accuracy near chance on this XOR problem. In NLP, analogous limitations appear in situations where meaning depends on word interactions. Detecting sarcasm, understanding negation ("not good"), or recognizing compositional phrases all require capturing nonlinear feature interactions that linear classifiers cannot represent.
Where Linear Boundaries Fail in Language
The limitations of linear classifiers are particularly visible in natural language understanding. Consider sentiment analysis with the word "not." In a bag-of-words representation, "not good" and "not bad" are treated as independent occurrences of "not," "good," and "bad." A linear classifier sees the same feature values and cannot distinguish between "The movie was not bad at all" (positive sentiment) and "The movie was not good" (negative sentiment), since both contain the word "not" and either "bad" or "good." Handling negation requires detecting the interaction between "not" and the sentiment word that follows it, a nonlinear operation.
Sarcasm presents a similar challenge. "Oh great, another meeting" is sarcastic and negative, but "Oh great, we won the game" is sincere and positive. The word "great" appears in both, but its meaning depends entirely on context. A linear classifier that weights "great" as a positive indicator will fail on the sarcastic case. It cannot consider the interaction between "great" and the surrounding context.
These are not edge cases but common patterns in real language. They explain why even high-quality logistic regression models on bag-of-words features typically plateau well below human performance on sentiment analysis benchmarks. The features needed to capture these patterns (like bigrams or trigrams capturing word sequences) can partially address negation, but the feature space explodes and the fundamental limitation remains.
The solution is introduced in the next chapter on Activation Functions and fully developed in the Multilayer Perceptrons chapter: stack linear classifiers with nonlinear activations between them. Each layer computes a linear transformation, then applies a nonlinear function, and the resulting composition can represent arbitrarily complex boundaries. Linear classifiers are not obsolete; they become the layers inside neural networks.
Feature Engineering as a Partial Remedy
Before deep learning, practitioners addressed the limitations of linear classifiers through feature engineering: manually designing features that make the relevant patterns more linearly separable. Adding bigrams (pairs of adjacent words) to the feature space lets the classifier learn that "not good" is a distinct feature from "good" appearing alone. Adding character n-grams helps with morphological variants. Adding handcrafted features like "does the sentence contain a negation word followed within three positions by a sentiment word?" can capture specific linguistic patterns directly.
This approach worked well enough to drive decades of NLP research, and feature-engineered linear models remained competitive well into the 2010s on many tasks. The key insight is that the transformation from raw text to features is itself encoding nonlinear structure, just in a hand-crafted rather than learned way. Neural networks automate this feature discovery, learning representations that make the final classification problem linearly easy. The final layer of a neural network classifier is always a linear layer with softmax. Deep learning did not abolish linear classifiers; it put them at the end of a learned feature hierarchy.
Summary
Linear classifiers are the foundation of modern neural networks. Every neuron in a deep network performs a linear transformation followed by a nonlinear activation, the same core operation as logistic regression. Understanding how linear classifiers work, what they can and cannot learn, and how gradient descent trains them gives you the conceptual tools to understand every more complex architecture that follows.
The trajectory of this chapter mirrors the broader arc of neural network design. We started with the basic weighted sum, added the sigmoid to produce probabilities, extended to multiple classes with softmax, added regularization to prevent overfitting, and then confronted the fundamental barrier of linear separability. Each step adds something necessary while retaining the core dot-product computation. When we move to multilayer networks in the chapters ahead, we are not replacing this foundation but building on it, adding the capacity to learn representations that make linearly inseparable problems tractable.
The key ideas from this chapter:
- A linear classifier computes and classifies based on the sign of
- The weight vector is perpendicular to the decision boundary and points toward the positive region; the bias translates the boundary parallel to itself
- The dot product measures alignment between the input and the weight vector, serving as a template-matching operation that reappears in transformer attention mechanisms
- Logistic regression applies the sigmoid function to convert the score into a probability, with the cross-entropy loss arising naturally from maximum likelihood estimation
- Softmax generalizes logistic regression to classes by computing ; numerical stability requires subtracting the maximum logit before exponentiating
- The cross-entropy loss is the natural loss for probability outputs because its gradients are large when the model is confidently wrong, unlike mean squared error
- Gradient descent updates weights by the prediction error times the input:
- The cross-entropy loss is convex in the parameters, guaranteeing a unique global optimum that gradient descent will find
- Regularization (L1 or L2) prevents overfitting when features outnumber training examples; L2 shrinks all weights uniformly while L1 promotes sparsity
- The perceptron (1958) was the first trainable linear classifier; its convergence proof and failure on XOR directly shaped the history of neural network research
- Linear classifiers cannot model nonlinear boundaries; adding nonlinear activation functions, covered in the Activation Functions chapter, resolves this limitation and forms the basis of multilayer networks
Quiz
Ready to test your understanding? Take this quick quiz to reinforce what you've learned about linear classifiers.
Linear Classifiers Quiz
Reference
Citation details
Cite or share this article.
Continue with the full handbook
This chapter is part of Language AI Handbook. Use the handbook page to browse the complete table of contents and continue reading in sequence.
Explore Language AI HandbookStay up to date
Get articles, book updates, and news delivered to your inbox.
No spam, unsubscribe anytime.
Join the community
Sign in to remove popups, track your reading progress, and join the discussion.

Comments
No comments yet. Be the first to share your thoughts!