两维数据标准差差 100 倍。 同样学习率 0.01 跑 200 步:不标准化时损失在 0.69 到 2.73 之间来回荡,最后停在 1.4238; 标准化后单调降到 0.4793,差 3.0 倍。
上一节调超参。这一节讲更基础的一件事:喂进去的数据本身要不要先处理。很多时候它比调参有用得多。
一、标准化在解决什么问题
标准化就是每个特征减去自己的均值、再除以自己的标准差。做完之后所有特征都在 0 附近、标准差为 1。 为什么要这么做?因为梯度下降用的是一个统一的学习率。 特征量纲差得远时,同一个步长对一维太大、对另一维太小。 Demo 造了两维数据,第二维乘了 100。第一维标准差 1.00、第二维 103.14。 梯度下降在第二维上会剧烈震荡(步长乘上大梯度,直接跨过最优点),在第一维上几乎不动。 结果是损失不降反升、来回跳。
二、实测:震荡 vs 单调
不标准化的损失轨迹:0.69 起步,第 1 步冲到 2.73,第 10 步回到 1.01,第 50 步又窜到 2.26, 第 200 步停在 1.42。 标准化之后:0.69、0.69、0.62、0.48,一路单调下降。 两者差 3.0 倍。而且不标准化那个数完全不可信——它只是震荡中的某个瞬间,换个迭代次数结论就变。 这件事的教训:「训练不收敛」很多时候不是学习率的问题,是数据没标准化。 先去检查特征量纲, 再考虑调学习率。 反过来说,如果你在一个已经标准化的数据上调学习率,那才是有意义的调参。
三、哪些模型需要,哪些不需要
需要:所有基于梯度的模型——线性回归、逻辑回归、神经网络、SVM。它们对特征的绝对尺度敏感。 不需要:树模型——决策树、随机森林、XGBoost、LightGBM。 树只看「某个特征大于某个阈值」,做单调变换不改变切分顺序,所以标准化没用。 部分需要:K 近邻、K 均值这类基于距离的模型。它们必须标准化,否则量纲大的特征会主导距离。 这不是梯度的问题,是距离度量的定义问题。 所以「要不要标准化」取决于模型,不是「最佳实践」里的一句空话。 别人说「一定要标准化」,通常是在做神经网络。
四、预处理还包括什么
缺失值:删行、填均值/中位数、或者用模型预测。 要注意「缺失」本身可能是信息(比如「没填收入」和「收入低」常常相关), 可以加一个「是否缺失」的标记列。 类别编码:独热编码(类别少时)、目标编码(类别多时)、 或者直接交给支持类别的模型(如 LightGBM)。 异常值:可以截断(缩尾)、可以删、也可以保留。 删之前先想清楚——异常值可能是数据错误,也可能是最有价值的样本(欺诈、故障)。 分布变换:偏态严重的特征可以取对数或开方,让它接近正态。这对线性模型有帮助。 这些处理都要在训练集上算出参数、再套到测试集上。 用全量数据算均值和标准差,等于把测试集的信息泄露进训练,分数会虚高。这是预处理里最容易犯的错。
五、动手 Demo:标准化:不处理时损失在 1.0 和 2.7 之间来回荡
造 300 个 2 维样本,第二维乘 100 造出量纲差; 用同一个学习率 0.01、同一个逻辑回归跑 200 步,分别记录原始数据和标准化数据在第 1、10、50、 200 步的交叉熵损失。
X = np.column_stack([a, b * 100.0]) # 第二维量纲差 100 倍
Z = (X - X.mean(0)) / X.std(0) # 标准化
for t in range(iters):
p = H.sigmoid(Z @ w + bb)
w -= lr * (Z.T @ (p - y) / n)
bb -= lr * float((p - y).mean())
实跑输出:
--------------------------------------------------------------------
数据预处理:不标准化,梯度下降在震荡里打转
--------------------------------------------------------------------
数据 300 个样本、2 维
第一维标准差 1.00
第二维标准差 103.14
同样的学习率 0.01,跑 200 步,看损失怎么降:
第几步 不标准化 标准化后
---------------------------
1 2.7299 0.6915
10 1.0091 0.6770
50 2.2612 0.6198
200 1.4238 0.4793
不标准化 200 步后 损失 1.4238
标准化后 200 步后 损失 0.4793
差距 3.0 倍
不标准化那列不是「不动」,是**来回荡**:0.69 起步,第 1 步冲到 2.73,第 10 步回到 1.01,第 50 步又窜到 2.26,最后停在 1.42。
原因是第二维的数值到几百,梯度在这一维上大得离谱,学习率 0.01 乘上去就跨过头;而第一维梯度很小,几乎原地踏步。一个步长同时满足两个尺度,做不到。
标准化之后两维都在 0 附近、标准差 1,梯度量级一致,同一个学习率对两边都合适,损失单调降到 **0.4793**。
所以「标准化」不是为了好看,是为了让梯度下降能用同一个步长同时应付所有维度。
这一步在树模型(随机森林、XGBoost)上不需要——树只看大小顺序,不看绝对值。但在任何基于梯度的模型上都建议做,包括线性模型和所有神经网络。
第二维标准差 103.14,不是正好 100——因为乘 100 之后又叠加了随机波动。 这个细节说明标准化必须用实际算出来的标准差,不能拍脑袋填 100。 不标准化那列四个数是 2.73、1.01、2.26、1.42,完全不单调。它不是在收敛,是在最优点附近绕大圈。 标准化那列 0.69、0.68、0.62、0.48,单调下降。 同一条代码、同一个学习率、同一个迭代次数,唯一的差别是输入有没有处理。 差距 3.0 倍。这个数字还会随迭代次数变——如果只跑 10 步,差距是 1.5 倍; 跑 1000 步,差距可能更大。所以「差几倍」要看步数,不能当固定值记。
30 秒实验
- 把第二维乘 10 而不是 100,看不标准化还能不能收敛。
- 把学习率从 0.01 降到 0.001,看不标准化那列会不会变好。
- 想一想:为什么用全量数据算均值和标准差会造成信息泄露?
常见误区
- 「所有模型都要标准化」——树模型完全不需要,做了也没坏处但没意义。
- 「训练不收敛就调学习率」——先检查特征量纲,这个更常见。
- 「用全量数据算标准化参数」——测试集信息会泄露进训练,分数虚高。
自测三问(点开对答案)
1. 标准化在数学上做了什么? —— 每个特征减均值、除以标准差,变成 0 均值 1 方差。 2. 为什么梯度下降需要标准化? —— 它用一个统一学习率,量纲差得远时同一个步长对有的维度太大、有的太小。 3. 哪些模型不需要标准化? —— 树模型,因为它们只比较大小顺序,对绝对值不敏感。数据标准化了,还有一件事:是不是所有特征都该喂进去。下一节讲特征选择。
- ☐ (本节完,下一节 9.2.7 特征选择:降低维度、提高模型性能的有效方法)