| """Task definitions for KaggleSimEnv v3. |
| |
| Each task now includes: |
| - DatasetProperties → causal ground truth driving reward logic |
| - failure_modes → traps the agent can fall into |
| - context_relevance → per-action relevance to THIS dataset |
| - strategy_combos → synergy bonuses |
| - score_modifiers → deterministic CV/test deltas |
| """ |
|
|
| from __future__ import annotations |
|
|
| from dataclasses import dataclass, field |
| from typing import Any |
|
|
| from kaggle_sim_env.models import ( |
| ColumnInfo, |
| DatasetMetadata, |
| DatasetProperties, |
| FailureMode, |
| ) |
|
|
|
|
| @dataclass(frozen=True) |
| class StrategyComboDef: |
| name: str |
| required: frozenset[str] |
| cv_bonus: float |
| test_bonus: float |
|
|
|
|
| @dataclass(frozen=True) |
| class TaskDefinition: |
| task_id: str |
| title: str |
| difficulty: str |
| description: str |
| dataset_metadata: DatasetMetadata |
| dataset_properties: DatasetProperties |
| base_cv_score: float |
| base_test_score: float |
| expected_strategies: list[str] |
| ghost_scores: list[float] |
| hints: list[str] |
| score_modifiers: dict[str, dict[str, float]] = field(default_factory=dict) |
| overfitting_risk: dict[str, float] = field(default_factory=dict) |
| strategy_combos: list[StrategyComboDef] = field(default_factory=list) |
| failure_modes: list[FailureMode] = field(default_factory=list) |
| context_relevance: dict[str, float] = field(default_factory=dict) |
| max_steps: int = 20 |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
|
|
|
|
| |
| |
| |
|
|
| def _easy_task() -> TaskDefinition: |
| columns = [ |
| ColumnInfo(name="id", dtype="int64", missing_pct=0.0, unique_count=10000), |
| ColumnInfo(name="age", dtype="float64", missing_pct=0.0, unique_count=80), |
| ColumnInfo(name="income", dtype="float64", missing_pct=0.0, unique_count=5000), |
| ColumnInfo(name="credit_score", dtype="float64", missing_pct=0.0, unique_count=300), |
| ColumnInfo(name="num_products", dtype="int64", missing_pct=0.0, unique_count=4), |
| ColumnInfo(name="tenure", dtype="int64", missing_pct=0.0, unique_count=12), |
| ColumnInfo(name="balance", dtype="float64", missing_pct=0.0, unique_count=6000), |
| ColumnInfo(name="has_credit_card", dtype="int64", missing_pct=0.0, unique_count=2), |
| ColumnInfo(name="is_active_member", dtype="int64", missing_pct=0.0, unique_count=2), |
| ColumnInfo(name="target", dtype="int64", missing_pct=0.0, unique_count=2), |
| ] |
|
|
| props = DatasetProperties( |
| has_imbalance=True, imbalance_ratio=0.20, |
| ) |
|
|
| failure_modes = [ |
| FailureMode( |
| name="unnecessary_shift_detection", |
| trigger_tag="detect_shift:adversarial_validation", |
| condition_field="has_shift", condition_value=False, |
| cv_effect=0.0, test_effect=0.0, |
| message="No distribution shift exists — adversarial validation wasted a step.", |
| ), |
| FailureMode( |
| name="image_aug_on_tabular", |
| trigger_tag="augmentation:geometric", |
| condition_field="has_images", condition_value=False, |
| cv_effect=0.0, test_effect=-0.01, |
| message="Geometric augmentation is meaningless on tabular data.", |
| ), |
| FailureMode( |
| name="target_encoding_without_group_cv", |
| trigger_tag="feature_engineering:target_encoding", |
| condition_field="has_group_column", condition_value=False, |
| cv_effect=0.06, test_effect=-0.04, |
| message="Target encoding without group-aware CV causes leakage — CV inflated but test hurt.", |
| ), |
| ] |
|
|
| context_relevance = { |
| |
| "set_cv:kfold": 1.0, |
| "set_cv:repeated_kfold": 0.8, |
| "feature_engineering:normalize": 0.8, |
| "feature_engineering:domain_ratios": 1.0, |
| "train_model:xgboost": 1.0, |
| "train_model:lightgbm": 0.9, |
| "handle_imbalance:scale_pos_weight": 1.0, |
| "handle_imbalance:optimize_threshold": 0.8, |
| "ensemble:weighted_average": 0.7, |
| |
| "feature_engineering:log_transform": 0.3, |
| "regularize:strong_regularization": 0.2, |
| |
| "detect_shift:adversarial_validation": -0.5, |
| "augmentation:geometric": -1.0, |
| "augmentation:color_transform": -1.0, |
| "augmentation:camera_simulation": -1.0, |
| "feature_engineering:sin_cos_encoding": -0.8, |
| "feature_engineering:relative_coordinates": -1.0, |
| "feature_engineering:frequency_features": -0.8, |
| "tune_loss:auxiliary_physics_loss": -1.0, |
| "postprocess:physics_constraints": -1.0, |
| "train_model:pretrained_backbone": -0.5, |
| "train_model:temporal_cnn": -0.8, |
| "train_model:transformer_encoder": -0.5, |
| } |
|
|
| return TaskDefinition( |
| task_id="easy_churn", |
| title="Customer Churn Prediction", |
| difficulty="easy", |
| description=( |
| "Predict customer churn from clean tabular banking data. " |
| "Mild class imbalance (80/20). No missing values, no shift." |
| ), |
| dataset_metadata=DatasetMetadata( |
| num_rows=10000, num_features=9, columns=columns, |
| target_column="target", task_type="classification", |
| class_balance={"0": 0.80, "1": 0.20}, |
| ), |
| dataset_properties=props, |
| base_cv_score=0.50, |
| base_test_score=0.50, |
| expected_strategies=[ |
| "set_cv:kfold", |
| "feature_engineering:normalize", |
| "feature_engineering:domain_ratios", |
| "train_model:xgboost", |
| "handle_imbalance:scale_pos_weight", |
| ], |
| ghost_scores=[0.90, 0.88, 0.86, 0.84, 0.82, 0.79, 0.75, 0.72, 0.68], |
| hints=[ |
| "This is a clean tabular dataset — standard k-fold CV works well.", |
| "Create domain ratios like balance/income, products/tenure.", |
| "XGBoost dominates clean tabular data.", |
| "Tune scale_pos_weight for the 80/20 class split.", |
| "No distribution shift exists — don't waste steps detecting it.", |
| ], |
| score_modifiers={ |
| "set_cv:kfold": {"cv": 0.05, "test": 0.05}, |
| "set_cv:repeated_kfold": {"cv": 0.06, "test": 0.06}, |
| "set_cv:group_kfold": {"cv": 0.03, "test": 0.03}, |
| "set_cv:time_split": {"cv": 0.02, "test": 0.01}, |
| "feature_engineering:normalize": {"cv": 0.04, "test": 0.04}, |
| "feature_engineering:log_transform": {"cv": 0.02, "test": 0.02}, |
| "feature_engineering:interaction_terms": {"cv": 0.03, "test": 0.02}, |
| "feature_engineering:domain_ratios": {"cv": 0.05, "test": 0.05}, |
| "feature_engineering:target_encoding": {"cv": 0.06, "test": -0.04}, |
| "feature_engineering:quantile_features": {"cv": 0.02, "test": 0.02}, |
| "train_model:xgboost": {"cv": 0.20, "test": 0.19}, |
| "train_model:lightgbm": {"cv": 0.19, "test": 0.18}, |
| "train_model:catboost": {"cv": 0.18, "test": 0.18}, |
| "train_model:random_forest": {"cv": 0.16, "test": 0.15}, |
| "train_model:linear": {"cv": 0.10, "test": 0.10}, |
| "train_model:neural_network": {"cv": 0.08, "test": 0.06}, |
| "handle_imbalance:scale_pos_weight": {"cv": 0.04, "test": 0.04}, |
| "handle_imbalance:calibrate_probabilities": {"cv": 0.02, "test": 0.03}, |
| "handle_imbalance:optimize_threshold": {"cv": 0.03, "test": 0.03}, |
| "ensemble:weighted_average": {"cv": 0.04, "test": 0.03}, |
| "ensemble:stacking": {"cv": 0.05, "test": 0.03}, |
| "ensemble:multi_seed_averaging": {"cv": 0.03, "test": 0.03}, |
| "regularize:strong_regularization": {"cv": 0.01, "test": 0.02}, |
| "pseudo_label:1": {"cv": 0.01, "test": 0.00}, |
| "postprocess:bias_correction": {"cv": 0.01, "test": 0.01}, |
| "inspect_top_solution": {"cv": 0.0, "test": 0.0}, |
| }, |
| overfitting_risk={ |
| "feature_engineering:target_encoding": 0.06, |
| "feature_engineering:interaction_terms": 0.01, |
| "ensemble:stacking": 0.02, |
| }, |
| strategy_combos=[ |
| StrategyComboDef( |
| name="clean_tabular_pipeline", |
| required=frozenset({"set_cv:kfold", "train_model:xgboost", "feature_engineering:normalize"}), |
| cv_bonus=0.02, test_bonus=0.02, |
| ), |
| StrategyComboDef( |
| name="imbalance_aware", |
| required=frozenset({"handle_imbalance:scale_pos_weight", "handle_imbalance:optimize_threshold"}), |
| cv_bonus=0.02, test_bonus=0.03, |
| ), |
| ], |
| failure_modes=failure_modes, |
| context_relevance=context_relevance, |
| max_steps=20, |
| ) |
|
|
|
|
| |
| |
| |
|
|
| def _medium_task() -> TaskDefinition: |
| columns = [ |
| ColumnInfo(name="id", dtype="int64", missing_pct=0.0, unique_count=50000), |
| ColumnInfo(name="timestamp", dtype="datetime64", missing_pct=0.0, unique_count=365), |
| ColumnInfo(name="merchant_id", dtype="int64", missing_pct=0.0, unique_count=500), |
| ColumnInfo(name="amount", dtype="float64", missing_pct=1.2, unique_count=15000), |
| ColumnInfo(name="category", dtype="object", missing_pct=0.0, unique_count=15), |
| ColumnInfo(name="customer_age", dtype="float64", missing_pct=3.5, unique_count=70), |
| ColumnInfo(name="customer_region", dtype="object", missing_pct=0.5, unique_count=8), |
| ColumnInfo(name="prev_transactions", dtype="int64", missing_pct=0.0, unique_count=200), |
| ColumnInfo(name="is_weekend", dtype="int64", missing_pct=0.0, unique_count=2), |
| ColumnInfo(name="device_type", dtype="object", missing_pct=2.0, unique_count=4), |
| ColumnInfo(name="is_fraud", dtype="int64", missing_pct=0.0, unique_count=2), |
| ] |
|
|
| props = DatasetProperties( |
| has_shift=True, |
| has_imbalance=True, imbalance_ratio=0.05, |
| has_time_column=True, has_group_column=True, |
| is_safety_critical=True, |
| ) |
|
|
| failure_modes = [ |
| FailureMode( |
| name="kfold_on_temporal_data", |
| trigger_tag="set_cv:kfold", |
| condition_field="has_shift", condition_value=True, |
| cv_effect=0.08, test_effect=-0.04, |
| message="Random k-fold on shifted temporal data — CV is optimistic, test will be much worse.", |
| ), |
| FailureMode( |
| name="ignoring_shift", |
| trigger_tag="train_model:xgboost", |
| condition_field="has_shift", condition_value=True, |
| cv_effect=0.0, test_effect=-0.06, |
| message="Training without addressing distribution shift — model memorises train distribution.", |
| ), |
| FailureMode( |
| name="target_encoding_leakage", |
| trigger_tag="feature_engineering:target_encoding", |
| condition_field="has_shift", condition_value=True, |
| cv_effect=0.05, test_effect=-0.06, |
| message="Target encoding on shifted data leaks train-specific patterns.", |
| ), |
| ] |
|
|
| context_relevance = { |
| "detect_shift:adversarial_validation": 1.0, |
| "detect_shift:remove_identifiers": 1.0, |
| "detect_shift:domain_invariant_features": 0.9, |
| "set_cv:time_split": 1.0, |
| "set_cv:combined_group_time": 0.9, |
| "set_cv:kfold": -0.8, |
| "feature_engineering:log_transform": 0.8, |
| "feature_engineering:domain_ratios": 0.9, |
| "train_model:xgboost": 0.9, |
| "handle_imbalance:scale_pos_weight": 1.0, |
| "handle_imbalance:optimize_threshold": 0.9, |
| "tune_loss:asymmetric_loss": 1.0, |
| "regularize:strong_regularization": 0.8, |
| "ensemble:weighted_average": 0.7, |
| |
| "augmentation:geometric": -1.0, |
| "augmentation:color_transform": -1.0, |
| "feature_engineering:sin_cos_encoding": -0.5, |
| "feature_engineering:relative_coordinates": -1.0, |
| "tune_loss:auxiliary_physics_loss": -1.0, |
| "postprocess:physics_constraints": -1.0, |
| "train_model:pretrained_backbone": -0.5, |
| } |
|
|
| return TaskDefinition( |
| task_id="medium_fraud", |
| title="Fraud Detection with Distribution Shift", |
| difficulty="medium", |
| description=( |
| "Detect fraudulent transactions. Test set comes from a later time " |
| "period with distribution shift. Heavy imbalance (95/5). Safety-critical." |
| ), |
| dataset_metadata=DatasetMetadata( |
| num_rows=50000, num_features=10, columns=columns, |
| target_column="is_fraud", task_type="classification", |
| has_time_column=True, has_group_column=True, |
| class_balance={"0": 0.95, "1": 0.05}, |
| ), |
| dataset_properties=props, |
| base_cv_score=0.42, |
| base_test_score=0.38, |
| expected_strategies=[ |
| "detect_shift:adversarial_validation", |
| "detect_shift:remove_identifiers", |
| "set_cv:time_split", |
| "feature_engineering:log_transform", |
| "feature_engineering:domain_ratios", |
| "train_model:xgboost", |
| "handle_imbalance:scale_pos_weight", |
| "handle_imbalance:optimize_threshold", |
| "tune_loss:asymmetric_loss", |
| "ensemble:weighted_average", |
| "regularize:strong_regularization", |
| ], |
| ghost_scores=[0.92, 0.90, 0.87, 0.84, 0.80, 0.76, 0.72, 0.67, 0.60], |
| hints=[ |
| "Adversarial validation AUC > 0.82 — significant distribution shift exists!", |
| "Use time-based CV — random k-fold will give you a false sense of accuracy.", |
| "Log-transform 'amount' — it has extreme skew.", |
| "Remove merchant_id and device_type — they are identifiers causing shift.", |
| "This is safety-critical: asymmetric loss prioritises fraud recall.", |
| "Tune scale_pos_weight on OOF outputs, then optimize threshold.", |
| "Strong regularisation prevents memorising train-specific patterns.", |
| ], |
| score_modifiers={ |
| "set_cv:kfold": {"cv": 0.08, "test": -0.04}, |
| "set_cv:group_kfold": {"cv": 0.06, "test": 0.05}, |
| "set_cv:time_split": {"cv": 0.05, "test": 0.10}, |
| "set_cv:combined_group_time": {"cv": 0.05, "test": 0.09}, |
| "detect_shift:adversarial_validation": {"cv": 0.02, "test": 0.08}, |
| "detect_shift:feature_importance_shift": {"cv": 0.01, "test": 0.04}, |
| "detect_shift:remove_identifiers": {"cv": -0.01, "test": 0.06}, |
| "detect_shift:domain_invariant_features": {"cv": 0.02, "test": 0.05}, |
| "feature_engineering:log_transform": {"cv": 0.05, "test": 0.06}, |
| "feature_engineering:normalize": {"cv": 0.02, "test": 0.02}, |
| "feature_engineering:domain_ratios": {"cv": 0.04, "test": 0.05}, |
| "feature_engineering:interaction_terms": {"cv": 0.04, "test": 0.01}, |
| "feature_engineering:target_encoding": {"cv": 0.05, "test": -0.06}, |
| "train_model:xgboost": {"cv": 0.18, "test": 0.16}, |
| "train_model:lightgbm": {"cv": 0.17, "test": 0.16}, |
| "train_model:catboost": {"cv": 0.16, "test": 0.15}, |
| "train_model:random_forest": {"cv": 0.14, "test": 0.12}, |
| "train_model:linear": {"cv": 0.08, "test": 0.07}, |
| "handle_imbalance:scale_pos_weight": {"cv": 0.04, "test": 0.05}, |
| "handle_imbalance:calibrate_probabilities": {"cv": 0.02, "test": 0.03}, |
| "handle_imbalance:optimize_threshold": {"cv": 0.03, "test": 0.04}, |
| "tune_loss:asymmetric_loss": {"cv": 0.03, "test": 0.05}, |
| "ensemble:weighted_average": {"cv": 0.05, "test": 0.05}, |
| "ensemble:stacking": {"cv": 0.06, "test": 0.04}, |
| "ensemble:multi_seed_averaging": {"cv": 0.03, "test": 0.04}, |
| "ensemble:heterogeneous": {"cv": 0.04, "test": 0.05}, |
| "regularize:strong_regularization": {"cv": -0.01, "test": 0.04}, |
| "regularize:ema": {"cv": 0.01, "test": 0.02}, |
| "pseudo_label:1": {"cv": 0.02, "test": 0.01}, |
| "pseudo_label:2": {"cv": 0.03, "test": -0.02}, |
| "postprocess:bias_correction": {"cv": 0.01, "test": 0.02}, |
| "clean_data:remove_outliers": {"cv": 0.01, "test": 0.02}, |
| "clean_data:remove_leaky_features": {"cv": -0.02, "test": 0.04}, |
| "inspect_top_solution": {"cv": 0.0, "test": 0.0}, |
| }, |
| overfitting_risk={ |
| "set_cv:kfold": 0.08, |
| "pseudo_label:2": 0.05, |
| "feature_engineering:target_encoding": 0.05, |
| "feature_engineering:interaction_terms": 0.03, |
| }, |
| strategy_combos=[ |
| StrategyComboDef( |
| name="shift_aware_pipeline", |
| required=frozenset({ |
| "detect_shift:adversarial_validation", |
| "set_cv:time_split", |
| "detect_shift:remove_identifiers", |
| }), |
| cv_bonus=0.03, test_bonus=0.06, |
| ), |
| StrategyComboDef( |
| name="safety_critical_fraud", |
| required=frozenset({ |
| "handle_imbalance:scale_pos_weight", |
| "tune_loss:asymmetric_loss", |
| "handle_imbalance:optimize_threshold", |
| }), |
| cv_bonus=0.02, test_bonus=0.04, |
| ), |
| StrategyComboDef( |
| name="robust_generalisation", |
| required=frozenset({ |
| "regularize:strong_regularization", |
| "detect_shift:domain_invariant_features", |
| }), |
| cv_bonus=0.01, test_bonus=0.03, |
| ), |
| ], |
| failure_modes=failure_modes, |
| context_relevance=context_relevance, |
| max_steps=25, |
| ) |
|
|
|
|
| |
| |
| |
|
|
| def _hard_task() -> TaskDefinition: |
| columns = [ |
| ColumnInfo(name="id", dtype="int64", missing_pct=0.0, unique_count=100000), |
| ColumnInfo(name="timestamp", dtype="datetime64", missing_pct=0.0, unique_count=730), |
| ColumnInfo(name="group_id", dtype="int64", missing_pct=0.0, unique_count=1000), |
| ColumnInfo(name="feature_0", dtype="float64", missing_pct=8.5, unique_count=50000), |
| ColumnInfo(name="feature_1", dtype="float64", missing_pct=12.0, unique_count=40000), |
| ColumnInfo(name="feature_2", dtype="float64", missing_pct=0.0, unique_count=60000), |
| ColumnInfo(name="feature_3", dtype="float64", missing_pct=5.0, unique_count=30000), |
| ColumnInfo(name="feature_4", dtype="object", missing_pct=15.0, unique_count=20), |
| ColumnInfo(name="feature_5_leaky", dtype="float64", missing_pct=0.0, unique_count=80000), |
| ColumnInfo(name="noise_0", dtype="float64", missing_pct=0.0, unique_count=100000), |
| ColumnInfo(name="noise_1", dtype="float64", missing_pct=0.0, unique_count=100000), |
| ColumnInfo(name="noise_2", dtype="float64", missing_pct=0.0, unique_count=100000), |
| ColumnInfo(name="target", dtype="int64", missing_pct=0.0, unique_count=2), |
| ] |
|
|
| props = DatasetProperties( |
| has_shift=True, has_leakage=True, has_noise_features=True, |
| has_missing_data=True, has_imbalance=True, imbalance_ratio=0.08, |
| has_time_column=True, has_group_column=True, |
| ) |
|
|
| failure_modes = [ |
| FailureMode( |
| name="kfold_on_grouped_data", |
| trigger_tag="set_cv:kfold", |
| condition_field="has_group_column", condition_value=True, |
| cv_effect=0.10, test_effect=-0.05, |
| message="Random k-fold on grouped data leaks group structure — CV hugely inflated.", |
| ), |
| FailureMode( |
| name="keeping_leaky_feature", |
| trigger_tag="train_model:xgboost", |
| condition_field="has_leakage", condition_value=True, |
| cv_effect=0.0, test_effect=-0.08, |
| message="Training on leaky features — model depends on data that won't exist at test time.", |
| ), |
| FailureMode( |
| name="interaction_terms_on_noisy_data", |
| trigger_tag="feature_engineering:interaction_terms", |
| condition_field="has_noise_features", condition_value=True, |
| cv_effect=0.05, test_effect=-0.04, |
| message="Interaction terms on noisy features amplify noise — CV up, test down.", |
| ), |
| FailureMode( |
| name="pseudo_label_overfit", |
| trigger_tag="pseudo_label:2", |
| condition_field="has_shift", condition_value=True, |
| cv_effect=0.05, test_effect=-0.06, |
| message="Iterative pseudo-labeling on shifted data compounds distribution errors.", |
| ), |
| ] |
|
|
| context_relevance = { |
| "detect_shift:adversarial_validation": 1.0, |
| "detect_shift:remove_identifiers": 0.9, |
| "set_cv:stratified_group_kfold": 1.0, |
| "set_cv:kfold": -0.9, |
| "clean_data:remove_leaky_features": 1.0, |
| "clean_data:remove_outliers": 0.8, |
| "clean_data:analytical_reconstruction": 1.0, |
| "clean_data:nan_native_model": 0.8, |
| "feature_engineering:log_transform": 0.7, |
| "feature_engineering:domain_ratios": 0.8, |
| "feature_engineering:interaction_terms": -0.7, |
| "feature_engineering:target_encoding": -0.9, |
| "train_model:xgboost": 0.9, |
| "train_model:lightgbm": 0.9, |
| "handle_imbalance:scale_pos_weight": 1.0, |
| "handle_imbalance:calibrate_probabilities": 0.9, |
| "ensemble:stacking": 0.8, |
| "ensemble:diverse_features": 0.9, |
| "regularize:strong_regularization": 0.9, |
| "pseudo_label:1": 0.5, |
| "pseudo_label:2": -0.8, |
| |
| "augmentation:geometric": -1.0, |
| "augmentation:camera_simulation": -1.0, |
| "tune_loss:auxiliary_physics_loss": -1.0, |
| "postprocess:physics_constraints": -1.0, |
| "train_model:pretrained_backbone": -0.5, |
| } |
|
|
| return TaskDefinition( |
| task_id="hard_leaky_noisy", |
| title="Leaky Noisy Imbalanced Classification", |
| difficulty="hard", |
| description=( |
| "High-dimensional classification with data leakage (feature_5_leaky), " |
| "pure-noise columns (noise_0-2), structured missing data, class imbalance " |
| "(92/8), and temporal distribution shift." |
| ), |
| dataset_metadata=DatasetMetadata( |
| num_rows=100000, num_features=12, columns=columns, |
| target_column="target", task_type="classification", |
| has_time_column=True, has_group_column=True, |
| class_balance={"0": 0.92, "1": 0.08}, |
| ), |
| dataset_properties=props, |
| base_cv_score=0.38, |
| base_test_score=0.32, |
| expected_strategies=[ |
| "detect_shift:adversarial_validation", |
| "detect_shift:remove_identifiers", |
| "set_cv:stratified_group_kfold", |
| "clean_data:remove_leaky_features", |
| "clean_data:remove_outliers", |
| "clean_data:analytical_reconstruction", |
| "feature_engineering:log_transform", |
| "feature_engineering:domain_ratios", |
| "train_model:xgboost", |
| "train_model:lightgbm", |
| "handle_imbalance:scale_pos_weight", |
| "handle_imbalance:calibrate_probabilities", |
| "ensemble:stacking", |
| "ensemble:diverse_features", |
| "pseudo_label:1", |
| "regularize:strong_regularization", |
| ], |
| ghost_scores=[0.91, 0.88, 0.85, 0.82, 0.78, 0.74, 0.69, 0.63, 0.55], |
| hints=[ |
| "'feature_5_leaky' is suspiciously predictive — it encodes target leakage. Remove it!", |
| "noise_0/1/2 have zero signal; removing them reduces overfitting dramatically.", |
| "Use stratified group k-fold — random k-fold will leak group structure.", |
| "Adversarial validation AUC 0.85 — heavy distribution shift.", |
| "Many rows with structured missing data can be analytically reconstructed.", |
| "Calibrate probabilities with isotonic regression on OOF predictions.", |
| "Stack XGBoost + LightGBM with diverse feature subsets.", |
| "One iteration of pseudo-labeling helps; two iterations overfit badly on shifted data.", |
| ], |
| score_modifiers={ |
| "set_cv:kfold": {"cv": 0.10, "test": -0.05}, |
| "set_cv:group_kfold": {"cv": 0.06, "test": 0.08}, |
| "set_cv:stratified_group_kfold": {"cv": 0.05, "test": 0.10}, |
| "set_cv:time_split": {"cv": 0.05, "test": 0.07}, |
| "detect_shift:adversarial_validation": {"cv": 0.02, "test": 0.08}, |
| "detect_shift:remove_identifiers": {"cv": -0.02, "test": 0.07}, |
| "clean_data:remove_leaky_features": {"cv": -0.05, "test": 0.08}, |
| "clean_data:remove_outliers": {"cv": 0.02, "test": 0.03}, |
| "clean_data:analytical_reconstruction": {"cv": 0.03, "test": 0.04}, |
| "clean_data:nan_native_model": {"cv": 0.02, "test": 0.03}, |
| "feature_engineering:log_transform": {"cv": 0.04, "test": 0.05}, |
| "feature_engineering:domain_ratios": {"cv": 0.04, "test": 0.05}, |
| "feature_engineering:interaction_terms": {"cv": 0.05, "test": -0.04}, |
| "feature_engineering:target_encoding": {"cv": 0.06, "test": -0.05}, |
| "feature_engineering:normalize": {"cv": 0.03, "test": 0.03}, |
| "train_model:xgboost": {"cv": 0.16, "test": 0.14}, |
| "train_model:lightgbm": {"cv": 0.15, "test": 0.14}, |
| "train_model:catboost": {"cv": 0.14, "test": 0.13}, |
| "train_model:random_forest": {"cv": 0.12, "test": 0.10}, |
| "train_model:linear": {"cv": 0.06, "test": 0.06}, |
| "handle_imbalance:scale_pos_weight": {"cv": 0.04, "test": 0.05}, |
| "handle_imbalance:calibrate_probabilities": {"cv": 0.02, "test": 0.04}, |
| "handle_imbalance:optimize_threshold": {"cv": 0.03, "test": 0.03}, |
| "tune_loss:asymmetric_loss": {"cv": 0.02, "test": 0.04}, |
| "ensemble:stacking": {"cv": 0.06, "test": 0.05}, |
| "ensemble:diverse_features": {"cv": 0.04, "test": 0.05}, |
| "ensemble:weighted_average": {"cv": 0.04, "test": 0.04}, |
| "regularize:strong_regularization": {"cv": -0.02, "test": 0.05}, |
| "regularize:ema": {"cv": 0.01, "test": 0.02}, |
| "pseudo_label:1": {"cv": 0.03, "test": 0.03}, |
| "pseudo_label:2": {"cv": 0.05, "test": -0.06}, |
| "postprocess:bias_correction": {"cv": 0.01, "test": 0.02}, |
| "inspect_top_solution": {"cv": 0.0, "test": 0.0}, |
| }, |
| overfitting_risk={ |
| "set_cv:kfold": 0.10, |
| "pseudo_label:2": 0.06, |
| "feature_engineering:interaction_terms": 0.05, |
| "feature_engineering:target_encoding": 0.06, |
| }, |
| strategy_combos=[ |
| StrategyComboDef( |
| name="data_hygiene", |
| required=frozenset({ |
| "clean_data:remove_leaky_features", |
| "clean_data:remove_outliers", |
| "detect_shift:adversarial_validation", |
| }), |
| cv_bonus=0.02, test_bonus=0.06, |
| ), |
| StrategyComboDef( |
| name="missing_data_mastery", |
| required=frozenset({ |
| "clean_data:analytical_reconstruction", |
| "clean_data:nan_native_model", |
| }), |
| cv_bonus=0.02, test_bonus=0.03, |
| ), |
| StrategyComboDef( |
| name="diverse_ensemble", |
| required=frozenset({ |
| "train_model:xgboost", "train_model:lightgbm", |
| "ensemble:diverse_features", "ensemble:stacking", |
| }), |
| cv_bonus=0.03, test_bonus=0.05, |
| ), |
| StrategyComboDef( |
| name="calibrated_imbalance", |
| required=frozenset({ |
| "handle_imbalance:scale_pos_weight", |
| "handle_imbalance:calibrate_probabilities", |
| "handle_imbalance:optimize_threshold", |
| }), |
| cv_bonus=0.02, test_bonus=0.04, |
| ), |
| ], |
| failure_modes=failure_modes, |
| context_relevance=context_relevance, |
| max_steps=30, |
| ) |
|
|
|
|
| |
| |
| |
|
|
| def _image_task() -> TaskDefinition: |
| columns = [ |
| ColumnInfo(name="image_id", dtype="int64", missing_pct=0.0, unique_count=25000), |
| ColumnInfo(name="image_path", dtype="object", missing_pct=0.0, unique_count=25000), |
| ColumnInfo(name="camera_model", dtype="object", missing_pct=0.0, unique_count=12), |
| ColumnInfo(name="exposure", dtype="float64", missing_pct=2.0, unique_count=500), |
| ColumnInfo(name="iso", dtype="int64", missing_pct=1.0, unique_count=20), |
| ColumnInfo(name="focal_length", dtype="float64", missing_pct=0.5, unique_count=30), |
| ColumnInfo(name="width", dtype="int64", missing_pct=0.0, unique_count=10), |
| ColumnInfo(name="height", dtype="int64", missing_pct=0.0, unique_count=10), |
| ColumnInfo(name="quality_score", dtype="float64", missing_pct=0.0, unique_count=1000), |
| ] |
|
|
| props = DatasetProperties( |
| has_heavy_tails=True, has_group_column=True, |
| has_images=True, |
| ) |
|
|
| failure_modes = [ |
| FailureMode( |
| name="no_augmentation_on_images", |
| trigger_tag="submit", |
| condition_field="has_images", condition_value=True, |
| cv_effect=0.0, test_effect=-0.04, |
| message="Submitting image model without augmentation — overfitting on small image data.", |
| ), |
| FailureMode( |
| name="tree_model_on_images", |
| trigger_tag="train_model:xgboost", |
| condition_field="has_images", condition_value=True, |
| cv_effect=0.04, test_effect=-0.02, |
| message="Tree models on raw image metadata miss the visual signal entirely.", |
| ), |
| ] |
|
|
| context_relevance = { |
| "train_model:pretrained_backbone": 1.0, |
| "regularize:freeze_backbone": 1.0, |
| "augmentation:geometric": 1.0, |
| "augmentation:color_transform": 1.0, |
| "augmentation:camera_simulation": 1.0, |
| "augmentation:clahe": 0.9, |
| "postprocess:tta": 1.0, |
| "postprocess:per_group_calibration": 0.9, |
| "tune_loss:gaussian_nll": 1.0, |
| "tune_loss:multi_task": 0.8, |
| "regularize:ema": 0.8, |
| "ensemble:multi_seed_averaging": 0.8, |
| "ensemble:swa": 0.8, |
| "feature_engineering:log_transform": 0.7, |
| "set_cv:group_kfold": 1.0, |
| "set_cv:kfold": -0.6, |
| |
| "feature_engineering:tfidf_features": -1.0, |
| "feature_engineering:relative_coordinates": -0.8, |
| "tune_loss:auxiliary_physics_loss": -0.8, |
| "detect_shift:adversarial_validation": 0.2, |
| "train_model:xgboost": -0.3, |
| "train_model:linear": -0.7, |
| } |
|
|
| return TaskDefinition( |
| task_id="image_quality", |
| title="Image Quality Assessment", |
| difficulty="hard", |
| description=( |
| "Predict continuous quality scores from photographs. Images from " |
| "multiple cameras with varying resolution. Heavy-tailed target " |
| "and camera-specific biases." |
| ), |
| dataset_metadata=DatasetMetadata( |
| num_rows=25000, num_features=8, columns=columns, |
| target_column="quality_score", task_type="regression", |
| has_image_data=True, has_group_column=True, |
| target_distribution="heavy_tailed", |
| ), |
| dataset_properties=props, |
| base_cv_score=0.35, |
| base_test_score=0.30, |
| expected_strategies=[ |
| "set_cv:group_kfold", |
| "train_model:pretrained_backbone", |
| "augmentation:geometric", |
| "augmentation:color_transform", |
| "augmentation:camera_simulation", |
| "augmentation:clahe", |
| "feature_engineering:log_transform", |
| "tune_loss:gaussian_nll", |
| "tune_loss:multi_task", |
| "regularize:freeze_backbone", |
| "regularize:ema", |
| "ensemble:multi_seed_averaging", |
| "ensemble:swa", |
| "postprocess:tta", |
| "postprocess:per_group_calibration", |
| ], |
| ghost_scores=[0.90, 0.87, 0.84, 0.81, 0.77, 0.73, 0.68, 0.62, 0.55], |
| hints=[ |
| "Group k-fold by camera_model — camera bias leaks between folds.", |
| "Pretrained ImageNet backbones are essential with only 25k images.", |
| "Freeze backbone first, train head, then fine-tune.", |
| "Geometric + color augmentations are a must for image tasks.", |
| "Camera simulation augmentation handles focal length variance.", |
| "CLAHE normalisation helps with exposure variation.", |
| "Heavy-tailed target → log transform + Gaussian NLL loss.", |
| "Multi-task: add classification head for quality bins alongside regression.", |
| "EMA and SWA stabilise training; multi-seed averaging adds robustness.", |
| "TTA with brightness + crops gives 1-2% boost at inference.", |
| ], |
| score_modifiers={ |
| "set_cv:kfold": {"cv": 0.06, "test": 0.00}, |
| "set_cv:group_kfold": {"cv": 0.04, "test": 0.08}, |
| "train_model:pretrained_backbone": {"cv": 0.22, "test": 0.20}, |
| "train_model:neural_network": {"cv": 0.14, "test": 0.11}, |
| "train_model:xgboost": {"cv": 0.04, "test": -0.02}, |
| "train_model:linear": {"cv": 0.02, "test": 0.02}, |
| "augmentation:geometric": {"cv": 0.04, "test": 0.05}, |
| "augmentation:color_transform": {"cv": 0.03, "test": 0.04}, |
| "augmentation:clahe": {"cv": 0.03, "test": 0.03}, |
| "augmentation:camera_simulation": {"cv": 0.03, "test": 0.04}, |
| "augmentation:gaussian_noise": {"cv": 0.02, "test": 0.02}, |
| "augmentation:image_rectification": {"cv": 0.02, "test": 0.03}, |
| "augmentation:multi_view_processing": {"cv": 0.03, "test": 0.03}, |
| "feature_engineering:log_transform": {"cv": 0.03, "test": 0.04}, |
| "feature_engineering:normalize": {"cv": 0.02, "test": 0.02}, |
| "tune_loss:gaussian_nll": {"cv": 0.04, "test": 0.05}, |
| "tune_loss:multi_task": {"cv": 0.03, "test": 0.04}, |
| "tune_loss:interval_regression": {"cv": 0.02, "test": 0.03}, |
| "tune_loss:quantile_regression": {"cv": 0.02, "test": 0.03}, |
| "regularize:freeze_backbone": {"cv": 0.03, "test": 0.05}, |
| "regularize:ema": {"cv": 0.02, "test": 0.03}, |
| "regularize:dropout": {"cv": 0.01, "test": 0.02}, |
| "ensemble:multi_seed_averaging": {"cv": 0.03, "test": 0.04}, |
| "ensemble:swa": {"cv": 0.03, "test": 0.04}, |
| "ensemble:weighted_average": {"cv": 0.03, "test": 0.03}, |
| "postprocess:tta": {"cv": 0.03, "test": 0.04}, |
| "postprocess:per_group_calibration": {"cv": 0.02, "test": 0.04}, |
| "postprocess:prediction_shrinkage": {"cv": 0.02, "test": 0.03}, |
| "pseudo_label:1": {"cv": 0.02, "test": 0.01}, |
| "inspect_top_solution": {"cv": 0.0, "test": 0.0}, |
| }, |
| overfitting_risk={ |
| "set_cv:kfold": 0.06, |
| "train_model:xgboost": 0.06, |
| }, |
| strategy_combos=[ |
| StrategyComboDef( |
| name="vision_pipeline", |
| required=frozenset({ |
| "train_model:pretrained_backbone", "regularize:freeze_backbone", |
| "augmentation:geometric", "augmentation:color_transform", |
| }), |
| cv_bonus=0.03, test_bonus=0.05, |
| ), |
| StrategyComboDef( |
| name="heavy_tail_handling", |
| required=frozenset({ |
| "feature_engineering:log_transform", |
| "tune_loss:gaussian_nll", |
| "postprocess:prediction_shrinkage", |
| }), |
| cv_bonus=0.02, test_bonus=0.04, |
| ), |
| StrategyComboDef( |
| name="inference_boost", |
| required=frozenset({ |
| "postprocess:tta", "ensemble:multi_seed_averaging", "ensemble:swa", |
| }), |
| cv_bonus=0.02, test_bonus=0.04, |
| ), |
| StrategyComboDef( |
| name="camera_robustness", |
| required=frozenset({ |
| "augmentation:camera_simulation", "augmentation:clahe", |
| "postprocess:per_group_calibration", |
| }), |
| cv_bonus=0.02, test_bonus=0.04, |
| ), |
| ], |
| failure_modes=failure_modes, |
| context_relevance=context_relevance, |
| max_steps=30, |
| ) |
|
|
|
|
| |
| |
| |
|
|
| def _trajectory_task() -> TaskDefinition: |
| columns = [ |
| ColumnInfo(name="scene_id", dtype="int64", missing_pct=0.0, unique_count=5000), |
| ColumnInfo(name="frame_id", dtype="int64", missing_pct=0.0, unique_count=50), |
| ColumnInfo(name="agent_id", dtype="int64", missing_pct=0.0, unique_count=20), |
| ColumnInfo(name="x", dtype="float64", missing_pct=0.0, unique_count=100000), |
| ColumnInfo(name="y", dtype="float64", missing_pct=0.0, unique_count=100000), |
| ColumnInfo(name="vx", dtype="float64", missing_pct=0.0, unique_count=50000), |
| ColumnInfo(name="vy", dtype="float64", missing_pct=0.0, unique_count=50000), |
| ColumnInfo(name="heading", dtype="float64", missing_pct=0.0, unique_count=3600), |
| ColumnInfo(name="agent_type", dtype="object", missing_pct=0.0, unique_count=4), |
| ColumnInfo(name="future_x", dtype="float64", missing_pct=0.0, unique_count=100000), |
| ColumnInfo(name="future_y", dtype="float64", missing_pct=0.0, unique_count=100000), |
| ] |
|
|
| props = DatasetProperties( |
| has_time_column=True, has_group_column=True, |
| has_spatial_data=True, needs_physics=True, |
| ) |
|
|
| failure_modes = [ |
| FailureMode( |
| name="tree_model_on_trajectories", |
| trigger_tag="train_model:xgboost", |
| condition_field="has_spatial_data", condition_value=True, |
| cv_effect=0.04, test_effect=-0.03, |
| message="Tree models cannot capture spatial-temporal dynamics — use neural approaches.", |
| ), |
| FailureMode( |
| name="raw_heading_without_sincos", |
| trigger_tag="submit", |
| condition_field="has_spatial_data", condition_value=True, |
| cv_effect=0.0, test_effect=-0.03, |
| message="Submitting without sin/cos encoding — raw heading angles wrap around and hurt predictions.", |
| ), |
| ] |
|
|
| context_relevance = { |
| "set_cv:group_kfold": 1.0, |
| "feature_engineering:sin_cos_encoding": 1.0, |
| "feature_engineering:relative_coordinates": 1.0, |
| "feature_engineering:distance_features": 1.0, |
| "train_model:transformer_encoder": 1.0, |
| "train_model:temporal_cnn": 0.9, |
| "augmentation:rotation_invariant": 1.0, |
| "augmentation:symmetry_augmentation": 0.9, |
| "augmentation:temporal_augmentation": 0.9, |
| "tune_loss:gaussian_nll": 1.0, |
| "tune_loss:auxiliary_physics_loss": 1.0, |
| "regularize:ema": 0.9, |
| "ensemble:multi_seed_averaging": 0.8, |
| "postprocess:physics_constraints": 1.0, |
| "clean_data:remove_corrupted": 0.8, |
| "clean_data:remove_outliers": 0.7, |
| "set_cv:kfold": -0.8, |
| |
| "train_model:xgboost": -0.6, |
| "train_model:linear": -0.9, |
| "augmentation:color_transform": -1.0, |
| "augmentation:clahe": -1.0, |
| "augmentation:camera_simulation": -0.8, |
| "feature_engineering:tfidf_features": -1.0, |
| "feature_engineering:target_encoding": -0.7, |
| } |
|
|
| return TaskDefinition( |
| task_id="trajectory_pred", |
| title="Multi-Agent Trajectory Prediction", |
| difficulty="hard", |
| description=( |
| "Predict future (x,y) positions of multiple interacting agents in " |
| "driving scenes. Requires spatial-temporal encoding, rotation-invariant " |
| "processing, multi-agent interaction modeling, and physics-aware predictions." |
| ), |
| dataset_metadata=DatasetMetadata( |
| num_rows=500000, num_features=10, columns=columns, |
| target_column="future_x,future_y", task_type="regression", |
| has_time_column=True, has_group_column=True, |
| has_spatial_data=True, |
| ), |
| dataset_properties=props, |
| base_cv_score=0.32, |
| base_test_score=0.28, |
| expected_strategies=[ |
| "set_cv:group_kfold", |
| "feature_engineering:sin_cos_encoding", |
| "feature_engineering:relative_coordinates", |
| "feature_engineering:distance_features", |
| "clean_data:remove_corrupted", |
| "clean_data:remove_outliers", |
| "train_model:transformer_encoder", |
| "train_model:temporal_cnn", |
| "augmentation:rotation_invariant", |
| "augmentation:symmetry_augmentation", |
| "augmentation:temporal_augmentation", |
| "tune_loss:gaussian_nll", |
| "tune_loss:auxiliary_physics_loss", |
| "regularize:ema", |
| "ensemble:multi_seed_averaging", |
| "postprocess:physics_constraints", |
| ], |
| ghost_scores=[0.89, 0.86, 0.83, 0.80, 0.76, 0.71, 0.66, 0.60, 0.52], |
| hints=[ |
| "Group k-fold by scene_id — prevents leaking scene-specific patterns.", |
| "Encode heading with sin/cos — raw angles wrap around and mislead models.", |
| "Use relative coordinates instead of absolute positions.", |
| "Distance features to nearby agents help interaction modeling.", |
| "Remove scenes with abnormal sequence lengths.", |
| "Transformer encoders capture multi-agent interactions best.", |
| "Temporal CNN with gradual pooling works well for positional time series.", |
| "Rotation-invariant augmentation: rotate scene, preserve relative positions.", |
| "Gaussian NLL lets the model express uncertainty per prediction.", |
| "Auxiliary physics loss: penalise unrealistic acceleration/jerk.", |
| "Physics post-processing: clamp velocity, smooth jerk, enforce kinematic limits.", |
| ], |
| score_modifiers={ |
| "set_cv:kfold": {"cv": 0.06, "test": -0.02}, |
| "set_cv:group_kfold": {"cv": 0.04, "test": 0.08}, |
| "feature_engineering:sin_cos_encoding": {"cv": 0.04, "test": 0.05}, |
| "feature_engineering:relative_coordinates": {"cv": 0.05, "test": 0.06}, |
| "feature_engineering:distance_features": {"cv": 0.04, "test": 0.05}, |
| "feature_engineering:normalize": {"cv": 0.02, "test": 0.02}, |
| "feature_engineering:spatial_encoding": {"cv": 0.03, "test": 0.03}, |
| "clean_data:remove_corrupted": {"cv": 0.02, "test": 0.03}, |
| "clean_data:remove_outliers": {"cv": 0.02, "test": 0.03}, |
| "train_model:transformer_encoder": {"cv": 0.18, "test": 0.17}, |
| "train_model:temporal_cnn": {"cv": 0.16, "test": 0.15}, |
| "train_model:neural_network": {"cv": 0.12, "test": 0.10}, |
| "train_model:xgboost": {"cv": 0.04, "test": -0.03}, |
| "train_model:linear": {"cv": 0.02, "test": 0.02}, |
| "augmentation:rotation_invariant": {"cv": 0.04, "test": 0.05}, |
| "augmentation:symmetry_augmentation": {"cv": 0.03, "test": 0.04}, |
| "augmentation:temporal_augmentation": {"cv": 0.03, "test": 0.04}, |
| "tune_loss:gaussian_nll": {"cv": 0.04, "test": 0.05}, |
| "tune_loss:auxiliary_physics_loss": {"cv": 0.03, "test": 0.05}, |
| "tune_loss:multi_task": {"cv": 0.02, "test": 0.03}, |
| "regularize:ema": {"cv": 0.03, "test": 0.04}, |
| "regularize:dropout": {"cv": 0.01, "test": 0.02}, |
| "ensemble:multi_seed_averaging": {"cv": 0.03, "test": 0.04}, |
| "ensemble:swa": {"cv": 0.02, "test": 0.03}, |
| "ensemble:heterogeneous": {"cv": 0.04, "test": 0.04}, |
| "postprocess:physics_constraints": {"cv": 0.03, "test": 0.05}, |
| "postprocess:tta": {"cv": 0.02, "test": 0.02}, |
| "pseudo_label:1": {"cv": 0.02, "test": 0.01}, |
| "inspect_top_solution": {"cv": 0.0, "test": 0.0}, |
| }, |
| overfitting_risk={ |
| "set_cv:kfold": 0.08, |
| "train_model:xgboost": 0.07, |
| }, |
| strategy_combos=[ |
| StrategyComboDef( |
| name="spatial_encoding_suite", |
| required=frozenset({ |
| "feature_engineering:sin_cos_encoding", |
| "feature_engineering:relative_coordinates", |
| "feature_engineering:distance_features", |
| }), |
| cv_bonus=0.03, test_bonus=0.05, |
| ), |
| StrategyComboDef( |
| name="geometric_augmentation_suite", |
| required=frozenset({ |
| "augmentation:rotation_invariant", |
| "augmentation:symmetry_augmentation", |
| "augmentation:temporal_augmentation", |
| }), |
| cv_bonus=0.03, test_bonus=0.05, |
| ), |
| StrategyComboDef( |
| name="physics_aware_training", |
| required=frozenset({ |
| "tune_loss:gaussian_nll", |
| "tune_loss:auxiliary_physics_loss", |
| "postprocess:physics_constraints", |
| }), |
| cv_bonus=0.03, test_bonus=0.06, |
| ), |
| StrategyComboDef( |
| name="stable_training", |
| required=frozenset({ |
| "regularize:ema", "ensemble:multi_seed_averaging", |
| }), |
| cv_bonus=0.02, test_bonus=0.03, |
| ), |
| ], |
| failure_modes=failure_modes, |
| context_relevance=context_relevance, |
| max_steps=30, |
| ) |
|
|
|
|
| |
| |
| |
|
|
| TASK_REGISTRY: dict[str, TaskDefinition] = { |
| "easy_churn": _easy_task(), |
| "medium_fraud": _medium_task(), |
| "hard_leaky_noisy": _hard_task(), |
| "image_quality": _image_task(), |
| "trajectory_pred": _trajectory_task(), |
| } |
|
|
|
|
| def get_task(task_id: str) -> TaskDefinition: |
| if task_id not in TASK_REGISTRY: |
| raise ValueError( |
| f"Unknown task '{task_id}'. Available: {list(TASK_REGISTRY.keys())}" |
| ) |
| return TASK_REGISTRY[task_id] |
|
|