← Waymo Interview Insights

Waymo·Machine Learning Engineer·Technical Phone Screen·Senior

SeniorPrefer not to say
Apr 2026

Summary

Waymo ML Engineer interview had me coding up logistic regression from scratch using only NumPy, plus a conceptual discussion on optimization and loss functions. Pretty deep for a single session, and the theory follow-ups caught me more off guard than the coding part did.

Questions Asked (4)

Q1

Implement binary logistic regression from scratch using only NumPy, including the forward pass, loss computation, gradient derivation, and a fit method with gradient descent.

Algorithms & Data StructuresTechnical Trade-offs
Author's notes

I started with sigmoid and cross-entropy, which was fine.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the problem setup and then systematically implement each component: forward pass (sigmoid), loss (binary cross-entropy), gradients (derived via chain rule), and gradient descent. Emphasize vectorization with NumPy for efficiency and discuss numerical stability and convergence checks.

Pro tip: Demonstrate numerical stability by using the log-sum-exp trick for the loss and adding a small epsilon to avoid log(0). Also, mention that you would monitor the loss curve and consider early stopping or learning rate schedules.

1. Clarify and Define

Confirm the input/output shapes, loss function (binary cross-entropy), and optimization method (batch gradient descent). Discuss any assumptions about the data (e.g., binary labels 0/1).

2. Forward Pass and Loss

Implement the linear combination z = X @ w + b, apply sigmoid activation to get probabilities, and compute the binary cross-entropy loss with numerical stability.

3. Gradient Derivation

Derive the gradients of the loss with respect to weights and bias using the chain rule. Show that dL/dw = (1/m) * X^T @ (y_hat - y) and dL/db = (1/m) * sum(y_hat - y).

4. Gradient Descent Implementation

Implement the fit method: initialize weights, iterate for a number of epochs, compute gradients, and update parameters with learning rate. Optionally include convergence checks.

5. Testing and Validation

Test on a small synthetic dataset (e.g., linearly separable) to verify convergence. Discuss how to check gradients numerically and handle edge cases like class imbalance.

Key Points to Mention

  • Vectorization with NumPy for efficient computation (avoid loops).
  • Numerical stability in loss computation (log-sum-exp trick, epsilon).
  • Gradient derivation using chain rule and matrix calculus.
  • Learning rate selection and its impact on convergence.
  • Regularization (L2) to prevent overfitting and its gradient.
  • Handling class imbalance via class weights or resampling.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q2

Why do we use binary cross-entropy loss for classification instead of mean squared error?

Technical Trade-offs
Author's notes

Knew this one but fumbled the explanation a bit.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by contrasting the probabilistic foundations of binary cross-entropy (BCE) and mean squared error (MSE) for classification. Explain how BCE's log-likelihood formulation and convexity lead to better optimization and calibrated probabilities, while MSE suffers from vanishing gradients and non-convexity. Conclude with practical implications for model performance and training stability.

Pro tip: Mention that BCE is equivalent to minimizing KL divergence between predicted and true distributions, and that using MSE for classification can lead to slow convergence and poor probability estimates, especially with sigmoid outputs.

1. Define the problem and losses

Clarify that binary classification predicts a probability, and compare BCE (log loss) and MSE (squared error) as loss functions.

2. Probabilistic interpretation

Explain that BCE arises from maximum likelihood estimation under a Bernoulli distribution, while MSE assumes a Gaussian distribution, which is inappropriate for binary labels.

3. Optimization properties

Discuss how BCE with sigmoid output is convex (or at least has better gradient behavior), whereas MSE with sigmoid is non-convex and suffers from vanishing gradients when predictions are saturated.

4. Gradient behavior

Show that BCE's gradient is proportional to the error (p - y), leading to larger gradients when the model is wrong, while MSE's gradient includes the sigmoid derivative, which can be very small.

5. Practical implications

Conclude that BCE leads to faster convergence, better calibrated probabilities, and improved classification performance compared to MSE.

Key Points to Mention

  • BCE is the negative log-likelihood of a Bernoulli distribution, aligning with binary classification.
  • MSE assumes Gaussian noise, which is not suitable for binary outcomes.
  • BCE with sigmoid output is convex, while MSE with sigmoid is non-convex.
  • BCE avoids vanishing gradients because its gradient does not include the sigmoid derivative.
  • MSE can lead to poor probability calibration and slower training.
  • BCE penalizes confident wrong predictions more heavily, which is desirable for classification.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q3

