
ML Engineer Interview Questions from Meta & Baidu
Machine Learning (ML) engineering interviews at top tech companies like Meta, Amazon, Baidu, and Atlassian are known for their challenging and practical questions. These companies assess not only algorithmic and coding skills but also a deep understanding of systems, data structures, and real-world ML system design.
ML Engineer Interview Questions from Meta, Amazon & Others: Solutions and Explanations
1. Efficient Range Sum Queries on a Matrix (Meta)
Problem Statement
Suppose you have a matrix of numbers. How can you efficiently compute the sum of any rectangle (i.e., a range defined by [row_start, row_end, col_start, col_end]) of those numbers? How would you code this?
Concepts Involved
- Prefix Sums / Integral Images
- Dynamic Programming
- 2D Array Manipulation
Brute Force Approach
The naive method is to iterate over all cells in the specified rectangle and sum them. Given a matrix of size m x n and a query rectangle of size (row_end - row_start + 1) x (col_end - col_start + 1), the time complexity per query is O(R x C), where R and C are the number of rows and columns in the query.
However, for multiple queries, this becomes inefficient. We need a way to preprocess the matrix to allow constant time sum queries.
Optimized Solution: 2D Prefix Sums
This technique is also known as the integral image in computer vision. The idea is to preprocess the matrix to build a prefix sum matrix S, where S[i][j] contains the sum of all elements from (0,0) to (i,j).
Mathematical Formulation
Let matrix[i][j] be the original matrix and S[i][j] the prefix sum matrix:
\[ S[i][j] = \sum_{x=0}^{i} \sum_{y=0}^{j} matrix[x][y] \]
To compute the sum of elements inside a rectangle defined by (r1, c1) (top-left) and (r2, c2) (bottom-right), we use the inclusion-exclusion principle:
\[ \text{Sum} = S[r2][c2] - S[r1-1][c2] - S[r2][c1-1] + S[r1-1][c1-1] \]
If r1 or c1 is 0, the corresponding terms are omitted.
Prefix Sum Matrix Construction (Python Example)
def build_prefix_sum(matrix):
if not matrix or not matrix[0]:
return []
m, n = len(matrix), len(matrix[0])
S = [[0] * (n + 1) for _ in range(m + 1)] # 1-based indexing for simplicity
for i in range(1, m + 1):
for j in range(1, n + 1):
S[i][j] = matrix[i - 1][j - 1] + S[i - 1][j] + S[i][j - 1] - S[i - 1][j - 1]
return S
def range_sum(S, row1, col1, row2, col2):
# Adjust for 1-based indexing
row1 += 1
col1 += 1
row2 += 1
col2 += 1
return S[row2][col2] - S[row1 - 1][col2] - S[row2][col1 - 1] + S[row1 - 1][col1 - 1]
# Example Usage:
matrix = [
[3, 0, 1, 4, 2],
[5, 6, 3, 2, 1],
[1, 2, 0, 1, 5],
[4, 1, 0, 1, 7],
[1, 0, 3, 0, 5]
]
S = build_prefix_sum(matrix)
result = range_sum(S, 2, 1, 4, 3) # Query sum of rectangle from (2,1) to (4,3)
print(result) # Output: 8
Time and Space Complexity
- Preprocessing: O(mn)
- Query: O(1)
- Space: O(mn)
Common Follow-up Questions
- How would you handle updates to the matrix? (Answer: Use a Binary Indexed Tree or Segment Tree for dynamic updates, but this is more advanced.)
- How would you handle very large matrices? (Answer: Use sparse representations or chunked storage.)
2. Designing a Recommendation System (Amazon)
Problem Statement
How would you design a recommendation system?
Key Concepts
- Collaborative Filtering
- Content-Based Filtering
- Hybrid Recommendation Systems
- System Architecture
- Evaluation Metrics
System Design Overview
A recommendation system suggests items (products, movies, songs, etc.) to users based on various signals. Let's break down the design into key phases.
1. Problem Scoping
- What is being recommended? (e.g., products, videos)
- Who are the users? What data is available?
- What are the business goals? (e.g., increase engagement, maximize sales)
2. Data Collection and Storage
- User data: profiles, demographics, behavior logs (views, clicks, purchases)
- Item data: attributes, categories, tags
- Interaction data: user-item interactions (ratings, purchases, likes)
3. Recommendation Algorithms
A. Collaborative Filtering
- User-User Collaborative Filtering: Find users similar to the target user and recommend items they liked.
- Item-Item Collaborative Filtering: Find items similar to those the user interacted with and recommend them.
- Matrix factorization (e.g., SVD): Decompose the user-item interaction matrix into latent features.
Example: Let \( R \) be the user-item interaction matrix. \[ R \approx U \cdot V^T \] where \( U \) is a user-feature matrix and \( V \) is an item-feature matrix.
B. Content-Based Filtering
- Represent items and users as feature vectors (e.g., TF-IDF, word2vec for text, CNN features for images).
- Recommend items similar to those the user has liked or interacted with, based on feature similarity (e.g., cosine similarity).
C. Hybrid Approaches
- Combine collaborative and content-based methods for better accuracy and coverage.
4. System Architecture
| Layer | Components |
|---|---|
| Data Ingestion | ETL pipelines, data lakes (e.g., S3, Hadoop) |
| Feature Engineering | Batch and real-time feature stores |
| Model Training | Offline training pipelines (e.g., Spark, SageMaker) |
| Serving | Online inference servers, caching, REST APIs |
| Monitoring & Feedback | Logging, A/B testing, drift detection |
5. Evaluation Metrics
- Precision, Recall, F1 Score
- Mean Average Precision (MAP)
- Normalized Discounted Cumulative Gain (NDCG)
- Coverage, Diversity, Serendipity
6. Sample (Simplified) Code: Item-Based Collaborative Filtering
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
# Assume item-user rating matrix: rows are items, cols are users
item_user_matrix = np.array([
[5, 3, 0, 1],
[4, 0, 0, 1],
[1, 1, 0, 5],
[1, 0, 0, 4],
[0, 1, 5, 4],
])
# Compute item-item similarity
item_similarity = cosine_similarity(item_user_matrix)
def recommend_items(user_id, item_user_matrix, item_similarity, top_k=2):
user_ratings = item_user_matrix[:, user_id]
scores = item_similarity.dot(user_ratings)
# Exclude already rated items
scores[user_ratings > 0] = -np.inf
recommended_items = np.argsort(scores)[-top_k:]
return recommended_items[::-1] # highest score first
recommended = recommend_items(2, item_user_matrix, item_similarity)
print("Recommended items for user 2:", recommended)
7. Scalability Considerations
- Use approximate nearest neighbor search for large datasets (e.g., Faiss, Annoy, ScaNN)
- Distributed training and inference (e.g., Spark, TensorFlow Serving)
- Real-time recommendation using precomputed candidate pools and caches
Key Takeaways
- Start with clear business and user requirements
- Choose model types based on data and scale
- Design for both offline training and online serving
- Continuously monitor and update models with fresh data
3. Gradient Descent Does Not Converge (Baidu)
Problem Statement
If the gradient descent algorithm does not converge, what might be the problem?
Concepts Involved
- Optimization Algorithms
- Learning Rate Tuning
- Data Preprocessing
- Loss Surface Properties
- Numerical Stability
Potential Causes & Solutions
- Learning Rate Too High
- If the learning rate (\( \eta \)) is too large, each update overshoots the minimum and the loss oscillates or diverges.
- Solution: Decrease the learning rate. Use learning rate schedules or adaptive optimizers (Adam, RMSprop).
- Poor Data Scaling / Feature Normalization
- Features with wildly different scales cause the optimization surface to be ill-conditioned, making convergence slow or unstable.
- Solution: Standardize or normalize features (e.g., zero mean, unit variance).
- Non-convex Loss Surface
- Deep networks have non-convex loss surfaces with many local minima and saddle points, which may trap gradient descent.
- Solution: Use better initialization (Xavier, He), stochastic gradient descent, and restarts.
- Inappropriate Batch Size
- Batch size affects the noise in the gradient estimate. Too small: high variance; too large: slow updates and memory issues.
- Solution: Use mini-batch gradient descent (e.g., 32, 64, 128 samples per batch).
- Vanishing/Exploding Gradients
- In deep networks, gradients may become too small (vanishing) or too large (exploding), stalling learning or causing instability.
- Solution: Use normalization layers (BatchNorm), proper weight initialization, gradient clipping.
- Incorrect Implementation
- Bugs in the code, such as wrong gradient calculation, incorrect loss function, or update step.
- Solution: Debug by checking gradients numerically, visualize loss curves, use frameworks' autodiff tools.
- Non-Differentiable Loss Function
- If the loss function is not smooth or has discontinuities, gradient descent may fail.
- Solution: Choose or approximate with smooth, differentiable losses.
Mathematical Example: Divergence Due to High Learning Rate
Gradient descent update rule:
\[ w_{t+1} = w_t - \eta \nabla L(w_t) \]
If eta is too large, w may oscillate or diverge.
Debugging Steps
- Plot the loss over epochs — is it decreasing, oscillating, or diverging?
- Try different learning rates, batch sizes, and normalization.
- Check gradients numerically and compare with backprop results.
Best Practices
- Start with a small learning rate
- Alwaysnormalize and preprocess your data
- Monitor loss curves and gradient norms during training
- Use modern optimizers (Adam, RMSprop) and initialization strategies
- Leverage tools for automatic differentiation and gradient checking
Sample Python Code: Diagnosis of Convergence Issues
import numpy as np
import matplotlib.pyplot as plt
# Simple quadratic loss function: L(w) = (w - 3)^2
def loss(w):
return (w - 3) ** 2
def grad(w):
return 2 * (w - 3)
w = 0
learning_rates = [0.01, 0.1, 1.0, 1.5]
epochs = 20
plt.figure(figsize=(10,6))
for lr in learning_rates:
ws = [w]
w_curr = w
for _ in range(epochs):
w_curr -= lr * grad(w_curr)
ws.append(w_curr)
plt.plot(ws, label=f"lr={lr}")
plt.xlabel('Epoch')
plt.ylabel('w value')
plt.title('Gradient Descent Convergence with Different Learning Rates')
plt.legend()
plt.show()
This code visually demonstrates how using too high a learning rate (e.g., 1.5) causes divergence, while a moderate rate (0.1) leads to smooth convergence.
4. System Design: API Rate Limiter (Atlassian, Principal ML Engineer)
Problem Statement
Design an API rate limiter. The system should restrict users (or API clients) to a maximum number of requests in a given time window, ensuring fair use and protecting backend resources.
Key Concepts
- Distributed Systems
- Sliding Window and Token Bucket Algorithms
- Concurrency and Scalability
- Latency and Throughput
Common Rate Limiting Algorithms
- Fixed Window Counter: Count requests in fixed intervals (e.g., per minute).
- Sliding Window Log: Track timestamps of each request, remove expired ones.
- Sliding Window Counter: Approximates sliding window with multiple counters.
- Token Bucket: Tokens are added at a fixed rate, each request consumes a token.
- Leaky Bucket: Requests are processed at a fixed rate.
Token Bucket Algorithm (Recommended for APIs)
The token bucket algorithm is widely used due to its balance of fairness and implementation simplicity.
- Each user/client has a "bucket" with a maximum capacity of tokens (e.g., 100).
- Tokens are refilled at a constant rate (e.g., 10 tokens/sec).
- Each request consumes one token. If the bucket is empty, the request is rejected or delayed.
High-Level Design
- Maintain a per-user/client bucket in an in-memory datastore (e.g., Redis, Memcached).
- Atomic operations are crucial for correctness under concurrency.
- For distributed systems, use centralized or sharded storage for buckets.
Python Example: Token Bucket (Single Process)
import time
class TokenBucket:
def __init__(self, capacity, refill_rate):
self.capacity = capacity
self.refill_rate = refill_rate # tokens per second
self.tokens = capacity
self.timestamp = time.time()
def allow_request(self, tokens=1):
now = time.time()
elapsed = now - self.timestamp
refill = elapsed * self.refill_rate
self.tokens = min(self.capacity, self.tokens + refill)
self.timestamp = now
if self.tokens >= tokens:
self.tokens -= tokens
return True # Allow request
return False # Rate limit exceeded
# Usage:
bucket = TokenBucket(capacity=10, refill_rate=1) # 10 requests max, refill 1/sec
for i in range(12):
allowed = bucket.allow_request()
print(f"Request {i+1} allowed: {allowed}")
time.sleep(0.5)
Distributed Rate Limiter Using Redis
In production, use Redis with Lua scripts to ensure atomic updates across multiple API servers.
- Track tokens and timestamps in a Redis hash per client.
- Leverage Redis' EXPIRE to auto-clean old buckets.
Design Considerations
- Should rate limiting be global, per user, per API key, or per IP?
- How to handle clock skew and distributed consistency?
- Should the system return 429 HTTP codes or queue/delay excess requests?
- What are the failure modes (e.g., Redis outage)? Fallback to local memory?
Best Practices
- Monitor rate limiter performance and effectiveness
- Allow for burst traffic up to a point (token bucket, not fixed window)
- Provide clear error messages and quotas to clients
5. System Design: ML Labeling System (Atlassian, Principal ML Engineer)
Problem Statement
Design an ML labeling system — a platform that allows human annotators to label large datasets efficiently and accurately for supervised learning tasks.
Core Requirements
- Efficient data annotation workflow (image, text, audio, etc.)
- Quality control and consensus (detect and mitigate noisy labels)
- Scalability to millions of samples and thousands of annotators
- Integration with ML pipelines
- Secure and auditable data management
System Components
| Component | Description |
|---|---|
| Frontend UI | Web/mobile application for annotators to view data and apply labels. Should support keyboard shortcuts, bulk actions, and interactive previews. |
| Task Assignment | Scheduler to assign labeling tasks based on annotator skill, availability, and redundancy needs. |
| Annotation Storage | Store raw annotations, metadata (timestamp, annotator, confidence), and final consensus labels in a secure database. |
| Quality Control | Inject gold-standard samples, track inter-annotator agreement, and use conflict resolution algorithms (e.g., majority vote, Dawid-Skene). |
| Admin Dashboard | Analytics for task progress, annotator performance, label distributions, and quality metrics. |
| APIs | Integrate with ML pipelines for data import/export, and automate labeling tasks. |
Workflow Example
- Import data (images, text, etc.) into the system
- Define labeling schema (classes, bounding boxes, etc.)
- Assign tasks to annotators with redundancy (e.g., each sample labeled by 3 people)
- Annotators label data through the UI
- Aggregate labels and resolve conflicts automatically or via expert review
- Export labeled data to ML pipeline for training
Quality Control Techniques
- Inter-annotator Agreement: Calculate metrics like Cohen’s Kappa to assess consistency.
For binary labels: \[ \kappa = \frac{p_o - p_e}{1 - p_e} \] where \( p_o \) is observed agreement and \( p_e \) is expected agreement by chance.
- Gold Standard Samples: Periodically insert samples with known labels to measure annotator accuracy.
- Consensus Algorithms: Majority vote, weighted voting, or model-based methods (e.g., Dawid-Skene).
- Feedback Loops: Provide annotators with feedback on errors to improve quality.
Scalability and Reliability
- Use distributed databases and object stores (e.g., PostgreSQL, S3) for data and label storage
- Queue tasks with distributed message brokers (e.g., Kafka, RabbitMQ)
- Horizontal scaling of frontend and backend services
- Handle annotator authentication, permissions, and auditing for data security
Sample Data Model (Schema)
CREATE TABLE samples (
sample_id SERIAL PRIMARY KEY,
data_uri TEXT NOT NULL,
type VARCHAR(20), -- image, text, etc.
metadata JSONB
);
CREATE TABLE annotations (
annotation_id SERIAL PRIMARY KEY,
sample_id INTEGER REFERENCES samples(sample_id),
annotator_id INTEGER,
label VARCHAR(50),
timestamp TIMESTAMP,
confidence FLOAT,
is_gold_standard BOOLEAN DEFAULT FALSE
);
CREATE TABLE consensus_labels (
sample_id INTEGER REFERENCES samples(sample_id),
label VARCHAR(50),
method VARCHAR(20), -- e.g., majority_vote, expert_review
updated_at TIMESTAMP
);
Integration with ML Pipelines
- APIs for data export (CSV/JSON), or direct integration with DVC, S3, or MLflow
- Track provenance of labels and annotation history for reproducibility
Conclusion
Preparing for ML engineer interviews at companies like Meta, Amazon, Baidu, and Atlassian requires a strong grasp of both fundamental algorithms and large-scale system design. By mastering efficient matrix queries, understanding end-to-end recommendation systems, diagnosing optimization issues, and designing robust infrastructure like rate limiters and labeling systems, you'll be well-equipped for even the toughest interviews.
Remember to always clarify problem requirements, communicate your thought process, and consider both correctness and scalability in your solutions. Continuous practice with real interview questions and system designs will help you stand out in your next ML engineering interview.