机器学习_第三篇_数据预处理

真正上手做过几个项目的人都知道,算法往往只占工作量的两成,剩下八成都在和数据较劲。
这篇文章我们先把机器学习的几种学习方式(有监督 / 无监督 / 半监督 / 强化学习)在开头理顺,搞清楚预处理到底是在为谁铺路,后面讲方法才不迷糊;然后再把「数据预处理」和「数据清洗」拆开讲清楚:它们是什么、有哪些方法、按什么步骤走、坑在哪儿,最后手把手在 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)
  • 数量规约:抽样(随机采样、分层采样)、用聚类中心点代替原始点
  • 压缩:存储层面的压缩,对建模无感但省空间

五、标准处理步骤:照着这个顺序走不容易乱

别一上来就瞎操作,给一套「先想清楚再动手」的流程:

  1. 明确目标 & 理解业务
    先搞明白你要预测啥、数据从哪来、字段代表什么含义。这一步偷懒,后面全白干。

  2. 探索性分析(EDA)
    看分布、看缺失比例、看相关性、画直方图和箱线图。先把数据「看熟」,再决定怎么处理。MATLAB 里 summaryhistogramboxplotcorrplot 都很好用。

  3. 数据清洗
    按上面「清洗」那块,处理缺失、异常、重复、不一致。

  4. 数据集成
    多源合并、消冗余、解决冲突。

  5. 数据变换
    归一化 / 标准化、编码、离散化、函数变换。

  6. 数据规约(按需)
    特征太多就降维,样本太多就抽样。

  7. 划分训练集 / 测试集
    这一步必须放在变换之后、建模之前,而且变换用的统计量只许来自训练集。

  8. 验证 & 回流
    跑模型看效果,不好就回到某一步重做。预处理不是一次性的,是反复迭代的。


六、注意点:实战里容易翻车的地方

1. 数据泄露(Data Leakage)——最阴险的坑
不要在划分训练/测试集之前,就对整个数据集算均值、做归一化、填缺失值。否则测试集的信息「漏」进了训练过程,模型在测试集上虚高,上线就崩。
正确做法:先 cvpartition 划分,再只用训练集算 musigma,然后拿同一组参数去 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(统计与机器学习工具箱),很多 fillmissingisoutliernormalize 函数都在里面。
  • 验证:装完打开,命令行输入 ver,能看到已装工具箱列表;输入 version 看版本号。

2. 四个最常用的窗口

  • 命令行窗口(Command Window):现写现跑,适合试一行代码。
  • 工作区(Workspace):看当前内存里有哪些变量、多大、啥类型。
  • 编辑器(Editor)/实时脚本(Live Script,.mlx):写多行脚本、加文字说明和图,发公众号截图特别方便。强烈推荐用 Live Script,代码、公式、图、讲解能放一起。
  • 当前文件夹(Current Folder):管理你的 .m / .mlx / 数据文件。

3. 两个核心数据类型(做数据处理必懂)

  • 矩阵(matrix):MATLAB 的老本行,数值计算快。但矩阵要求每列类型一致,装混合类型表格不太方便。
  • 表(table):做数据预处理的主力。它像 Excel 表,每列可以不同类型(数值、文本、类别),还能用列名访问,比如 T.AgeT(:,{'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

要点:

  • 有监督那条线,fitcknnX_trainy_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 上做数据清洗?

给你划几条明确的场景,命中哪条就用,没命中就别硬上:

  1. 数据源头就是 MATLAB 工作流:比如从 Simulink 仿真出来、从信号处理/图像处理工具箱出来、从工业传感器采集进 MATLAB 的。数据已经在 .mat / table 里了,就地清洗最省事,没必要导出去再导回来。
  2. 清洗完紧接着要建模/仿真:你清洗是为了后面跑 fitcknn、训练神经网络、做控制系统辨识。同一语言、同一内存、同一套矩阵,零切换成本。
  3. 矩阵/数值运算密集的清洗:比如要对大规模数值矩阵做向量化过滤、频域去噪、矩阵补全、用 SVD/PCA 做降维清洗——MATLAB 在这种数值活上比手写循环快得多,可读性也高。
  4. 教学 / 论文复现 / 课程作业:很多高校控制、信号、统计课程默认 MATLAB,作业和论文代码都是 .m/.mlx,那清洗顺手用 MATLAB 写进同一份报告,截图直接贴进论文,省事。
  5. 没有 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,把重复、确定的活全包了,人只审核那几个高风险决策点——异常策略、编码方案、业务规则、泄露防护。

落地三件套:

  1. 给 Agent 明确的「禁区」和顺序约束(尤其防泄露);
  2. 让它产出「预处理报告 + 待确认清单」,而不是直接改原始数据(呼应注意点 6:原始数据留一份);
  3. 人签完字再跑,且全程代码化、可复现。

说到底,前面说的「地基」原则不变——Agent 只是更快地把地基打好,但地基打多深、哪块不能动,还是人说了算


十三、收个尾

数据预处理和数据清洗,听起来不如「我训练了个 Transformer」那么唬人,但它决定了你后面所有努力是建立在沙子上还是石头上。开头说的几种学习方式,最后都回到同一份干净数据上——预处理就是那个共同的地基。

记住三句话就够了:

  1. 先理解业务,再看数据,最后才动手处理——顺序不能乱。
  2. 清洗解决「对不对」,预处理解决「合不合适」——两个都得做。
  3. 变换的统计量只许来自训练集——这是防泄露的命门。

MATLAB 在表格处理这块其实挺顺手的,readtable + fillmissing + isoutlier + normalize + categorical 这一套组合拳打下来,大部分脏活都能 cover 住。Live Script 还能把代码和图放一起,写报告、发公众号直接截图,省心得很。

与君共勉~

posted @ 2026-08-18 17:05  昂流  阅读(27)  评论(0)    收藏  举报
//替换成自己路径的js文件 hhttp(s)://static.tctip.com/tctip-1.0.4.min.js