first commit
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
# CV Knowledge Base
|
||||
|
||||
> Last updated: 2026-01-21
|
||||
> Source count: 0
|
||||
|
||||
## Original Summaries
|
||||
_No sources yet._
|
||||
|
||||
## Code Templates
|
||||
_No templates yet._
|
||||
|
||||
## Best Practices
|
||||
_No practices yet._
|
||||
|
||||
## Metadata
|
||||
| Source | Date | Tags |
|
||||
|--------|------|------|
|
||||
@@ -0,0 +1,17 @@
|
||||
# Multimodal Knowledge Base
|
||||
|
||||
> Last updated: 2026-01-21
|
||||
> Source count: 0
|
||||
|
||||
## Original Summaries
|
||||
_No sources yet._
|
||||
|
||||
## Code Templates
|
||||
_No templates yet._
|
||||
|
||||
## Best Practices
|
||||
_No practices yet._
|
||||
|
||||
## Metadata
|
||||
| Source | Date | Tags |
|
||||
|--------|------|------|
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,829 @@
|
||||
# Tabular Knowledge Base
|
||||
|
||||
> Last updated: 2025-01-22
|
||||
> Source count: 1
|
||||
|
||||
## Original Summaries
|
||||
|
||||
### CMI - Problematic Internet Use (2024) - 2025-01-22
|
||||
**Source:** [Kaggle Competition](https://www.kaggle.com/competitions/child-mind-institute-problematic-internet-use)
|
||||
**Category:** Tabular (表格数据 + 时序混合)
|
||||
**Key Techniques:**
|
||||
- **中间分数预测**:预测 PCIAT-PCIAT_Total 而非直接预测 sii
|
||||
- **多seed平均**:减少seed引起的方差
|
||||
- **高fold交叉验证**:10-fold stratified KFold
|
||||
- **Pseudo Labeling**:填充缺失target
|
||||
- **GBM主导的集成**:LGBM + XGBoost + CatBoost
|
||||
- **Tweedie Loss**:处理偏态分布
|
||||
- **时序特征工程**:k-means聚类
|
||||
- **特征清洗**:去除异常特征、PCA降维
|
||||
|
||||
**Results:** 多seed平均、预测中间分数、Pseudo Labeling 是关键技术
|
||||
|
||||
---
|
||||
|
||||
## Competition Brief (竞赛简介)
|
||||
|
||||
### CMI - Problematic Internet Use (2024)
|
||||
|
||||
**竞赛背景:**
|
||||
- **主办方**:Child Mind Institute
|
||||
- **目标**:预测儿童和青少年的问题性网络使用严重程度(sii)
|
||||
- **应用场景**:理解与抑郁和焦虑等心理健康问题相关的网络使用行为
|
||||
|
||||
**数据集规模:**
|
||||
- 总样本数:约 3,900+(训练集)
|
||||
- 特征:表格数据 + 部分时序数据
|
||||
- 类别:4 分类(sii = 0, 1, 2, 3)
|
||||
|
||||
**数据特点:**
|
||||
1. **混合数据类型**:表格数据(身体活动、健康指标)+ 时序数据
|
||||
2. **target 缺失**:训练集中部分样本的 sii 缺失
|
||||
3. **中间分数**:PCIAT-PCIAT_Total 是 sii 的连续分数版本
|
||||
4. **类别分布不均**:约 58.3% 为 0 类(无问题)
|
||||
|
||||
**评估指标:**
|
||||
- **Quadratic Weighted Kappa (QWK)**:衡量预测与实际的一致性
|
||||
- 分数范围:-1 到 1,越高越好
|
||||
- 特点:对分类错误的惩罚与严重程度成正比
|
||||
|
||||
**关键挑战:**
|
||||
1. **Seed 敏感**:不同 seed 导致 LB 分数剧烈波动
|
||||
2. **数据泄露**:公开 notebook 泄露了训练数据
|
||||
3. **LB 不可靠**:Private LB 大幅 shake(波动)
|
||||
4. **Target 缺失**:需要 Pseudo Labeling 处理
|
||||
|
||||
---
|
||||
|
||||
## Code Templates
|
||||
|
||||
### 中间分数预测 (PCIAT-PCIAT_Total)
|
||||
|
||||
**关键洞察:** 预测连续分数比直接预测类别更有效
|
||||
|
||||
```python
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
from lightgbm import LGBMRegressor
|
||||
from sklearn.model_selection import StratifiedKFold
|
||||
|
||||
# 原始 sii 标签: 0, 1, 2, 3
|
||||
# PCIAT-PCIAT_Total: 连续分数 (0-100)
|
||||
|
||||
def train_intermediate_target_model(X_train, y_train_total, X_test):
|
||||
"""
|
||||
预测 PCIAT-PCIAT_Total (中间分数),然后转换为 sii
|
||||
"""
|
||||
# 根据 sii 创建分层的 bins
|
||||
# 这确保每个 fold 中各类别比例一致
|
||||
train_df = X_train.copy()
|
||||
train_df['sii'] = (y_train_total > 30).astype(int) + \
|
||||
(y_train_total > 50).astype(int) + \
|
||||
(y_train_total > 80).astype(int)
|
||||
|
||||
# 10-fold stratified KFold
|
||||
n_folds = 10
|
||||
skf = StratifiedKFold(n_splits=n_folds, shuffle=True, random_state=42)
|
||||
|
||||
# 存储预测结果
|
||||
oof_preds = np.zeros(len(X_train))
|
||||
test_preds = np.zeros(len(X_test))
|
||||
|
||||
for fold, (train_idx, val_idx) in enumerate(skf.split(X_train, train_df['sii'])):
|
||||
X_tr, X_val = X_train.iloc[train_idx], X_train.iloc[val_idx]
|
||||
y_tr, y_val = y_train_total.iloc[train_idx], y_train_total.iloc[val_idx]
|
||||
|
||||
# LightGBM 回归器
|
||||
model = LGBMRegressor(
|
||||
n_estimators=1000,
|
||||
learning_rate=0.05,
|
||||
num_leaves=31,
|
||||
max_depth=-1,
|
||||
random_state=42 + fold # 每个 fold 不同 seed
|
||||
)
|
||||
|
||||
model.fit(X_tr, y_tr, eval_set=[(X_val, y_val)],
|
||||
early_stopping_rounds=100, verbose=False)
|
||||
|
||||
# 预测中间分数
|
||||
oof_preds[val_idx] = model.predict(X_val)
|
||||
test_preds += model.predict(X_test) / n_folds
|
||||
|
||||
return oof_preds, test_preds
|
||||
|
||||
def convert_total_to_sii(pred_total):
|
||||
"""
|
||||
将 PCIAT-PCIAT_Total 转换为 sii 标签
|
||||
阈值: 0-30→0, 31-50→1, 51-80→2, 81-100→3
|
||||
"""
|
||||
pred_sii = np.zeros(len(pred_total))
|
||||
pred_sii[pred_total > 30] = 1
|
||||
pred_sii[pred_total > 50] = 2
|
||||
pred_sii[pred_total > 80] = 3
|
||||
return pred_sii.astype(int)
|
||||
```
|
||||
|
||||
### 多 Seed 平均
|
||||
|
||||
**关键洞察:** 多个 seed 平均可以减少预测方差
|
||||
|
||||
```python
|
||||
import numpy as np
|
||||
from lightgbm import LGBMRegressor
|
||||
|
||||
def multi_seed_prediction(X_train, y_train, X_test, seeds=[42, 123, 456, 789, 1011]):
|
||||
"""
|
||||
多个 seed 训练模型,取平均预测
|
||||
"""
|
||||
test_preds_all = []
|
||||
|
||||
for seed in seeds:
|
||||
model = LGBMRegressor(
|
||||
n_estimators=1000,
|
||||
learning_rate=0.05,
|
||||
random_state=seed
|
||||
)
|
||||
|
||||
model.fit(X_train, y_train)
|
||||
test_preds_all.append(model.predict(X_test))
|
||||
|
||||
# 平均预测
|
||||
test_preds_mean = np.mean(test_preds_all, axis=0)
|
||||
|
||||
return test_preds_mean
|
||||
|
||||
# 更进一步:多 fold × 多 seed
|
||||
def multi_fold_multi_seed(X_train, y_train, X_test, n_folds=5, seeds=10):
|
||||
"""
|
||||
多 fold × 多 seed = 更稳定的预测
|
||||
"""
|
||||
n_folds = 5
|
||||
seeds = list(range(10)) # 10 个 seeds
|
||||
|
||||
test_preds = []
|
||||
|
||||
for seed in seeds:
|
||||
for fold in range(n_folds):
|
||||
model = LGBMRegressor(
|
||||
n_estimators=1000,
|
||||
random_state=seed + fold * 100
|
||||
)
|
||||
# ... train and predict
|
||||
test_preds.append(model.predict(X_test))
|
||||
|
||||
# 50 个模型的平均 (5 folds × 10 seeds)
|
||||
return np.mean(test_preds, axis=0)
|
||||
```
|
||||
|
||||
### Pseudo Labeling
|
||||
|
||||
**关键洞察:** 用模型预测填充缺失的 target
|
||||
|
||||
```python
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
def pseudo_labeling(X_train, y_train, X_missing, n_iterations=3):
|
||||
"""
|
||||
Pseudo Labeling 迭代填充缺失 target
|
||||
"""
|
||||
# 分割有标签和无标签数据
|
||||
has_label = ~y_train.isna()
|
||||
X_labeled = X_train[has_label]
|
||||
y_labeled = y_train[has_label]
|
||||
X_unlabeled = X_train[~has_label]
|
||||
|
||||
# 初始模型(仅用有标签数据训练)
|
||||
model = LGBMRegressor(random_state=42)
|
||||
model.fit(X_labeled, y_labeled)
|
||||
|
||||
# 迭代预测和训练
|
||||
for iteration in range(n_iterations):
|
||||
# 预测无标签数据
|
||||
pseudo_labels = model.predict(X_unlabeled)
|
||||
|
||||
# 合并有标签和伪标签数据
|
||||
X_combined = pd.concat([X_labeled, X_unlabeled])
|
||||
y_combined = pd.concat([y_labeled, pd.Series(pseudo_labels, index=X_unlabeled.index)])
|
||||
|
||||
# 重新训练模型
|
||||
model = LGBMRegressor(random_state=42 + iteration)
|
||||
model.fit(X_combined, y_combined)
|
||||
|
||||
return model
|
||||
|
||||
# 注意:CV 计算时不使用 pseudo labels
|
||||
def cv_with_pseudo(X_train, y_train, X_missing):
|
||||
"""
|
||||
交叉验证时不使用 pseudo labels
|
||||
"""
|
||||
has_label = ~y_train.isna()
|
||||
X_labeled = X_train[has_label]
|
||||
y_labeled = y_train[has_label]
|
||||
|
||||
# 训练 pseudo 模型(用于最终预测)
|
||||
pseudo_model = pseudo_labeling(X_train, y_train, X_missing)
|
||||
|
||||
# CV 仅用有标签数据
|
||||
from sklearn.model_selection import cross_val_score
|
||||
cv_model = LGBMRegressor(random_state=42)
|
||||
cv_scores = cross_val_score(cv_model, X_labeled, y_labeled, cv=5)
|
||||
|
||||
return pseudo_model, cv_scores
|
||||
```
|
||||
|
||||
### Tweedie Loss
|
||||
|
||||
**关键洞察:** 处理偏态分布的目标变量
|
||||
|
||||
```python
|
||||
import lightgbm as lgb
|
||||
|
||||
def train_with_tweedie_loss(X_train, y_train, X_val, y_val):
|
||||
"""
|
||||
使用 Tweedie Loss 训练 LightGBM
|
||||
适用于偏态分布(如保险索赔、疾病严重程度)
|
||||
"""
|
||||
train_data = lgb.Dataset(X_train, label=y_train)
|
||||
val_data = lgb.Dataset(X_val, label=y_val, reference=train_data)
|
||||
|
||||
params = {
|
||||
'objective': 'tweedie',
|
||||
'tweedie_variance_power': 1.5, # 1 < p < 2,控制偏态程度
|
||||
'metric': 'rmse',
|
||||
'learning_rate': 0.05,
|
||||
'num_leaves': 31,
|
||||
'max_depth': -1,
|
||||
'verbose': -1
|
||||
}
|
||||
|
||||
model = lgb.train(
|
||||
params,
|
||||
train_data,
|
||||
num_boost_round=1000,
|
||||
valid_sets=[val_data],
|
||||
early_stopping_rounds=100,
|
||||
verbose_eval=False
|
||||
)
|
||||
|
||||
return model
|
||||
```
|
||||
|
||||
### 时序特征 k-means 聚类
|
||||
|
||||
**关键洞察:** 将时序数据聚类成类别特征
|
||||
|
||||
```python
|
||||
import numpy as np
|
||||
from sklearn.cluster import KMeans
|
||||
from sklearn.preprocessing import StandardScaler
|
||||
|
||||
def extract_time_series_cluster_features(time_series_data, n_clusters=5):
|
||||
"""
|
||||
时序数据 k-means 聚类作为特征
|
||||
"""
|
||||
# 假设 time_series_data 是 (n_samples, n_timesteps, n_features)
|
||||
n_samples = time_series_data.shape[0]
|
||||
|
||||
# 展平时序数据: (n_samples, n_timesteps * n_features)
|
||||
ts_flat = time_series_data.reshape(n_samples, -1)
|
||||
|
||||
# 标准化
|
||||
scaler = StandardScaler()
|
||||
ts_scaled = scaler.fit_transform(ts_flat)
|
||||
|
||||
# k-means 聚类
|
||||
kmeans = KMeans(n_clusters=n_clusters, random_state=42, n_init=10)
|
||||
cluster_labels = kmeans.fit_predict(ts_scaled)
|
||||
|
||||
# 聚类距离作为特征
|
||||
cluster_distances = kmeans.transform(ts_scaled)
|
||||
|
||||
# 创建特征 DataFrame
|
||||
cluster_features = pd.DataFrame({
|
||||
f'ts_cluster_dist_{i}': cluster_distances[:, i]
|
||||
for i in range(n_clusters)
|
||||
})
|
||||
cluster_features['ts_cluster_label'] = cluster_labels
|
||||
|
||||
return cluster_features
|
||||
|
||||
# 使用示例
|
||||
# time_series_data 是原始时序数据
|
||||
# cluster_features = extract_time_series_cluster_features(time_series_data)
|
||||
# X_final = pd.concat([tabular_features, cluster_features], axis=1)
|
||||
```
|
||||
|
||||
### 特征清洗和 PCA 降维
|
||||
|
||||
**关键洞察:** 去除异常特征,PCA 降维减少噪声
|
||||
|
||||
```python
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
from sklearn.decomposition import PCA
|
||||
from sklearn.preprocessing import StandardScaler
|
||||
|
||||
def clean_features(X, threshold=0.99):
|
||||
"""
|
||||
清洗异常特征
|
||||
- 去除高度相关的特征
|
||||
- 去除方差过小的特征
|
||||
"""
|
||||
# 计算相关性矩阵
|
||||
corr_matrix = X.corr().abs()
|
||||
|
||||
# 找到高度相关的特征对
|
||||
upper_tri = corr_matrix.where(
|
||||
np.triu(np.ones(corr_matrix.shape), k=1).astype(bool)
|
||||
)
|
||||
|
||||
# 找出相关性 > threshold 的特征
|
||||
to_drop = [column for column in upper_tri.columns if any(upper_tri[column] > threshold)]
|
||||
|
||||
# 去除高度相关的特征
|
||||
X_cleaned = X.drop(columns=to_drop)
|
||||
|
||||
return X_cleaned, to_drop
|
||||
|
||||
def pca_reduction(X_train, X_test, variance_ratio=0.95):
|
||||
"""
|
||||
PCA 降维
|
||||
"""
|
||||
# 标准化
|
||||
scaler = StandardScaler()
|
||||
X_train_scaled = scaler.fit_transform(X_train)
|
||||
X_test_scaled = scaler.transform(X_test)
|
||||
|
||||
# PCA
|
||||
pca = PCA(n_components=variance_ratio)
|
||||
X_train_pca = pca.fit_transform(X_train_scaled)
|
||||
X_test_pca = pca.transform(X_test_scaled)
|
||||
|
||||
print(f"Original features: {X_train.shape[1]}")
|
||||
print(f"PCA components: {X_train_pca.shape[1]}")
|
||||
print(f"Variance explained: {pca.explained_variance_ratio_.sum():.4f}")
|
||||
|
||||
return X_train_pca, X_test_pca, pca
|
||||
```
|
||||
|
||||
### GBM Ensemble (LGBM + XGBoost + CatBoost)
|
||||
|
||||
**关键洞察:** 不同 GBM 的集成提升稳定性
|
||||
|
||||
```python
|
||||
import numpy as np
|
||||
from lightgbm import LGBMRegressor
|
||||
from xgboost import XGBRegressor
|
||||
from catboost import CatBoostRegressor
|
||||
|
||||
def train_gbm_ensemble(X_train, y_train, X_test):
|
||||
"""
|
||||
训练 GBM 集成: LGBM + XGBoost + CatBoost
|
||||
"""
|
||||
models = []
|
||||
test_preds = []
|
||||
|
||||
# 1. LightGBM
|
||||
lgbm = LGBMRegressor(
|
||||
n_estimators=1000,
|
||||
learning_rate=0.05,
|
||||
num_leaves=31,
|
||||
max_depth=-1,
|
||||
random_state=42,
|
||||
verbose=-1
|
||||
)
|
||||
lgbm.fit(X_train, y_train)
|
||||
models.append(lgbm)
|
||||
test_preds.append(lgbm.predict(X_test))
|
||||
|
||||
# 2. XGBoost
|
||||
xgb = XGBRegressor(
|
||||
n_estimators=1000,
|
||||
learning_rate=0.05,
|
||||
max_depth=6,
|
||||
random_state=42,
|
||||
verbosity=0
|
||||
)
|
||||
xgb.fit(X_train, y_train)
|
||||
models.append(xgb)
|
||||
test_preds.append(xgb.predict(X_test))
|
||||
|
||||
# 3. CatBoost
|
||||
cat = CatBoostRegressor(
|
||||
iterations=1000,
|
||||
learning_rate=0.05,
|
||||
depth=6,
|
||||
random_state=42,
|
||||
verbose=False
|
||||
)
|
||||
cat.fit(X_train, y_train)
|
||||
models.append(cat)
|
||||
test_preds.append(cat.predict(X_test))
|
||||
|
||||
# 简单平均
|
||||
ensemble_pred = np.mean(test_preds, axis=0)
|
||||
|
||||
return models, ensemble_pred
|
||||
|
||||
# 带权重的集成
|
||||
def weighted_gbm_ensemble(X_train, y_train, X_test, weights=[0.4, 0.3, 0.3]):
|
||||
"""
|
||||
带权重的 GBM 集成
|
||||
weights: [lgbm, xgb, cat]
|
||||
"""
|
||||
lgbm = LGBMRegressor(random_state=42, verbose=-1).fit(X_train, y_train)
|
||||
xgb = XGBRegressor(random_state=42, verbosity=0).fit(X_train, y_train)
|
||||
cat = CatBoostRegressor(random_state=42, verbose=False).fit(X_train, y_train)
|
||||
|
||||
pred_lgbm = lgbm.predict(X_test)
|
||||
pred_xgb = xgb.predict(X_test)
|
||||
pred_cat = cat.predict(X_test)
|
||||
|
||||
# 加权平均
|
||||
ensemble_pred = (
|
||||
weights[0] * pred_lgbm +
|
||||
weights[1] * pred_xgb +
|
||||
weights[2] * pred_cat
|
||||
)
|
||||
|
||||
return ensemble_pred
|
||||
```
|
||||
|
||||
### 数据增强(随机 NaN + 高斯噪声)
|
||||
|
||||
**关键洞察:** 添加噪声提高模型鲁棒性
|
||||
|
||||
```python
|
||||
import numpy as np
|
||||
|
||||
def augment_data_with_noise(X_train, y_train, n_augmented=2, nan_ratio=0.1, noise_std=0.01):
|
||||
"""
|
||||
数据增强:随机插入 NaN + 添加高斯噪声
|
||||
"""
|
||||
X_aug_list = [X_train.copy()]
|
||||
y_aug_list = [y_train.copy()]
|
||||
|
||||
for _ in range(n_augmented):
|
||||
X_aug = X_train.copy()
|
||||
|
||||
# 1. 随机插入 NaN
|
||||
mask = np.random.random(X_aug.shape) < nan_ratio
|
||||
X_aug[mask] = np.nan
|
||||
|
||||
# 2. 添加高斯噪声
|
||||
noise = np.random.normal(0, noise_std, X_aug.shape)
|
||||
X_aug = X_aug + noise
|
||||
|
||||
X_aug_list.append(X_aug)
|
||||
y_aug_list.append(y_train.copy())
|
||||
|
||||
# 合并原始数据和增强数据
|
||||
X_final = pd.concat(X_aug_list, axis=0, ignore_index=True)
|
||||
y_final = pd.concat(y_aug_list, axis=0, ignore_index=True)
|
||||
|
||||
return X_final, y_final
|
||||
|
||||
# 使用示例(需要支持 NaN 处理的模型)
|
||||
# X_aug, y_aug = augment_data_with_noise(X_train, y_train)
|
||||
# model = LGBMRegressor().fit(X_aug, y_aug)
|
||||
```
|
||||
|
||||
### 阈值优化(CGAS=80, SDS=35)
|
||||
|
||||
**关键洞察:** 特定健康分数的阈值可预测严重问题
|
||||
|
||||
```python
|
||||
import numpy as np
|
||||
from scipy.optimize import minimize
|
||||
|
||||
def optimize_thresholds(y_true, y_pred_total):
|
||||
"""
|
||||
优化将 PCIAT-PCIAT_Total 转换为 sii 的阈值
|
||||
默认阈值: [30, 50, 80]
|
||||
"""
|
||||
def qwk_loss(thresholds):
|
||||
t1, t2, t3 = thresholds
|
||||
pred_sii = np.zeros(len(y_pred_total))
|
||||
pred_sii[y_pred_total > t1] = 1
|
||||
pred_sii[y_pred_total > t2] = 2
|
||||
pred_sii[y_pred_total > t3] = 3
|
||||
|
||||
# 计算 QWK(简化版本)
|
||||
from sklearn.metrics import cohen_kappa_score
|
||||
kappa = cohen_kappa_score(y_true, pred_sii, weights='quadratic')
|
||||
return -kappa # 最小化负 QWK
|
||||
|
||||
# 初始阈值
|
||||
x0 = [30, 50, 80]
|
||||
|
||||
# 优化(确保 t1 < t2 < t3)
|
||||
bounds = [(0, 40), (40, 60), (60, 100)]
|
||||
constraints = {'type': 'ineq', 'fun': lambda x: x[1] - x[0]}
|
||||
|
||||
result = minimize(qwk_loss, x0, bounds=bounds, constraints=constraints)
|
||||
|
||||
optimal_thresholds = result.x
|
||||
print(f"Optimal thresholds: {optimal_thresholds}")
|
||||
|
||||
return optimal_thresholds
|
||||
|
||||
# 特定阈值的使用(4th Place 发现)
|
||||
def apply_specific_thresholds(pred_total):
|
||||
"""
|
||||
使用特定健康分数阈值
|
||||
CGAS=80, SDS=35 可预测严重问题
|
||||
"""
|
||||
pred_sii = np.zeros(len(pred_total))
|
||||
|
||||
# 默认阈值
|
||||
pred_sii[pred_total > 30] = 1
|
||||
pred_sii[pred_total > 50] = 2
|
||||
pred_sii[pred_total > 80] = 3
|
||||
|
||||
# 特殊情况:如果有 CGAS 或 SDS 数据,结合判断
|
||||
# 这需要原始数据中的这些特征
|
||||
# if has_cgas_data and cgas_score > 80:
|
||||
# pred_sii = 3
|
||||
|
||||
return pred_sii.astype(int)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
### 表格数据竞赛策略
|
||||
|
||||
| 策略 | 何时使用 | 说明 |
|
||||
|------|---------|------|
|
||||
| **预测中间分数** | 有连续分数和类别标签时 | 预测 PCIAT-PCIAT_Total 比直接预测 sii 更有效 |
|
||||
| **多 Seed 平均** | Seed 导致结果波动大时 | 多个 seed 训练,取平均减少方差 |
|
||||
| **高 Fold CV** | 数据量较小或类别不平衡时 | 10-fold stratified KFold 稳定验证 |
|
||||
| **Pseudo Labeling** | Target 有缺失时 | 用模型预测填充缺失 target |
|
||||
| **GBM Ensemble** | 单模型不够稳定时 | LGBM + XGBoost + CatBoost 集成 |
|
||||
| **Tweedie Loss** | 目标变量偏态分布时 | 处理保险、疾病严重程度等偏态数据 |
|
||||
| **时序聚类特征** | 有时序数据时 | k-means 聚类将时序转为类别特征 |
|
||||
| **特征清洗** | 特征过多或有噪声时 | 去除高度相关特征,PCA 降维 |
|
||||
|
||||
### QWK 评估指标的优化
|
||||
|
||||
**Quadratic Weighted Kappa (QWK):**
|
||||
- 衡量预测与实际的一致性
|
||||
- 分数范围:-1 到 1,越高越好
|
||||
- 特点:对严重错误的惩罚更重
|
||||
|
||||
**优化策略:**
|
||||
|
||||
| 策略 | 效果 |
|
||||
|------|------|
|
||||
| **预测中间分数** | 预测连续值比直接分类更精细 |
|
||||
| **阈值优化** | 在验证集上优化转换阈值 |
|
||||
| **分层 KFold** | 确保每个 fold 中类别比例一致 |
|
||||
| **多 Seed 平均** | 减少 seed 引起的 QWK 波动 |
|
||||
|
||||
### 数据增强策略
|
||||
|
||||
**表格数据增强:**
|
||||
|
||||
| 方法 | 适用场景 | 注意事项 |
|
||||
|------|---------|---------|
|
||||
| **随机 NaN** | 提高缺失值鲁棒性 | 需要模型支持 NaN 处理 |
|
||||
| **高斯噪声** | 提高模型泛化能力 | 噪声强度需调参 |
|
||||
| **特征 Shuffle** | 特征独立性强时 | 破坏特征相关性时慎用 |
|
||||
| **SMOTE** | 类别不平衡时 | 可能导致过拟合 |
|
||||
|
||||
### Target 缺失处理
|
||||
|
||||
**处理策略对比:**
|
||||
|
||||
| 策略 | 优点 | 缺点 |
|
||||
|------|------|------|
|
||||
| **删除缺失样本** | 简单直接 | 损失数据,减少样本量 |
|
||||
| **Pseudo Labeling** | 利用无标签数据 | 可能引入噪声 |
|
||||
| **两阶段训练** | Stage 1 用有标签,Stage 2 用全部 | 需要精心设计 |
|
||||
|
||||
**推荐做法:**
|
||||
```python
|
||||
# 1. CV 计算时不使用 pseudo labels
|
||||
# 2. 最终模型用 pseudo labels
|
||||
# 3. 迭代多次,每次用上一轮的预测
|
||||
```
|
||||
|
||||
### 模型选择指南
|
||||
|
||||
**表格数据竞赛模型选择:**
|
||||
|
||||
| 场景 | 推荐模型 | 理由 |
|
||||
|------|---------|------|
|
||||
| **表格数据(主要)** | LightGBM | 速度快,效果好 |
|
||||
| **类别特征多** | CatBoost | 自动处理类别特征 |
|
||||
| **需要调参灵活性** | XGBoost | 参数丰富,调参空间大 |
|
||||
| **数据量大** | LightGBM | 内存效率高 |
|
||||
| **集成** | LGBM + XGB + Cat | 多样性提升稳定性 |
|
||||
|
||||
**不推荐场景:**
|
||||
- 神经网络:表格数据通常不如 GBM
|
||||
- 深度学习:除非有特殊结构(如图嵌入)
|
||||
|
||||
---
|
||||
|
||||
## Top 10 Solutions Comparison (前 10 名方案对比分析)
|
||||
|
||||
> 基于前排解决方案的横向对比分析,提取共性技术和差异创新
|
||||
|
||||
### 前 5 名详细对比
|
||||
|
||||
#### 1st Place - Lennart Haupts
|
||||
|
||||
**核心架构:** GBM Ensemble (LGBM + XGBoost + CatBoost + ExtraTrees)
|
||||
|
||||
**关键技术:**
|
||||
- **预测 PCIAT-PCIAT_Total**:预测中间分数而非直接预测 sii
|
||||
- **10-Fold Stratified KFold**:高 fold 提升稳定性
|
||||
- **特征清洗**:去除异常特征
|
||||
- **PCA 降维**:减少特征噪声
|
||||
|
||||
**模型组合:**
|
||||
```
|
||||
LGBMRegressor
|
||||
+ XGBoost Regressors
|
||||
+ CatBoostRegressor
|
||||
+ ExtraTreesRegressor
|
||||
→ Ensemble (平均/加权)
|
||||
```
|
||||
|
||||
#### 3rd Place
|
||||
|
||||
**核心架构:** LightGBM with Multi-Seed
|
||||
|
||||
**关键技术:**
|
||||
- **Multi-Seed Training**:seed 不固定,5-fold 重复 100 次
|
||||
- **Optuna 调参**:自动化超参数优化
|
||||
- **数据增强**:
|
||||
- 随机插入 NaN
|
||||
- 添加高斯噪声
|
||||
- **特征工程**:多样化的特征变换
|
||||
|
||||
**训练策略:**
|
||||
```python
|
||||
for seed in range(100):
|
||||
for fold in range(5):
|
||||
model = LGBMRegressor(random_state=seed)
|
||||
train_and_evaluate()
|
||||
```
|
||||
|
||||
#### 5th Place
|
||||
|
||||
**核心架构:** Multi-Model Ensemble
|
||||
|
||||
**关键技术:**
|
||||
- **时序特征工程**:k-means 聚类将时序转为类别特征
|
||||
- **Pseudo Labeling**:填充缺失 target
|
||||
- **多模型集成**:LGB + Cat + XGB + Lasso + NN
|
||||
|
||||
**模型组合:**
|
||||
```
|
||||
LGBM + CatBoost + XGBoost
|
||||
+ Lasso (线性模型)
|
||||
+ Neural Network
|
||||
→ Ensemble
|
||||
```
|
||||
|
||||
#### 7th Place
|
||||
|
||||
**核心架构:** LGBM + XGBoost Ensemble
|
||||
|
||||
**关键技术:**
|
||||
- **Tweedie Loss**:处理偏态分布
|
||||
- **Pseudo Labeling**:有效提升分数
|
||||
- **缺失值处理**:用中位数填补
|
||||
- **Multi-Seed Ensemble**:10 个 seed 平均
|
||||
|
||||
#### 4th Place (underfit squad)
|
||||
|
||||
**核心发现:**
|
||||
- **CGAS=80 阈值**:CGAS 分数 > 80 可预测严重问题
|
||||
- **SDS=35 阈值**:SDS 分数 > 35 可预测严重问题
|
||||
|
||||
**关键技术:**
|
||||
- TabNet(效果不佳)
|
||||
- 预测 PCIAT-PCIAT_Total
|
||||
- 特征工程:CGAS, SDS 阈值
|
||||
|
||||
### 共性技术("银弹" - 高分者共同使用)
|
||||
|
||||
| 技术 | 使用排名 | 说明 |
|
||||
|------|---------|------|
|
||||
| **预测中间分数** | 1st, 3rd, 5th, 7th | 预测 PCIAT-PCIAT_Total 比直接预测 sii |
|
||||
| **多 Seed 平均** | 3rd, 7th | 减少 seed 引起的方差 |
|
||||
| **Pseudo Labeling** | 5th, 7th | 填充缺失 target |
|
||||
| **GBM Ensemble** | 1st, 5th, 7th | LGBM + XGBoost + CatBoost |
|
||||
| **高 Fold CV** | 1st | 10-fold stratified KFold |
|
||||
| **特征清洗** | 1st | 去除异常特征,PCA 降维 |
|
||||
|
||||
### 差异创新
|
||||
|
||||
**1st Place vs 其他:**
|
||||
|
||||
| 方面 | 1st Place | 其他 |
|
||||
|------|-----------|------|
|
||||
| **模型组合** | LGBM + XGB + Cat + ExtraTrees | 主要 3 个 GBM |
|
||||
| **Fold 数量** | 10-fold | 5-fold 或更多 |
|
||||
| **特征处理** | 严格清洗 + PCA | 较少使用 PCA |
|
||||
|
||||
**3rd Place vs 其他:**
|
||||
|
||||
| 方面 | 3rd Place | 其他 |
|
||||
|------|-----------|------|
|
||||
| **训练策略** | 5-fold × 100-seed | 单次训练或少 seed |
|
||||
| **调参方法** | Optuna 自动调参 | 手动调参 |
|
||||
| **数据增强** | 随机 NaN + 高斯噪声 | 较少数据增强 |
|
||||
|
||||
**5th Place vs 其他:**
|
||||
|
||||
| 方面 | 5th Place | 其他 |
|
||||
|------|-----------|------|
|
||||
| **时序处理** | k-means 聚类 | 较少特殊处理 |
|
||||
| **模型多样性** | GBM + 线性 + NN | 主要是 GBM |
|
||||
| **Pseudo Labeling** | 显著有效 | 效果不一 |
|
||||
|
||||
**7th Place vs 其他:**
|
||||
|
||||
| 方面 | 7th Place | 其他 |
|
||||
|------|-----------|------|
|
||||
| **Loss 函数** | Tweedie Loss | 主要是 MSE/MAE |
|
||||
| **缺失值处理** | 中位数填补 | 其他方法 |
|
||||
| **Ensemble 策略** | 10-seed 平均 | 少 seed 或不用 |
|
||||
|
||||
### Target 预测策略对比
|
||||
|
||||
| 排名 | 预测目标 | 理由 |
|
||||
|------|---------|------|
|
||||
| **1st** | PCIAT-PCIAT_Total | 连续值比类别更精细 |
|
||||
| **3rd** | PCIAT-PCIAT_Total | 同左 |
|
||||
| **5th** | PCIAT-PCIAT_Total | 同左 |
|
||||
| **7th** | PCIAT-PCIAT_Total | 同左 |
|
||||
|
||||
**结论:** 所有前排方案都选择预测中间分数
|
||||
|
||||
### 特征工程对比
|
||||
|
||||
| 排名 | 特征工程策略 |
|
||||
|------|-------------|
|
||||
| **1st** | 清洗异常特征 + PCA 降维 |
|
||||
| **3rd** | 随机 NaN + 高斯噪声 |
|
||||
| **5th** | 时序 k-means 聚类 |
|
||||
| **7th** | 中位数填补缺失值 |
|
||||
|
||||
### 数据增强对比
|
||||
|
||||
| 排名 | 数据增强策略 |
|
||||
|------|-------------|
|
||||
| **1st** | 较少数据增强 |
|
||||
| **3rd** | 随机 NaN + 高斯噪声 |
|
||||
| **5th** | Pseudo Labeling |
|
||||
| **7th** | Multi-Seed 平均 |
|
||||
|
||||
### Pseudo Labeling 对比
|
||||
|
||||
| 排名 | 是否使用 | 效果 |
|
||||
|------|---------|------|
|
||||
| **1st** | 未提及 | - |
|
||||
| **3rd** | 未提及 | - |
|
||||
| **5th** | 使用 | 显著有效 |
|
||||
| **7th** | 使用 | 显著有效 |
|
||||
|
||||
**结论:** Pseudo Labeling 在 5th 和 7th 有效,可能需要正确实现
|
||||
|
||||
### 关键数据洞察总结
|
||||
|
||||
1. **预测中间分数是关键**:所有前排方案都预测 PCIAT-PCIAT_Total
|
||||
2. **多 Seed 平均有效**:减少 seed 引起的方差
|
||||
3. **Pseudo Labeling 需要正确实现**:5th 和 7th 报告有效
|
||||
4. **GBM Ensemble 是主流**:LGBM + XGBoost + CatBoost
|
||||
5. **高 Fold CV 提升稳定性**:10-fold 比 5-fold 更稳定
|
||||
6. **特征清洗很重要**:去除异常特征,PCA 降维
|
||||
7. **Tweedie Loss 适用于偏态数据**:7th Place 使用
|
||||
8. **时序数据可聚类处理**:k-means 将时序转为类别特征
|
||||
|
||||
### 表格数据竞赛的最佳实践
|
||||
|
||||
| 方面 | 推荐 |
|
||||
|------|------|
|
||||
| **目标预测** | 预测中间分数(如有),而非直接预测类别 |
|
||||
| **交叉验证** | 高 Fold(10-fold)Stratified KFold |
|
||||
| **模型选择** | LGBM + XGBoost + CatBoost Ensemble |
|
||||
| **Seed 策略** | Multi-Seed 平均减少方差 |
|
||||
| **Target 缺失** | Pseudo Labeling(CV 不用 pseudo) |
|
||||
| **特征工程** | 清洗异常特征,PCA 降维 |
|
||||
| **数据增强** | 随机 NaN + 高斯噪声(需模型支持) |
|
||||
| **Loss 函数** | Tweedie Loss(偏态数据) |
|
||||
| **时序数据** | k-means 聚类转为类别特征 |
|
||||
|
||||
---
|
||||
|
||||
## Metadata
|
||||
| Source | Date | Tags |
|
||||
|--------|------|------|
|
||||
| [Child Mind Institute - Problematic Internet Use](https://www.kaggle.com/competitions/child-mind-institute-problematic-internet-use) | 2025-01-22 | 表格数据, QWK, Pseudo Labeling, 多Seed平均, GBM Ensemble, Tweedie Loss |
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user