机器学习_第三篇_数据预处理
真正上手做过几个项目的人都知道,算法往往只占工作量的两成,剩下八成都在和数据较劲。
这篇文章我们先把机器学习的几种学习方式(有监督 / 无监督 / 半监督 / 强化学习)在开头理顺,搞清楚预处理到底是在为谁铺路,后面讲方法才不迷糊;然后再把「数据预处理」和「数据清洗」拆开讲清楚:它们是什么、有哪些方法、按什么步骤走、坑在哪儿,最后手把手在 MATLAB 上跑一遍。
一、机器学习到底有几种「学习方式」
我们先把机器学习的几种「学习方式」摆平,后面所有 preprocessing 都是为它们服务的。
有监督学习(Supervised Learning)
数据里带「标准答案」(标签 y),每个样本都是「特征 X + 答案 y」成对出现,模型学的是映射 f:X → y。
- 典型任务:分类(邮件垃圾/正常、图片猫/狗)、回归(预测房价、温度)。
- 常见算法:线性回归、逻辑回归、决策树、随机森林、XGBoost、SVM、神经网络。
无监督学习(Unsupervised Learning)
数据只有特征 X,没有 y,模型得自己从数据里「看出门道」、找隐藏结构。
- 典型任务:聚类(客户分群)、降维(PCA、t-SNE)、异常检测(欺诈、故障)、关联规则(买了 A 常买 B)。
- 常见算法:K-Means、DBSCAN、层次聚类、PCA、孤立森林、Apriori。
半监督学习(Semi-Supervised Learning)
现实里标注很贵(比如医学影像要专家标),往往只有少量标签 + 大量无标签数据。思路是先拿海量无标签数据学出数据的整体结构/表征,再用那一点标签去校正、微调。
- 典型任务:标注成本高的分类(医学影像、语音)。
- 常见玩法:自训练(self-training)、伪标签(pseudo-label)、图半监督、对比学习预训练。
强化学习(Reinforcement Learning, RL)
前面三种都是「给样本学映射」,RL 不是。它是智能体在环境里试错,靠环境给的奖励信号 r 学出一套「怎么行动最好」的策略。没有现成的「输入→输出」对,只有「状态 → 动作 → 奖励」的轨迹。
- 典型任务:控制 / 决策 / 博弈(游戏 AI、机器人、推荐排序、自动驾驶)。
- 常见算法:Q-learning、DQN、PPO、AlphaGo 那一套。
一张表看全四种
| 学习方式 | 数据里有什么 | 学的是什么 | 典型任务 | 典型算法 |
|---|---|---|---|---|
| 有监督 | 特征 + 标签 | 输入→输出的映射 | 分类、回归 | 线性回归、随机森林、XGBoost、SVM、神经网络 |
| 无监督 | 只有特征 | 数据里的隐藏结构 | 聚类、降维、异常检测 | K-Means、DBSCAN、PCA、孤立森林 |
| 半监督 | 少量标签 + 大量无标签 | 借无标签补标签不足 | 标注贵的分类 | 自训练、伪标签、图半监督、对比学习 |
| 强化学习 | 状态 + 动作 + 奖励 | 最大化长期奖励的策略 | 控制、决策、博弈 | Q-learning、DQN、PPO、AlphaGo |
核心区别一句话:有没有标签 y、靠不靠奖励 r,是分界线。有监督/半监督吃标签,无监督不吃标签,强化学习吃奖励。
那数据预处理跟它们啥关系?先给结论
预处理是这四种学习的共同地基,不分阵营——清洗缺失、去重、集成、标准化,不管你后面跑分类、跑聚类还是跑 RL,都得做。真正「分阵营」的只有这几类:
- 只属于有监督 / 半监督:跟「标签 y」相关的处理。比如目标变量编码、标签缺失怎么处理、用标签引导的特征选择(如互信息挑和 y 最相关的特征)。没有 y,这些步骤不存在。
- 只属于无监督:由「找结构」派生出来的预处理,比如聚类前必须标准化(K-Means 吃尺度)、PCA 降维本身、为异常检测做的统计/距离预处理。
- 强化学习特有:它的数据是「状态-动作-奖励」轨迹,预处理还多两步——状态标准化、奖励裁剪/归一化、经验回放 buffer 去重。思路同源,形态不同。
- 两边都要、动机不同:特征缩放。有监督为收敛快、距离模型不被带偏;无监督为聚类/降维不被大数值特征 dominate;做的是同一件事,理由不一样。
一句话记:涉及「标签 y」或「奖励 r」引导的步骤才分阵营,纯粹把数据弄干净、弄规整的步骤,四种学习都逃不掉。
把这几类学习方式记在心里,我们下面就把预处理本身拆开——先分清它和「数据清洗」到底是不是一回事。
二、预处理和清洗到底是不是一回事
很多人把「数据预处理」和「数据清洗」混着说,其实它们是有包含关系的,不是同义词。
数据清洗(Data Cleaning) 是预处理里的一个子集,它主要盯三件事:缺失值、异常值、重复值。你拿到一份脏数据,先把它弄「干净」,这就是清洗。
数据预处理(Data Preprocessing) 是更大的一个筐。除了清洗,它还包括数据集成(把多个来源拼到一起)、数据变换(归一化、编码、离散化)、数据规约(降维、抽样、压缩)。
一句话记:清洗是让数据「没毛病」,预处理是让数据「好喂给模型」。清洗解决的是「对不对」,预处理解决的是「合不合适」。
为啥要分清楚?因为很多新手一上来就想着「去掉异常值、填个缺失值」就完事了,结果模型还是跑不好——他只做了清洗,没做变换和规约,特征尺度天差地别,模型根本学不动。
三、为什么数据预处理决定模型上限:训练翻车案例与龙格现象
「数据科学家 80% 的时间花在数据准备上」这句话听着像吐槽,但它背后是真金白银的教训:预处理不只是把数据弄干净,它直接决定了模型能不能训、训得快不快、以及最终天花板在哪。下面先用几个训练现场的真实翻车,再借数值分析里的经典「龙格现象」,把这事说透。
1. 训练现场:不做预处理,模型是怎么死的
案例 A:量纲不一致,梯度下降「跛脚」
做房价预测,特征有「面积(㎡,几十到几百)」和「房龄(年,0~50)」。不标准化就丢进线性回归 / 神经网络,损失面会变成一条极狭长的峡谷——面积方向的梯度步长远大于房龄方向,优化器只能在谷壁之间反复横跳,收敛极慢甚至卡死。这不是调学习率能救的,是特征尺度没对齐。KNN、SVM、PCA 同理,距离被大数值特征主导。
案例 B:一个异常值,把整条回归线拽歪
身高-体重做线性回归,数据集里混进一条「身高 1.8m、体重 999kg」的脏记录。最小二乘对离群点极敏感,这一条就能把斜率整体拉偏,R² 直接腰斩。你以为模型学错了,其实是数据里有颗老鼠屎。树模型相对抗造,但异常值照样会诱导出奇怪的分裂点。
案例 C:缺失值,让训练直接报错或悄悄偏置
线性模型、SVM 遇到 NaN 直接崩;类别变量里有缺失,若不做处理被当成一个「未知类」,模型可能学出一套根本不存在的假规律。更隐蔽的是:缺失本身往往和标签相关(比如低收入群体更不填收入),无脑删行会引入选择性偏差,测出来的效果全是假的。
案例 D:类别没编码,算法当场罢工
把「红/黄/蓝」这种文本直接喂给要求数值矩阵的算法(带正则的回归、PCA、神经网络),不是报错就是被当成无意义数字乱算。编码是预处理里最容易被新手忘、却最基础的一步。
这四个案例的共同点:都不是「换个更强模型」能解决的,是预处理这道关没过。
2. 龙格现象:过拟合的数值分析原型
案例 B 那种「被少数点带偏」,在数值分析里有个更一般的名字——龙格现象(Runge Phenomenon)。
1901 年 Runge 发现:用高阶多项式在等距节点上做插值,节点之间的曲线会在两端剧烈振荡,而且阶数越高、振荡越凶。经典例子是函数 f(x)=1/(1+25x²),定义在区间 [-1, 1]:
% 龙格现象:高阶多项式插值在等距节点上端点炸裂
f = @(x) 1 ./ (1 + 25*x.^2); % 经典 Runge 函数
x = linspace(-1, 1, 400);
xe = linspace(-1, 1, 11); % 11 个等距节点
ye = f(xe);
p = polyfit(xe, ye, 10); % 10 次多项式硬穿所有点
yfit = polyval(p, x);
plot(x, f(x), 'k-', x, yfit, 'r--', xe, ye, 'bo');
legend('真函数', '10次插值', '采样点');
title('龙格现象:阶数越高,端点越疯');
跑出来你会看到:中间勉强贴住,两端直接甩飞。本质是模型容量(多项式阶数)太大,硬要去穿过每一个采样点,结果在样本之间的空白区疯狂过拟合。
3. 龙格现象和机器学习的血缘关系
这跟数据预处理有啥关系?关系大了——它是 ML 里一类坑的数值分析原型:
- 多项式特征扩展 = 亲手造龙格现象。做特征工程时常把 x 扩成 [x, x², x³, …]。若不做标准化,高阶项数值量级会爆炸(x=10 时 x³=1000),设计矩阵瞬间病态(条件数巨大),回归系数直接发散、数值不稳。数据变换那一步里「先标准化再扩展」,就是 ML 里的「降阶 + 缩放」解药。
- 脏数据 + 高容量模型 = 记住噪声。Runge 是「为穿过噪声点而过拟合」,ML 是「为记住脏样本而过拟合」,内核一模一样。清洗缺失/异常、加正则(岭回归/L2)、控制模型容量,等价于数值分析里「换 Chebyshev 节点 + 降阶 + 用样条」那套思路。
- 采样分布比数量更重要。龙格告诉我们:等距均匀采样反而坏事,节点往两端加密(Chebyshev)才好。ML 里同理——盲目堆数据不如分层抽样、先看分布(后面第五章的 EDA 和第四章的数据规约就是干这个的)。
一句话:龙格现象告诉我们,模型不是越复杂越好,喂进去的数据长什么样,比模型本身更先决定结果。而这正是预处理的地盘。
4. 回到开头
所以「花一半以上时间」不是夸张。预处理同时守着两道门:
- 数值稳定性之门:标准化、编码、合理采样,避免龙格式的病态和发散;
- 泛化上限之门:清洗噪声、控制容量、防泄露,避免过拟合和线上虚高。
这两道门没守好,后面再牛的算法也是白搭。
四、数据处理方法:四个大块
我们把预处理拆成四个动作来讲,这是公认最顺的分类方式(参考 Han 的《数据挖掘:概念与技术》那套框架)。
1. 数据清洗( Cleaning)
盯的是「错」和「漏」。
| 问题 | 常见表现 | 处理手段 |
|---|---|---|
| 缺失值 | 空值、NaN、占位符(如 0 或 ?) | 删除、均值/中位数填充、模型预测填充、保留为「缺失」类别 |
| 异常值 | 远超正常范围的离群点 | 删除、盖帽(winsorize)、用分位数/边界替换、单独建模 |
| 重复值 | 同一记录多次出现 | 去重 |
| 不一致 | 格式/单位/命名不统一 | 标准化、映射、规则校验 |
2. 数据集成(Integration)
把来自不同表、不同系统的数据拼成一个整体。
- 实体识别:判断「user_id=1001」和「uid=1001」是不是同一个人
- 冗余消除:两列高度相关(比如「总价」和「单价×数量」),留一个
- 冲突解决:同一字段在不同源里值不一致,按可信度规则选一个
这一步最容易出事的就是「悄悄把测试集信息混进来」,后文注意点里会专门讲。
3. 数据变换(Transformation)
把数据变成模型好吃的形态。
- 归一化 / 标准化:把不同尺度的特征拉到同一区间(Min-Max 到 [0,1])或同一分布(Z-score 均值 0 方差 1)
- 编码:类别变量(男/女、红/绿)转成数值。有序的用序号编码,无序的用 One-Hot(独热)
- 离散化:连续值切块,比如把「年龄」切成「少年/青年/中年/老年」
- 函数变换:对数、平方根,用来压一压长尾分布(比如收入、房价)
- 平滑:移动平均、分箱,消掉噪声
4. 数据规约(Reduction)
在不怎么丢信息的前提下,让数据变小、变快。
- 维度规约:PCA 降维、特征选择(卡方、互信息、LASSO)
- 数量规约:抽样(随机采样、分层采样)、用聚类中心点代替原始点
- 压缩:存储层面的压缩,对建模无感但省空间
五、标准处理步骤:照着这个顺序走不容易乱
别一上来就瞎操作,给一套「先想清楚再动手」的流程:
-
明确目标 & 理解业务
先搞明白你要预测啥、数据从哪来、字段代表什么含义。这一步偷懒,后面全白干。 -
探索性分析(EDA)
看分布、看缺失比例、看相关性、画直方图和箱线图。先把数据「看熟」,再决定怎么处理。MATLAB 里summary、histogram、boxplot、corrplot都很好用。 -
数据清洗
按上面「清洗」那块,处理缺失、异常、重复、不一致。 -
数据集成
多源合并、消冗余、解决冲突。 -
数据变换
归一化 / 标准化、编码、离散化、函数变换。 -
数据规约(按需)
特征太多就降维,样本太多就抽样。 -
划分训练集 / 测试集
这一步必须放在变换之后、建模之前,而且变换用的统计量只许来自训练集。 -
验证 & 回流
跑模型看效果,不好就回到某一步重做。预处理不是一次性的,是反复迭代的。
六、注意点:实战里容易翻车的地方
1. 数据泄露(Data Leakage)——最阴险的坑
不要在划分训练/测试集之前,就对整个数据集算均值、做归一化、填缺失值。否则测试集的信息「漏」进了训练过程,模型在测试集上虚高,上线就崩。
正确做法:先 cvpartition 划分,再只用训练集算 mu、sigma,然后拿同一组参数去 transform 测试集。
2. 异常值不是一律删
异常值可能是脏数据,也可能是真实的关键事件(比如欺诈交易、设备故障峰值)。先搞清楚它「为什么异常」再决定删不删。金融风控里,那些离群点往往才是你最该学的。
3. 缺失值填充别无脑填均值
均值填充会压缩方差、破坏变量间关系;类别变量填众数可能引入虚假主导类别。缺失比例太高(比如 >60%)的列,不如直接丢掉,或者单独做成「是否缺失」的标记特征,有时候这个标记本身很有预测力。
4. 类别编码要前后一致
训练时「城市」编码成 5 类,上线时来了个新城市没见过,直接报错或归到错类。用 categorical 并显式指定类别集合,能避免这类问题。
5. 量纲影响比你想的大
只要用到「距离」「梯度」「正则」「点积」的模型(线性回归、逻辑回归、SVM、KNN、K-Means、神经网络、PCA),都必须做尺度统一,否则大数值特征会一脚把别的特性踹飞。树模型(决策树、随机森林、XGBoost)可以不做,但做了也不亏。
6. 原始数据永远留一份
所有清洗、变换都在副本上做,原始 CSV 别动。哪天发现处理错了,还能重来。养成「只读原始、写新文件」的习惯。
7. 业务理解优先于统计规则
一个值「异常」不异常,得看业务。体温 41 度在体检数据里是异常,在 ICU 数据里可能是常态。别拿纯统计阈值一刀切,先问业务方。
8. 处理要有可复现性
每一步用代码写清楚(别在 Excel 里手动改),参数固化下来。三个月后你自己都忘了当时怎么处理的,复现不了就是灾难。
七、MATLAB 安装与使用(新手向)
下面说的 MATLAB,就是你在问题里写的「mathslab」,正式名字是 MATLAB(MathWorks 出品)。如果你是特指某个叫 MathSlab 的教学平台,那这节就不适用,告诉我我再改。
1. 安装
- 官网下载:去 mathworks.com,注册账号,选「下载试用版」(30 天全功能)或购买许可证。
- 学生/教育版:如果你在学校,走校园授权通常免费或极便宜,找你们学校的 IT 或 MATLAB portal 拿 license。
- 安装器:Windows 上跑
matlab_R20xxx_Win64.exe,按向导走,记得勾选你需要的工具箱——做数据预处理至少装 Statistics and Machine Learning Toolbox(统计与机器学习工具箱),很多fillmissing、isoutlier、normalize函数都在里面。 - 验证:装完打开,命令行输入
ver,能看到已装工具箱列表;输入version看版本号。
2. 四个最常用的窗口
- 命令行窗口(Command Window):现写现跑,适合试一行代码。
- 工作区(Workspace):看当前内存里有哪些变量、多大、啥类型。
- 编辑器(Editor)/实时脚本(Live Script,.mlx):写多行脚本、加文字说明和图,发公众号截图特别方便。强烈推荐用 Live Script,代码、公式、图、讲解能放一起。
- 当前文件夹(Current Folder):管理你的 .m / .mlx / 数据文件。
3. 两个核心数据类型(做数据处理必懂)
- 矩阵(matrix):MATLAB 的老本行,数值计算快。但矩阵要求每列类型一致,装混合类型表格不太方便。
- 表(table):做数据预处理的主力。它像 Excel 表,每列可以不同类型(数值、文本、类别),还能用列名访问,比如
T.Age、T(:,{'Age','Score'})。读 CSV 直接readtable,比手搓矩阵省事太多。
八、在 MATLAB 上做数据预处理与清洗(含代码)
下面给一套能直接跑的流程。假设我们有一份 raw.csv,字段有 Age(年龄)、Income(收入)、City(城市)、Score(分数)。
步骤 1:读入并先「看一眼」
% 读入数据,table 类型
T = readtable('raw.csv');
% 看整体概况:每列类型、缺失数、最小值最大值
summary(T)
% 看前几行
head(T)
% 单独看缺失情况
missCount = sum(ismissing(T));
disp(missCount);
summary 会直接告诉你每列有多少缺失、分布如何,EDA 第一步就靠它。
步骤 2:处理缺失值
% 数值列用中位数填充(比均值稳,不怕异常值)
T.Age = fillmissing(T.Age, 'median');
T.Income = fillmissing(T.Income, 'linear'); % 按序号线性插值,适合有序数据
% 类别列用众数填充,或直接标成 'Unknown'
T.City = fillmissing(T.City, 'constant', 'Unknown');
% 如果某行缺失太多想直接删:删掉任意列有缺失的行
% T = rmmissing(T);
% 反向查看哪些被填了:ismissing 配合原表对比即可
经验:数值用中位数,有序用插值,类别用常量,基本不会出大错。
步骤 3:处理异常值
% 用移动中位数法检测异常(默认基于中位数绝对偏差)
[outIdx, outlierScores] = isoutlier(T.Income);
% 把异常值用中位数盖掉(保留样本,不删行)
T.Income = filloutliers(T.Income, 'median', 'movmedian', 5);
% 想直接删异常行:
% T = rmoutliers(T, 'movmedian', 5);
% 画个箱线图确认一下
boxplot(T.Income); title('Income 异常值处理前后');
filloutliers 比「手写 if 大于 3 倍标准差就删」稳,因为它默认用的是稳健的 MAD 方法,不会被异常值本身带偏。
步骤 4:去重
% 去掉完全重复的行
T = unique(T);
% 只按某几列判断是否重复(比如按用户 ID)
% T = unique(T(:, 'UserID'), 'rows');
步骤 5:归一化 / 标准化
% Z-score 标准化:均值0,方差1(大多数模型的首选)
T.Age_z = normalize(T.Age, 'zscore');
T.Income_z = normalize(T.Income, 'zscore');
% Min-Max 归一化到 [0,1](神经网络、需要边界时常用)
T.Score_01 = normalize(T.Score, 'range');
% 或者直接用统计工具箱的 zscore
% [T.Age_z, mu, sigma] = zscore(T.Age); % 记下 mu/sigma 以后给测试集用
步骤 6:类别编码(One-Hot)
% 先转成 categorical,显式指定类别,避免新类别翻车
T.City = categorical(T.City, {'Beijing','Shanghai','Guangzhou','Unknown'});
% 无序类别做 One-Hot(独热)
cityOneHot = dummyvar(T.City); % 老版本稳妥写法
% 或用新版 onehotencode:onehotencode(T.City, 'cat', 1)
% 有序类别(如学历)直接序号编码
% T.EduLevel = double(categorical(T.EduLevel, {'高中','本科','硕士','博士'}, 'Ordinal', true));
步骤 7:正确划分训练/测试集(防泄露)
% 先划分,再在训练集上算统计量
cv = cvpartition(height(T), 'HoldOut', 0.3); % 70%训练 30%测试
T_train = T(training(cv), :);
T_test = T(test(cv), :);
% 只在训练集上算均值和标准差
mu = mean(T_train.Income, 'omitnan');
sigma = std(T_train.Income, 'omitnan');
% 用同一组参数 transform 测试集,绝不用测试集自己算
T_test.Income_z = (T_test.Income - mu) / sigma;
T_train.Income_z = (T_train.Income - mu) / sigma;
这一步就是前面「注意点 1」里说的防泄露写法,照着抄基本不会错。
步骤 8:整理成模型输入
% 挑出数值特征列,拼成矩阵 X,标签列 y
featureNames = {'Age_z','Income_z','Score_01'};
X = T_train{:, featureNames};
y = T_train{:, 'Label'}; % 假设 Label 是目标列
% 到这儿,X 和 y 就能直接丢给 fitcensemble / fitglm / fitcsvm 之类的训练函数了
九、同一个预处理,两种学习都吃得下(MATLAB 示例)
预处理做完,X 是数值矩阵、y 是标签。这个时候同一份干净数据,可以分别交给有监督和无监督模型——正好印证第一节说的「预处理是共同地基,只有标签相关步骤才分阵营」。
% 假设 X 是预处理后的数值特征矩阵(全部样本),y 是对应的标签(有监督才需要)
%% 有监督:KNN 分类器
% 用训练集训练,测试集看准确率
mdl_sup = fitcknn(X_train, y_train, 'NumNeighbors', 5);
pred = predict(mdl_sup, X_test);
acc = sum(pred == y_test) / numel(y_test);
fprintf('有监督 KNN 分类准确率:%.2f%%\n', acc * 100);
%% 无监督:K-Means 聚类
% 不需要 y,直接按特征把样本分成 3 堆
[idx, C] = kmeans(X, 3); % X 是全部干净数据
disp('每堆的中心点:');
disp(C);
% 聚类结果可拿去打标签、做客户分群,或当异常检测用
% 看一眼两条线“吃”的是不是同一份 X
whos X
要点:
- 有监督那条线,
fitcknn吃X_train和y_train,最后用X_test算准确率——y 只在这条线出现。 - 无监督那条线,
kmeans只吃X,完全不碰y,自己把样本分成几堆。 - 它们喂的是同一套预处理产物,区别只在「要不要标签」。这就是开头说的:预处理是地基,两种楼都盖在上面。
想换模型很简单:fitcknn 换成 fitctree / fitcensemble 是有监督,kmeans 换成 dbscan 是无监督,预处理代码一行都不用改。半监督可以在此基础上加「伪标签」回灌,强化学习则把 X 换成「状态」、再加奖励裁剪——地基还是同一套。
十、一个最小可运行示例(直接照抄)
把下面这段存成 preprocess_demo.mlx,配一份带缺失和异常的小 CSV 就能跑通整条链路:
%% 最小预处理 demo
T = table([23; NaN; 45; 999; 31; 28], ...
categorical({'BJ';'SH';'BJ';'SH';'Unknown';'BJ'}), ...
'VariableNames', {'Age','City'});
% 缺失
T.Age = fillmissing(T.Age, 'median');
% 异常
T.Age = filloutliers(T.Age, 'median');
% 编码
T.City = categorical(T.City, {'BJ','SH','Unknown'});
onehot = dummyvar(T.City);
disp('清洗后预览:');
disp(T);
disp('One-Hot 编码:');
disp(onehot);
跑完你会看到:NaN 被中位数填了、999 被盖掉了、城市变成了 0/1 编码矩阵。整条链路通了。
十一、顺带聊聊:数据清洗工具都有哪些?PowerBI、BI 工具、MATLAB 各算哪边的?
前面我们一直在 MATLAB 上折腾清洗,你大概率心里嘀咕过:平时大家到底用什么工具搞数据清洗?PowerBI 算不算?那种 BI 工具算不算?一般人真的会在 MATLAB 上做清洗吗?这一节把工具全景摆一下,顺便给 MATLAB 定个位——免得你要么以为 MATLAB 是清洗主力,要么反过来以为它没法清洗。
1. 常见的数据清洗工具有哪些
先把市面上常碰到的分个类,免得混在一起说:
-
编程语言 / 库(主力干活层)
- Python:pandas、numpy、scikit-learn 的 preprocessing 模块,这是现在数据科学和 ML 圈的绝对主力。数据量不大、要喂模型,基本就是它。
- R:dplyr、tidyr,统计圈和学术圈的好朋友。
- MATLAB:就是我们前面用的那套,table +
fillmissing+normalize,自带统计工具箱。 - SQL:很多脏数据在数据库里就先洗了,
WHERE过滤、JOIN校验、窗口函数去重,这是离数据最近的一层清洗。
-
可视化 / 探索式清洗工具(点鼠标层)
- OpenRefine:专门搞脏数据清洗的利器,聚类式去重、按规则批量改值、看分布找异常,免费开源,上手快。
- Excel / Google Sheets:别笑,真实世界里大量清洗就是在这里手动搞的,小数据集够用,但不可复现、易手滑。
- Tableau Prep、Alteryx、KNIME:拖拽式数据流,把「过滤→连接→填充→去重」画成流程图,业务同学爱用,还能落脚本。
-
大数据 / 工程层
- Spark(PySpark):数据量大到内存放不下,就用它分布式洗。
- Talend、Informatica、DataStage:企业级 ETL 流水线,定时跑、有血缘追踪,公司数据平台那一层。
-
BI 工具(这里要单独拎出来说,见下):PowerBI、Tableau、FineBI、Superset 等。
2. PowerBI 算吗?一般 BI 工具算吗?
算一半,但得讲清楚「算哪一半」。
BI 工具(PowerBI、Tableau 那一挂)确实能「洗数据」,但它们洗的层次和我们前面说的「为机器学习喂料」的清洗,目的不太一样:
- BI 里能做的清洗:PowerBI 自带的 Power Query 编辑器里可以删列、改类型、替换值、合并查询、做透视/逆透视、按规则填充——这些确实是在清洗。很多人第一份数据清洗就是在 Power Query 里完成的。
- 但它洗的是「为了出报表、做看板」的数据,不是「为了训练模型」的数据。报表不在乎你用中位数填还是直接过滤掉、不在乎 One-Hot 编码、不在乎训练/测试集分开防泄露——这些 ML 专属的动作,BI 工具基本没有原生概念。
- 所以准确说法:BI 工具是「业务探索 + 报表前清洗」的好工具,但不算「机器学习数据预处理」的主力。它洗完的数据,真要喂模型,往往还得导出来进 Python/MATLAB 再走一遍我们前面那八步。
一句话:BI 做「看得见的清洗」,ML 做「喂得进去的清洗」,目标不同,工具不同,别混为一谈。
3. 一般人会在 MATLAB 上做数据清洗吗?
坦白讲,不会是大多数人的首选。
数据科学和 ML 的主流生态早就是 Python(pandas)+ R 的天下了。你问一个今天入行的数据科学家「你在哪洗数据」,十有八九答 pandas。MATLAB 在清洗这件事上:
- 优点:矩阵/向量化运算极顺手、统计工具箱函数齐全(
fillmissing/isoutlier/normalize一行搞定)、和后面的建模/仿真/控制系统同生态,学术界和工程仿真圈(信号处理、控制系统、图像处理)天然就用它。 - 缺点:贵(要授权)、生态小(清洗用的第三方包远没 pandas 丰富)、协作差(同事未必有 license,脚本不好共享)。
所以现实是:如果你本就在 MATLAB 生态里做科研/工程仿真,那顺手在 MATLAB 上把清洗做了天经地义;但如果你是纯做 ML/数据分析,通常不会为了清洗专门开 MATLAB。
4. 那什么情况才会在 MATLAB 上做数据清洗?
给你划几条明确的场景,命中哪条就用,没命中就别硬上:
- 数据源头就是 MATLAB 工作流:比如从 Simulink 仿真出来、从信号处理/图像处理工具箱出来、从工业传感器采集进 MATLAB 的。数据已经在
.mat/table里了,就地清洗最省事,没必要导出去再导回来。 - 清洗完紧接着要建模/仿真:你清洗是为了后面跑
fitcknn、训练神经网络、做控制系统辨识。同一语言、同一内存、同一套矩阵,零切换成本。 - 矩阵/数值运算密集的清洗:比如要对大规模数值矩阵做向量化过滤、频域去噪、矩阵补全、用 SVD/PCA 做降维清洗——MATLAB 在这种数值活上比手写循环快得多,可读性也高。
- 教学 / 论文复现 / 课程作业:很多高校控制、信号、统计课程默认 MATLAB,作业和论文代码都是
.m/.mlx,那清洗顺手用 MATLAB 写进同一份报告,截图直接贴进论文,省事。 - 没有 Python 环境、但有 MATLAB 授权:现实里有些公司/实验室就是只装了 MATLAB,那它在那你就在它那洗,能用就行,别纠结生态。
反过来,下面这些情况就别在 MATLAB 上洗了:数据在数据库里要 ETL、数据量大到要 Spark、团队用 Python 协作、要接 sklearn 的 pipeline、预算紧不想买 license——这些直接上 Python/SQL/BI,别硬凹 MATLAB。
5. 一句话总结工具怎么选
别迷信某个工具。清洗的本质是「按规则把脏数据变干净」,哪个工具能让你又快又准又复现,就用哪个:
- 小数据、要出报表 → Excel / PowerBI(Power Query)/ OpenRefine
- 大数据、要喂模型、团队协作 → Python(pandas)+ SQL,大了上 Spark
- 本就在 MATLAB 科研/仿真生态、清洗后直接建模 → MATLAB 就地做,就是我们前面写的那些代码
- 企业定时流水线 → Talend / Informatica / KNIME
前面那八步流程、八大注意点,跟用什么工具无关——换 Python 是同一套思路,换 MATLAB 也是同一套思路,换 BI 只是洗得浅一层。工具是手里的锤子,干净数据是你要的钉子。
十二、让智能体 Agent 做预处理?能完全放手吗?
前面讲的每一步,看着都像是人拍脑袋定的规则。那问题自然就来了:这些预处理步骤都是人为制定的吗?现在 Agent 这么火,能不能让智能体把脏活全包了?又能不能彻底放手?这一节把话说透。
1. 预处理真是「人为制定」的吗?
不全是,得分两层看:
- 策略层靠人:什么算「异常」、缺失该不该删、某列业务上怎么编码,这些判断来自领域知识。比如「体温 41 度在 ICU 不算异常」(呼应注意点 7),算法自己不知道,得人告诉它。
- 执行层是算法:缺失值填充、标准化、One-Hot,本质都是有明确定义的算法,人只是「选方法、定超参」。
- 所以现实是「人定策略 + 算法执行」的混合。而且这层「选方法」也早被自动化了——AutoML(auto-sklearn、TPOT、H2O)和自动特征工程(FeatureTools)干的就是这事。
2. 智能体确实能接管大部分机械活
一个数据分析 Agent 的工作流,和前面「标准处理步骤」那节的八步流程几乎一一对应:读数据 → summary 看分布 → 提议清洗方案 → 写代码执行 → 验证 → 回流。区别只在于它用工具调用跑,而不是你手敲。
它能干好的,是那些确定性的活:检测缺失比例、跑 summary、按规则填值、去重、标准化、产出可复现脚本(呼应注意点 8)。这些它比人快且稳。现在的 LLM Agent 甚至能读字段名和样例,自己推断「这列大概是类别、那列大概是金额」,起草预处理代码——像个初级分析师。
给个具体点的 prompt 例子:
你是一个数据分析 agent。请对 raw.csv 做预处理:
1. 先 summary 看缺失与分布;
2. 数值列缺失用中位数填,类别列填 'Unknown';
3. 用 MAD 法处理异常,保留样本不删行;
4. 类别做 One-Hot,显式指定类别集合;
5. 先划分训练/测试集,再只在训练集上标准化,防泄露;
6. 输出干净 table + 一段说明,并单独列出你不敢擅自决定的点。
注意最后一条——这才是关键。
3. 但「完全放手」不行,四个绕不开的理由
- 业务语义 Agent 不懂(呼应注意点 7):什么算异常、什么算合理,得业务定。Agent 拿纯统计阈值一刀切,会把 ICU 的正常高体温当异常清掉。
- 数据泄露风险(呼应注意点 1):Agent 图省事对整个数据集先标准化,测试集信息就漏进去了,线上虚高。得靠人为约束流水线顺序。
- 它会「好心办坏事」删掉信号(呼应注意点 2):欺诈、故障这些最有价值的离群点,Agent 可能当成脏数据清掉。删不删得人拍板。
- 幻觉与沉默失败:LLM Agent 会写出跑不通的代码,或编出看似合理的统计结论。预处理里一个错填充,模型不报错却悄悄偏了——人得 review。
- 再补一条:责任与可复现(呼应注意点 8):生产环境模型出问题要有人背锅、要能复现。完全黑箱放手,出了事查无可查。
4. 现实里的正确姿势:人定边界,Agent 开路
不是「人做 vs Agent 做」二选一,而是 human-in-the-loop(人在环内):Agent 当 Copilot,把重复、确定的活全包了,人只审核那几个高风险决策点——异常策略、编码方案、业务规则、泄露防护。
落地三件套:
- 给 Agent 明确的「禁区」和顺序约束(尤其防泄露);
- 让它产出「预处理报告 + 待确认清单」,而不是直接改原始数据(呼应注意点 6:原始数据留一份);
- 人签完字再跑,且全程代码化、可复现。
说到底,前面说的「地基」原则不变——Agent 只是更快地把地基打好,但地基打多深、哪块不能动,还是人说了算。
十三、收个尾
数据预处理和数据清洗,听起来不如「我训练了个 Transformer」那么唬人,但它决定了你后面所有努力是建立在沙子上还是石头上。开头说的几种学习方式,最后都回到同一份干净数据上——预处理就是那个共同的地基。
记住三句话就够了:
- 先理解业务,再看数据,最后才动手处理——顺序不能乱。
- 清洗解决「对不对」,预处理解决「合不合适」——两个都得做。
- 变换的统计量只许来自训练集——这是防泄露的命门。
MATLAB 在表格处理这块其实挺顺手的,readtable + fillmissing + isoutlier + normalize + categorical 这一套组合拳打下来,大部分脏活都能 cover 住。Live Script 还能把代码和图放一起,写报告、发公众号直接截图,省心得很。
与君共勉~

浙公网安备 33010602011771号