← Startups.com Interview Insights

Startups.com·Machine Learning Engineer·Technical Phone Screen·Senior

Senior
May 2026

Summary

Technical screen for an ML Engineer role at Startups.Com, focused entirely on implementing neural network primitives from scratch in PyTorch without touching torch.nn. Pretty deep dive, felt more like a take-home style problem compressed into a live setting.

Questions Asked (6)

Q1

Implement ReLU from scratch using only basic PyTorch tensor operations, without using any torch.nn or torch.nn.functional calls.

Technical Trade-offsAlgorithms & Data Structures
Author's notes

Easiest one on the list.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying that ReLU is element-wise max(0, x), then implement it using basic tensor operations like torch.clamp or torch.maximum with a zero tensor. Discuss the trade-offs of each approach, such as in-place operations for memory efficiency and gradient behavior.

Pro tip: Mention that using torch.clamp(min=0) is concise and efficient, but if you need to avoid any torch.nn or functional calls, torch.maximum(x, torch.zeros_like(x)) is a safe bet. Also, highlight that in-place ReLU (x.clamp_(min=0)) saves memory but can break autograd if not careful.

1. Define ReLU mathematically

State that ReLU(x) = max(0, x) element-wise, and emphasize it's a simple non-linear activation.

2. Choose basic tensor operations

Select operations like torch.clamp, torch.maximum, or torch.where that are allowed (not torch.nn or functional).

3. Implement and test

Write the function, test with sample tensors including negatives, zeros, and positives, and verify gradients if needed.

4. Discuss trade-offs

Compare approaches: in-place vs out-of-place, memory vs safety, and performance implications.

Key Points to Mention

  • ReLU is element-wise max(0, x), so any operation that achieves this is valid.
  • torch.clamp(min=0) is the most concise and efficient out-of-place implementation.
  • torch.maximum(x, torch.zeros_like(x)) is an alternative that avoids clamp but creates an extra tensor.
  • In-place operations (e.g., x.clamp_(min=0)) save memory but can cause issues with autograd if the input is needed for gradient computation.
  • Gradient of ReLU is 1 for x > 0, 0 for x < 0, and undefined (often set to 0) at x = 0.
  • Always test with edge cases: negative values, zero, and positive values.

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

Q2

Implement numerically stable softmax from scratch for an arbitrary dimension.

Algorithms & Data StructuresTechnical Trade-offs
Author's notes

The 'numerically stable' part is the whole point here.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by explaining the numerical instability of the naive softmax and the standard max-subtraction trick. Then describe how to generalize this to arbitrary dimensions by subtracting the maximum along the specified axis while preserving shape for broadcasting. Finally, discuss implementation details like handling edge cases and potential trade-offs.

Pro tip: Mention that for very large inputs, even after max subtraction, exponentials can underflow to zero, but this is acceptable because it reflects the true distribution. Also, note that using `keepdims=True` is crucial for correct broadcasting.

1. Explain the naive softmax and its instability

Describe the formula softmax(x_i) = exp(x_i) / sum(exp(x_j)) and why large values cause overflow, leading to NaN or Inf.

2. Introduce the max-subtraction trick

Show that subtracting a constant from all inputs does not change the output, and choosing the maximum ensures the largest exponent is 0, preventing overflow.

3. Generalize to arbitrary dimensions

Explain how to compute the maximum along the specified axis (e.g., axis=1 for batch of vectors) and subtract it using broadcasting, ensuring the shape is preserved with keepdims=True.

4. Implement the softmax function

Write pseudocode or actual code: compute max along axis, subtract, exponentiate, sum along axis, and divide. Mention handling of edge cases like all -inf inputs.

5. Discuss trade-offs and optimizations

Talk about memory usage (e.g., creating intermediate arrays), potential for in-place operations, and numerical stability in extreme cases (e.g., underflow to zero).

Key Points to Mention

  • Numerical stability: overflow and underflow issues in naive softmax.
  • Max-subtraction trick: subtracting the maximum value along the axis to prevent overflow.
  • Broadcasting: using keepdims=True to maintain dimensions for correct subtraction and division.
  • Arbitrary dimension: specifying the axis parameter to compute softmax along any dimension.
  • Edge cases: handling -inf inputs (e.g., masked softmax) and ensuring no division by zero.
  • Trade-offs: memory overhead of intermediate arrays vs. numerical stability, and potential for in-place operations.

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

Q3

