寻找向量的线性组合,使其最适合目标向量

3
我将尝试找到一些权重,以便在多个预测结果中得出一个与已知目标(例如均方误差)最接近的结果。
以下是一个简化的示例,展示了四个数据点上三种不同类型的预测:
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库,但我不知道如何将这个问题转换成求解器所需的形式。是否有人可以指点我正确的方向?


系数有限制吗?例如,是否全部为正数,总和为1等?与维度相比,有多少个向量可以组合? - Marat
是的,系数应该全部为非负数。理想情况下,它们应该全部加起来等于1,尽管能够打开和关闭此约束的能力会更好。每个向量的长度将超过向量的数量。 - Matthew Strawbridge
2个回答

5

如果我理解你的意思正确,你想建模并解决一些优化问题。如果你对于一般情况(没有任何约束条件)感兴趣,你的问题似乎非常接近普通最小二乘误差问题(例如你可以使用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]不同,但这取决于您如何定义问题。这是最小二乘误差的解决方案。


你为什么没有使用帖子中的数据,例如目标和预测来解决示例问题? - DarrylG
@DarrylG 不是的,我只是沿用了cvxpy文档中的示例。我编辑了我的答案,并添加了使用帖子数据的示例。 - Roim

2
我们可以把这个问题看作是一个最小二乘问题,实际上等价于二次规划。如果我理解正确,您要寻找的权重向量是一个凸组合,因此在最小二乘形式中,问题为:
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确实是一个很好的起点!)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接