search_ads_recsys / 37 · Data quality, EDA, anti-fraud lesson 37 / 39

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.

Book anchors
Based on 5.1.1-5.1.5 missing values, outliers, sample imbalance, distributed preprocessing, real-time dirty-data detection; 5.2.1-5.2.5 EDA, long-tail behavior, brush-traffic detection, segment analysis, viewing-experience indicators; and 5.4.1/5.4.5 feature-quality monitoring and Kafka backlog incident thinking.

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?"

data trust ladder schema valid -> event volume sane -> timestamps aligned -> duplicates removed -> joins complete -> missingness explained -> outliers classified -> fraud filtered or down-weighted -> labels complete -> training snapshot approved

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

BoundaryChecksFailure exampleImpact
Client eventRequired fields, timestamp, request_id, app version, duration boundsNew app stops sending video_durationCompletion feature corrupt
CollectorVolume, duplicate IDs, retry rate, status code, regionRetry storm duplicates likesInteraction labels inflated
Stream jobLag, late events, invalid schema, watermark drop rateKafka backlog delays real-time hotnessRanker sees stale features
ETL joinJoin rate, null rate, key cardinality, partition freshnessUser profile join drops 8% of new usersSegment bias
Training tableLabel delay, class balance, distribution drift, leakage scanRecent conversions incompleteModel learns false negatives
Feature serviceOnline/offline parity, freshness, lookup latencyOnline feature defaulting silentlyA/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 patternInterpretationTreatment
Random profile field missingOrdinary incompletenessMedian/mode fill, model fill, or unknown bucket
Video duration missing by app versionInstrumentation bugFix logging; exclude or backfill affected slice
Watch time missing after fast swipeMay be valid negative behaviorSpecial event flag, not simple mean fill
Long inactivityLifecycle stateFeature as churn/return signal
New-video visual embedding missingCold-start pipeline lagDefault 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 outlierCould be validCould be invalidAction
Watch time > video durationRewatch loopClient bug or replay attackCap, flag rewatch, inspect device/app slice
Many likes in secondsPower user or live eventBot clusterDevice/IP graph, velocity threshold, trust score
Extreme creator exposureViral videoBrush traffic or old-ranker biasHead/tail split, fraud model, exposure debiasing
Very low completionBad match or latencyAutoplay failureSlice by network, app version, video load time
Do not blindly delete extremes
Some "abnormal" behavior is the product signal you need: repeated watching may mean high value, fast swipes may be strong negative feedback, and long-tail videos may be the discovery surface. Classify before filtering.

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.

MethodUseRisk
Negative downsamplingReduce training volume and class imbalancePredicted probabilities need correction
Hard-negative miningKeep informative negativesCan overfocus on ambiguous cases
Time-decay weightingReduce stale-label impactMay erase seasonal patterns
Focal loss / label weightingFocus on hard examplesCan harm calibration
Auxiliary labelsUse completion/watch time with clickMulti-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.

RuleMechanismWhy it improves the signal
Invalid-exposure filterDrop 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-ruleKeep high-confidence negatives - full play but no click/like - and drop random "easy" negatives the model already separates triviallyThe informative gradient is at the decision boundary; easy negatives just dilute it
Time-decay negative weightsWeight recent non-clicks higher: w = e^(−λ·Δt)An old non-click may reflect stale interest; recent rejection is stronger evidence
Per-epoch dynamic undersampleEach epoch randomly draw negatives equal to the positive count; leave validation/test at the true distributionThe 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.

FrameworkBest useWhyLimit
SparkTB-scale batch cleaning, SQL feature extraction, daily training tablesDataFrame/Spark SQL, mature Hive/HDFS integration, good iterative preprocessingMicro-batch latency is not ideal for sub-second features
FlinkReal-time/stateful cleaning, sliding-window anomaly detection, exactly-once streamsEvent-time processing, keyed state, checkpointsState/schema evolution needs discipline
Hadoop MapReduceCold historical fallback and archival jobsReliable batch over HDFSMultiple 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:

Kafka event -> schema registry validation -> rule checks -> statistical/model anomaly checks -> decision: accept / repair / drop / quarantine / alert -> clean stream and audit stream -> dashboards and threshold feedback
Check typeExampleDecision
SchemaMissing user_id, invalid timestamp, bad enumReject or quarantine
Rangewatch_time < 0 or watch_time > 5 × durationCap, flag, or drop
LogicLike event without valid exposureDrop label or investigate instrumentation
Distribution1-minute mean shifts by 3 sigmaAlert and slice
FraudDevice/IP/account burst clusterDown-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:

