Classical Models Compared
Linear and logistic regression, trees and forests, SVM, KNN and Naive Bayes side by side, with when to use each.
- Concepts and terms
- Tasks and commands
- Annotated code
- Diagrams
- Comparisons
- Defaults and numbers
- Troubleshooting
- Questions and tips
Models side by side#
| Model | Trains with | Boundary, prediction cost and memory |
|---|---|---|
| Linear regression | Gradient descent | A hyperplane. Normal equation is O(n^3) in features |
| Logistic regression | binary cross-entropy | Always linear. Boundary where p = 0.5 |
| Decision tree | Gini impurity | Rectangular regions from greedy splits. High variance |
| Random forest | Bagging | Majority vote or average of many trees |
| SVM | Hinge loss | Maximum margin. Stores only the support vectors |
| KNN | Lazy | No training. O(n \cdot d) per query, stores all data |
| Naive Bayes | Count frequencies | Linear. Prediction is one matrix multiply |
From Lesson 02.02, Lesson 02.03, Lesson 02.04, Lesson 02.05, Lesson 02.06, Lesson 02.14
Scaling and best data#
| Model | Scale features | Wins on |
|---|---|---|
| Linear regression | yes | Baselines for every regression task |
| Trees and forests | no | Tabular data, mixed types, under 10k rows |
| SVM | yes | Small or high-dimensional sparse data |
| KNN | yes | Small data, up to about 20-50 features |
| Multinomial NB | no | Text with few training samples |
| Gaussian NB | no | Continuous features near a bell curve |
From Lesson 02.02, Lesson 02.04, Lesson 02.05, Lesson 02.06, Lesson 02.14
Defaults in the lesson code#
| Setting | Default | Note |
|---|---|---|
Tree max_depth | None | Grows until every leaf is pure |
Tree min_samples_split | 2 | A pre-pruning control |
Tree criterion | "gini" | Gini and entropy split almost the same |
Forest n_trees | 100 | scikit-learn uses n_estimators=100 |
Forest max_features | "sqrt" | Regression uses n_features/3 |
KNN k | 5 | Start near sqrt(N). Odd K for binary |
SVM rbf_kernel gamma | 0.5 | polynomial_kernel degree 3 |
GaussianNB var_smoothing | 1e-9 | Stops division by zero variance |
From 02.04 code/trees.py, Lesson 02.04, 02.06 code/knn.py, Lesson 02.06, 02.05 code/svm.py, 02.14 code/naive_bayes.py, Lesson 02.14
Failures and fixes#
| Symptom | Cause | Fix |
|---|---|---|
| Logistic fails on circles | The boundary is always linear | Add polynomial features |
| SVM accuracy is poor | Unscaled features distort the margin | StandardScaler in a Pipeline |
SVC too slow | Dual form is O(n^2) to O(n^3) | LinearSVC primal form |
| KNN degrades with many features | Curse of dimensionality | PCA or UMAP first |
| One tree changes with the data | A single tree is high variance | Use a random forest |
| MDI ranks a noise feature high | Bias to high cardinality | Permutation importance |
| NB gives probability 0 | Unseen word in a class | Laplace smoothing, alpha 1 |
| MultinomialNB rejects features | Negative feature values | GaussianNB or shift values |
From Lesson 02.03, Lesson 02.04, Lesson 02.05, Lesson 02.06, Lesson 02.14
Use each model when#
- Use linear regression as the baseline for every regression task.
- Use logistic regression for yes-or-no answers with probabilities and a linear boundary.
- Use a random forest for flat tables. It needs almost no hyperparameter tuning.
- Use an SVM for small data or sparse text with TF-IDF features.
- Use KNN when the data changes often and you want zero training time.
- Use TF-IDF with MultinomialNB for text with fewer than 10,000 training samples.
- Use BernoulliNB for short text. Set
binary=Truein CountVectorizer.
From Lesson 02.02, Lesson 02.03, Lesson 02.04, Lesson 02.05, Lesson 02.06, Lesson 02.14
Losses and formulas#
- MSE
- \frac{1}{n} \sum (\hat{y} - y)^2. The gradient for w is \frac{2}{n} \sum (\hat{y} - y) x.
- R squared
- 1 - SS_{\text{res}} / SS_{\text{tot}}. 1.0 is perfect. 0.0 equals the mean.
- Sigmoid
- \sigma(z) = 1 / (1 + e^{-z}). At z = 0 it gives 0.5.
- Binary cross-entropy
- -\frac{1}{n} \sum (y \log p + (1-y) \log(1-p)). Gradient \frac{1}{n} \sum (p - y) x.
- Gini
- 1 - \sum_k p_k^2. 6 cats and 4 dogs give 0.48.
- Hinge
- \max(0, 1 - y f(x)). Zero beyond the margin.
- RBF kernel
- \exp(-\gamma \lVert x - z \rVert^2). Near 1 for close points.
- Multinomial NB
- (\text{count} + \alpha) / (\text{total} + \alpha \cdot V), summed in log space.
From Lesson 02.02, Lesson 02.03, Lesson 02.04, Lesson 02.05, Lesson 02.06, Lesson 02.14
Scale, then fit#
clf = Pipeline([ ("scaler", StandardScaler()),SVM and KNN need it ("svm", SVC(kernel="rbf", C=1.0, gamma="scale")),dual form, kernels])clf.fit(X_train, y_train)clf.score(X_test, y_test)accuracyclf['svm'].n_support_support vectors("svm", LinearSVC(C=1.0, max_iter=10000))large data, primal("knn", KNeighborsClassifier(n_neighbors=5, metric="euclidean"))mnb = MultinomialNB(alpha=1.0)counts, no scalingmnb.fit(X_train_counts, y_train)From Lesson 02.05, Lesson 02.06, Lesson 02.14
Grow a random forest#
Knobs that trade bias and variance#
| Command | What it does |
|---|---|
Large C | Narrow margin, fewer misclassifications. Overfits |
Small C | Wide margin, more violations. Underfits |
K = | Zero training error. High variance |
K = | Predicts the majority class. Maximum bias |
| Max depth | Stops the tree early. Pre-pruning |
NB alpha | Higher alpha gives stronger smoothing |
| Ridge \lambda | Higher gives smaller weights |
| SVR \epsilon | Wider tube, fewer support vectors |
From Lesson 02.05, Lesson 02.06, Lesson 02.04, Lesson 02.14, Lesson 02.02
Questions#
- Why not MSE for logistic regression?
- With a sigmoid, MSE is non-convex. Binary cross-entropy is convex.
- Why does NB work with a wrong assumption?
- Classification needs correct rankings, not correct probabilities.
- Why does a forest beat one tree?
- Averaging decorrelated trees reduces variance without more bias.
- Why do only support vectors count?
- Points beyond the margin have zero hinge loss.
- NB or logistic regression?
- Start with NB. Switch when data is large and NB plateaus.
- Normal equation or gradient descent?
- Normal equation for small data. Gradient descent for large data.
- Do I trust NB probabilities?
- No. Use
CalibratedClassifierCVwithcv=5.
From Lesson 02.02, Lesson 02.03, Lesson 02.04, Lesson 02.05, Lesson 02.14
From-scratch classes#
| Task | Code |
|---|---|
| Closed-form line | LinearRegressionNormal() |
| Node impurity | gini_impurity(labels) |
| Kernel value | rbf_kernel(x, |
| Batch hinge loss | hinge_loss(X, |
| Text classifier | MultinomialNB(alpha= |
From 02.02 code/linear_regression.py, 02.03 code/logistic_regression.py, 02.04 code/trees.py, 02.05 code/svm.py, 02.14 code/naive_bayes.py