本节我们将多变量梯度下降法进行矩阵化改造。这种改造将会带来很多好处。首先是简化逻辑,用统一的矩阵运算替代逐样本、逐参数的重复计算,步骤更清晰。其次,矩阵运算依托底层优化库,通过并行计算、缓存优化等技术,比手动循环计算快一个数量级,样本越多优势越明显。此外,当影响房价的因素(如面积、房间数、楼层等)增加时,无需修改核心运算逻辑,仅需调整矩阵维度即可实现扩展。
我们还是以房屋面积和数量两个因素预测房价的例子为例,从简单计算到批量求解,逐步完成梯度下降法的矩阵化改造。 单个房屋的房价预测公式为 。对于 个样本,需要逐个计算:
( )
其中 是第 套房屋的面积, 是第 套房屋的房间数量, 是第 套房屋的预测房价。我们使用 表示第 套房屋的真实价格。
为了让基础房价 能和权重 一起参与批量计算,需要给数据矩阵增加一个取值全为1的列,形成增广特征矩阵。即数据矩阵由 矩阵变化为 的增广特征矩阵:
每行对应 1 套房屋,结构为 ,最后一列的 1 是基础房价 的系数,确保 能融入矩阵运算,无需单独处理。
为方便统一管理和更新,将面积权重 、房间数权重 和基础房价 整合为一个 3 维列向量:
为便于批量对比预测结果,将 套房屋的实际房价整合为一维列向量:
有了上述矩阵,我们可以将逐个样本的预测公式表达为以下矩阵预测公式:
我们在上一节介绍的均方误差损失函数公式为
其中 是第 套房屋的预测房价,是预测结果向量 的第 个元素。 是真实结果向量 的第 个元素。观察上述损失函数公式右边求和公式内部,我们发现它正是误差向量 的第 个元素的平方,根据向量内积的定义,整个求和公式可以表示为:
因此均方误差损失函数可以表示为以下矩阵和向量的表达式:
基于上述损失函数表达式,计算梯度向量(包含所有参数的梯度,与 维度一致):
现在,我们可以将梯度下降法更新参数的迭代公式写为以下批量方式:
其中 为学习率。利用上述更新式,我们无需逐个调整参数,通过向量减法、矩阵转置、矩阵和向量乘法等操作可一次性完成所有更新。
在 Numpy 中,矩阵乘法可以使用np.matmul或@操作符实现,矩阵转置则可以使用np.transpose函数或者ndarray的.T属性来计算。在构造增长矩阵时,需要生成全1列,可以用np.ones 函数,它的作用是创建指定形状、元素均为 1.0(默认浮点型)的数组。其基本语法为 np.ones(shape, dtype=None),其中 shape 是必填参数,可传入整数(生成一维数组)或元组(生成多维数组),用于指定数组的维度;dtype 是可选参数,用于指定数组的数据类型(默认是 float64,可指定为 int 等)。
np.column_stack 是 Numpy 中按列方向拼接数组的函数,核心作用是将多个一维或二维数组拼接成一个新的二维数组。其基本语法为 np.column_stack(tup),其中 tup 是待拼接的数组序列(需用括号括起,数组间用逗号分隔)。以下是构造增广特征矩阵示例代码:
import numpy as np
# 准备原始特征(x1、x2 为一维数组,样本数量均为 n)
n = 6
x1 = np.array([2, 3, 5, 7, 11, 13])
x2 = np.array([4, 6, 8, 10, 12, 14])
# 生成偏置项全1数组
bias = np.ones(n)
# 按列拼接特征与偏置项,得到 (n, 3) 增广特征矩阵
X = np.column_stack((x1, x2, bias))
# 验证结果
print("增广特征矩阵 X:")
print(X)
print("X 的形状:", X.shape)