CheckMechanismCatches
Improved Z-ScoreRobust 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 huntPoint outliers in skewed watch-time without a fat tail poisoning the threshold
Isolation forestRandom 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 decompositionSplit a metric series into trend + seasonal + residual; alarm on the residual, not the raw valueTrue 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 gradeExampleTier
Minor~10% of optional fields missing; one numeric feature mildly out of bandAuto-repair - backfill from user profile / last-known value, emit with a repaired flag
ModerateSuspected fake clicks, isolation-forest score high but not certainHuman-review queue + alert - hold out of the training snapshot until adjudicated
SevereSchema violation, future-label leak, confirmed bot clusterBlock 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.

Worked example - static vs dynamic band
Watch-time mean on a normal day ≈ 28 s; a static range rule sets [15, 45] s. On a holiday the genuine mean shifts to 41 s with wider spread - still healthy, but a static upper bound of 45 s is one noisy minute from firing.
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:

LayerWhat it watchesTrip thresholdAuto-response
Raw / loggingNull rate and format validity on landed eventsNull rate > 5% on a required fieldAlert logging owner; quarantine the bad slice
FeatureDistribution drift and categorical entropy of computed featuresPSI > 0.25, or entropy collapse on a categoryCore feature → auto-trigger retrain; non-core → fall back to historical mean or a lighter model
ServingOnline-vs-offline parityDouble-run mismatch beyond toleranceBlock 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.

Name the tooling - with the job each does
Great Expectations / Deequ (Spark-native, AWS) - declarative expectation suites that assert null-rate, range, uniqueness, and distribution on batch tables, failing the pipeline before a bad partition is published. Apache Griffin - scheduled T+1 data-quality measurement over Hive partitions (accuracy, completeness, timeliness). DataHub / Apache Atlas - field-level lineage so when a feature alarms you can trace event → feature → model and find the upstream change. The tools are not the system; the graded tiers and dynamic thresholds are. The tools just execute the assertions.

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 questionViewDecision it informs
Is traffic healthy?Events over time by region/app/deviceLogging incident or rollout artifact?
Is watch time long-tailed?Histogram, log histogram, quantilesCap, log transform, segment metrics
Are labels delayed?Conversion/completion by label ageTraining cutoff and label maturity
Do groups differ?New/old users, high/low activity, region, creator cohortSegment models, stratified A/B, fairness checks
Are features stable?Train vs serve histograms, PSI, top valuesDrift response and retraining
Is there suspicious behavior?IP/device/account graph, burst heatmap, sequence rulesFraud 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.

brush-detection features account velocity device / IP sharing identical watch durations watch-before-like consistency burst timing after upload repeated comment text creator-level abnormal growth refund / report / block after conversion
Suspicious patternLikely issueTraining response
Very short watch + high like/commentFake engagementDown-weight labels; add fraud feature
Many accounts on one device/IPAccount farmCluster and suppress
Identical behavior sequencesAutomation scriptQuarantine events
New videos exploited for trial trafficCold-start spamTrust-tiered exploration
High conversion followed by refund/reportLow-quality conversionDelay 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:

SignalThresholdWhy this value
Per-user operation frequencyFlag beyond the 99th percentile of the daily ops/user distributionPercentile, 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 IPA 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 itemsBusiness rule fed into the model score; catches the "no watch, instant like" automation pattern
Watch-vs-interactwatch_time < 2 s and like/comment presentEngagement without consumption is the signature of fake preference data
Worked threshold example
A creator's new video gets 50,000 likes in its first hour. EDA on the liking accounts:
• 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.

Adversarial brushing defeats simple thresholds
Sophisticated click farms mimic the normal distribution: they throttle to stay under 100 ops/min, spread across many IPs, and add randomized watch time so the per-feature flags miss them. Two escalations: (1) behavior-dynamics signals a script cannot easily fake - mouse-trajectory / touch-pressure patterns; (2) a GNN over the user-device-IP-item graph to find linked-account clusters. Individually each account looks human; collectively they form a dense bipartite subgraph (many accounts, few shared devices/payment instruments, synchronized targets) that graph embedding surfaces even when no single account trips a threshold. The same toolkit transfers to e-commerce order-brushing (watch the order→refund time gap) and social bot-follower detection.

10 · Define incident severity for data problems

SeverityExampleAction
LowOptional context feature missing for 0.2% trafficDefault value, alert owner, monitor impact
MediumFeature drift in one region or device tierSlice A/B, pause retraining, backfill if needed
HighPrimary label duplicated or delayedBlock training, invalidate affected metrics, replay
CriticalFuture-label leakage or privacy-sensitive field in trainingStop pipeline, purge, incident process, legal/security review

Interview prompts you should be ready for

  1. "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.
  2. "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.
  3. "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.
  4. "What quality monitors belong in a feature pipeline?" Freshness, missingness, range, cardinality, entropy, PSI, join rate, label completeness, parity, and feature-store latency.
  5. "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.
  6. "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.
Takeaway
The book's data-quality lesson is: logs are not truth until validated. A senior recommender engineer cleans, explains, monitors, and sometimes rejects data before letting it become model signal.