欢迎光临
我们一直在努力

建模Pipeline——嵌套式交叉验证特征工程与模型评估框架(Nested Cross-Validation Feature Engineering and Evaluation Framework)

目录

一、特征构建:

1.1 第1个新特征:负债收入比

1.2 第2个新特征:工龄(月数)

1.3 第3个新特征:贷款金额占收入比重

1.4 补充一个关键点

二、特征选择:

2.1 主要概念

2.2 具体方法

2.2.1. 过滤法

2.2.2. 包裹法

2.3.3. 嵌入法

三、模型评估指标

3.1 第一把尺子:精确率(Precision)—— “抓得准不准”

3.2 第二把尺子:召回率(Recall)—— “捞得全不全”

3.3 第三把尺子:AUC(最牛的综合成绩单)

四、交叉验证

五、机器学习建模标准流程


本文要干什么?

从最原始的贷款数据出发,带你手把手走完特征构建、特征选择、模型评估和交叉验证的全流程。会用最接地气的大白话和代码示例,把机器学习建模这件事掰开揉碎讲明白。不用背公式,先理解“为什么这么做”和“到底发生了什么”,看完你就能自己照猫画虎建一套评分卡或风控模型。


一、特征构建:

原始数据(你手里拿到的烂数据,我们需要整理)

用户ID月收入负债总额申请贷款金额入职日期本次申请日期
A001 8000 50000 20000 2020-03-15 2026-08-06
A002 15000 80000 50000 2024-01-01 2026-08-06
A003 5000 45000 30000 2018-07-01 2026-08-06

1.1 第1个新特征:负债收入比

  • 怎么造:负债总额 ÷ 月收入

  • 算出来:

    • A001:50000 ÷ 8000 = 6.25

    • A002:80000 ÷ 15000 = 5.33

    • A003:45000 ÷ 5000 = 9.0

为啥有用:月收入8000欠5万,和月收入5万欠5万,风险能一样吗?原始数据里只有“负债”和“收入”两列,模型看不出来,你造出这个比值,模型一眼就能看出谁还款压力大。


1.2 第2个新特征:工龄(月数)

  • 怎么造:本次申请日期 – 入职日期(算出干了多少个月)

  • 算出来:

    • A001:2026年8月 – 2020年3月 = 77个月

    • A002:2026年8月 – 2024年1月 = 19个月

    • A003:2026年8月 – 2018年7月 = 97个月

为啥有用:工龄越长,工作越稳,越不容易违约。原始数据里只有两个日期,你把它相减变成“工龄”,模型就能用上了。


1.3 第3个新特征:贷款金额占收入比重

  • 怎么造:申请贷款金额 ÷ 月收入

  • 算出来:

    • A001:20000 ÷ 8000 = 2.5倍

    • A002:50000 ÷ 15000 = 3.33倍

    • A003:30000 ÷ 5000 = 6.0倍

为啥有用:一个月挣5000的人想贷3万(6个月工资),和挣1.5万贷5万(3个月工资),明显前者风险更高。这个新特征直接反映了“借钱是否超出承受能力”。


最终你造完的新数据(送给模型去训练的干净数据集)

用户ID月收入负债总额申请金额负债收入比工龄(月)贷款收入比
A001 8000 50000 20000 6.25 77 2.5
A002 15000 80000 50000 5.33 19 3.33
A003 5000 45000 30000 9.0 97 6.0

1.4 补充一个关键点

像 随机森林(RF) 和 XGBoost 这类模型,它们是“切豆腐块”的逻辑(不断二分数据),天生不擅长做“除法”和“加减日期”。如果你不亲手造出“负债收入比”和“工龄”这两个新特征,模型自己很难悟出来。你造得好,模型AUC直接涨一截;你懒得造,模型就只能用那几列原始数据,效果差一大截。


二、特征选择:

2.1 主要概念

  • 特征构建 = 做加法(自己动脑子“造”出新列)

  • 特征选择 = 做减法(从一大堆列里,把没用的、拖后腿的“扔掉”)

还用刚才那个贷款的例子,对比着看:

你现在手里经过“构建”之后,已经有了这些列: 月收入负债总额申请金额负债收入比工龄(月)贷款收入比……可能还有几十上百个其他特征。

这时候问题来了:是不是所有列都要喂给模型?

当然不是!有些列是“垃圾”:

  • 无效列:比如“用户ID”(A001、A002),这对判断违约毫无用处,留着只会让模型学歪。

  • 重复列:你造了“负债收入比”,那原始的“负债总额”和“月收入”可能就没必要同时存在了(因为信息已经包含在新列里了)。

  • 拖后腿列:有些列跟结果(是否违约),留着只会增加计算量,甚至导致模型“过拟合”。

