← Amazon Interview Insights

Amazon·Machine Learning Engineer·Technical Phone Screen·Senior

Senior
Jun 2026

Summary

Amazon ML engineer interview that was basically one big coding question: implement a GPT-style decoder-only transformer from scratch, modular, four classes, correct shapes throughout. No behavioral stuff from what I remember, just pure implementation.

Questions Asked (4)

Q1

Implement a multi-head self-attention module with a causal mask. The class should take a tensor of shape (B, T, d_model), project into Q/K/V, split into heads, compute scaled dot-product attention with a causal mask, and return the concatenated output projected back to (B, T, d_model).

System DesignTechnical Trade-offsAlgorithms & Data Structures
Author's notes

The causal mask part is where I fumbled a bit.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the requirements and assumptions (e.g., batch-first, learned projections, causal mask). Then walk through the implementation step-by-step: linear projections, head splitting, scaled dot-product attention with causal masking, concatenation, and output projection. Emphasize numerical stability, efficiency, and correctness of the causal mask.

Pro tip: Mention that you would use PyTorch's scaled_dot_product_attention with is_causal=True for efficiency and numerical stability, but also be prepared to implement it manually to demonstrate understanding. Also, discuss the importance of masking before softmax to avoid attending to future positions.

1. Clarify requirements and assumptions

Confirm input shape (B, T, d_model), number of heads, and whether projections are learned. Ask about masking requirements (causal) and any performance constraints.

2. Project Q, K, V and split into heads

Use linear layers to project input into Q, K, V of shape (B, T, d_model). Reshape to (B, num_heads, T, head_dim) by splitting d_model into num_heads * head_dim.

3. Compute scaled dot-product attention with causal mask

Compute attention scores = Q @ K^T / sqrt(head_dim). Apply causal mask (upper triangular -inf) before softmax. Compute attention weights and output = weights @ V.

4. Concatenate heads and project output

Reshape attention output back to (B, T, d_model) by concatenating heads. Apply final linear projection to get output of shape (B, T, d_model).

5. Discuss optimizations and edge cases

