机器学习 多变量的特征缩放和学习率
·
一、多变量线性回归梯度下降调参实验
这是一个房价预测的多变量线性回归任务:
- 特征:房屋面积(平方英尺)、卧室数量、楼层数、房龄
- 目标:预测房价(千美元)
- 核心任务:调试梯度下降的学习率 α,观察不同 α 对收敛的影响。
1. 环境与数据加载
import numpy as np
import matplotlib.pyplot as plt
from lab_utils_multi import load_house_data, run_gradient_descent, plot_cost_i_w
# 加载数据集
X_train, y_train = load_house_data()
X_features = ['size(sqft)','bedrooms','floors','age']
X_train:形状为(m, n),其中m是样本数,n=4是特征数y_train:形状为(m,),是房价标签
2. 特征 - 价格关系可视化
从散点图可以看出:
- 面积(size)与价格有明显的正相关趋势,是强特征
- 卧室数、楼层数、房龄与价格的线性相关性较弱,是弱特征 / 噪声特征
3. 多变量梯度下降公式
重复迭代直到收敛:

其中偏导数为:

4. 不同学习率的效果对比
(1)学习率过大:α=9.9e−7
- 现象:成本函数(Cost)随迭代次数上升,模型不收敛
- 原因:学习率过高,参数更新步长过大,导致在损失函数曲面上来回震荡,甚至越过最小值点,成本不降反升
- 可视化验证:Cost vs Iteration 曲线持续上升,Cost vs w [0] 曲线显示参数在最小值两侧大幅来回跳动
(2)学习率适中:α=9e−7
- 现象:成本函数随迭代次数稳定下降,模型收敛
- 特点:参数在最小值附近小幅波动,每次迭代都向最优解靠近,收敛速度较快
- 可视化验证:Cost vs Iteration 曲线单调下降,Cost vs w [0] 曲线显示参数在最小值附近小幅震荡
(3)学习率过小:α=1e−7
- 现象:成本函数缓慢下降,模型收敛,但速度远慢于适中的 α
- 特点:参数更新步长太小,每次迭代只向最优解移动很小的距离,需要更多迭代次数才能收敛
- 可视化验证:Cost vs Iteration 曲线下降平缓,Cost vs w [0] 曲线显示参数一直向最小值靠近,没有越过最小值
5.关键结论与调参技巧
(1)学习率 α 的影响规律
| 学习率大小 | 成本函数变化 | 收敛性 | 特点 |
|---|---|---|---|
| 过大 | 上升 / 震荡 | 不收敛 | 参数更新步长过大,越过最小值点 |
| 适中 | 稳定下降 | 收敛 | 收敛速度快,效果好 |
| 过小 | 缓慢下降 | 收敛 | 收敛速度慢,需要更多迭代 |
(2)如何选择合适的 α
- 调试方法:从较大的 α 开始尝试,观察成本函数曲线:
- 若成本上升 / 震荡,说明 α 过大,除以 10 或 2,重新尝试
- 若成本缓慢下降,可适当增大 α,提高收敛速度
- 找到成本稳定下降的最大 α,即为合适的学习率
- 收敛判断:当成本函数的下降幅度小于某个阈值(如10−3)时,可认为模型收敛
(3)优化建议:特征缩放
本实验中,不同特征的数值范围差异很大(如面积在 1000-3000,房龄在 0-100),会导致梯度下降收敛缓慢。可以通过特征缩放(如标准化 / 归一化)解决:
# 标准化示例
X_mean = X_train.mean(axis=0)
X_std = X_train.std(axis=0)
X_norm = (X_train - X_mean) / X_std
缩放后,不同特征的数值范围相近,梯度下降的收敛速度会显著提升,对学习率的选择也更友好。
import numpy as np
import matplotlib.pyplot as plt
from lab_utils_multi import load_house_data, run_gradient_descent, plot_cost_i_w
# 1. 加载数据
X_train, y_train = load_house_data()
X_features = ['size(sqft)','bedrooms','floors','age']
# 2. 可视化特征与价格的关系
fig,ax=plt.subplots(1, 4, figsize=(12, 3), sharey=True)
for i in range(len(ax)):
ax[i].scatter(X_train[:,i],y_train)
ax[i].set_xlabel(X_features[i])
ax[0].set_ylabel("Price (1000's)")
plt.show()
# 3. 调试不同学习率
# α=9.9e-7(过大)
_,_,hist = run_gradient_descent(X_train, y_train, 10, alpha = 9.9e-7)
plot_cost_i_w(X_train, y_train, hist)
# α=9e-7(适中)
_,_,hist = run_gradient_descent(X_train, y_train, 10, alpha = 9e-7)
plot_cost_i_w(X_train, y_train, hist)
# α=1e-7(过小)
_,_,hist = run_gradient_descent(X_train, y_train, 10, alpha = 1e-7)
plot_cost_i_w(X_train, y_train, hist)
二.分数归一化
1.为什么要做特征缩放?
在房价预测任务中,不同特征的数值范围差异极大:
- 房屋面积:约
1000-3000平方英尺 - 卧室数 / 楼层数:约
0-4 - 房龄:约
0-100
这种尺度差异会带来两个严重问题:
- 参数更新失衡:梯度下降时,数值大的特征会主导成本函数,导致权重更新步长差异巨大,模型收敛缓慢甚至震荡。
- 成本曲面扭曲:成本等高线会变成 “狭长椭圆”,梯度下降需要大量迭代才能找到最小值;缩放后等高线近似圆形,收敛速度大幅提升。
2.三种常见特征缩放方法
| 方法 | 公式 | 特点 |
|---|---|---|
| 最大缩放 | xi=xi/max(x) | 仅适用于非负特征,简单易用 |
| 均值归一化 | xi=xi−μ/max(x)−min(x) | 将特征缩放到[-1,1]区间 |
| Z 分数归一化 | xi=xi−μ/σ | 均值为 0、标准差为 1,对异常值更鲁棒,工业界最常用 |
其中,μj 是特征j的均值,σj 是特征j的标准差:

