1

我试图在多个预测中找到权重,以给出尽可能接近已知目标的结果(例如,均方误差)。

这是一个简化的示例,显示了跨四个数据点的三种不同类型的预测:

target = [1.0, 1.02, 1.01, 1.04]  # all approx 1.0
forecasts = [
    [0.9, 0.91, 0.92, 0.91],  # all approx 0.9
    [1.1, 1.11, 1.13, 1.11],  # all approx 1.1
    [1.21, 1.23, 1.21, 1.23]  # all approx 1.2
]

其中一个预测总是大约 0.9,一个总是大约 1.1,一个总是大约 1.2。

我想要一种自动查找[0.5, 0.5, 0.0]三个预测的权重的方法,因为平均前两个预测并忽略第三个预测非常接近目标。理想情况下,权重将被限制为非负且总和为 1。

我需要使用某种形式的线性规划或二次规划来做到这一点。我已经安装了 Python quadprog 库,但我不确定如何将这个问题转换为像这样的求解器所需的形式。谁能指出我正确的方向?

4

2 回答 2

3

如果我理解正确,您想建模一些优化问题并解决它。如果您对一般情况感兴趣(没有任何限制),您的问题似乎非常接近常规最小二乘误差问题(scikit-learn例如,您可以解决)。

我建议使用cvxpy库来建模优化问题。这是对凸优化问题进行建模的便捷方式,您可以选择要在后台工作的求解器。

通过添加您提到的约束来扩展cvxpy 最小二乘示例

# Import packages.
import cvxpy as cp
import numpy as np

# Generate data.
m = 20
n = 15
np.random.seed(1)
A = np.random.randn(m, n)
b = np.random.randn(m)

# Define and solve the CVXPY problem.
x = cp.Variable(n)
cost = cp.sum_squares(A @ x - b)
prob = cp.Problem(cp.Minimize(cost), [x>=0, cp.sum(x)==1])
prob.solve()

# Print result.
print("\nThe optimal value is", prob.value)
print("The optimal x is")
print(x.value)
print("The norm of the residual is ", cp.norm(A @ x - b, p=2).value)

在此示例中,A(矩阵)是所有向量的矩阵,x(变量)是权重,并且b是已知目标。

编辑:您的数据示例:

forecasts = np.array([
    [0.9, 0.91, 0.92, 0.91],
    [1.1, 1.11, 1.13, 1.11],
    [1.21, 1.23, 1.21, 1.23]
])

target = np.array([1.0, 1.02, 1.01, 1.04])
x = cp.Variable(forecasts.shape[0])
cost = cp.sum_squares(forecasts.T @ x - target)
prob = cp.Problem(cp.Minimize(cost), [x >= 0, cp.sum(x) == 1])
prob.solve()
print("\nThe optimal value is", prob.value)
print("The optimal x is")
print(x.value)

输出:

The optimal value is 0.0005306233766233817
The optimal x is
[ 6.52207792e-01 -1.45736370e-24  3.47792208e-01]

结果大约[0.65, 0, 0.34][0.5, 0.5, 0.0]您提到的不同,但这取决于您如何定义问题。这是最小二乘误差的解决方案。

于 2021-09-10T20:15:01.417 回答
1

我们可以把这个问题看成最小二乘法,它确实相当于二次规划。如果我理解正确,您正在寻找的权重向量是一个凸组合,因此以最小二乘形式出现的问题是:

minimize  || [w0 w1 w2] * forecasts - target ||^2
    s.t.  w0 >= 0, w1 >= 0, w2 >= 0
          w0 + w1 + w2 == 1

您可以在qpsolvers包中开箱即用地使用最小二乘函数:

import numpy as np
from qpsolvers import solve_ls

target = np.array(target)
forecasts = np.array(forecasts)
w = solve_ls(forecasts.T, target, G=-np.eye(3), h=np.zeros(3), A=np.array([1, 1., 1]), b=np.array([1.]))

您可以在文档中查看矩阵 G、h、A 和 b 对应于上述问题。使用quadprog作为后端求解器,我在我的机器上得到以下解决方案:

In [6]: w
Out[6]: array([6.52207792e-01, 9.94041282e-15, 3.47792208e-01])

In [7]: np.dot(w, forecasts)
Out[7]: array([1.00781558, 1.02129351, 1.02085974, 1.02129351])

这与 Roim 的回答中的解决方案相同。(CVXPY 确实是一个很好的开始方式!)

于 2021-10-09T16:54:12.740 回答