我是靠谱客的博主 害羞芝麻,最近开发中收集的这篇文章主要介绍2022 CCF BDCI 返乡发展人群预测 [0.9117+],觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

一、赛题介绍

比赛地址:返乡发展人群预测

1.1 任务介绍

基于中国联通的大数据能力,通过使用对联通的信令数据、通话数据、互联网行为等数据进行建模,对个人是否会返乡工作进行判断

1.2 数据简介

train.csv:包含全量数据集的70%(dataNoLabel是训练集的一部分,选手可以自己决定是否使用)
test.csv:包含全量数据集的30%
位置类特特征:基于联通基站产生的用户信令数据;
互联网类特征:基于联通用户上网产生的上网行为数据;
通话类特征:基于联通用户日常通话、短信产生的数据

1.3 评估指标

使用ROC曲线下面积AUC(Area Under Curve)作为评价指标,AUC越大,预测越准确

二、解题思路

这是一个二分类任务,主要是从数据清洗、特征构造和筛选以及模型融合的思路

  • 数据清洗
  • 特征构造和筛选
  • 模型融合

最终提交结果:

榜单分数
A榜0.91171720

1.1 库导入

# -*- coding: utf-8 -*-
import numpy as np
import pandas as pd
from sklearn.preprocessing import LabelEncoder
from sklearn.linear_model import LogisticRegression
from xgboost import XGBClassifier
from lightgbm import LGBMClassifier
from catboost import CatBoostClassifier
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.ensemble import HistGradientBoostingClassifier
from sklearn.ensemble import StackingClassifier
from sklearn.model_selection import StratifiedKFold
from sklearn.metrics import roc_auc_score
from sklearn.model_selection import train_test_split
import warnings
from tqdm import tqdm
warnings.filterwarnings('ignore')

1.2 数据读取

train_data = pd.read_csv('data/dataTrain.csv')
test_data = pd.read_csv('data/dataA.csv')
submission = pd.read_csv('data/submit_example_A.csv')
data_nolabel = pd.read_csv('data/dataNoLabel.csv')
print(f'train_data.shape = {train_data.shape}')
print(f'test_data.shape  = {test_data.shape}')

1.3 特征构造

自己DIY的特征

train_data['f47'] = train_data['f1'] * 10 + train_data['f2']
test_data['f47'] = test_data['f1'] * 10 + test_data['f2']