Implement LayerNorm from scratch, including learnable gamma and beta parameters, normalizing over the last k dimensions.

System DesignTechnical Trade-offs
Author's notes

I defaulted to just the last dim at first and had to be nudged about the general 'last k dims' case.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the input shape and which dimensions to normalize over, then derive the formula and implement it using vectorized operations. Emphasize numerical stability with epsilon and explain how gamma and beta are applied. Finally, discuss trade-offs and potential optimizations.

Pro tip: Mention that LayerNorm is typically applied per-sample and that using biased variance (divide by N) is standard, but be prepared to discuss unbiased variance if asked. Also, note that in practice, frameworks like PyTorch fuse operations for speed, so a from-scratch implementation is mainly for understanding.

1. Clarify requirements and input shape

Ask or state assumptions about the input tensor shape (e.g., [batch, seq_len, features]) and which last k dimensions to normalize over. Confirm that gamma and beta are learnable parameters with the same shape as the normalized dimensions.

2. Derive the normalization formula

Write the mathematical formula: mean and variance computed over the last k dimensions, then normalize: (x - mean) / sqrt(variance + epsilon). Explain that epsilon is a small constant for numerical stability.

3. Implement with vectorized operations

Use array operations (e.g., NumPy or PyTorch) to compute mean and variance along the specified axes, avoiding loops. Apply the normalization and then scale and shift with gamma and beta.

4. Handle numerical stability and edge cases

Add epsilon to the variance before taking the square root. Consider cases like zero variance or very small values. Also, ensure gradients can flow through gamma and beta if implementing in an autograd framework.

5. Discuss trade-offs and optimizations

Mention computational complexity, memory usage, and potential optimizations like fusing operations or using Welford's algorithm for streaming mean/variance. Compare with other normalization techniques (e.g., BatchNorm) and explain when LayerNorm is preferred.

Key Points to Mention

  • Normalization is performed over the last k dimensions, which are specified by the user; mean and variance are computed per sample and per normalized group.
  • Learnable parameters gamma (scale) and beta (shift) have the same shape as the normalized dimensions and are applied element-wise after normalization.
  • Epsilon is added to the variance for numerical stability, typically a small value like 1e-5.
  • Implementation should be vectorized to avoid explicit loops, using operations like mean and var with keepdims=True.
  • LayerNorm is invariant to batch size and works well for sequence models, unlike BatchNorm which depends on batch statistics.
  • Trade-offs include increased computation compared to no normalization, but benefits like improved training stability and convergence.

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

Q4

Implement BatchNorm for both training and inference modes from scratch, including running mean/variance updates with momentum.

Technical Trade-offsSystem DesignAlgorithms & Data Structures
Author's notes

This one took the most time.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the requirements and assumptions, then explain the mathematical formulation of BatchNorm for training and inference. Walk through the implementation details, including the forward pass, running statistics updates with momentum, and handling of learnable parameters. Finally, discuss practical considerations and potential pitfalls.

Pro tip: Emphasize the importance of using unbiased variance for running statistics updates while using biased variance for normalization during training, and mention how frameworks like PyTorch handle this. Also, highlight the need to set the module to evaluation mode to use running statistics during inference.

1. Clarify Requirements and Assumptions

Ask about input shape (e.g., (N, C, H, W) for images), whether to implement in NumPy or a specific framework, and if affine parameters (gamma, beta) are required. Confirm that running mean/variance are used only during inference.

2. Explain Training Mode Computation

Describe computing batch mean and variance (biased) over the appropriate dimensions (e.g., N, H, W for each channel). Normalize using these statistics, then apply scale and shift if affine. Update running mean and variance using momentum: running = (1 - momentum) * running + momentum * batch_stat.

3. Explain Inference Mode Computation

Use the running mean and variance (unbiased) to normalize the input. Apply the same scale and shift. Note that no statistics are computed from the batch during inference.

4. Discuss Implementation Details

Mention the need for a small epsilon for numerical stability. Explain how to handle different input dimensions (e.g., for fully connected layers, normalize over batch dimension). Discuss initialization of running statistics (mean=0, var=1) and affine parameters (gamma=1, beta=0).

5. Address Practical Considerations

Talk about the difference between biased and unbiased variance, and why running variance uses unbiased estimate. Mention that during training, the module uses batch statistics even if running stats are updated. Also, discuss how to handle batch size of 1 during training (variance zero) and potential issues.

