
第一篇咱们聊了机器学习是什么今天聊点实在的——为什么你的模型训出来一团糟但别人用同样的算法就能跑出好结果答案十有八九是数据预处理和特征工程。这俩活儿在教科书里通常只占一两章但在真实项目里它们吃掉的时间至少是整个项目周期的80%。你调模型花一周调数据得花一个月——这话听起来夸张干过的都知道我说得保守了。咱们一项一项拆。缺失值处理——你永远不知道数据能有多脏真实数据里缺失值无处不在。传感器某天坏了、人工录入漏了几行、系统迁移丢了一部分、用户没填那个字段——原因千奇百怪结果就一个你拿到的DataFrame里一堆NaN。处理缺失值没有标准答案只有场景适配最简单的做法是直接删除。如果缺失的行占比很低比如小于5%删掉就行了省事。但如果某个字段缺失率超过30%你直接删列可能会丢掉重要信息删行的话数据量损失又太大。均值/中位数/众数填充是最常见的补救措施。连续型数据填均值或中位数中位数对异常值更鲁棒分类型数据填众数。但这么做有个隐患——人为地给数据引入了峰值相当于你在原本没有数据的地方强行塞了一个最可能的值这个值在模型看来就是事实会扭曲模型对真实分布的认知。稍微高级一点的是模型预测填充——用其他字段做特征把缺失的那个字段当作预测目标用随机森林或者KNN去预测缺失值。这个方法的逻辑是用数据本身的信息来补全数据比填均值更贴近真实分布。代价是计算量大如果数据量小还可能引入过拟合。还有一种更极端的方式在某些场景下反而效果不错——把缺失当特征。不填充缺失值而是加一个二值标志列该字段是否缺失然后把缺失的那个字段本身填充成一个固定值比如-1或者0。这样模型可以学习到缺失本身是一个信号——在某些业务场景里用户不填某个字段本身就包含了信息比如用户不填收入可能意味着收入不稳定。异常值检测——那几个离谱的数据点可能毁了你的整个模型异常值这事儿吧有时候是数据录错了比如年龄填了250岁有时候是真的存在但极其罕见比如某天的流量暴增了100倍。你得区分这两种情况。统计方法上最常用的是3σ原则——超过均值±3个标准差的数据点视为异常。这个方法的假设是数据服从正态分布如果你的数据是长尾分布那3σ会误杀很多正常值。更稳健的是IQR四分位距法——Q1-1.5IQR和Q31.5IQR作为上下界。这个不依赖正态分布假设对大部分数据分布都适用。还有一个极易被忽略的事儿——异常值的判断要结合业务逻辑。某个产品的转化率在促销日从2%涨到了8%在统计模型看来这是异常值远超3σ但在业务层面这就是促销正常效果。你如果机械地把这个样本删了模型就学不到促销能带来转化率飙升这个关键规律。所以在工业界异常值处理一般分两步先用统计方法粗筛出一批疑似异常然后让业务专家逐个确认这些值到底该不该留。这不是算法问题是领域知识问题。数据归一化/标准化——不做的后果就是模型学偏了如果你的特征里既有年龄范围0-100又有年收入范围3万-200万两者的数值尺度差了好几个数量级。对于依赖距离度量的算法KNN、SVM、K-means来说尺度大的特征会主导距离计算年龄那点差异完全被忽略。解决方式就是归一化或者标准化。Min-Max归一化把数据压缩到[0,1]区间公式是(x-min)/(max-min)。好处是保留原始数据的分布形状坏处是对异常值极其敏感——你的某个值如果远远大于其他值其他所有值都会被挤压到接近0的位置。Z-Score标准化把数据变成均值为0、标准差为1的标准正态分布。公式是(x-均值)/标准差。这个不怕异常值因为用的是均值和标准差单个点影响有限是工业界用得最多的方式。对于树模型随机森林、GBDT归一化基本不需要做因为树模型的决策边界跟特征尺度无关。但深度学习和基于距离的模型归一化是必做且要做在前面的。编码分类变量——把男女变成数字没你想的那么简单机器学习模型只认数字不认字符串。你的性别列里写着男女必须变成1和0才能喂进模型。最直接的是Label Encoding直接把男映射成0、女映射成1。这个简单粗暴但有个隐含问题——你给类别赋予了顺序模型可能误以为01、男女在某些线性模型里会产生误导。所以大部分场景下推荐One-Hot Encoding——性别变成两列性别_男和性别_女一个人如果是男则性别_男1、性别_女0。这样彻底消除了顺序关系。但One-Hot有个致命缺陷——如果某个分类字段有上百个取值比如城市有200个城市One-Hot出来就是200列特征维度直接爆炸。这时候可以考虑Target Encoding——用该类别下目标变量的均值来编码。比如城市这个类别特征用该城市用户的平均购买率作为编码值。这种方法信息量丰富、维度低但容易过拟合通常需要用交叉验证来做平滑处理。特征工程——让你跟普通玩家拉开差距的真正壁垒前面说的都是数据清洗现在到了特征创造——这是真正区分会用工具的人和真正懂的人的分水岭。特征交互是特征工程里最经典的操做。比如年龄和收入单独看可能都一般但年龄×收入这个交叉特征可能跟购买力高度相关。人为创造这种乘法特征加法特征或者比值特征能让线性模型学到非线性关系。统计聚合在处理用户行为数据时特别有效。比如原始数据是用户的每次点击记录几十万行你要预测这个用户会不会购买。你需要把点击记录按用户聚合起来——这个用户过去7天的点击总次数过去30天的平均停留时长最近一次点击距离今天的天数。这些聚合统计量才是真正跟购买意愿相关的特征。时间窗口特征非常容易被忽略但在很多场景下极其关键。今天周几是否节假日距离上一次购买过去了多少天——这些基于时间的特征在电商、金融、交通预测里往往比复杂的模型架构更管用。领域知识的注入——这个没法教只能靠积累。做信贷风控的人知道负债收入比比单独的收入和负债都有用做推荐系统的人知道用户最近浏览的品类比用户历史总购买品类更有预测力。这些特征不可能从原始数据里自动发现必须靠对这个行业的理解。特征选择——少即是多你创造了100个特征不是所有都有用。有些特征是噪声、有些特征互相高度相关比如房屋面积和房屋面积10几乎是同一回事。保留过多的无效特征不但增加训练时间还会造成过拟合。常用的特征选择方法过滤法计算每个特征和目标变量的相关性皮尔逊相关系数、互信息只选排名靠前的K个包裹法用模型本身来评估特征的重要性比如随机森林的feature_importance、L1正则化自动压缩不重要特征的系数到0嵌入法在训练过程中自动做特征选择比如XGBoost的增益重要性会自动告诉每个特征的贡献度我个人最常用的是先用随机森林跑一遍看feature_importance砍掉贡献度最低的30%特征再用XGBoost做精细调优。这个流程不复杂但效果极其稳定。说了这么多你可能已经发现了——数据预处理和特征工程没有一键完成的傻瓜式操作。每一份数据都有自己的脾气你必须跟它相处一段时间摸透它的缺失模式、分布形态、异常来源、业务含义然后针对性地做处理。这个跟数据相处的过程任何AutoML工具都替代不了。很多新人把大量精力花在调模型上觉得换一个更先进的架构就解决问题了。但真实情况是——一个清洗得干干净净、特征设计得恰到好处的数据集配上最简单的逻辑回归效果往往优于一团乱麻的数据配上最牛逼的Transformer。别再问哪个模型最厉害了。先问问自己我的数据准备好了吗