Mention using fused kernels (e.g., PyTorch's scaled_dot_product_attention), handling variable sequence lengths, and ensuring numerical stability (e.g., subtracting max before softmax).

Key Points to Mention

  • Causal mask ensures autoregressive property: position i can only attend to positions ≤ i.
  • Scaling by 1/sqrt(head_dim) prevents softmax saturation.
  • Efficient implementation: use torch.nn.functional.scaled_dot_product_attention with is_causal=True.
  • Head splitting: reshape and permute to (B, num_heads, T, head_dim).
  • Numerical stability: mask with -inf before softmax, and optionally subtract max for stability.
  • Complexity: O(T^2 * d_model) time and memory, can be optimized with flash attention.

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

Q2

Implement a position-wise feed-forward network class that applies two linear layers with a nonlinear activation in between, independently at each sequence position.

System DesignTechnical Trade-offs
Author's notes

Easiest part of the whole thing.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the input/output shapes and the requirement for position-wise independence. Then implement the class with two linear layers and a configurable activation, ensuring the same weights are applied across all positions. Finally, discuss trade-offs like activation choice, parameter count, and computational efficiency.

Pro tip: Mention that this is the standard FFN block in Transformers and that using a larger intermediate dimension (e.g., 4x) is common. Also, note that applying linear layers position-wise is equivalent to a 1x1 convolution, which can be more efficient in some frameworks.

1. Clarify Requirements

Confirm input dimensions (batch, sequence length, hidden size) and expected output shape. Ask about activation function preference and whether dropout or layer normalization should be included.

2. Design the Architecture

Define two linear layers: first expands hidden size to intermediate size (often 4x), second projects back to hidden size. Choose a nonlinear activation (e.g., ReLU, GELU) to apply between them.

3. Implement Position-wise Application

Ensure the linear layers are applied independently to each position. This can be done by reshaping the input to (batch*seq_len, hidden_size), applying the layers, then reshaping back.

4. Discuss Trade-offs and Optimizations

Talk about parameter count, computational complexity, and alternatives like using 1x1 convolutions. Mention how activation choice affects performance and training dynamics.

5. Test and Validate

Describe how to test with sample inputs, check output shapes, and verify that positions are processed independently (e.g., by permuting sequence order).

Key Points to Mention

  • Position-wise independence: same weights applied to each position, no cross-position interaction.
  • Typical intermediate dimension expansion factor (e.g., 4x) and its impact on model capacity.
  • Choice of activation function (ReLU, GELU, SwiGLU) and its effect on performance.
  • Implementation efficiency: reshaping vs. 1x1 convolution, and use of batch matrix multiplication.
  • Parameter count and computational cost: O(batch * seq_len * hidden_size * intermediate_size).
  • Relation to Transformer architecture: this is the FFN sub-layer in each encoder/decoder block.

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

Q3

Implement a single decoder block that combines masked self-attention and the feed-forward network using pre-norm residual connections (LayerNorm applied before each sub-layer).

System DesignTechnical Trade-offs
Author's notes

I initially wrote post-norm by reflex because that's what I learned first, and the interviewer asked me to clarify which normalization order I was using.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the architecture: a single decoder block with pre-norm residual connections, masked self-attention, and a feed-forward network. Then walk through the implementation step-by-step, explaining the purpose of each component and how they interact. Finally, discuss trade-offs such as computational efficiency, training stability, and scalability.

Pro tip: Emphasize that pre-norm residual connections improve gradient flow and training stability, especially for deep networks, and mention that this is a key design choice in modern transformers like GPT. Also, note that masking ensures autoregressive property, which is crucial for generation tasks.

1. Clarify the architecture

Confirm the components: masked self-attention, feed-forward network, and pre-norm residual connections. Explain that pre-norm means LayerNorm is applied before each sub-layer, and residuals are added after.

2. Implement masked self-attention

Describe how to compute queries, keys, and values, apply scaling, and use a causal mask to prevent attending to future positions. Mention softmax and dropout.

3. Implement the feed-forward network

Explain the two linear layers with a ReLU activation in between, and possibly dropout. Note that it operates position-wise.

4. Integrate pre-norm residual connections

Show how to apply LayerNorm to the input before each sub-layer, then add the residual connection. Emphasize that this differs from post-norm.

5. Discuss trade-offs and optimizations

Talk about why pre-norm is preferred for deep networks, potential issues like increased memory, and how to optimize (e.g., using fused kernels).

Key Points to Mention

  • Pre-norm vs post-norm: pre-norm applies LayerNorm before sub-layers, improving gradient flow and allowing deeper networks without warm-up.
  • Masked self-attention: causal mask ensures autoregressive generation by preventing attention to future tokens.
  • Residual connections: help mitigate vanishing gradients and enable training of very deep models.
  • Feed-forward network: typically expands dimension (e.g., 4x) and uses ReLU, adding non-linearity.
  • LayerNorm placement: in pre-norm, LayerNorm is applied to the input of each sub-layer, and the residual is added after.
  • Scalability: pre-norm is standard in large language models like GPT, but may require careful initialization.

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

Q4

Implement the full GPT model class: token embeddings plus positional encodings, a stack of N decoder layers, and a final linear projection to vocabulary logits. The forward pass should take integer token IDs and return logits of shape (B, T, V).

System DesignTechnical Trade-offsAlgorithms & Data Structures
Author's notes

Tying it all together was fine conceptually but I spent too long debating out loud whether to use learned vs fixed positional encodings.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by outlining the overall architecture and the shape transformations at each stage, then implement the model in a modular way with clear separation of embeddings, decoder layers, and output projection. Emphasize the importance of weight tying, positional encoding choice, and handling of the causal mask to ensure autoregressive generation.

Pro tip: Mention that you would tie the weights of the token embedding and the final output projection to reduce parameters and improve performance, a common practice in GPT models. Also, note that you would use a learned positional embedding for simplicity, but be prepared to discuss the trade-offs with sinusoidal or relative positional encodings.

1. Define the model architecture

Specify the hyperparameters: vocabulary size (V), embedding dimension (d_model), number of layers (N), number of attention heads (h), and maximum sequence length (T_max). Explain that the model consists of token embeddings, positional embeddings, N decoder layers, and a final linear layer.

2. Implement token and positional embeddings

Create an embedding layer for tokens (shape V x d_model) and a positional embedding layer (shape T_max x d_model). In the forward pass, sum the token embeddings with the positional embeddings for the input token IDs.

3. Build the decoder layer stack

Each decoder layer should contain masked multi-head self-attention and a position-wise feed-forward network, with residual connections and layer normalization. Stack N such layers, ensuring the causal mask is applied to prevent attending to future tokens.

4. Add the final projection and output logits

Apply a final linear layer (d_model x V) to project the hidden states to vocabulary logits. Optionally tie the weights with the token embedding matrix. The output shape should be (B, T, V).

5. Discuss training and inference considerations

Mention that during training, the model processes the entire sequence in parallel with teacher forcing, while during inference, it generates tokens autoregressively. Also, note the use of dropout for regularization and the importance of initializing weights properly.

Key Points to Mention

  • Weight tying between token embeddings and output projection to reduce parameters and improve performance.
  • Choice of positional encoding: learned vs. sinusoidal, and their trade-offs.
  • Causal masking in self-attention to ensure autoregressive property.
  • Residual connections and layer normalization for stable training.
  • Handling variable sequence lengths with padding and attention masks.
  • Computational complexity and memory considerations for large models.

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