Key Points to Mention

  • BatchNorm normalizes activations per channel across the batch dimension during training, and uses running statistics during inference.
  • Running mean and variance are updated with momentum: running = (1 - momentum) * running + momentum * batch_stat.
  • Use biased variance for normalization during training, but unbiased variance for running variance updates (to match framework behavior).
  • Affine parameters (gamma and beta) allow the network to undo normalization if needed, preserving representational power.
  • Epsilon is added to the variance for numerical stability during normalization.
  • During inference, the module uses the running statistics, so it must be in evaluation mode (e.g., model.eval() in PyTorch).

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

Q5

Implement RMSNorm from scratch. How does it differ from LayerNorm and when might you prefer it?

Technical Trade-offsAlgorithms & Data Structures
Author's notes

Simpler than LayerNorm since there's no mean subtraction, just divide by the root mean square.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clearly defining RMSNorm and its mathematical formulation, then implement it in code, highlighting the key differences from LayerNorm. Finally, discuss scenarios where RMSNorm is preferred, emphasizing computational efficiency and empirical performance.

Pro tip: Mention that RMSNorm is used in state-of-the-art models like LLaMA and T5, and that it often matches or exceeds LayerNorm performance while being faster, showing awareness of current industry practices.

1. Define RMSNorm

Explain that RMSNorm normalizes the input by its root mean square, without mean centering or bias, and optionally applies a learnable scale.

2. Implement RMSNorm

Write pseudocode or actual code (e.g., in PyTorch) showing the computation: calculate RMS, divide input by RMS, multiply by weight.

3. Compare with LayerNorm

Contrast the two: LayerNorm subtracts mean and divides by standard deviation, includes bias; RMSNorm only scales by RMS, no mean subtraction or bias.

4. Discuss Trade-offs

Highlight that RMSNorm is computationally cheaper (no mean calculation) and often performs similarly or better, but may be less robust for inputs with large mean shifts.

5. When to Prefer RMSNorm

Suggest using RMSNorm in large-scale models where efficiency matters, or when mean centering is unnecessary, as in many transformer architectures.

Key Points to Mention

  • Mathematical formula: RMSNorm(x) = x / sqrt(mean(x^2) + eps) * weight
  • No mean subtraction or bias term, unlike LayerNorm
  • Computational efficiency: fewer operations, faster training/inference
  • Empirical success in models like LLaMA, T5, and other transformers
  • Potential limitations: may not handle inputs with non-zero mean well
  • Implementation details: epsilon for numerical stability, learnable scale parameter

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

Q6

For each of the components you implemented, how would you verify correctness? Walk through your testing strategy including numerical checks and edge cases.

Technical Trade-offsSystem Design
Author's notes

Talked about comparing outputs against reference implementations, running finite-difference gradient checks, and testing edge cases like fp16 inputs, near-zero variance, and unusual shapes.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Structure your answer by walking through each component in the ML pipeline (data, features, model, serving) and describe a layered testing strategy: unit tests for deterministic logic, numerical gradient checks, and integration tests with edge cases. Emphasize how you prioritize tests based on risk and business impact, and how you automate them in CI/CD.

Pro tip: Show that you think about testing as a continuous process, not a one-time task—mention how you monitor for data drift and model degradation in production, and how you use canary deployments to catch issues early.

1. Component Breakdown

List the key components you implemented (e.g., data preprocessing, feature engineering, model training, inference API) and briefly state the purpose of each.

2. Unit & Numerical Tests

For each component, describe specific unit tests (e.g., input/output shape checks, data type validation) and numerical checks (e.g., gradient checking, loss convergence, metric thresholds).

3. Edge Case & Robustness Testing

Identify edge cases such as missing values, outliers, empty inputs, and extreme values, and explain how you test for them (e.g., fuzzing, property-based tests).

4. Integration & End-to-End Tests

Explain how you test the components together, including data flow, API contracts, and end-to-end pipeline runs with synthetic and real data.

5. Monitoring & Continuous Validation

Describe how you monitor model performance in production (e.g., drift detection, A/B tests) and how you incorporate feedback into your testing strategy.

Key Points to Mention

  • Gradient checking for custom layers or loss functions
  • Unit tests for data preprocessing (e.g., handling missing values, scaling)
  • Edge cases: empty inputs, NaNs, out-of-range values, high-cardinality categoricals
  • Integration tests with mocked services and contract testing
  • Automated testing in CI/CD pipelines with thresholds for model metrics
  • Production monitoring: data drift, concept drift, and performance degradation alerts

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