The 60 machine learning questions interviewers actually ask, with direct answers, scikit-learn code, and what the interviewer is listening for. Grouped by fundamentals, algorithms, and evaluation plus system design.
60 questions with answersKey Takeaways
Machine learning is a branch of artificial intelligence where a program improves at a task by learning patterns from data rather than following instructions a developer coded by hand. You give an algorithm examples, it fits a model that maps inputs to outputs, and that model then generalizes to data it hasn't seen. The three broad families are supervised learning (learning from labeled examples, like spam or not-spam), unsupervised learning (finding structure with no labels, like customer segments), and reinforcement learning (an agent learning from rewards as it acts). In interviews, ML questions probe judgment more than recall: which algorithm fits the data, how you'd evaluate a model without fooling yourself, how you'd catch overfitting, and how the thing behaves in production once real traffic hits it. This page collects the 60 questions that come up most, each with a direct answer and, where it helps, runnable scikit-learn code. If you're building fundamentals, the scikit-learn User Guide is a canonical reference; increasingly the first ML round is a live AI coding interview, so pair this bank with our AI interview preparation guides for the format side.
Watch: A Gentle Introduction to Machine Learning
Video: A Gentle Introduction to Machine Learning (StatQuest with Josh Starmer, YouTube)
Test yourself and earn a certificate
10 quick questions. Score 70%+ to download your Machine Learning certificate.
The concepts every ML round checks first. If any answer here surprises you, that's your study list.
Machine learning builds programs that learn patterns from data instead of following rules a person coded by hand. In traditional programming you write the logic and the computer applies it; in ML you supply examples and the algorithm infers the logic as a model.
That flip matters for problems too messy for hand-written rules, like recognizing faces or ranking search results. You trade explicit control for the ability to generalize from data, which is why data quality and evaluation become the hard parts.
Key point: Interviewers open with this to hear how you frame the field. A one-line definition plus one concrete 'rules don't scale here' example beats a memorized paragraph.
Supervised learning trains on labeled examples (input plus the correct output) and learns to predict labels for new inputs: spam detection, price prediction. Unsupervised learning has no labels and finds structure on its own: clustering customers, reducing dimensions. Reinforcement learning has an agent that takes actions in an environment and learns from rewards, like a game player or a robot.
The quick tell is the signal you learn from: correct answers (supervised), the data's own structure (unsupervised), or rewards from actions (reinforcement).
| Type | Learns from | Example tasks |
|---|---|---|
| Supervised | Labeled input-output pairs | Classification, regression |
| Unsupervised | Unlabeled data structure | Clustering, dimensionality reduction |
| Reinforcement | Rewards from actions | Game playing, robotics, control |
Key point: The follow-up is usually 'give an example of each'. Have one concrete task per type ready so you're not inventing them live.
Both are supervised, but they differ in the output. Classification predicts a discrete category (spam or not, which of five classes). Regression predicts a continuous number (a house price, tomorrow's temperature).
The distinction drives your whole setup: the loss function, the model's output layer, and the metrics. Classification uses accuracy, precision, recall, or ROC-AUC; regression uses error metrics like MAE, MSE, or R-squared.
from sklearn.linear_model import LogisticRegression, LinearRegression
# Classification: predict a category (0 or 1)
clf = LogisticRegression().fit(X_train, y_class)
# Regression: predict a continuous value
reg = LinearRegression().fit(X_train, y_price)Key point: A common trap: some tasks can be framed either way. Predicting a rating from 1 to 5 can be regression or ordinal classification. Saying that shows you think about problem framing, not just labels.
You train on the training set, tune hyperparameters and pick models with the validation set, and report final performance on the test set, which the model has never influenced. Three sets keep your final number honest.
If you tune on the test set, the model has effectively seen it, and your reported accuracy is optimistic. The validation set absorbs the tuning bias so the test set stays a clean estimate of how the model behaves on genuinely new data.
from sklearn.model_selection import train_test_split
# First split off the test set, then carve validation from what remains
X_temp, X_test, y_temp, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
X_train, X_val, y_train, y_val = train_test_split(X_temp, y_temp, test_size=0.25, random_state=42)
# Result: 60% train, 20% validation, 20% testKey point: For small datasets, cross-validation often replaces a fixed validation set. Mentioning that trade-off (fixed split for large data, cross-validation for small) indicates experience.
Overfitting is when a model learns the training data too well, including its noise, so it scores high on training data but poorly on new data. Underfitting is when a model is too simple to capture the real pattern, so it scores poorly on both training and test data.
The tell is the gap. A big train-test gap means overfitting; low scores on both means underfitting. Fix overfitting with more data, regularization, or a simpler model; fix underfitting with a more capable model or better features.
Key point: This question sets up bias-variance. the key signal is whether you diagnose from the train-versus-test gap rather than guessing.
Bias is error from wrong assumptions: a model too simple for the data (underfitting). Variance is error from sensitivity to the specific training set: a model so flexible it fits noise (overfitting). Total error combines both plus irreducible noise.
The tradeoff is that reducing one tends to raise the other. Simpler models have high bias and low variance; complex models have low bias and high variance. The goal is the balance point where total error is lowest, which is why you tune complexity rather than always maximizing it.
Bias and variance as model complexity rises
Illustrative shape (relative error units). As a model gets more complex, bias falls but variance rises; total error is lowest at the balance point.
Key point: The connection to nail: high variance IS overfitting, high bias IS underfitting. Interviewers often ask you to link the two vocabularies.
Watch a deeper explanation
Video: A Gentle Introduction to Machine Learning (StatQuest with Josh Starmer, YouTube)
Regularization adds a penalty on model complexity to the loss, discouraging large coefficients so the model generalizes instead of memorizing. It's a primary tool against overfitting.
L2 (Ridge) penalizes the sum of squared coefficients, shrinking them smoothly toward zero but rarely to exactly zero. L1 (Lasso) penalizes the sum of absolute values, which can drive some coefficients exactly to zero, so it doubles as feature selection. Elastic Net blends both.
from sklearn.linear_model import Ridge, Lasso
ridge = Ridge(alpha=1.0).fit(X_train, y_train) # L2: shrinks all coefficients
lasso = Lasso(alpha=0.1).fit(X_train, y_train) # L1: can zero some out
# Lasso zeros out weak features; count how many survived
(lasso.coef_ != 0).sum()| L1 (Lasso) | L2 (Ridge) | |
|---|---|---|
| Penalty | Sum of |coefficients| | Sum of coefficients squared |
| Effect | Can zero coefficients out | Shrinks smoothly, rarely to zero |
| Bonus | Built-in feature selection | Handles correlated features better |
Key point: The memorable hook the technical value is: 'L1 for a sparse model that selects features, L2 for stable shrinkage.' Lead with that, then the math.
Watch a deeper explanation
Video: Regularization Part 1: Ridge (L2) Regression (StatQuest with Josh Starmer, YouTube)
K-fold cross-validation splits the data into k parts, trains on k-1 of them, validates on the held-out part, and rotates so every part is validated once. You average the k scores for a more stable estimate than a single split.
It matters most when data is limited: a single train-validation split can be lucky or unlucky, but averaging over folds smooths that out and uses all the data for both training and validation. Stratified k-fold preserves class proportions in each fold, which you want for imbalanced classification.
from sklearn.model_selection import cross_val_score
from sklearn.ensemble import RandomForestClassifier
scores = cross_val_score(RandomForestClassifier(), X, y, cv=5, scoring='f1')
print(scores.mean(), scores.std()) # average performance and how much it variesKey point: Mention that you fit any preprocessing (scaling, encoding) inside the cross-validation loop, not before it. Fitting a scaler on the whole dataset first leaks information across folds.
Watch a deeper explanation
Video: Machine Learning Fundamentals: Cross Validation (StatQuest with Josh Starmer, YouTube)
Feature scaling puts numeric features on a comparable range so no single feature dominates by magnitude alone. Standardization (subtract mean, divide by standard deviation) and min-max normalization (rescale to 0 to 1) are the common methods.
Distance and gradient-based models need it: KNN, SVM, k-means, logistic and linear regression with regularization, and neural networks. Tree-based models (decision trees, random forests, gradient boosting) split on thresholds and don't care about scale, so they usually skip it.
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import make_pipeline
from sklearn.svm import SVC
# Put the scaler in a pipeline so it's fit on train folds only
model = make_pipeline(StandardScaler(), SVC())
model.fit(X_train, y_train)Key point: The strong move is putting the scaler in a Pipeline. Fitting a StandardScaler on all your data before splitting leaks test statistics into training, a classic subtle bug.
Models need numbers, so categories get encoded. One-hot encoding makes a binary column per category and suits nominal features with few levels. Ordinal encoding maps ordered categories (small, medium, large) to integers that preserve order. For high-cardinality features, target or frequency encoding avoids exploding the column count.
The trap is using ordinal integers for unordered categories: encoding cities as 1, 2, 3 tells a linear model that city 3 is 'more than' city 1, which is nonsense. Match the encoding to whether the category has a real order.
from sklearn.preprocessing import OneHotEncoder
enc = OneHotEncoder(handle_unknown='ignore', sparse_output=False)
encoded = enc.fit_transform(X_train[['city']])
# handle_unknown='ignore' avoids a crash when a new city appears in productionKey point: handle_unknown for categories unseen during training matters.
First understand why it's missing, then choose. Simple imputation fills gaps with the mean, median, or most frequent value. Model-based imputation predicts the missing value from other features. Sometimes you drop rows or columns, and sometimes missingness itself is a signal worth flagging with an indicator column.
The judgment the question needs: dropping data is fine when little is missing and it's random, but with substantial or non-random missingness, dropping biases the model. Median imputation resists outliers better than mean, which is why it's a safe default for skewed numeric features.
from sklearn.impute import SimpleImputer
imputer = SimpleImputer(strategy='median') # resists outliers better than mean
X_train_filled = imputer.fit_transform(X_train)
X_test_filled = imputer.transform(X_test) # reuse train's medians, no leakageKey point: Always fit the imputer on training data and reuse its values on the test set. Computing medians over the full dataset is another quiet leakage bug.
When one class vastly outnumbers the other (fraud, disease, defaults), a model can score high accuracy by ignoring the rare class. You fix it at three layers: the data (oversample the minority with SMOTE, or undersample the majority), the algorithm (class weights that penalize minority errors more), and the evaluation (use precision, recall, F1, and ROC-AUC, never plain accuracy).
The cleanest first step is often class_weight='balanced', because it needs no resampling and no synthetic data. Escalate to SMOTE when weighting alone doesn't give enough recall on the minority class.
from sklearn.linear_model import LogisticRegression
# Tell the model minority errors cost more, no resampling needed
clf = LogisticRegression(class_weight='balanced')
clf.fit(X_train, y_train)Key point: The strongest coverage names all three layers (data, algorithm, evaluation) and stresses that the metric change matters most: fixing the data without fixing the metric just hides the problem.
Feature engineering is creating, transforming, and selecting the input variables a model learns from: extracting the day of week from a timestamp, combining height and weight into BMI, binning ages into groups, or building interaction terms.
It matters because a simple model on well-crafted features usually beats a fancy model on raw ones. On tabular data especially, the gains from good features tend to exceed the gains from swapping algorithms, which is why experienced practitioners spend real time here.
Key point: A great concrete answer beats theory: The feature you engineered and how it helped. It proves you've done applied work, not just read about it.
As you add features, the space grows exponentially and data points become sparse: everything ends up roughly equidistant, so distance-based methods lose meaning and models need far more data to generalize.
Practical consequences include worse KNN and clustering, more overfitting, and slower training. The remedies are dimensionality reduction (PCA), feature selection, and simply gathering more data or fewer, better features.
Key point: it maps back to a concrete model: 'this is why KNN degrades in high dimensions' lands better than an abstract definition.
PCA is an unsupervised technique that finds new axes (principal components) along which the data varies most, then projects the data onto the top few. It reduces dimensions while keeping as much variance as possible.
Use it to compress correlated features, speed up training, or visualize high-dimensional data in two or three dimensions. The cost is interpretability: components are combinations of original features, so you trade meaning for compactness. Scale features first, since PCA is variance-based.
from sklearn.decomposition import PCA
pca = PCA(n_components=0.95) # keep enough components for 95% of variance
X_reduced = pca.fit_transform(X_scaled)
print(pca.n_components_) # how many components that tookKey point: Setting n_components to a variance fraction (0.95) instead of a fixed count shows you think about how much information you keep, not just how many columns you drop.
Gradient descent is the optimization workhorse that trains most models. It computes the gradient (slope) of the loss with respect to each parameter, then steps the parameters in the opposite direction, scaled by the learning rate, repeating until the loss stops improving.
The learning rate is the key knob: too large and it overshoots or diverges, too small and it crawls. Variants trade off speed and stability: batch descent uses all data per step, stochastic uses one example, and mini-batch (the practical default) uses small batches.
# Gradient descent for simple linear regression, one feature
w, b, lr = 0.0, 0.0, 0.01
for _ in range(1000):
y_pred = w * X + b
error = y_pred - y
w -= lr * (2 * (error * X).mean()) # step down the slope for w
b -= lr * (2 * error.mean()) # step down the slope for bKey point: If asked about getting stuck, mention local minima and saddle points, and that momentum and adaptive optimizers like Adam help escape them. Don't overclaim; for convex losses there's one minimum.
Watch a deeper explanation
Video: Gradient Descent, Step-by-Step (StatQuest with Josh Starmer, YouTube)
A loss function measures how wrong a prediction is; training minimizes it. The choice follows the task. Regression commonly uses mean squared error (penalizes big errors heavily) or mean absolute error (less sensitive to outliers). Classification uses cross-entropy (log loss), which rewards confident correct predictions and punishes confident wrong ones.
The interview point is that the loss encodes what you care about. If large errors are especially costly, MSE fits; if outliers shouldn't dominate, MAE fits. The loss is a design decision, not a default.
Key point: Distinguish the loss (what the model optimizes during training) from the metric (what you report to stakeholders). They're often different, and confusing them is a common slip.
Parametric models assume a fixed form with a set number of parameters learned from data: linear and logistic regression, for example. They're fast and data-efficient but limited by the assumed form. Non-parametric models make fewer assumptions and let complexity grow with the data: KNN, decision trees, kernel SVMs.
The trade-off is flexibility versus data hunger. Parametric models generalize from less data but underfit complex patterns; non-parametric models capture complex patterns but need more data and risk overfitting.
Key point: A neat clarification: 'non-parametric' doesn't mean no parameters, it means the number isn't fixed in advance and can grow with the dataset.
Discriminative models learn the boundary between classes directly, modeling the probability of a label given the input: logistic regression, SVMs, most neural network classifiers. Generative models learn how each class generates data, modeling the joint distribution, and use that to classify: naive Bayes, Gaussian mixture models.
Discriminative models usually win on pure classification accuracy with enough data. Generative models can work with less data, handle missing features more gracefully, and can generate new samples, which is the whole basis of modern generative AI.
Key point: A one-liner that lands: 'discriminative draws the line between classes; generative learns what each class looks like.'
Ensemble learning combines multiple models so the group outperforms any single member. Bagging trains models in parallel on bootstrap samples and averages them to cut variance (random forests). Boosting trains models in sequence, each correcting the previous one's errors, to cut bias (gradient boosting). Stacking feeds several models' predictions into a final model.
It works because independent errors partly cancel out. The tell for when to reach for it: strong tabular performance where a single model plateaus, accepting more compute and less interpretability in return.
Key point: Map the two vocabularies for the interviewer: bagging reduces variance (random forest), boosting reduces bias (XGBoost). That mapping is exactly what this question screens for.
Parameters are learned from data during training: the weights of a linear model, the split thresholds of a tree. Hyperparameters are set before training and control how learning happens: the learning rate, the number of trees, the regularization strength, k in KNN.
You tune hyperparameters with search over the validation set (grid search, random search, or Bayesian optimization), while the parameters get fit by the training process itself.
from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import RandomForestClassifier
grid = {'n_estimators': [100, 300], 'max_depth': [5, 10, None]}
search = GridSearchCV(RandomForestClassifier(), grid, cv=5, scoring='f1')
search.fit(X_train, y_train)
print(search.best_params_)Key point: Mention random search or Bayesian optimization for large spaces: grid search gets exponentially expensive, and interviewers like hearing you'd pick the search method to fit the budget.
Detect them with simple statistics and plots first: the interquartile range rule flags points far outside the middle 50%, z-scores flag points many standard deviations from the mean, and box plots or scatter plots make them visible. For many features together, isolation forests or clustering can surface unusual points.
Handling depends on the cause. A data-entry error you fix or drop. A genuine rare event you usually keep, because it may be the signal (fraud, a spike). You can also cap extreme values (winsorize) or pick models that tolerate outliers, like tree ensembles. The wrong move is deleting outliers blindly, since that can throw away the very cases you care about.
import numpy as np
q1, q3 = np.percentile(x, [25, 75])
iqr = q3 - q1
low, high = q1 - 1.5 * iqr, q3 + 1.5 * iqr
outliers = (x < low) | (x > high) # the classic IQR flagKey point: The judgment the question needs is 'understand why it's an outlier before removing it.' Blindly deleting outliers is the anti-pattern this question checks for.
Good training data is representative of what the model will see in production, correctly and consistently labeled, and large enough to cover the important cases including rare ones. Garbage in means garbage out: no algorithm fixes biased or mislabeled data.
Getting it means sampling to match real-world distribution (not just the easy-to-collect cases), writing clear labeling guidelines so annotators agree, measuring inter-annotator agreement, and auditing for bias against groups you care about. When labels are scarce, techniques like active learning label the most informative examples first, and weak or semi-supervised labeling stretch a small labeled set.
Key point: the key signal is 'representative and consistently labeled' plus awareness of bias. Naming inter-annotator agreement shows you've thought about label quality, not just quantity.
For candidates who model regularly: how the core algorithms work, when to reach for each, and the trade-offs interviewers probe.
Linear regression fits a straight-line relationship between features and a continuous target by finding the coefficients that minimize squared error. Each coefficient is the expected change in the target per unit change in that feature, holding others fixed, which makes it highly interpretable.
Its assumptions matter in interviews: a roughly linear relationship, independent errors, constant error variance (homoscedasticity), and little multicollinearity among features. Violate them and coefficients get unreliable even if predictions look okay.
from sklearn.linear_model import LinearRegression
model = LinearRegression().fit(X_train, y_train)
print(model.coef_) # effect of each feature
print(model.intercept_) # baseline predictionKey point: Being able to name even two assumptions (linearity, no strong multicollinearity) separates people who understand the model from people who only call .fit().
Watch a deeper explanation
Video: Linear Regression, Clearly Explained!!! (StatQuest with Josh Starmer, YouTube)
Logistic regression predicts the probability of a class by passing a linear combination of features through the sigmoid function, which squashes any number into the 0 to 1 range. You then threshold that probability (often at 0.5) to get a class.
The 'regression' name comes from its roots: it's a linear model under the hood, fit by maximizing likelihood rather than minimizing squared error. It stays interpretable and is the standard strong baseline for classification.
from sklearn.linear_model import LogisticRegression
clf = LogisticRegression().fit(X_train, y_train)
probs = clf.predict_proba(X_test)[:, 1] # probability of the positive class
preds = (probs >= 0.5).astype(int) # threshold to a labelKey point: The point interviewers wait for: it outputs a probability, and the 0.5 threshold is a choice you can move to trade precision for recall. That flexibility is a feature, not a detail.
Watch a deeper explanation
Video: StatQuest: Logistic Regression (StatQuest with Josh Starmer, YouTube)
A decision tree splits the data with a series of yes/no questions on features, choosing at each node the split that best separates the target (by Gini impurity or information gain), until leaves are pure enough. To predict, you follow the questions down to a leaf.
Its strength is interpretability: you can read the rules. Its main weakness is overfitting: an unrestricted tree can memorize the training data. You control that by limiting depth, requiring minimum samples per leaf, or pruning, which is also why ensembles of trees usually beat a single one.
from sklearn.tree import DecisionTreeClassifier
# Depth limit is the simplest guard against overfitting
tree = DecisionTreeClassifier(max_depth=5, min_samples_leaf=20)
tree.fit(X_train, y_train)Key point: 'A single tree overfits' is the answer the question needs, and it's the natural bridge to random forests and boosting as the fix.
A random forest trains many decision trees on bootstrap samples of the data and, at each split, considers only a random subset of features. It averages their predictions (or takes a majority vote). This is bagging: independent trees make different errors that partly cancel, cutting variance.
The result is far less overfitting than one deep tree, strong out-of-the-box performance on tabular data, and low tuning effort. You trade the readability of a single tree for accuracy, though feature importances still give you some insight.
from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier(n_estimators=300, max_features='sqrt')
rf.fit(X_train, y_train)
print(rf.feature_importances_) # relative contribution of each featureKey point: The two sources of randomness (row sampling AND feature sampling at each split) are what interviewers check. Missing the feature sampling is the most common half-answer.
Watch a deeper explanation
Video: StatQuest: Random Forests Part 1 - Building, Using and Evaluating (StatQuest with Josh Starmer, YouTube)
Both are tree ensembles, but they build differently. Random forests train trees independently in parallel and average them (bagging, cuts variance). Gradient boosting trains trees sequentially, each new tree fitting the errors the previous ones made (boosting, cuts bias). Popular implementations are XGBoost, LightGBM, and CatBoost.
Boosting often reaches higher accuracy on structured data but is easier to overfit and has more hyperparameters (learning rate, number of trees, depth) that need careful tuning. Random forests are more forgiving; boosting is the accuracy play when you have time to tune.
Key point: The crisp contrast wins here: forests build in parallel to reduce variance; boosting builds sequentially to reduce bias. Say it that cleanly and the follow-ups get easier.
Watch a deeper explanation
Video: Gradient Boost Part 1 (of 4): Regression Main Ideas (StatQuest with Josh Starmer, YouTube)
KNN classifies a new point by finding its k closest points in the training data (by a distance metric) and taking the majority label, or averaging for regression. There's no training phase: it just stores the data and does the work at prediction time, which is why it's called a lazy learner.
It's simple and makes no assumptions about the data's shape, but it's slow to predict on large datasets, sensitive to feature scaling and irrelevant features, and degrades in high dimensions. Small k overfits (noisy); large k oversmooths.
from sklearn.neighbors import KNeighborsClassifier
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
# Scaling matters: KNN uses raw distances
knn = make_pipeline(StandardScaler(), KNeighborsClassifier(n_neighbors=5))
knn.fit(X_train, y_train)Key point: Two things the key point is: KNN needs feature scaling, and choosing k trades bias for variance (small k overfits, large k underfits).
Watch a deeper explanation
Video: StatQuest: K-nearest neighbors, Clearly Explained (StatQuest with Josh Starmer, YouTube)
K-means is unsupervised. You pick k, place k centroids, assign each point to its nearest centroid, move each centroid to the mean of its assigned points, and repeat until assignments stop changing. It partitions data into k clusters that minimize within-cluster distance.
To choose k, the elbow method plots within-cluster error against k and looks for the bend; the silhouette score measures how well-separated clusters are. K-means assumes roughly round, similar-size clusters and is scale-sensitive, so standardize features first and don't expect it to find oddly shaped groups.
from sklearn.cluster import KMeans
inertias = []
for k in range(1, 10):
km = KMeans(n_clusters=k, n_init=10).fit(X_scaled)
inertias.append(km.inertia_) # plot these to find the elbowKey point: Naming both the elbow method and the silhouette score, and k-means assumes spherical clusters, is the fuller answer that.
Watch a deeper explanation
Video: StatQuest: K-means clustering (StatQuest with Josh Starmer, YouTube)
An SVM finds the boundary (hyperplane) that separates classes with the widest possible margin, defined by the closest points from each class, called support vectors. A wide margin tends to generalize better.
The kernel trick lets SVMs draw non-linear boundaries by implicitly mapping data into a higher-dimensional space where classes become linearly separable, without ever computing that space explicitly. SVMs shine on smaller, high-dimensional datasets but get slow on very large ones and need feature scaling.
Key point: You don't need the dual optimization math. Explaining 'maximize the margin' plus 'the kernel trick handles non-linear boundaries' at a concept level is what this question is really after.
Watch a deeper explanation
Video: Support Vector Machines Part 1 (of 3): Main Ideas!!! (StatQuest with Josh Starmer, YouTube)
Naive Bayes applies Bayes' theorem to compute the probability of each class given the features, then picks the most probable class. It's 'naive' because it assumes all features are independent given the class, which is rarely true but works surprisingly well in practice.
It's fast, needs little data, and handles high dimensions gracefully, which is why it's a classic baseline for text classification and spam filtering. The independence assumption is its main weakness: strongly correlated features can throw off the probability estimates.
from sklearn.naive_bayes import MultinomialNB
# Common for text: features are word counts
nb = MultinomialNB().fit(X_train_counts, y_train)
preds = nb.predict(X_test_counts)Key point: Say where it shines (text and spam) and why (fast, works in high dimensions with little data). Naming the independence assumption as its weakness completes the answer.
Watch a deeper explanation
Video: Naive Bayes, Clearly Explained!!! (StatQuest with Josh Starmer, YouTube)
Tree models expose built-in importances (how much each feature reduces impurity), but those are biased toward high-cardinality features and can mislead. Permutation importance is more trustworthy: shuffle one feature and measure how much performance drops. SHAP values give per-prediction, direction-aware explanations.
The pitfall to name is correlation: when two features are correlated, importance gets split or double-counted, so a truly useful feature can look weak. Importance shows association, not causation, which is a distinction interviewers like to hear.
from sklearn.inspection import permutation_importance
result = permutation_importance(model, X_val, y_val, n_repeats=10, random_state=42)
for i in result.importances_mean.argsort()[::-1]:
print(feature_names[i], round(result.importances_mean[i], 4))Key point: Preferring permutation or SHAP over raw tree importances, and flagging the correlation pitfall, is a strong production signal on this question.
Data leakage is when information the model won't have at prediction time slips into training, so offline scores look great and production performance collapses. Classic forms: fitting a scaler or imputer on the whole dataset before splitting, including a feature that's a proxy for the target, or using future data to predict the past.
Prevent it by splitting first and fitting all preprocessing inside a pipeline on training folds only, by thinking hard about whether each feature is truly available at prediction time, and by respecting time order for temporal data (train on the past, test on the future).
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
# Pipeline fits the scaler only on training folds, blocking leakage
pipe = Pipeline([('scale', StandardScaler()), ('clf', LogisticRegression())])
pipe.fit(X_train, y_train)Key point: This is a favorite because it separates notebook users from people who ship. Volunteering 'suspiciously high accuracy is often a leakage smell' shows real experience.
A neural network is layers of connected nodes (neurons). Each neuron takes a weighted sum of its inputs, adds a bias, and passes the result through a non-linear activation function. Stacking layers lets the network learn complex, non-linear patterns. Training adjusts the weights via gradient descent using backpropagation to compute the gradients.
The non-linear activations are what give a network power: without them, stacking layers would collapse into one linear model. Networks excel on unstructured data (images, audio, text) and large datasets, at the cost of needing lots of data, compute, and being hard to interpret.
Key point: The insight the technical value is: activation functions provide the non-linearity. Without them a deep network is just a fancy linear model, which is a common follow-up question.
Watch a deeper explanation
Video: But what is a neural network? | Deep learning chapter 1 (3Blue1Brown, YouTube)
An activation function decides a neuron's output and, critically, introduces non-linearity so the network can model complex patterns. Common choices are sigmoid, tanh, and ReLU (outputs the input if positive, else zero).
ReLU dominates hidden layers because it's cheap to compute and avoids the vanishing gradient problem that plagues sigmoid and tanh in deep networks, so training converges faster. Its downside, dead neurons that get stuck at zero, is handled by variants like Leaky ReLU.
Key point: Connecting ReLU to the vanishing gradient problem is the depth interviewers look for. 'It's fast' alone is a surface answer.
Watch a deeper explanation
Video: Gradient descent, how neural networks learn | Deep Learning Chapter 2 (3Blue1Brown, YouTube)
Backpropagation is the algorithm that computes how much each weight in a network contributed to the error, so gradient descent knows how to adjust them. It applies the chain rule from calculus, propagating the error backward from the output layer to the input layer, layer by layer.
In short: a forward pass produces a prediction and a loss, then backpropagation flows the gradients backward, and the optimizer updates every weight. It's what makes training deep networks tractable instead of impossibly slow.
Key point: You don't need to derive the chain rule live. Explaining 'it efficiently computes the gradient of the loss for every weight so we can update them' is the level this question expects.
An embedding is a dense vector of numbers that represents something (a word, a product, a user) in a way that captures meaning, so similar items land near each other in the vector space. Instead of a sparse one-hot code, you get a compact learned representation where distance encodes similarity.
They're useful because models can then reason about similarity: recommendation systems find nearby items, search finds semantically related results, and language models turn words into vectors that capture context. Modern retrieval systems store embeddings in a vector database to fetch relevant content by meaning rather than exact keywords.
Key point: Connecting embeddings to vector search and RAG is timely and shows current awareness. The core idea to state: 'similar things get similar vectors.'
Watch a deeper explanation
Video: Word Embedding and Word2Vec, Clearly Explained!!! (StatQuest with Josh Starmer, YouTube)
Convolutional neural networks (CNNs) exploit spatial structure, so they're the classic fit for images and grid-like data: filters detect local patterns like edges that combine into shapes. Recurrent neural networks (RNNs) process sequences step by step, carrying state, and once dominated text and time series.
Transformers have largely replaced RNNs for language and many sequence tasks because their attention mechanism handles long-range dependencies and parallelizes far better. A safe modern answer: CNNs for images, transformers for text and sequences, RNNs mostly as legacy or for niche streaming cases.
Key point: Acknowledging that transformers have overtaken RNNs for most sequence work signals you're current. Claiming RNNs are still state of the art for NLP would date you.
A confusion matrix is a table of a classifier's predictions versus actual labels. For binary classification it has four cells: true positives (correctly predicted positive), true negatives (correctly predicted negative), false positives (predicted positive but actually negative), and false negatives (predicted negative but actually positive).
It's the foundation for the real metrics: precision comes from the positive column, recall from the positive row. Reading it directly tells you not just how often the model is wrong, but how it's wrong, which is what matters when false positives and false negatives cost differently.
from sklearn.metrics import confusion_matrix
tn, fp, fn, tp = confusion_matrix(y_test, y_pred).ravel()
print(f'TP={tp} FP={fp} FN={fn} TN={tn}')Key point: Interviewers often ask you to derive precision and recall from the matrix live. Practice the two formulas until you can point to the cells without hesitating.
Watch a deeper explanation
Video: Machine Learning Fundamentals: The Confusion Matrix (StatQuest with Josh Starmer, YouTube)
Attack it in order. Get more or cleaner training data if you can, since that's the most reliable fix. Simplify the model or add regularization (L1, L2, dropout for networks). Reduce features or engineer better ones to cut noise. Use cross-validation to get an honest read, and for boosting or networks, early stopping halts training when validation error starts climbing.
the structured escalation, not a single trick is the technical point. Naming why each step helps (regularization penalizes complexity, dropout forces redundancy, early stopping catches the turn) beats listing techniques.
Key point: Lead with 'more data if possible,' then regularization and simplification, and mention early stopping for iterative models. Structure indicates experience.
Batch learning trains on the full dataset at once and produces a fixed model you retrain periodically. Online (incremental) learning updates the model one example or mini-batch at a time as new data arrives, so it adapts continuously without a full retrain.
Online learning suits streaming data, concept drift, and situations where the whole dataset won't fit in memory. Its risk is instability: a burst of bad or adversarial data can degrade the model quickly, so you monitor closely and can roll back.
Key point: online learning maps to drift and streaming. Interviewers like hearing the trade-off: adaptability in exchange for the risk that bad recent data corrupts the model fast.
Some algorithms handle multiple classes natively (decision trees, random forests, naive Bayes, softmax-based models). For inherently binary algorithms, two wrapping strategies apply. One-vs-rest trains one classifier per class against all others, so k classes means k models, and you pick the highest-scoring one. One-vs-one trains a classifier for every pair of classes and votes.
One-vs-rest is the common default: fewer models and simple to reason about, though classes can be imbalanced within each model. One-vs-one trains more classifiers but each on a smaller, balanced slice, which can help when per-class data is limited. scikit-learn wires this up automatically, but knowing the trade-off is the interview point.
from sklearn.multiclass import OneVsRestClassifier
from sklearn.svm import SVC
# Wrap a binary SVM to handle many classes
clf = OneVsRestClassifier(SVC()).fit(X_train, y_train)Key point: Knowing that one-vs-rest scales with the number of classes while one-vs-one scales with the number of pairs shows you understand the cost, not just the names.
All three are gradient boosting libraries that build trees sequentially, but they optimize different pain points. XGBoost is the established, widely-tuned choice with strong regularization. LightGBM grows trees leaf-wise and uses histogram-based splits, so it trains faster on large datasets, at some risk of overfitting on small ones. CatBoost handles categorical features natively with a special encoding, which saves preprocessing and reduces a class of leakage.
In practice you'd pick LightGBM for speed on big tabular data, CatBoost when you have many categorical columns, and XGBoost as a reliable, well-documented default. The honest answer is that on a given problem the differences are often small, so you'd benchmark a couple with cross-validation rather than argue theory.
| Library | Edge | Watch out for |
|---|---|---|
| XGBoost | Mature, strong regularization, well-documented | Slower than LightGBM on very large data |
| LightGBM | Fast, leaf-wise growth, scales to big data | Can overfit on small datasets |
| CatBoost | Native categorical handling, less preprocessing | Slower to train than LightGBM |
Key point: The strong move is 'they're close on most problems, so I'd benchmark two with cross-validation.' Claiming one is universally best is the overconfident answer to avoid.
advanced rounds probe honest evaluation, production judgment, and modern-model awareness. Expect every answer here to draw a follow-up.
Accuracy is the fraction of all predictions that are correct. Precision is, of the items predicted positive, how many really are positive. Recall is, of all actual positives, how many the model caught. F1 is the harmonic mean of precision and recall, useful when you want a single balanced number.
The choice follows the cost of errors. When false positives are expensive (flagging legitimate transactions as fraud annoys customers), optimize precision. When false negatives are expensive (missing a disease), optimize recall. F1 balances the two when both matter.
from sklearn.metrics import precision_score, recall_score, f1_score
print('precision', precision_score(y_test, y_pred))
print('recall ', recall_score(y_test, y_pred))
print('f1 ', f1_score(y_test, y_pred))Key point: The best answers each metric maps to a real cost of error. 'Recall for cancer screening, precision for spam' shows you pick metrics by consequences, which is exactly the judgment being tested.
Watch a deeper explanation
Video: Machine Learning Fundamentals: The Confusion Matrix (StatQuest with Josh Starmer, YouTube)
Accuracy lies hardest on imbalanced data. If 99% of transactions are legitimate, a model that predicts 'legitimate' every time scores 99% accuracy while catching zero fraud, which is useless. The majority class drowns out the metric.
It also misleads when errors have different costs: 90% accuracy sounds fine until you learn the 10% of misses are all the high-value cases. On imbalanced or asymmetric-cost problems, reach for precision, recall, F1, ROC-AUC, or PR-AUC instead.
Key point: Have the imbalanced-fraud example ready. It's the canonical illustration, and delivering it crisply proves you understand why the metric matters, not just its definition.
The ROC curve plots the true positive rate against the false positive rate across every classification threshold; ROC-AUC is the area under it, a single number from 0.5 (random) to 1.0 (perfect) that measures how well the model ranks positives above negatives, independent of any one threshold.
On heavily imbalanced data, ROC-AUC can look optimistic because the false positive rate barely moves when negatives dominate. The precision-recall curve (PR-AUC) focuses on the positive class and gives a more honest picture when positives are rare, like fraud or rare-disease detection.
from sklearn.metrics import roc_auc_score, average_precision_score
probs = model.predict_proba(X_test)[:, 1]
print('ROC-AUC', roc_auc_score(y_test, probs))
print('PR-AUC ', average_precision_score(y_test, probs))Key point: Knowing to switch from ROC-AUC to PR-AUC on rare-positive problems is a sharp signal. It shows you've hit the limits of the default metric in practice.
Watch a deeper explanation
Video: ROC and AUC, Clearly Explained! (StatQuest with Josh Starmer, YouTube)
MAE (mean absolute error) is the average absolute difference, in the target's units, and treats all errors linearly, so it resists outliers. MSE (mean squared error) squares errors, punishing large ones heavily, and RMSE is its square root back in the original units. R-squared reports the fraction of variance the model explains, from 0 to 1.
Pick by what you care about. If big misses are especially bad, MSE or RMSE. If you want a stable, interpretable average error, MAE. R-squared is good for communicating overall fit but can be misleading on its own, so pair it with an error metric.
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
import numpy as np
print('MAE ', mean_absolute_error(y_test, y_pred))
print('RMSE', np.sqrt(mean_squared_error(y_test, y_pred)))
print('R2 ', r2_score(y_test, y_pred))Key point: The MAE-versus-RMSE distinction (RMSE punishes large errors more, so it's sensitive to outliers) is the follow-up interviewers reliably ask. Have that one ready.
Most classifiers output a probability, and you choose the threshold that converts it to a label. Lowering the threshold catches more positives (higher recall) but also more false alarms (lower precision); raising it does the reverse. The precision-recall curve shows the whole trade-off so you can pick the operating point that fits the business cost.
So the trade-off isn't fixed by the model; it's a decision. For fraud you might accept more false positives to miss less fraud (favor recall); for a costly automated action you might demand high precision. Tune the threshold to the consequences, not to a default 0.5.
Key point: The key realization the technical value is: the 0.5 threshold is arbitrary and adjustable. Framing precision-recall as a tunable business decision, not a model limitation, is the mature answer.
a simple, strong baseline (logistic or linear regression, or even a majority-class predictor) so you have a floor to beat and a sanity check on the pipeline comes first. Then consider the data: tabular and structured points toward tree ensembles like random forests or gradient boosting; images, audio, or text point toward neural networks. Weigh interpretability needs, data volume, latency limits, and training budget.
The honest answer is empirical: you try a few candidates with proper cross-validation and pick by the metric that matches the goal, not by which algorithm is trendiest. Always beat the baseline before declaring victory.
Key point: 'a baseline' is the phrase interviewers wait for comes first. Jumping straight to a deep network for a small tabular problem is the anti-pattern this question screens for.
Clarify the goal and how success is measured first (the business metric, not just the model metric). Then the pipeline: collect and label data, engineer features, split honestly, train and tune with cross-validation, evaluate on a held-out test set against the baseline, and only then deploy. After deployment, serve predictions (batch or real-time), monitor performance and data drift, and retrain on a schedule or trigger.
The parts juniors skip are the ends: framing the metric up front and monitoring after launch. A model that works well offline but has no drift monitoring is a production incident waiting to happen, and saying that is the production signal.
An end-to-end ML system
The most-skipped steps are framing the metric up front and monitoring for drift after launch.
Key point: the seams: how data flows between stages, and especially the post-deployment loop is the technical point. monitoring and retraining is useful because separates production-ready answers from textbook ones.
Model drift is when a deployed model degrades because the world changed. Data drift is when the input distribution shifts (new user behavior, a new product mix). Concept drift is when the relationship between inputs and the target changes (what predicted fraud last year no longer does).
Detect it by monitoring input feature distributions and, where labels arrive, live performance metrics against a baseline. Handle it by retraining on fresh data, either on a schedule or triggered when drift crosses a threshold, and keep the ability to roll back a bad model quickly.
Key point: Separating data drift from concept drift, and pairing detection (monitoring) with response (retraining plus rollback), is exactly the production maturity this question checks for.
Offline evaluation measures a model on historical, held-out data before deployment: cross-validation scores, test-set metrics. It's cheap and fast but can't capture how real users react. Online evaluation measures the model on live traffic, usually through an A/B test comparing it against the current model on the actual business metric.
You need both. A model can win offline yet lose online because the offline metric was a proxy, the data drifted, or user behavior responds to the model itself. Offline to filter candidates, online to confirm real impact.
Key point: The point the question needs: offline wins don't guarantee online wins. Committing to an A/B test on the business metric before full rollout is the disciplined answer.
It depends on how fast the data changes and how costly retraining is. Scheduled retraining (say, weekly or monthly) is simple and predictable. Triggered retraining fires when monitoring detects drift or a performance drop past a threshold, which reacts faster but needs solid monitoring. Fast-moving domains lean toward frequent or continuous retraining; stable ones can go longer.
Whichever you choose, validate the retrained model against the current one before promoting it, and keep rollback ready. Automatically shipping a retrained model without a gate is how a bad data batch quietly breaks production.
Key point: Contrasting scheduled versus triggered retraining, and insisting on a validation gate before promotion, indicates someone who has actually operated models, not just trained them.
prompting: it's the cheapest and fastest, and for many tasks a good prompt with a few examples is enough comes first. Reach for retrieval augmented generation (RAG) when the model needs current or private knowledge it wasn't trained on; you retrieve relevant documents and feed them into the prompt so answers stay grounded and citable. Fine-tune when you need a consistent format, tone, or a specialized skill that prompting can't reliably produce, and you have quality training examples.
The judgment interviewers probe: don't fine-tune to add knowledge (RAG is usually cheaper and easier to keep fresh), and don't jump to fine-tuning before exhausting prompting. Match the tool to whether the gap is knowledge (RAG), behavior (fine-tuning), or neither (prompting).
| Approach | Best for | Main cost |
|---|---|---|
| Prompting | General tasks, fast iteration | Limited by the base model's knowledge |
| RAG | Current or private knowledge, grounded answers | Retrieval pipeline and vector store to maintain |
| Fine-tuning | Consistent format, tone, specialized behavior | Training data, cost, and staleness over time |
Key point: The mature 2026 answer is an escalation: prompting, then RAG for knowledge gaps, then fine-tuning for behavior. Reaching for fine-tuning first, or to inject facts, is the anti-pattern being tested.
Hallucination is when a language model produces fluent, confident text that's factually wrong or made up. It happens because these models predict likely next tokens rather than looking up verified facts, so they'll fill gaps plausibly rather than admit uncertainty.
You reduce it by grounding: RAG feeds the model retrieved source documents so answers cite real data, clear prompts ask it to say when it doesn't know, and you add verification steps or human review for high-stakes outputs. You can't fully eliminate it, so design the system to check the model rather than trust it blindly.
Key point: The honest framing wins: hallucination can be reduced (grounding, verification) but not eliminated, so the system design matters. Overclaiming that RAG 'solves' it is a red flag.
There's no single accuracy number, so you combine methods. Human evaluation rates outputs on relevance, correctness, and helpfulness, which is the gold standard but slow. Automated metrics and reference comparisons help at scale for tasks with known answers. Increasingly, a stronger model acts as an LLM judge to score outputs against a rubric, cross-checked against human ratings.
For a real application, you build a fixed evaluation set of representative inputs with expected behavior, score every change against it, and track task-specific signals (did the answer cite a source, follow the format, avoid unsafe content). Evaluation is an ongoing harness, not a one-time score.
Key point: Mentioning a held-out evaluation set plus LLM-as-judge validated against human ratings is current and practical. It shows you'd measure a generative system rather than eyeball it.
Deep learning is a subset of machine learning that uses neural networks with many layers. Classical ML (linear models, trees, SVMs) usually relies on human-engineered features and works well on structured, tabular data with modest dataset sizes. Deep learning learns features automatically from raw data and dominates unstructured inputs like images, audio, and text.
The practical trade-off: deep learning needs far more data and compute and is harder to interpret, so for a typical tabular business problem a gradient-boosted tree often beats a neural network with less effort. Deep learning earns its cost when the data is large and unstructured.
Key point: Resisting the assumption that deep learning is always better is the signal here. Saying 'for tabular data, boosting usually wins' shows judgment over hype.
Explainability matters because stakeholders need to trust decisions, regulated domains (credit, hiring, healthcare) require justifications, and debugging a wrong prediction is impossible if the model is a black box. An unexplainable model can also hide bias that only surfaces when someone asks 'why this decision?'
You provide it at two levels: global explanations (feature importances, SHAP summaries) show what drives the model overall, and local explanations (SHAP or LIME per prediction) show why one specific decision came out the way it did. When the domain demands full transparency, choosing an inherently interpretable model like logistic regression can be the right call over a marginally more accurate black box.
Key point: Distinguishing global from local explanations, and naming SHAP, shows practical fluency. Adding that you'd sometimes trade a little accuracy for an interpretable model indicates real-world judgment.
Confirm it's real first: check whether the metric drop is genuine or a monitoring artifact, and correlate it with recent changes (a new deploy, a data pipeline change, a shift in traffic). Then check for data issues: broken feature pipelines, new categories, missing values, or a distribution shift (drift) in the inputs. Compare current input stats against training stats.
If the data is fine, look at the model and serving path: is the right model version live, is preprocessing consistent between training and serving (training-serving skew), are there latency or timeout errors? Fix at the layer you find the cause, retrain if it's drift, and add a monitor so the same failure is caught automatically next time.
Key point: The structure (confirm, check data and drift, check serving and skew, fix, add monitoring) matters more than any single tool, and training-serving skew is the detail that flags experience.
There's no single best algorithm; the right one depends on your data, your need for interpretability, and how much data you have. A useful interview instinct is to start simple (logistic or linear regression as a baseline), then reach for tree ensembles when relationships are non-linear and features interact, and reserve neural networks for large datasets with unstructured inputs like images, audio, or text. Saying why you'd pick one over another, out loud, is itself a strong signal: it shows you choose tools on the problem, not on habit or hype.
| Algorithm | Type | Best at | Watch out for |
|---|---|---|---|
| Logistic / Linear Regression | Supervised | Fast, interpretable baseline; linear relationships | Underfits non-linear patterns; needs scaling for regularized versions |
| Random Forest | Supervised | Tabular data, non-linear interactions, low tuning effort | Large models, slower inference, less interpretable than one tree |
| Gradient Boosting (XGBoost / LightGBM) | Supervised | Strong tabular accuracy on structured data | Easy to overfit, more hyperparameters to tune carefully |
| K-Means | Unsupervised | Grouping unlabeled data into k clusters | Must pick k; assumes round, similar-size clusters; scale-sensitive |
| Neural Networks | Supervised | Images, audio, text, very large datasets | Data-hungry, compute-heavy, hard to interpret and debug |
Prepare in layers, and out loud is the explanation path. Most ML rounds move from concept questions to modeling choices to how you evaluate results and then to a system design or production discussion, so rehearse each stage rather than only reading answers.
The typical machine learning interview flow
Earlier rounds increasingly run as AI coding interviews. The concepts on this page are what gets probed at every stage.
10 questions, about 6 minutes. Score 70% or higher to earn a shareable certificate.
Hyring builds the AI Coding Interviewer that runs live technical rounds in 20+ languages, including machine learning problems in Python. These questions reflect what actually gets asked and evaluated inside the interviews we host for 5,000+ HR teams.
See how the AI Coding Interviewer works