Skip to main content

very-simple-fela

Feature engineering skill for taobao/dia AUC maximization. Provides dataset-specific domain knowledge and code patterns — no forced pipeline.

Informations de source

Dépôt
Tencent/AdaSkill
Dernière activité de la source
14 avril 2026 à 07:44
Langue détectée de SKILL.md
anglais
Étoiles
2
Forks
1

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
very_simple_fela
description
Feature engineering skill for taobao/dia AUC maximization. Provides dataset-specific domain knowledge and code patterns — no forced pipeline.
version
1.2.0
# Feature Engineering: Knowledge + Patterns You are a feature engineering expert optimizing AUC on a tabular benchmark. Use the knowledge below however makes sense — there is no required workflow. Simple ideas may need one evaluation; complex ones may need systematic ablation. Your goal: maximize AUC by iteratively building and evaluating feature sets via `bench.evaluate(features_list)`. Stop when AUC stops improving (implement early-stop in your code). **First: detect which dataset you are on** by checking `bench.dataset` (returns `'taobao'` or `'dia'`). Use the corresponding section below. Inspect `bench.feature_columns_original` and `bench.X_train.dtypes` to understand the actual schema — do not rely on skill hardcoded names. --- ## Benchmark API ```python import sys sys.path.insert(0, "benchmarks/feature_engineering") # relative to AdaSkill project root from feature_engineering import Benchmark, BenchmarkLimitReached bench = Benchmark(dataset='<taobao or dia>', work_dir='<provided in prompt>', max_evaluations=500) orig = bench.feature_columns_original.copy() # inspect this first dataset = bench.dataset # 'taobao' or 'dia' # Evaluate auc = bench.evaluate(features_list) # returns float AUC; raises BenchmarkLimitReached ``` **Non-negotiable rules:** - Always modify **both** `bench.X_train` and `bench.X_test` when adding features - For Taobao: compute CVR/count features from `train_hist` / `valid_hist` — never from X_train/X_test labels - For Dia: all features derived directly from `bench.X_train` / `bench.X_test` columns (no history log) - `fillna()` every new column before calling `evaluate()` - Pass only columns that exist in `bench.X_train` to `evaluate()` **Early-stop (implement this in your code):** ```python best_auc, no_improve = 0.0, 0 PATIENCE = 30 # from --early-stop arg passed in prompt while True: auc = bench.evaluate(features) if auc > best_auc: best_auc = auc no_improve = 0 else: no_improve += 1 if no_improve >= PATIENCE: break ``` --- ## Taobao Dataset Ad conversion prediction. Target column indicates whether a purchase occurred (~1.9% positive rate). The dataset contains features in these semantic groups — inspect the actual column names via `bench.feature_columns_original`: - **User entity**: user ID, demographic attributes (age level, gender, occupation, star level) - **Item entity**: item ID, category, brand, city, price level, sales level, collection level, page-view level, property count - **Shop entity**: shop ID, review count level, positive review rate, star level, service/delivery/description scores - **Context**: timestamp, page ID (extracted hour and day are also available) - **Prediction signal**: predicted category/property match features **Time split:** history log covers a train window and a validation window (sequential days). ```python train_hist = bench.train_history_df # history log — safe to use (no leakage) valid_hist = bench.valid_history_df TARGET = bench.target_column # purchase indicator column name G_CVR = train_hist[TARGET].mean() G_CVR_V = valid_hist[TARGET].mean() ``` ### Taobao: Feature Engineering Directions This is a sparse, high-cardinality CTR/CVR prediction task. The most valuable signal comes from **behavioral statistics** computed from the history log. **Productive directions:** - **Entity CVR**: For each entity type (user, item, shop, category, brand), compute its historical conversion rate from the history log. Bayesian smoothing prevents overfitting on rare entities. - **Interaction CVR**: CVR conditioned on two entities jointly (e.g., user × category, user × shop) captures preference alignment beyond marginal rates. - **Frequency/activity counts**: How often does each entity appear in history? Log-transform these — count distributions are heavy-tailed. - **Price deviation**: Whether this item is cheap or expensive relative to what this user typically sees — captures price sensitivity. - **Quality composites**: The item has multiple popularity-related ordinal features (sales, collection, page-views); combining them into a single composite reduces noise. Similarly for shop quality scores. - **Temporal features**: Hour of day and day extracted from the timestamp — useful when combined with CVR, weak alone. ### Taobao: Code Patterns ```python # Bayesian-smoothed CVR — core pattern for any high-cardinality entity column def add_cvr(key_col, feat_name, k=20): """k controls smoothing: larger k = more shrinkage toward global mean. Use larger k for 1-way, smaller k for 2-way (fewer samples per cell).""" def _cvr(hist, g): s = hist.groupby(key_col)[TARGET].agg(['sum', 'count']) s['v'] = (s['sum'] + k * g) / (s['count'] + k) return s['v'].to_dict() tr = _cvr(train_hist, G_CVR) va = _cvr(valid_hist, G_CVR_V) bench.X_train[feat_name] = bench.X_train[key_col].map(tr).fillna(G_CVR) bench.X_test[feat_name] = bench.X_test[key_col].map(va).fillna(G_CVR_V) # Log-count frequency — how active is this entity in history? def add_count(key_col, feat_name): tr = train_hist[key_col].value_counts().apply(np.log1p).to_dict() va = valid_hist[key_col].value_counts().apply(np.log1p).to_dict() bench.X_train[feat_name] = bench.X_train[key_col].map(tr).fillna(0) bench.X_test[feat_name] = bench.X_test[key_col].map(va).fillna(0) # Numeric aggregation from history (e.g., user's average price preference) def add_agg(group_col, value_col, agg_fn, feat_name): tr = train_hist.groupby(group_col)[value_col].agg(agg_fn).to_dict() va = valid_hist.groupby(group_col)[value_col].agg(agg_fn).to_dict() fb_tr = train_hist[value_col].agg(agg_fn) fb_va = valid_hist[value_col].agg(agg_fn) bench.X_train[feat_name] = bench.X_train[group_col].map(tr).fillna(fb_tr) bench.X_test[feat_name] = bench.X_test[group_col].map(va).fillna(fb_va) # Cross-feature product of two CVR signals # bench.X_train['user_x_cat_cvr'] = bench.X_train['user_cvr'] * bench.X_train['cat_cvr'] # bench.X_test['user_x_cat_cvr'] = bench.X_test['user_cvr'] * bench.X_test['cat_cvr'] ``` ### Taobao: Engineering Principles 1. **Raw high-cardinality ID columns become redundant once you have their CVR.** The entity ID columns (user, item, shop, brand, city) as raw integers carry almost no signal for tree models once their corresponding CVR features are computed. Explicitly exclude them from `FEATURES` — keeping them adds noise. This is a standard principle in CTR feature engineering, not dataset-specific. 2. **Ratio/division needs protection.** Always use `denominator + 1e-6`. Groupby means on sparse keys: fillna with global mean. 3. **Log-transform count features.** Raw counts are heavy-tailed and hurt model calibration. 4. **Smoothing strength scales with data density.** Denser keys tolerate less smoothing; sparse 2-way combination keys need more smoothing. 5. **Composite scores reduce noise.** Summing a group of related ordinal features is usually better than using each separately. 6. **Ablate from a strong set.** Once you have a promising feature set, try removing features one at a time — lean sets often generalize better. --- ## Dia Dataset Diabetes risk prediction based on a health survey. Target column is a binary diabetes indicator. All original features are binary (0/1) or low-cardinality ordinal integers. **No history log — all features derived directly from X_train/X_test columns.** Inspect the actual column names via `bench.feature_columns_original`. The dataset contains features in these semantic groups: - **Metabolic/cardiovascular risk indicators**: binary flags for high blood pressure, high cholesterol, cholesterol check, heart disease/attack history, stroke history - **BMI**: continuous body mass index - **Lifestyle behaviors**: binary flags for smoking, physical activity, fruit/vegetable consumption, heavy alcohol consumption - **Healthcare access**: binary flags for healthcare coverage, cost-related doctor avoidance - **Functional health**: ordinal general health status (1–5), days of poor physical/mental health (0–30), walking difficulty - **Sociodemographic**: sex (binary), age category (ordinal), education level (ordinal), income level (ordinal) ### Dia: Feature Engineering Directions The original features are already clinically meaningful, so gains come from **capturing non-linearity and interactions** between them. **Productive directions:** - **BMI non-linearity**: BMI has well-known clinical thresholds (overweight ≥25, obese ≥30) with a non-linear relationship to metabolic risk. Threshold indicators and polynomial terms capture this. - **Cardiovascular composite**: Blood pressure, heart disease, stroke, and cholesterol indicators share common pathological mechanisms (insulin resistance, inflammation). Summing them into a composite score can be more informative than using each separately. - **Lifestyle composite**: Smoking, physical inactivity, heavy alcohol, and poor diet interact synergistically — a cumulative unhealthy lifestyle score captures joint behavioral risk. - **Health burden composite**: General health status, days of poor physical/mental health, and walking difficulty all reflect functional health — combining them is a natural direction. - **Target encoding of ordinals**: Age, general health, income, and education are ordinal but their relationship with diabetes risk may not be strictly linear. Cross-validated target encoding captures the true pattern without leakage. - **Pairwise interaction encodings**: Combinations of age × general health, age × blood pressure, etc. may capture interaction effects worth encoding via cross-validated target encoding. - **Socioeconomic interactions**: Income, education, and healthcare access interact — lower socioeconomic status affects both lifestyle choices and medical access. - **Age × sex interaction**: Diabetes risk has different age trajectories by sex (e.g., post-menopausal elevated risk). An interaction term can capture this. **Important:** The baseline is already high. Each feature must earn its place. A clean set of 20–30 well-chosen features typically beats 100+ noisy ones. ### Dia: Code Patterns ```python # Cross-validated target encoding — prevents leakage from target variable from sklearn.model_selection import KFold def cv_target_encode(X_tr, X_te, col, y_tr, n_splits=5): """Encode ordinal/categorical column by per-fold mean target rate. KFold prevents target leakage on the training set.""" global_mean = y_tr.mean() kf = KFold(n_splits=n_splits, shuffle=True, random_state=42) train_enc = np.zeros(len(X_tr)) for tr_idx, val_idx in kf.split(X_tr): fold_mean = (X_tr.iloc[tr_idx] .assign(_y=y_tr.iloc[tr_idx]) .groupby(col)['_y'].mean()) train_enc[val_idx] = X_tr.iloc[val_idx][col].map(fold_mean).fillna(global_mean) full_mean = X_tr.assign(_y=y_tr).groupby(col)['_y'].mean() test_enc = X_te[col].map(full_mean).fillna(global_mean) return train_enc, test_enc y_train = bench.y_train # target labels — safe to use for computing train-side encodings # Encode ordinal columns by their mean target rate (identify them from bench.feature_columns_original) # for col in <ordinal columns>: # tr_enc, te_enc = cv_target_encode(bench.X_train, bench.X_test, col, y_train) # bench.X_train[f'{col}_te'] = tr_enc # bench.X_test[f'{col}_te'] = te_enc # BMI threshold indicators (WHO/CDC clinical standards — not data-derived) # for df in [bench.X_train, bench.X_test]: # df['bmi_overweight'] = (df[bmi_col] >= 25).astype(int) # df['bmi_obese'] = (df[bmi_col] >= 30).astype(int) # df['bmi_sq'] = df[bmi_col] ** 2 # Composite scores — sum binary indicators that share a clinical mechanism # for df in [bench.X_train, bench.X_test]: # df['cardio_composite'] = df[bp_col] + df[heart_col] + df[stroke_col] + df[chol_col] # df['lifestyle_risk'] = df[smoker_col] + (1 - df[activity_col]) + df[alcohol_col] + ... # df['health_burden'] = df[physhlth_col] + df[menthlth_col] + df[diffwalk_col] * 5 # Polynomial terms for non-linear ordinals # for df in [bench.X_train, bench.X_test]: # df['age_sq'] = df[age_col] ** 2 # df['genhlth_sq'] = df[genhlth_col] ** 2 # df['age_x_genhlth'] = df[age_col] * df[genhlth_col] # Interaction target encoding: build combo key, encode, drop string column # for col_a, col_b in [<pair1>, <pair2>]: # combo = f'{col_a}_x_{col_b}' # bench.X_train[combo] = bench.X_train[col_a].astype(str) + '_' + bench.X_train[col_b].astype(str) # bench.X_test[combo] = bench.X_test[col_a].astype(str) + '_' + bench.X_test[col_b].astype(str) # tr_enc, te_enc = cv_target_encode(bench.X_train, bench.X_test, combo, y_train) # bench.X_train[f'{combo}_te'] = tr_enc # bench.X_test[f'{combo}_te'] = te_enc # bench.X_train.drop(columns=[combo], inplace=True) # bench.X_test.drop(columns=[combo], inplace=True) ``` ### Dia: Engineering Principles 1. **Always use KFold target encoding, never fit-on-full-train.** Encoding ordinals without cross-validation leaks the target into training features and inflates AUC artificially. 2. **BMI thresholds are clinically grounded, not data-mined.** The ≥25 (overweight) and ≥30 (obese) cutoffs come from WHO/CDC standards. 3. **Composite scores capture synergy.** Multiple co-occurring risk factors (cardiovascular, lifestyle) have cumulative effects — a sum composite is often more informative than each factor individually. 4. **Log-transform day-count features.** The 0–30 count features for days of poor health are right-skewed; log1p stabilizes variance. 5. **Non-linearity in ordinals matters.** Age and general health status have non-linear effects; squared terms and target encoding both worth trying. 6. **Lean sets outperform large ones here.** The baseline is already high; noise features actively hurt. Test removal of features that don't contribute. 7. **Ratio features need protection.** Any division: use `denominator + 1e-6`.
Voir sur GitHub