来自网上的特征(来源:https://github.com/librauee/CCF2022/blob/main/FX/FX_baseline.py)

# 暴力Feature 位置
loc_f = ['f1', 'f2', 'f4', 'f5', 'f6']
for df in [train_data, test_data]:
    for i in range(len(loc_f)):
        for j in range(i + 1, len(loc_f)):
            df[f'{loc_f[i]}+{loc_f[j]}'] = df[loc_f[i]] + df[loc_f[j]]
            df[f'{loc_f[i]}-{loc_f[j]}'] = df[loc_f[i]] - df[loc_f[j]]
            df[f'{loc_f[i]}*{loc_f[j]}'] = df[loc_f[i]] * df[loc_f[j]]
            df[f'{loc_f[i]}/{loc_f[j]}'] = df[loc_f[i]] / (df[loc_f[j]]+1)

# 暴力Feature 通话
com_f = ['f43', 'f44', 'f45', 'f46']
for df in [train_data, test_data]:
    for i in range(len(com_f)):
        for j in range(i + 1, len(com_f)):
            df[f'{com_f[i]}+{com_f[j]}'] = df[com_f[i]] + df[com_f[j]]
            df[f'{com_f[i]}-{com_f[j]}'] = df[com_f[i]] - df[com_f[j]]
            df[f'{com_f[i]}*{com_f[j]}'] = df[com_f[i]] * df[com_f[j]]
            df[f'{com_f[i]}/{com_f[j]}'] = df[com_f[i]] / (df[com_f[j]]+1)

ID类特征数值化

cat_columns = ['f3']
data = pd.concat([train_data, test_data])

for col in cat_columns:
    lb = LabelEncoder()
    lb.fit(data[col])
    train_data[col] = lb.transform(train_data[col])
    test_data[col] = lb.transform(test_data[col])

最后构造出训练集和测试集

num_columns = [ col for col in train_data.columns if col not in ['id', 'label', 'f3']]
feature_columns = num_columns + cat_columns
target = 'label'

train = train_data[feature_columns]
label = train_data[target]
test = test_data[feature_columns]

1.4 模型训练代码

常用的交叉验证模型框架

def model_train(model, model_name, kfold=5):
    oof_preds = np.zeros((train.shape[0]))
    test_preds = np.zeros(test.shape[0])
    skf = StratifiedKFold(n_splits=kfold)
    print(f"Model = {model_name}")
    for k, (train_index, test_index) in enumerate(skf.split(train, label)):
        x_train, x_test = train.iloc[train_index, :], train.iloc[test_index, :]
        y_train, y_test = label.iloc[train_index], label.iloc[test_index]

        model.fit(x_train,y_train)

        y_pred = model.predict_proba(x_test)[:,1]
        oof_preds[test_index] = y_pred.ravel()
        auc = roc_auc_score(y_test,y_pred)
        print("- KFold = %d, val_auc = %.4f" % (k, auc))
        test_fold_preds = model.predict_proba(test)[:, 1]
        test_preds += test_fold_preds.ravel()
    print("Overall Model = %s, AUC = %.4f" % (model_name, roc_auc_score(label, oof_preds)))
    return test_preds / kfold

1.5 数据清洗

在训练数据中存在很大一部分的干扰数据,导致模型训练存在很多噪声数据,所以需要对噪声数据进行清洗

这里我使用一个简易的模型,将数据切割成60份,对每一份数据单独作为验证集,如果验证集的AUC几乎接近于0.5,则验证集中的数据大多数为干扰数据。

gbc = GradientBoostingClassifier()
gbc_test_preds = model_train(gbc, "GradientBoostingClassifier", 60)

测试结果为

KFlodAUC
00.9034
10.9112
20.9045
30.9006
40.9013
50.8986
60.9009
70.9116
80.9245
90.8902
100.8995
110.9047
120.9291
130.8980
140.9279
150.8995
160.9080
170.8942
180.9179
190.9044
200.8937
210.9138
220.9024
230.9091
240.8937
250.9173
260.9047
270.9010
280.9047
290.9144
300.8984
310.9079
320.9240
330.8899
340.8780
350.8942
360.9112
370.9221
380.9273
390.9137
400.9206
410.9053
420.9033
430.9193
440.9141
450.9087
460.8957
470.9142
480.9179
490.9128
500.5608
510.5328
520.5020
530.5067
540.4888
550.5065
560.5163
570.5019
580.5235
590.4842

很明显可以看出,50~59的数据为干扰数据
所以剔除干扰数据

train = train[:50000]
label = label[:50000]

1.6 模型融合

选取了

  • GradientBoostingClassifier
  • HistGradientBoostingClassifier
  • XGBClassifier
  • LGBMClassifier
  • CatBoostClassifier
    这6个树模型作为基础模型
gbc = GradientBoostingClassifier(
    n_estimators=50, 
    learning_rate=0.1,
    max_depth=5
)
hgbc = HistGradientBoostingClassifier(
    max_iter=100,
    max_depth=5
)
xgbc = XGBClassifier(
    objective='binary:logistic',
    eval_metric='auc',
    n_estimators=100, 
    max_depth=6, 
    learning_rate=0.1
)
gbm = LGBMClassifier(
    objective='binary',
    boosting_type='gbdt',
    num_leaves=2 ** 6, 
    max_depth=8,
    colsample_bytree=0.8,
    subsample_freq=1,
    max_bin=255,
    learning_rate=0.05, 
    n_estimators=100, 
    metrics='auc'
)
cbc = CatBoostClassifier(
    iterations=210, 
    depth=6, 
    learning_rate=0.03, 
    l2_leaf_reg=1, 
    loss_function='Logloss', 
    verbose=0
)

通过StackingClassifier将6个模型进行Stack,Stack模型用LogisticRegression

estimators = [
    ('gbc', gbc),
    ('hgbc', hgbc),
    ('xgbc', xgbc),
    ('gbm', gbm),
    ('cbc', cbc)
]
clf = StackingClassifier(
    estimators=estimators, 
    final_estimator=LogisticRegression()
)

1.7 特征筛选

特征筛选思路:先将模型训练好,然后对验证集进行测试得到基础AUC,之后循环遍历所有特征,在验证集上对单个特征进行mask后,得到mask后的AUC,评估两个AUC的差值,差值越大,则说明特征重要性越高。

先将训练数据划分成训练集和验证集

X_train, X_test, y_train, y_test = train_test_split(
    train, label, stratify=label, random_state=2022)

然后用组合模型进行训练和验证

clf.fit(X_train, y_train)
y_pred = clf.predict_proba(X_test)[:, 1]
auc = roc_auc_score(y_test, y_pred)
print('auc = %.8f' % auc)

循环遍历特征,对验证集中的特征进行mask

ff = []
for col in feature_columns:
    x_test = X_test.copy()
    x_test[col] = 0
    auc1 = roc_auc_score(y_test, clf.predict_proba(x_test)[:, 1])
    if auc1 < auc:
        ff.append(col)
    print('%5s | %.8f | %.8f' % (col, auc1, auc1 - auc))

特征重要性TOP20

特征AUCdiff
f460.91137151-0.00207482
f2/f40.91193439-0.00151194
f2/f60.9121758-0.00127053
f4/f50.91224485-0.00120148
f470.91252212-0.00092421
f5-f60.91257545-0.00087088
f4-f50.91269045-0.00075589
f44/f450.91274186-0.00070447
f30.9127596-0.00068673
f190.91277603-0.00067031
f4-f60.91288475-0.00056158
f2-f40.91292365-0.00052268
f44/f460.91296255-0.00048378
f45/f460.91296478-0.00048156
f2/f50.91303568-0.00041066
f5/f60.91307167-0.00037466
f1/f60.91309919-0.00034714
f80.91310869-0.00033764
f1/f50.91315365-0.00029269
f1-f40.91318568-0.00026066

这里选取所有差值为负的特征,对比特征筛选后的特征提升

clf.fit(X_train[ff], y_train)
y_pred = clf.predict_proba(X_test[ff])[:, 1]
auc = roc_auc_score(y_test, y_pred)
print('auc = %.8f' % auc)
特征筛选前特征筛选后
0.913446330.91385538

1.8 模型训练

train = train[ff]
test = test[ff]

clf_test_preds = model_train(clf, "StackingClassifier", 10)

submission['label'] = clf_test_preds
submission.to_csv('submission.csv', index=False)

最后线下训练结果为

KFoldAUC
00.9069
10.9091
20.9156
30.9059
40.9075
50.9083
60.9007
70.9173
80.9160
90.9146
overall0.9100

三、总结

最后线上A榜的结果为0.91171720

后续优化思路:

  • 半监督学习, 使用pseudo_labeling
  • 特征工程,使用PolynomialFeatures进行多项式特征组合

最后

以上就是害羞芝麻为你收集整理的2022 CCF BDCI 返乡发展人群预测 [0.9117+]的全部内容,希望文章能够帮你解决2022 CCF BDCI 返乡发展人群预测 [0.9117+]所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(42)

评论列表共有 0 条评论

立即
投稿
返回
顶部