Data quality, EDA, and anti-fraud - trust the log before the model
The book gives data cleaning and EDA the same seriousness as model design. This lesson linearizes that operational layer: validate raw events, handle missingness and outliers, manage class imbalance, automate dirty-data detection, use EDA to understand long tails and segments, detect brush traffic, and decide when bad data blocks training or launch.
1 · Data quality is model quality
A recommender is trained on logs produced by product code, clients, networks, old rankers, creators, and sometimes attackers. When a metric moves, the first question is not always "what did the model learn?" It may be "what changed in the data?"
The book's data-cleaning sections emphasize missing values, abnormal values, duplicate data, non-structured noise, and business-specific invalid events. In recommendation, those are not just ETL nuisances; they directly define labels and features.
2 · Validate every boundary
| Boundary | Checks | Failure example | Impact |
|---|---|---|---|
| Client event | Required fields, timestamp, request_id, app version, duration bounds | New app stops sending video_duration | Completion feature corrupt |
| Collector | Volume, duplicate IDs, retry rate, status code, region | Retry storm duplicates likes | Interaction labels inflated |
| Stream job | Lag, late events, invalid schema, watermark drop rate | Kafka backlog delays real-time hotness | Ranker sees stale features |
| ETL join | Join rate, null rate, key cardinality, partition freshness | User profile join drops 8% of new users | Segment bias |
| Training table | Label delay, class balance, distribution drift, leakage scan | Recent conversions incomplete | Model learns false negatives |
| Feature service | Online/offline parity, freshness, lookup latency | Online feature defaulting silently | A/B underperforms offline |
3 · Treat missing values as information first
The book distinguishes deletion, filling, prediction, and special-event marking. In recommender logs, missingness often has meaning.
| Missing pattern | Interpretation | Treatment |
|---|---|---|
| Random profile field missing | Ordinary incompleteness | Median/mode fill, model fill, or unknown bucket |
| Video duration missing by app version | Instrumentation bug | Fix logging; exclude or backfill affected slice |
| Watch time missing after fast swipe | May be valid negative behavior | Special event flag, not simple mean fill |
| Long inactivity | Lifecycle state | Feature as churn/return signal |
| New-video visual embedding missing | Cold-start pipeline lag | Default vector, async fill, or cold-start path |
Always add a missingness indicator for important fields. A filled value without a missing flag hides the fact that the model is seeing uncertainty.
4 · Separate outliers, fraud, and valid long-tail behavior
The book lists 3-sigma, IQR, KNN, DBSCAN, isolation forest, and business rules. Use statistics to find candidates, then business logic to classify them.
| Observed outlier | Could be valid | Could be invalid | Action |
|---|---|---|---|
| Watch time > video duration | Rewatch loop | Client bug or replay attack | Cap, flag rewatch, inspect device/app slice |
| Many likes in seconds | Power user or live event | Bot cluster | Device/IP graph, velocity threshold, trust score |
| Extreme creator exposure | Viral video | Brush traffic or old-ranker bias | Head/tail split, fraud model, exposure debiasing |
| Very low completion | Bad match or latency | Autoplay failure | Slice by network, app version, video load time |
5 · Handle class imbalance without breaking calibration
The book highlights severe positive/negative imbalance in click data. Most impressions are non-clicks; most users do not comment; conversions may be rare and delayed. If you sample carelessly, the model may rank better offline but produce miscalibrated scores online.
| Method | Use | Risk |
|---|---|---|
| Negative downsampling | Reduce training volume and class imbalance | Predicted probabilities need correction |
| Hard-negative mining | Keep informative negatives | Can overfocus on ambiguous cases |
| Time-decay weighting | Reduce stale-label impact | May erase seasonal patterns |
| Focal loss / label weighting | Focus on hard examples | Can harm calibration |
| Auxiliary labels | Use completion/watch time with click | Multi-objective conflicts |
Keep validation and test sets close to real traffic distribution unless you have a specific counterfactual evaluation design. Sampling may help learning; it should not make evaluation fictional.
5.1 · Constructing negative samples is a data-quality decision
Before imbalance is a loss-function problem (focal loss, class weights - see 06 for the training-side sampling), it is a data-construction problem. In a feed, every impression that was not clicked is a candidate negative - but many of those impressions are garbage, and feeding garbage negatives teaches the model false negatives. The data layer decides which impressions are even allowed to become negatives, and how heavily each counts.
| Rule | Mechanism | Why it improves the signal |
|---|---|---|
| Invalid-exposure filter | Drop impressions where the page never finished rendering, judged by a dwell-time threshold (e.g. dwell < 1 s = the item was likely never seen) | A "non-click" the user never actually saw is not a preference signal; keeping it injects label noise |
| Hard-negative keep-rule | Keep high-confidence negatives - full play but no click/like - and drop random "easy" negatives the model already separates trivially | The informative gradient is at the decision boundary; easy negatives just dilute it |
| Time-decay negative weights | Weight recent non-clicks higher: w = e^(−λ·Δt) | An old non-click may reflect stale interest; recent rejection is stronger evidence |
| Per-epoch dynamic undersample | Each epoch randomly draw negatives equal to the positive count; leave validation/test at the true distribution | The model sees a balanced stream that varies across epochs (more coverage than one fixed subset) while evaluation stays honest |
Two cautions carry over from above. Keep auxiliary labels (watch-time) attached while you sample on click, so CTR-driven undersampling does not silently wreck the watch-time objective. And because undersampling lifts the positive rate the model sees, online scores come back inflated - a calibration layer (cross-link 06) maps them back to true-distribution probabilities. The hard-negative keep-rule here is the data-side counterpart to in-batch hard-negative mining in 06; this lesson decides which logged rows qualify, 06 decides how to sample them in the loss.
6 · Choose the preprocessing engine by latency and state
The book asks candidates to compare distributed frameworks for TB-scale preprocessing. The answer should be practical, not tribal.
| Framework | Best use | Why | Limit |
|---|---|---|---|
| Spark | TB-scale batch cleaning, SQL feature extraction, daily training tables | DataFrame/Spark SQL, mature Hive/HDFS integration, good iterative preprocessing | Micro-batch latency is not ideal for sub-second features |
| Flink | Real-time/stateful cleaning, sliding-window anomaly detection, exactly-once streams | Event-time processing, keyed state, checkpoints | State/schema evolution needs discipline |
| Hadoop MapReduce | Cold historical fallback and archival jobs | Reliable batch over HDFS | Multiple disk writes make it too slow for modern feature iteration |
Mini-scenario: if the task is "clean last quarter of logs and rebuild training data," Spark is the natural answer. If the task is "detect watch_time > duration in the live stream and quarantine bad events before they reach features," Flink is the natural answer. Hadoop is usually the cold-storage fallback, not the frontline tool.
7 · Automate dirty-data detection in the stream
The book proposes an automated real-time dirty-data system with Kafka, schema validation, Flink/Spark Streaming, rule checks, model checks, repair/drop/degrade decisions, and monitoring. The linear architecture is:
| Check type | Example | Decision |
|---|---|---|
| Schema | Missing user_id, invalid timestamp, bad enum | Reject or quarantine |
| Range | watch_time < 0 or watch_time > 5 × duration | Cap, flag, or drop |
| Logic | Like event without valid exposure | Drop label or investigate instrumentation |
| Distribution | 1-minute mean shifts by 3 sigma | Alert and slice |
| Fraud | Device/IP/account burst cluster | Down-weight, block, or review |
7.1 · Model-based anomaly checks beyond rules
Static rules catch what you already know to forbid. They miss the anomaly nobody wrote a rule for - a feature that drifts 20% over a week, a new device tier whose watch-time distribution is subtly bimodal. Run a thin layer of statistical/model checks beside the rule engine, per numeric feature, cheap enough for the stream:
| Check | Mechanism | Catches |
|---|---|---|
| Improved Z-Score | Robust Z using median and MAD instead of mean/std: z = 0.6745 (x − median) / MAD; flag |z| > 3.5. Median/MAD are not dragged by the very outliers you hunt | Point outliers in skewed watch-time without a fat tail poisoning the threshold |
| Isolation forest | Random split trees; anomalies isolate in few splits → short path → high score. Score a feature vector (watch_time, like_rate, ops/min, device entropy) | Multivariate weirdness no single range rule sees (short watch + high like + one IP) |
| STL decomposition | Split a metric series into trend + seasonal + residual; alarm on the residual, not the raw value | True breaks hidden under daily/weekly seasonality - a Tuesday-2am dip that is normal seasonally |
7.2 · Graded decision tiers, not one verdict
A binary accept/reject throws away good rows on a minor blemish and quietly admits fraud that "passed schema." Grade the response to the severity:
| Anomaly grade | Example | Tier |
|---|---|---|
| Minor | ~10% of optional fields missing; one numeric feature mildly out of band | Auto-repair - backfill from user profile / last-known value, emit with a repaired flag |
| Moderate | Suspected fake clicks, isolation-forest score high but not certain | Human-review queue + alert - hold out of the training snapshot until adjudicated |
| Severe | Schema violation, future-label leak, confirmed bot cluster | Block from training - drop or quarantine, never let it become a label |
The flag travels with the row. A repaired value carries a repaired marker and a missingness indicator (section 3) so downstream models and audits know it was synthesized, not observed.
7.3 · Dynamic thresholds - why static bands false-alarm
This is the failure mode that pages on-call at 9pm on a holiday. A static rule like "alert if 1-minute event volume drops below X" is calibrated to an ordinary Tuesday. On Chinese New Year, Black Friday, or during a live event, traffic legitimately triples or craters - and the static band fires a flood of false alarms exactly when humans are least available. After a few false pages, on-call mutes the alert, and then the real incident slips through. Static thresholds train people to ignore them.
A Prophet / holiday-aware forecast instead predicts the expected value for that timestamp with holiday regressors on: expected ≈ 41 s, 95% interval [34, 49] s. Alarm only when the observed value leaves the forecast interval, not the fixed band. The holiday peak is inside the predicted envelope → no page. A genuine logging bug that pins watch-time at 5 s leaves both bands → still caught.
Mechanism: Prophet (or STL above) fits trend + weekly/daily seasonality + an explicit holiday term, and emits a prediction interval per timestamp. The "threshold" becomes a moving function of time instead of a constant. Same idea applied to volume, null-rate, and CTR turns "3-sigma off a global mean" into "3-sigma off the seasonally-expected mean."
7.4 · Layered monitoring - three gates, three owners
One dashboard of 200 metrics gets ignored. Split monitoring into layers that map to where damage happens, each with its own threshold and its own auto-response:
| Layer | What it watches | Trip threshold | Auto-response |
|---|---|---|---|
| Raw / logging | Null rate and format validity on landed events | Null rate > 5% on a required field | Alert logging owner; quarantine the bad slice |
| Feature | Distribution drift and categorical entropy of computed features | PSI > 0.25, or entropy collapse on a category | Core feature → auto-trigger retrain; non-core → fall back to historical mean or a lighter model |
| Serving | Online-vs-offline parity | Double-run mismatch beyond tolerance | Block the rollout; the A/B will underperform offline (cross-link 29, 36) |
The split matters because the response differs by layer. A raw null spike is a logging incident; a feature-layer PSI alarm is a retraining trigger; a serving-layer mismatch is a launch blocker. Routing all three to one channel loses that signal. Feature importance should rank which features are "core" - monitoring all of them equally wastes compute, so prioritize the top features that actually move the model.
8 · Use EDA to understand the product story
EDA is not just charts. It asks whether the data matches the product mechanism. The book's EDA section focuses on long-tail watch time, brush traffic, missing values/outliers, group differences, and viewing-experience metrics.
| EDA question | View | Decision it informs |
|---|---|---|
| Is traffic healthy? | Events over time by region/app/device | Logging incident or rollout artifact? |
| Is watch time long-tailed? | Histogram, log histogram, quantiles | Cap, log transform, segment metrics |
| Are labels delayed? | Conversion/completion by label age | Training cutoff and label maturity |
| Do groups differ? | New/old users, high/low activity, region, creator cohort | Segment models, stratified A/B, fairness checks |
| Are features stable? | Train vs serve histograms, PSI, top values | Drift response and retraining |
| Is there suspicious behavior? | IP/device/account graph, burst heatmap, sequence rules | Fraud filtering and label down-weighting |
9 · Detect brush traffic as biased training signal
Brush traffic is not only a security problem. It becomes fake preference data if it reaches training. The book's EDA answer suggests operation frequency, time patterns, device/IP aggregation, sequence anomalies, heatmaps, and anomaly models such as isolation forest or LOF.
| Suspicious pattern | Likely issue | Training response |
|---|---|---|
| Very short watch + high like/comment | Fake engagement | Down-weight labels; add fraud feature |
| Many accounts on one device/IP | Account farm | Cluster and suppress |
| Identical behavior sequences | Automation script | Quarantine events |
| New videos exploited for trial traffic | Cold-start spam | Trust-tiered exploration |
| High conversion followed by refund/report | Low-quality conversion | Delay label or use fraud-adjusted CVR |
9.1 · Put numbers on the thresholds
The table above is qualitative; an interviewer wants the actual flags. The EDA procedure is: compute a per-capita distribution, set a percentile cut, then escalate the survivors to an unsupervised model. Concrete defaults teams start from:
| Signal | Threshold | Why this value |
|---|---|---|
| Per-user operation frequency | Flag beyond the 99th percentile of the daily ops/user distribution | Percentile, not a constant - it auto-adapts to the platform's own activity level instead of a guessed number |
| Single-IP velocity | > 100 ops/min from one IP | A human cannot like/scroll 100 times a minute; sustained means scripted or a NAT/proxy farm |
| Burst interaction | ≥ 5 likes in 10 s on distinct items | Business rule fed into the model score; catches the "no watch, instant like" automation pattern |
| Watch-vs-interact | watch_time < 2 s and like/comment present | Engagement without consumption is the signature of fake preference data |
• per-account ops that hour sit at the 99.7th percentile of the platform - flag.
• 1,800 of the likes trace to 40 IPs → 45 likes/IP, and one IP shows 120 ops/min > the 100 cap.
• median watch_time before the like is 1.3 s (< 2 s), and 320 accounts each fired ≥ 5 likes in 10 s.
Three independent flags converge on the same ~2,000 likes. Action: quarantine those events, down-weight the labels, and feed a fraud-score feature; do not let the inflated count become a popularity signal that the ranker then amplifies (this is the bias loop covered in 07).
9.2 · Visualize, then score, then escalate
A time-density heatmap (time-of-day on one axis, user/account on the other) makes unnatural clustering pop out - a block of accounts all active at 3am, or all firing in the same 10-second column, that no organic audience produces. Use it to find candidate clusters; use a model to score them.
For scoring, run isolation forest or LOF (Local Outlier Factor) over the behavior vector (ops/min, watch-vs-like ratio, IP/device sharing, inter-event timing) and combine the unsupervised score with the business rules above - a row needs both a high anomaly score and a rule hit before it is quarantined, which keeps the false-positive rate down. The precision/recall trade-off (kill a real power user vs miss a bot) is validated by A/B, not assumed.
10 · Define incident severity for data problems
| Severity | Example | Action |
|---|---|---|
| Low | Optional context feature missing for 0.2% traffic | Default value, alert owner, monitor impact |
| Medium | Feature drift in one region or device tier | Slice A/B, pause retraining, backfill if needed |
| High | Primary label duplicated or delayed | Block training, invalidate affected metrics, replay |
| Critical | Future-label leakage or privacy-sensitive field in training | Stop pipeline, purge, incident process, legal/security review |
Interview prompts you should be ready for
- "How do you handle missing values and outliers in watch logs?" Classify missingness, add flags, fill by segment when appropriate, detect outliers with IQR/statistics/models, and preserve valid business signals.
- "How do you detect brush traffic?" Use frequency, time, device/IP/account graph, behavior sequence consistency, burst patterns, anomaly models, and business rules; down-weight or quarantine fake labels.
- "Offline AUC jumped overnight. What do you check?" Schema, row count, join rate, duplicate events, label delay, leakage, fraud, feature distribution drift, and train/test split.
- "What quality monitors belong in a feature pipeline?" Freshness, missingness, range, cardinality, entropy, PSI, join rate, label completeness, parity, and feature-store latency.
- "Your watch-time alert pages on-call every holiday but missed a real logging bug. Fix the alerting." Static bands false-alarm on seasonal peaks and train people to mute them; switch to dynamic thresholds - Prophet/STL forecast with holiday regressors, alarm on the prediction-interval breach (or the residual), not a constant. The real bug that pins a feature outside the seasonal envelope still fires.
- "A new video gets 50k likes in an hour. How do you decide if it is brushed, and what do you do with the events?" Per-account ops past the 99th percentile, single-IP >100 ops/min, ≥5 likes/10s, watch <2s with a like; converge multiple flags, score survivors with isolation forest/LOF plus the business rule, escalate to a GNN on the user-device-IP graph for linked-account clusters when accounts individually look human. Quarantine and down-weight - do not let the count feed the popularity loop.