3.Z 分数归一化实现与验证
import numpy as np
def zscore_normalize_features(X):
"""
对特征矩阵X按列进行Z分数归一化
Args:
X (ndarray (m,n)): 输入数据,m个样本,n个特征
Returns:
X_norm (ndarray (m,n)): 归一化后的数据
mu (ndarray (n,)): 每个特征的均值
sigma (ndarray (n,)): 每个特征的标准差
"""
# 计算每列(特征)的均值
mu = np.mean(X, axis=0)
# 计算每列(特征)的标准差
sigma = np.std(X, axis=0)
# 归一化:(X - 均值) / 标准差
X_norm = (X - mu) / sigma
return X_norm, mu, sigma
归一化效果验证
# 加载数据
X_train, y_train = load_house_data()
X_features = ['size(sqft)','bedrooms','floors','age']
# 归一化处理
X_norm, X_mu, X_sigma = zscore_normalize_features(X_train)
# 查看归一化前后的特征范围
print(f"原始数据峰峰值(每列): {np.ptp(X_train, axis=0)}")
print(f"归一化后峰峰值(每列): {np.ptp(X_norm, axis=0)}")
- 原始数据:峰峰值跨度从几千(面积)到个位数(卧室数)
- 归一化后:所有特征的峰峰值都缩小到 2-6 之间,数值范围趋于一致
4.归一化前后的梯度下降对比
(1)关键差异
| 对比项 | 未归一化 | 归一化后 |
|---|---|---|
| 学习率 | 只能取极小值(如10−7级别),否则震荡 | 可以取较大值(如 0.1),收敛速度快 |
| 迭代次数 | 需要上千次迭代才能收敛 | 几百次迭代即可收敛 |
| 成本曲线 | 下降缓慢,易震荡 | 快速平滑下降,稳定收敛 |
| 成本等高线 | 狭长椭圆,梯度下降路径曲折 | 近似圆形,梯度下降路径直接 |
(2) 归一化后梯度下降代码
# 归一化后的数据运行梯度下降,学习率设为0.1(远大于之前的1e-7)
w_norm, b_norm, hist = run_gradient_descent(X_norm, y_train, 1000, alpha=1.0e-1)
- 结果:迭代 1000 次后成本就稳定收敛,参数梯度趋近于 0,收敛速度大幅提升。
5.归一化后预测新数据
⚠️ 重要提醒:对新数据进行预测时,必须使用训练集的均值和标准差进行归一化,不能用测试数据的统计量!
# 预测一套1200平方英尺、3间卧室、1层、房龄40年的房屋价格
x_house = np.array([1200, 3, 1, 40])
# 使用训练集的均值和标准差归一化
x_house_norm = (x_house - X_mu) / X_sigma
print(x_house_norm) # [-0.53 0.43 -0.79 0.06]
# 预测价格
x_house_predict = np.dot(x_house_norm, w_norm) + b_norm
print(f"预测价格: ${x_house_predict*1000:0.0f}") # $318709
6.关键结论
- 特征缩放是多变量线性回归的必备步骤,尤其是在特征尺度差异大的场景中。
- Z 分数归一化是最通用的缩放方法,它能让所有特征的分布标准化,大幅提升梯度下降的效率和稳定性。
- 缩放必须基于训练集统计量,测试 / 预测数据必须使用训练集的均值和标准差,避免数据泄露。
- 归一化后可以使用更大的学习率,显著减少迭代次数,同时避免成本震荡问题。
更多推荐
所有评论(0)