“特征选择”要做的,就是把这些该扔的扔出去。


2.2 具体方法

过滤法/包裹法/嵌入法”就是三种“扔东西”的策略:

方法大白话解释生活例子
过滤法 给每个特征打个分(比如算算它和“是否违约”的相关性),分数低的直接淘汰,不看模型脸色。 像过安检,用X光机扫一遍,看着有问题的直接挑出来扔掉。
包裹法 把特征当“队员”去组队比赛。每次加一个或减一个特征,跑一遍模型看成绩,成绩好就留下,成绩差就踢走,反复试。 像组篮球队,不知道谁行谁不行,就挨个换人上场打比赛,看实战效果定去留。
嵌入法 让算法边训练边自己打分(如随机森林自带“重要性排序”),算法觉得没用的特征,自动就把权重降成0了。 像教练边训练边观察,谁表现不好直接在训练过程中就被淘汰了。

2.2.1. 过滤法

代码逻辑:给每个特征和“标签(答案)”算一个相关分(比如卡方检验、皮尔逊系数),分太低的直接剔除。

from sklearn.feature_selection import SelectKBest, chi2
from sklearn.datasets import make_classification
造个假数据:10个特征,100个样本
X, y = make_classification(n_samples=100, n_features=10, random_state=42)
【减法操作】:只保留分数最高的前 5 个特征(把另外5个直接砍掉)
selector = SelectKBest(score_func=chi2, k=5)

X_new = selector.fit_transform(X, y)
print(f"原始特征数: {X.shape[1]}") # 输出 10
print(f"过滤后特征数: {X_new.shape[1]}") # 输出 5
核心精髓:这里的 score_func 独立于模型,切完再喂给随机森林。

2.2.2. 包裹法

代码逻辑:把特征选择当成“寻宝游戏”。指定一个模型(比如随机森林),反复训练,穷举或贪心地加特征(看加了涨分没)或减特征(看减了掉分没)。

最经典的叫 RFE(递归特征消除),它干的事是:先全量训练一次,把最不重要的那个扔了,再训练,再扔最不重要的……直到剩下你指定的数量。

from sklearn.feature_selection import RFE
from sklearn.ensemble import RandomForestClassifier
先定个模型(注意:包裹法必须依赖这个模型来当“裁判”)
estimator = RandomForestClassifier(random_state=42)
【减法操作】:目标只保留 3 个最重要的特征
selector = RFE(estimator, n_features_to_select=3, step=1)
selector = selector.fit(X, y) # 这一步在后台循环了很多次!
查看哪些列被留下了(True是留下,False是被减掉了)
print("特征保留掩码:", selector.support_)
比如输出: [False False True True False False False True False False]
减去没用的,得到新数据
X_new = selector.transform(X)
print(f"包裹法选择后特征数: {X_new.shape[1]}") # 输出 3

2.3.3. 嵌入法

代码逻辑:这类算法(Lasso回归、决策树、XGBoost)在训练时,内部自带惩罚项或分裂机制。训练完,没用的特征权重系数直接就是 0。

from sklearn.linear_model import LogisticRegression
from sklearn.feature_selection import SelectFromModel
用带 L1 惩罚项的逻辑回归(L1惩罚会把不重要的系数直接压成0)
这里的 C=0.1 控制惩罚力度,惩罚越狠,减掉的越多
estimator = LogisticRegression(penalty='l1', solver='liblinear', C=0.1, random_state=42)
【训练中进行减法】:训练的同时,自动把没用的特征权重减成 0
selector = SelectFromModel(estimator, threshold='mean') # threshold表示系数大于平均值才保留
selector = selector.fit(X, y)
查看权重系数,你会发现有些列是 0.0
print("特征权重系数:", selector.estimator_.coef_)
比如: [ 0. 0. 0.5 0.8 0. 0. 0.2 0. 0. 0.1] <- 有4个直接被归零了
X_new = selector.transform(X)
print(f"嵌入法选择后特征数: {X_new.shape[1]}")


三、模型评估指标

接下来:模型跑完了,怎么给它“打分”?精确率、召回率、AUC,就是三把不一样的“尺子”。

3.1 第一把尺子:精确率(Precision)—— “抓得准不准”

大白话: 你抓回来100个人,说他们是小偷,结果里面只有60个是真的,40个是冤枉的。那你的精确率就是 60%。

  • 啥时候用? 比如给用户推送“降薪预警”,如果你误判了(冤枉好人),用户会骂娘,投诉你。这时候必须保证“抓回来的人里,尽量都是真的”,就得看精确率。


