TheAlgorithms/Python 中局部加权线性回归(LWLR):从高斯加权代价函数到 NumPy 闭式解实现
TheAlgorithms/Python 中局部加权线性回归LWLR从高斯加权代价函数到 NumPy 闭式解实现【免费下载链接】PythonAll Algorithms implemented in Python项目地址: https://gitcode.com/GitHub_Trending/pyt/Python局部加权线性回归Locally Weighted Linear RegressionLWLR又称 Local Regression是一种非参数机器学习算法它不依赖一组全局固定的模型参数而是针对每个查询点单独求解局部回归系数。本文以仓库中 machine_learning/local_weighted_learning/README.md 的理论讲解为主线结合 local_weighted_learning.py 的 NumPy 实现完整覆盖术语定义、加权代价函数推导、数值算例、算法步骤以及源码级实现细节与运行方式。与普通线性回归的对比问题从何而来普通线性回归是一种监督学习算法用于计算输入X与输出Y之间的线性关系。根据 README 的术语约定number_of_features(i)特征数量number_of_training_examples(m)训练样本数量output_sequence(y)输出序列$\theta^T x$预测点$J(\theta)$代价函数。普通线性回归的流程分两步训练阶段计算 $\theta$ 以最小化代价$$J(\theta) \sum_{i1}^{m} \left(\theta^T x^i - y^i\right)^2$$预测阶段对给定查询点 x返回 $\theta^T x$。这种先训练一次、再处处复用同一组 $\theta$的机制隐含了一个前提假设数据点之间存在全局线性关系。一旦 x 与 y 之间的关系是非线性的README 中给出了非线性数据的示意图场景固定的全局参数就无法贴合局部弯曲趋势。此时需要非参数算法不基于固定参数集做预测而是让参数 $\theta$针对每个查询点 x 单独计算。这就是 LWLR 的核心思想在计算 $\theta$ 时对离查询点 x 更近的样本赋予更高权重离得更远的样本权重更低。加权代价函数与高斯权重将权重 $w^i$ 引入代价函数后得到 LWLR 的目标$$J(\theta) \sum_{i1}^{m} w^i \left(\theta^T x^i - y^i\right)^2$$其中$w^i$ 是训练点 $x^i$ 的非负权重离查询点 x 近的 $x^i$$w^i$ 较大离查询点 x 远的 $x^i$$w^i$ 较小。一个典型的高斯权重函数为$$w^i \exp\left(-\frac{(x^i - x)(x^i - x)^T}{2\tau^2}\right)$$其中 $\tau$ 是带宽bandwidth参数控制 $w^i$ 随与 x 距离增长的衰减速率。可以把它想象成一条以预测点为中心的钟形曲线样本离中心越远权重越低$\tau$ 控制钟形曲线的宽度——$\tau$ 越大曲线越宽远处样本仍保留较高权重拟合结果越平滑$\tau$ 越小权重衰减越快拟合越贴近近邻点、越容易受局部噪声影响。README 中的数值算例复算验证README 给出的算例查询点 $x 5.0$训练点 $x^1 4.9$另一点按 README 的代入过程 $(3-5)^2$ 取值为 3.0README 正文将其写作 $x^2 5.0$与其后代入的 3 不符属于原文笔误下文以代入值 3.0 为准带宽 $\tau 0.5$$w^1 \exp\left(-\frac{(4.9-5)^2}{2(0.5)^2}\right) \approx 0.9802$$w^2 \exp\left(-\frac{(3-5)^2}{2(0.5)^2}\right) \approx 0.000335$于是代价函数变为$$J(\theta) 0.9802\left(\theta^T x^1 - y^1\right)^2 0.000335\left(\theta^T x^2 - y^2\right)^2$$结论与 README 一致权重随 x 与 $x^i$ 间距离的增大指数级下降$x^i$ 的预测误差对总代价的贡献也随之指数级下降。上面的两个数值已用 NumPy 实际复算与 README 给出的 0.9802 / 0.000335 完全吻合。LWLR 的完整算法步骤继承 README 的描述LWLR 的每一步都发生在预测时刻对每个查询点 x计算权重 $w^i$计算 $\theta$ 以最小化加权代价 $J(\theta) \sum_{i1}^{m} w^i \left(\theta^T x^i - y^i\right)^2$预测输出对查询点 x 返回 $\theta^T x$。与普通回归训练一次、预测多次不同LWLR 每次预测都要对全部 m 个训练点求解一次加权最小二乘因此它是典型的时间换拟合灵活性的非参数方法。源码实现NumPy 闭式解与函数结构local_weighted_learning.py 将上述理论落地为四个核心函数weight_matrix、local_weight、local_weight_regression、load_data/plot_preds文件头部 docstring 直接给出了加权最小二乘的闭式解$$\beta (X^T W X)^{-1}(X^T W y)$$其中 X 是设计矩阵y 是响应向量W 是对角权重矩阵权重采用与 README 相同的高斯形式 $w_i \exp(-|x_i - x|^2 / 2\tau^2)$$|x|$ 为欧几里得范数2-范数。源码还特别注明LOESSLocally Estimated Scatterplot Smoothing等其它局部加权回归通常使用不同的权重函数本实现选用的是高斯权重。weight_matrix构造查询点周围的权重矩阵见 local_weighted_learning.py#L38-L67def weight_matrix(point: np.ndarray, x_train: np.ndarray, tau: float) - np.ndarray: m len(x_train) # Number of training samples weights np.eye(m) # Initialize weights as identity matrix for j in range(m): diff point - x_train[j] weights[j, j] np.exp(diff diff.T / (-2.0 * tau**2)) return weights输入point是预测点x_train是训练 x 值矩阵tau为带宽从源码结构看实现用np.eye(m)初始化后仅填充对角线元素这正是 $W$ 为对角权重矩阵的体现$w^i$ 只乘在 $x^i$ 自身的残差平方上样本之间不产生交叉权重项注意当 $x^i$ 远离预测点时$\exp(-\text{大数})$ 会下溢为 0如 doctest 中距离较远的样本权重直接为0.0最近的样本权重也只有1.4e-207量级这与权重指数级衰减的理论预期一致。local_weight对单个查询点求解局部系数 β见 local_weighted_learning.py#L70-L99def local_weight(point, x_train, y_train, tau): weight_mat weight_matrix(point, x_train, tau) weight np.linalg.inv(x_train.T weight_mat x_train) ( x_train.T weight_mat y_train.T ) return weight两行核心运算精确对应闭式解 $\beta (X^T W X)^{-1}(X^T W y)$x_train.T weight_mat x_train即 $X^T W X$对其求逆后再乘 $X^T W y$。函数名沿用了文档中局部权重local weights的叫法返回的向量就是针对该查询点的局部 $\beta$文档中的 $\theta$。local_weight_regression对每个点做即查即算的预测见 local_weighted_learning.py#L102-L127def local_weight_regression(x_train, y_train, tau): y_pred np.zeros(len(x_train)) # Initialize array of predictions for i, item in enumerate(x_train): y_pred[i] np.dot(item, local_weight(item, x_train, y_train, tau)).item() return y_pred这个循环正是 LWLR 步骤对给定查询点 x 返回 $\theta^T x$的代码化对训练集中的每一个点依次当作查询点重新计算局部 $\beta$再做内积np.dot(item, β)得到预测值。doctest 用 3 个 2 维样本验证了这一点输入[[16.99, 10.34], [21.01, 23.68], [24.59, 25.69]]与响应[[1.01, 1.66, 3.5]]、$\tau 0.6$ 时输出array([1.07173261, 1.65970737, 3.50160179])。数据加载与可视化load_datalocal_weighted_learning.py#L130-L148从 seaborn 内置数据集读取数据并通过np.column_stack((one, x_data))在特征矩阵最左列拼接一列全 1——即截距项保证局部模型形如 $\beta_0 \beta_1 x$这也解释了为何 doctest 中预测值能平滑地穿过样本附近而非过原点。plot_predslocal_weighted_learning.py#L151-L174按 x 排序后绘制散点加黄色粗线展示局部线性曲线随数据走势弯曲的非参数特性。运行方式与依赖文件底部以__main__块先跑 doctest再用 seaborn 的tips数据集做完整演示local_weighted_learning.py#L177-L185if __name__ __main__: import doctest doctest.testmod() # Demo with a dataset from the seaborn module training_data_x, total_bill, tip load_data(tips, total_bill, tip) predictions local_weight_regression(training_data_x, tip, 5) plot_preds(training_data_x, predictions, total_bill, tip, total_bill, tip)运行前提与注意事项pyproject.toml 声明requires-python 3.14且numpy、matplotlib、pandas均在其dependencies中需要额外说明的是load_data在函数内部import seaborn as sns而 seaborn并未出现在pyproject.toml 的依赖列表中因此运行该演示前需自行确保环境装有 seaborn否则load_data(tips, ...)会抛出 ImportError演示中带宽取 $\tau 5$这是一个相对较大的带宽对total_bill量级为 1050 的数据而言远处样本仍保有可观权重画出的局部回归线相对平滑若把tau调小如 doctest 所用的 0.6权重衰减极快曲线会更贴近近邻点。调整tau是观察带宽—平滑度权衡最直接的实验文件头部的 doctestweight_matrix、local_weight、local_weight_regression随doctest.testmod()在模块导入测试pyproject.toml 中 pytest 配置了--doctest-modules时自动执行可作为对闭式解实现的快速正确性校验该模块在 DIRECTORY.md 的目录索引中登记为 Local Weighted Learning入口即 machine_learning/local_weighted_learning/local_weighted_learning.py。复杂度与适用边界从源码结构看local_weight_regression对每个查询点调用一次local_weight后者需做 $m \times m$ 权重矩阵构造与一次矩阵求逆因此单个查询点的计算开销随训练集规模近似为 $O(m^3)$求逆主导整体预测为 $O(m^4)$ 量级——这正是非参数局部回归存储所有训练数据、每次查询现场求解的固有代价。它的适用场景因而是中小规模、关系不明或明显非线性、且不需要持久化模型参数的探索性回归任务反之若数据量大、需要快速批量预测或可部署的固定模型普通线性回归或显式基函数扩展通常更合适。小结本文对应的仓库材料可归纳为理论文档 machine_learning/local_weighted_learning/README.md 给出了术语、加权代价函数、高斯权重公式与手算数值例实现文件 machine_learning/local_weighted_learning/local_weighted_learning.py 用 NumPy 实现了 $(X^T W X)^{-1}(X^T W y)$ 闭式解、对角权重矩阵构造、逐点预测循环以及基于 seaborntips数据集的可视化演示。读懂这两个文件即可完整掌握 LWLR 按距离指数加权、逐查询点求解局部线性模型的算法全貌并能通过调节带宽 $\tau$ 直观理解非参数回归中平滑度与局部贴合度的权衡。【免费下载链接】PythonAll Algorithms implemented in Python项目地址: https://gitcode.com/GitHub_Trending/pyt/Python创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考