← Etsy Interview Insights

Etsy·Software Engineer·Technical Phone Screen·Senior

SeniorPrefer not to say
May 2026Remote

Summary

Etsy Applied Scientist interview that was basically a live debugging session on a broken NLP training pipeline, with some ML fundamentals thrown in when you least expected them. The code had like seven bugs stacked on top of each other and the clock was not your friend.

Questions Asked (7)

Q1

A dataset class is returning labels as raw strings instead of tensors. How do you find and fix this in a training pipeline?

Root Cause AnalysisTechnical Trade-offs
Author's notes

This one I spotted fast, which gave me false confidence.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by tracing the data flow from the dataset class through the DataLoader to the model to pinpoint where labels remain strings. Then, fix the issue at the source by converting labels to tensors in the dataset's __getitem__ method, ensuring compatibility with the training loop and loss function.

Pro tip: When debugging, add a quick assertion or print statement in the training loop to check the type of labels—this catches the issue early and shows you understand the importance of data validation in ML pipelines.

1. Reproduce and Identify

Run a minimal training script or data loading step to reproduce the error and confirm that labels are strings. Check the dataset's __getitem__ output and the DataLoader's batch types.

2. Trace the Data Pipeline

Follow the label from the dataset class through any transforms, collate functions, and into the training loop. Identify where the conversion to tensor should occur but is missing.

3. Implement the Fix

Modify the dataset's __getitem__ to convert labels to tensors, e.g., using torch.tensor(label) or a mapping for categorical labels. Ensure the conversion is efficient and handles edge cases.

4. Validate and Test

Add unit tests or assertions to verify that labels are tensors with correct dtype and shape. Run a training step to confirm the loss computes without errors.

5. Consider Trade-offs

Discuss whether to convert in the dataset vs. collate function, considering performance, flexibility, and maintainability. Mention potential impacts on other parts of the pipeline.

Key Points to Mention

  • DataLoader collate_fn and its role in batching
  • Tensor conversion methods: torch.tensor, torch.as_tensor, and handling categorical labels
  • Debugging techniques: type assertions, print statements, and using a debugger
  • Performance considerations: converting in dataset vs. collate function, and avoiding CPU-GPU transfer overhead
  • Testing: unit tests for dataset output and integration tests for training loop
  • Common pitfalls: forgetting to convert labels, mismatched dtypes, and ignoring edge cases like empty labels

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

Q2

There's a one-hot encoding helper function with a dimension mismatch bug. Walk through how you'd diagnose and fix it.

Root Cause AnalysisAlgorithms & Data Structures
Author's notes

Spent more time here than I should have.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the expected behavior and the exact error or symptom, then reproduce the bug with a minimal example. Systematically trace the data flow through the one-hot encoding function to isolate where the dimension mismatch occurs, and propose a fix with tests to prevent regression.

Pro tip: Demonstrate that you understand the mathematical foundation of one-hot encoding (e.g., output dimension equals number of categories) and mention that you'd add unit tests for edge cases like unseen categories or empty inputs.

1. Clarify and Reproduce

Ask clarifying questions about the expected input/output shapes and the exact error message. Reproduce the bug with a minimal, deterministic example to confirm the mismatch.

2. Trace the Data Flow

Inspect the function's code and trace how the input is transformed. Check where the dimension is supposed to be set (e.g., based on vocabulary size) and compare with the actual output shape.

3. Identify the Root Cause

Determine why the dimension is wrong: common causes include using the wrong variable for the number of categories, off-by-one errors, or incorrect handling of padding/unknown tokens.

4. Implement and Validate the Fix

Modify the code to correctly compute the output dimension, ensuring it matches the number of unique categories. Validate with the minimal example and additional edge cases.

5. Add Tests and Prevent Regression

Write unit tests that cover the fixed behavior, including edge cases like empty input, unseen categories, and varying batch sizes. Consider adding assertions or type hints to catch future mismatches.