How sensitive is logistic regression to the choice of learning rate, and how do you know when it has converged?

Technical Trade-offsAlgorithms & Data Structures
Author's notes

Talked about loss curves plateauing and gradient norms shrinking.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by explaining that logistic regression's sensitivity to learning rate depends on the optimizer and data scaling, then discuss convergence criteria such as gradient norm, loss plateau, and validation metrics. Emphasize practical monitoring and trade-offs between convergence speed and stability.

Pro tip: Mention that using adaptive optimizers like Adam can reduce learning rate sensitivity, but for interpretability and simplicity, SGD with a well-tuned learning rate and early stopping is often preferred in production. Also, always scale features and monitor the norm of the gradient relative to the loss.

1. Clarify the optimization setup

Specify whether you're using batch, stochastic, or mini-batch gradient descent, and which optimizer (e.g., SGD, Adam). This sets the context for learning rate sensitivity.

2. Discuss learning rate sensitivity

Explain that too high a learning rate can cause divergence or oscillation, while too low can lead to slow convergence. Mention that logistic regression's convex loss surface means it's less sensitive than deep networks, but still requires tuning.

3. Describe convergence criteria

List common criteria: gradient norm below a threshold, change in loss function below a tolerance, or validation performance plateau. Mention that monitoring these over epochs helps decide when to stop.

4. Highlight practical considerations

Talk about using learning rate schedules (e.g., decay) or adaptive methods to mitigate sensitivity. Also, mention that feature scaling and regularization affect convergence.

5. Conclude with trade-offs

Summarize that while logistic regression is relatively robust, proper tuning and convergence monitoring are essential for reliable performance, especially in production systems.

Key Points to Mention

  • Convexity of logistic regression loss ensures global minimum, but learning rate still affects convergence speed and stability.
  • Common convergence criteria: gradient norm, loss change, validation metric plateau, and parameter change.
  • Impact of feature scaling and regularization on learning rate sensitivity.
  • Use of adaptive optimizers (e.g., Adam, RMSprop) to reduce learning rate tuning.
  • Learning rate schedules (step decay, exponential decay) for better convergence.
  • Practical monitoring: early stopping based on validation loss to avoid overfitting.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q4

How would you implement a numerically stable version of the sigmoid function?

Algorithms & Data Structures
Author's notes

Clipping logits before passing through sigmoid, or using np.logaddexp for the log-probability version.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by explaining the numerical instability of the naive sigmoid implementation for large negative inputs, then present a branch-based solution that computes different expressions for positive and negative inputs to avoid overflow. Finally, discuss the mathematical equivalence and practical considerations for vectorized implementations.

Pro tip: Mention that in practice, you can use a single expression with np.where or torch.where to maintain vectorization while avoiding branches, and highlight that this is crucial for performance in deep learning frameworks.

1. Identify the instability

Explain that the naive sigmoid 1/(1+exp(-x)) overflows for large negative x because exp(-x) becomes huge, leading to inf and then 0/0 or inf/inf.

2. Derive stable expressions

Show that for x >= 0, sigmoid(x) = 1/(1+exp(-x)) is stable, and for x < 0, sigmoid(x) = exp(x)/(1+exp(x)) is stable, since exp(x) is small.

3. Implement with branching or masking

Describe how to implement this using if-else for scalars or using element-wise selection (e.g., np.where) for arrays to avoid branching overhead.

4. Verify correctness and stability

Test with extreme values like -1000, 0, 1000 to ensure no overflow and correct outputs (0, 0.5, 1).

5. Discuss performance and vectorization

Emphasize that vectorized operations are preferred in ML frameworks, and that the stable version maintains differentiability and efficiency.

Key Points to Mention

  • Overflow in exp(-x) for large negative x leads to NaN or incorrect results.
  • Mathematically equivalent forms: sigmoid(x) = 1/(1+exp(-x)) for x>=0, and exp(x)/(1+exp(x)) for x<0.
  • Use of np.where or torch.where for vectorized conditional selection.
  • Avoiding explicit Python loops for performance in array operations.
  • Testing with extreme values to ensure stability and correctness.
  • Relevance to deep learning: sigmoid is used in gates (e.g., LSTM) and output layers, so stability is critical.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.