3.2 第二把尺子:召回率(Recall)—— “捞得全不全”

大白话: 商场里今天实际溜进来100个小偷,你带着保安一顿操作,只抓回来60个,漏掉了40个。那你的召回率就是 60%。

  • 啥时候用? 比如“癌症早筛”或“信用卡盗刷检测”。漏掉一个真的病人(或盗刷),后果极其严重。这时候哪怕把正常人误判成病人,也得先把所有嫌疑人都捞出来,就得看召回率。

重点来了: 精确率和召回率是“跷跷板”——你调模型的时候,精确率高了,召回率通常会降;召回率高了,精确率通常会降。你要根据业务场景,决定优先保哪个。


3.3 第三把尺子:AUC(最牛的综合成绩单)

大白话: 前面两把尺子都是“偏科”分数,AUC看的是“综合排名能力”。

举个例子: 模型给10个人打分(分数越高越像小偷):

  • 真正的小偷(3个)打了:95分、90分、85分。

  • 普通好人(7个)打了:80分、70分、60分……

如果AUC=1.0(满分),说明所有小偷的分数,都比所有好人高,模型完美分开两类人。 如果AUC=0.5,说明模型纯属瞎蒙,跟抛硬币没区别(分数混在一起,分不出谁是小偷)。

四、交叉验证

把全部数据平均切成 N 份,轮流拿其中 1 份当“绝密高考卷”,剩下 N-1 份当“教材”,反复考 N 次,最后算平均分。

举例子—— K折交叉验证(K通常取5或10)。我拿 5折 给你拆解动作:

  • 原始数据:你手上有1000个学生的全部资料(特征)和高考成绩(标签)。

  • 切分:把这1000人随机平均分成5组,每组200人,编号A、B、C、D、E。

开始轮流传“绝密试卷”:

轮次当“教材”训练(4组=800人)当“绝密卷”测试(1组=200人)得分
第1轮 B + C + D + E 的数据喂给模型学 A组(模型完全没见过) 精确率/召回率/AUC = 85%
第2轮 A + C + D + E 的数据喂给模型学 B组(模型完全没见过) 精确率/召回率/AUC = 87%
第3轮 A + B + D + E 的数据喂给模型学 C组(模型完全没见过) 精确率/召回率/AUC = 82%
第4轮 A + B + C + E 的数据喂给模型学 D组(模型完全没见过) 精确率/召回率/AUC = 90%
第5轮 A + B + C + D 的数据喂给模型学 E组(模型完全没见过) 精确率/召回率/AUC = 86%

最终该模型的真实成绩 = (85% + 87% + 82% + 90% + 86%)÷ 5 = 86%。

为什么必须搞这么麻烦?(回答你的“为何物”)

如果不做交叉验证,最容易犯的错叫 “拿全部数据又当教材又当考卷”——模型把1000个人的答案全背下来了,最后精确率100%。但拉到现实中模型直接懵逼,这叫过拟合。

故,交叉验证的三大硬核作用:

  • 防作弊(最核心):保证每一份数据都当过“陌生人”,模型每轮都在做“没见过的题”,逼它学真本事。

  • 更稳当:如果只分一次训练集/测试集,万一你手气差,分到的那200个测试题恰好全是“简单题”,成绩虚高;或者全是“难题”,成绩虚低。循环5次取平均,成绩更接近真实水平。

  • 不浪费数据:如果你的数据本来就少(比如只有500条),你还硬抠出100条做测试、400条训练,模型会“吃不饱”。交叉验证让每一轮都有800人(4折)去训练,模型学得更扎实。

  • 1> 千万注意: 做特征选择(比如用过滤法算分、用包裹法RFE)的时候,必须只在训练集(那4份)上算,算完再应用到测试集(那1份)上。

    2> 错误做法:先用全部1000人的数据挑出最好的5个特征,再去做交叉验证。 3> 后果:你挑特征的时候,已经偷看了那200个“绝密考生”的信息,相当于考试前泄题,交叉验证白做了。

    4.>正确流程: 每一轮交叉验证的内部,都要重新做一次特征选择——只拿800人的训练数据挑特征,再用这个标准去过滤那200人的测试数据。


    五、机器学习建模标准流程

    预处理 → 特征构建 → 进入交叉验证循环(内含:切分 → 特征选择 → 跑RF/XGBoost → 看精确率/召回率/AUC)→ 循环结束,算平均分 → 撰写模型评估报告

    赞(0)
    未经允许不得转载:171主机测评 » 建模Pipeline——嵌套式交叉验证特征工程与模型评估框架(Nested Cross-Validation Feature Engineering and Evaluation Framework)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址