Key Points to Mention

  • One-hot encoding output dimension should equal the number of unique categories (vocabulary size).
  • Common causes: using len(input) instead of len(vocabulary), off-by-one in indexing, or mishandling unknown categories.
  • Use of debugging tools: print statements, debugger, or shape assertions to pinpoint the mismatch.
  • Importance of writing a minimal reproducible example to isolate the bug.
  • Testing edge cases: empty input, categories not seen during fit, and batch processing.
  • Consider using established libraries (e.g., scikit-learn's OneHotEncoder) to avoid reinventing the wheel, but understand their behavior.

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

Q3

A custom BERT-based model has dropout placed incorrectly and some BERT layers have wrong requires_grad settings. What problems does this cause and how do you fix it?

Technical Trade-offsRoot Cause Analysis
Author's notes

This is where I actually felt like I knew what I was talking about.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by explaining the expected behavior of dropout and requires_grad in BERT, then describe the symptoms caused by misplacement (e.g., underfitting, overfitting, unstable training, or frozen layers). Finally, outline a systematic debugging and fixing process, including verification steps.

Pro tip: Emphasize that you would first reproduce the issue with a small controlled experiment and use gradient checks or layer-wise learning rate inspection to confirm the problem before making changes. This shows a methodical, root-cause approach rather than guessing.

1. Understand correct configuration

Recall that dropout should be applied after activation functions and before residual connections in BERT, and requires_grad should be True for layers you want to fine-tune and False for frozen layers.

2. Identify symptoms

Incorrect dropout placement can cause underfitting (if dropout is too aggressive) or overfitting (if dropout is missing), while wrong requires_grad can lead to no learning in some layers or unintended catastrophic forgetting.

3. Diagnose the issue

Use tools like gradient norm monitoring, layer-wise learning rate inspection, and ablation studies to pinpoint which layers are affected and how performance deviates from expected.

4. Fix and verify

Correct dropout placement by reviewing the model architecture, and set requires_grad appropriately. Then retrain and validate with metrics and gradient checks to ensure the fix works.

Key Points to Mention

  • Dropout should be applied after the activation function (e.g., GELU) and before adding the residual, not after the residual or on the wrong tensor.
  • requires_grad=False on some BERT layers means those layers won't update during backpropagation, effectively freezing them and reducing model capacity.
  • Incorrect dropout can lead to vanishing gradients or over-regularization, causing underfitting, or no regularization causing overfitting.
  • Use of gradient checking (e.g., torch.autograd.gradcheck) or monitoring gradient norms to detect frozen layers.
  • Layer-wise learning rate decay or discriminative fine-tuning can mitigate issues if some layers are frozen unintentionally.
  • Always validate fixes with a small dataset and compare training/validation curves to ensure expected behavior.

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

Q4

The model is using last_hidden_state incorrectly, either pulling the wrong token or averaging over padding tokens. How do you identify and fix this?

Technical Trade-offsRoot Cause Analysis
Author's notes

You want the CLS token so index 0 on the sequence dimension.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by explaining how to detect the issue through systematic debugging: inspect the attention mask and tokenization, then verify which token's hidden state is being used. Then describe the fix: apply the attention mask when pooling and ensure the correct token (e.g., [CLS] or last non-padding token) is selected. Emphasize validation with a controlled test to confirm the correction.

Pro tip: Mention that you would add a unit test with a known input and expected output to catch this regression early, and that you always log the shape and values of the hidden states during debugging.

1. Reproduce and Inspect

Create a minimal example that triggers the issue, then print the input IDs, attention mask, and the shape of last_hidden_state to understand the data flow.

2. Identify the Root Cause

Check if padding tokens are included in the pooling (e.g., mean pooling over all tokens) or if the wrong token index is used (e.g., always taking the first token instead of the last non-padding token).

3. Implement the Fix

Apply the attention mask to exclude padding tokens when pooling, and select the correct token based on the model architecture (e.g., [CLS] for BERT, last token for GPT).

4. Validate the Solution

Write a test with a known input where the correct output is predictable, and compare the fixed implementation against a reference or expected result.

5. Prevent Regression

Add assertions or logging to monitor the shape and values of hidden states, and include unit tests in the CI pipeline to catch similar issues early.

Key Points to Mention

  • Attention mask: use it to ignore padding tokens in pooling operations.
  • Token selection: for BERT-like models, use the [CLS] token; for GPT-like models, use the last token (excluding padding).
  • Mean pooling: if used, ensure it's masked mean pooling, not simple mean over all tokens.
  • Debugging: print shapes and values of last_hidden_state and attention mask.
  • Testing: create a unit test with a simple input to verify correct token selection.
  • Model architecture: different models require different pooling strategies (e.g., sentence-transformers use mean pooling).

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

Q5

Softmax is being applied to the model output before CrossEntropyLoss. Why is this a bug and what do you do about it?

Root Cause AnalysisTechnical Trade-offs
Author's notes

Remove the softmax.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

First, explain that applying softmax before CrossEntropyLoss is a bug because CrossEntropyLoss expects raw logits and internally applies log_softmax, so pre-applying softmax leads to double normalization and incorrect gradients. Then, describe the fix: remove the softmax and pass logits directly to the loss function, and optionally discuss how to detect and prevent such issues.

Pro tip: Mention that this bug often silently degrades model performance without throwing errors, so it's crucial to verify the loss function's documentation and add unit tests for output ranges.

1. Identify the bug

State clearly that softmax is applied before CrossEntropyLoss, which is incorrect because CrossEntropyLoss expects unnormalized logits.

2. Explain why it's a bug

Describe that CrossEntropyLoss combines log_softmax and NLLLoss, so pre-applying softmax results in double softmax, leading to incorrect loss values and gradients.

3. Describe the fix

Remove the softmax operation and pass the raw model outputs (logits) directly to CrossEntropyLoss.

4. Discuss detection and prevention

Mention how to catch this bug, such as checking loss values, using unit tests, or reviewing documentation, and suggest best practices like keeping model outputs as logits.

Key Points to Mention

  • CrossEntropyLoss in PyTorch (and similar frameworks) expects raw logits, not probabilities.
  • Internally, CrossEntropyLoss applies log_softmax followed by negative log likelihood loss.
  • Applying softmax before CrossEntropyLoss causes double normalization, leading to incorrect loss and gradients.
  • The fix is to remove the softmax and pass logits directly to the loss function.
  • This bug can silently degrade model performance without raising errors, so testing and validation are important.
  • Best practice: keep model outputs as logits and only apply softmax during inference for probability interpretation.

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

Q6

The AUC metric is being called with incorrect arguments, passing logits instead of probabilities and using the wrong multi-class configuration. How do you fix this?

Root Cause AnalysisProduct Analytics & Metrics
Author's notes

Blanked for a second on the exact sklearn parameter name for multi-class AUC.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by diagnosing the error: AUC expects probabilities (or at least scores that are comparable across classes) and the correct multi-class configuration (e.g., 'ovr' or 'ovo' with average parameter). Then apply the fix: convert logits to probabilities via softmax (for multi-class) or sigmoid (for binary), and set the appropriate multi-class and averaging parameters. Finally, validate the fix by checking that AUC values are reasonable and comparing against a baseline.

Pro tip: Mention that you would add a unit test or assertion to catch this in the future, and consider using a pipeline that encapsulates preprocessing and model to prevent similar issues. Also, note that for multi-class AUC, you need to specify multi_class='ovr' (or 'ovo') and choose an averaging strategy (macro, weighted, etc.) based on class balance.

1. Identify the symptoms and root cause

Recognize that AUC is being computed on raw logits, which are not probabilities, and that the multi-class configuration is incorrect (e.g., missing multi_class parameter or wrong averaging).

2. Convert logits to probabilities

Apply softmax for multi-class or sigmoid for binary to transform logits into probabilities before passing to AUC.

3. Set correct multi-class and averaging parameters

Specify multi_class='ovr' or 'ovo' and choose an appropriate average (e.g., 'macro', 'weighted') based on the problem context.

4. Validate the fix

Recompute AUC and sanity-check the values (e.g., between 0.5 and 1.0) and compare with a known baseline or cross-validation.

5. Prevent recurrence

Add assertions or unit tests to ensure inputs are probabilities and parameters are correctly set, and consider using a pipeline to encapsulate these steps.

Key Points to Mention

  • Logits vs probabilities: AUC requires probability estimates, not raw logits.
  • Softmax for multi-class, sigmoid for binary conversion.
  • Multi-class AUC configuration: multi_class='ovr' or 'ovo' and averaging strategy (macro, weighted, etc.).
  • Impact of incorrect averaging on metric interpretation, especially with class imbalance.
  • Validation: check AUC range and compare with baseline.
  • Prevention: unit tests, assertions, or pipeline integration.

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

Q7

Interspersed ML fundamentals: things like why does dropout help generalization, what does the CLS token represent, when would you freeze pretrained weights vs fine-tune everything.

Technical Trade-offsAdaptability & Ambiguity
Author's notes

These came out of nowhere between debugging steps and that was the hard part.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Treat each sub-question as a mini whiteboard explanation: define the concept, explain the mechanism, and connect it to a practical trade-off. Use concrete examples from your experience to show depth, and explicitly tie answers back to Etsy's context (e.g., search relevance, recommendations, or image tagging).

Pro tip: Don't just recite definitions—frame each answer around the trade-off between model capacity, data size, and compute budget, which shows you think like an engineer, not just a researcher.

1. Clarify and structure

Acknowledge that the question has multiple parts and propose to tackle them one by one. This buys time and shows organization.

2. Explain the concept

For each sub-question, give a concise definition and the core intuition (e.g., dropout prevents co-adaptation; CLS token aggregates sequence info).

3. Discuss the mechanism

Briefly describe how it works technically (e.g., dropout randomly zeroes activations during training; CLS token is a learnable embedding whose final hidden state is used for classification).

4. Connect to trade-offs and practical scenarios

Explain when and why you would use it, including pros/cons (e.g., dropout helps generalization but slows training; freeze pretrained weights when data is small or compute limited).

5. Relate to Etsy's context

Tie the answer to potential applications at Etsy, such as using CLS tokens for image-based product search or freezing embeddings for cold-start recommendations.

Key Points to Mention

  • Dropout as regularization: prevents overfitting by reducing co-adaptation of neurons, akin to ensemble of subnetworks.
  • CLS token in transformers (e.g., BERT, ViT): a learnable token that aggregates global information, often used as input to classification head.
  • Freezing pretrained weights: beneficial when target dataset is small, similar to pretraining domain, or compute is limited; avoids catastrophic forgetting.
  • Fine-tuning all weights: better when target dataset is large and different from pretraining domain, allowing model to adapt fully.
  • Trade-offs: freezing is faster and less prone to overfitting but may underfit; fine-tuning is more powerful but requires more data and compute.
  • Practical examples: use frozen embeddings for fast prototyping or when serving latency matters; fine-tune for high-stakes tasks like search ranking.

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