isotonic_regression#
- scipy.optimize.isotonic_regression(y, *, weights=None, increasing=True)[源代码]#
非参数保序回归。
通过相邻违规池算法 (PAVA) 计算出一个(非严格)单调递增的数组 x,其长度与 y 相同,详见 [1]。更多详情请参阅“说明”部分。
- 参数:
- y(N,) array_like(类数组)
响应变量。
- weights(N,) array_like(类数组)或 None
案例权重。
- increasing布尔值
如果为 True,则拟合单调递增(即保序)回归。如果为 False,则拟合单调递减(即反序)回归。默认为 True。
- 返回:
- resOptimizeResult 对象
优化结果表示为一个
OptimizeResult
对象。重要属性包括:x
: 保序回归解,即与 y 长度相同的递增(或递减)数组,其元素范围介于 min(y) 和 max(y) 之间。weights
: 包含每个块(或池)B 的案例权重总和的数组。blocks
: 长度为 B+1 的数组,包含每个块(或池)B 的起始位置索引。第 j 个块由x[blocks[j]:blocks[j+1]]
给出,其中所有值都相同。
说明
给定数据 \(y\) 和案例权重 \(w\),保序回归解决了以下优化问题:
\[\operatorname{argmin}_{x_i} \sum_i w_i (y_i - x_i)^2 \quad \text{subject to } x_i \leq x_j \text{ whenever } i \leq j \,.\]对于每个输入值 \(y_i\),它会生成一个值 \(x_i\),使得 \(x\) 是递增的(但非严格),即 \(x_i \leq x_{i+1}\)。这通过 PAVA 实现。解决方案由池或块组成,即 \(x\) 的相邻元素,例如 \(x_i\) 和 \(x_{i+1}\),它们都具有相同的值。
最有趣的是,如果将平方损失替换为 Bregman 函数的广泛类别,即均值的唯一严格一致评分函数类别,则解决方案保持不变,详见 [2] 及其中引用的文献。
根据 [1] 实现的 PAVA 版本,其计算复杂度为 O(N),其中 N 为输入大小。
参考文献
[1] (1,2)Busing, F. M. T. A. (2022). Monotone Regression: A Simple and Fast O(n) PAVA Implementation. Journal of Statistical Software, Code Snippets, 102(1), 1-25. DOI:10.18637/jss.v102.c01
[2]Jordan, A.I., Mühlemann, A. & Ziegel, J.F. Characterizing the optimal solutions to the isotonic regression problem for identifiable functionals. Ann Inst Stat Math 74, 489-514 (2022). DOI:10.1007/s10463-021-00808-0
示例
此示例演示了
isotonic_regression
确实解决了受约束的优化问题。>>> import numpy as np >>> from scipy.optimize import isotonic_regression, minimize >>> y = [1.5, 1.0, 4.0, 6.0, 5.7, 5.0, 7.8, 9.0, 7.5, 9.5, 9.0] >>> def objective(yhat, y): ... return np.sum((yhat - y)**2) >>> def constraint(yhat, y): ... # This is for a monotonically increasing regression. ... return np.diff(yhat) >>> result = minimize(objective, x0=y, args=(y,), ... constraints=[{'type': 'ineq', ... 'fun': lambda x: constraint(x, y)}]) >>> result.x array([1.25 , 1.25 , 4. , 5.56666667, 5.56666667, 5.56666667, 7.8 , 8.25 , 8.25 , 9.25 , 9.25 ]) >>> result = isotonic_regression(y) >>> result.x array([1.25 , 1.25 , 4. , 5.56666667, 5.56666667, 5.56666667, 7.8 , 8.25 , 8.25 , 9.25 , 9.25 ])
与调用
minimize
相比,isotonic_regression
的巨大优势在于它更易于使用,即无需定义目标函数和约束函数,而且它的速度快了几个数量级。在商用硬件(2023 年)上,对于长度为 1000 的正态分布输入 y,minimizer 大约需要 4 秒,而isotonic_regression
大约需要 200 微秒。