【问题标题】:Find linear combination of vectors that is the best fit for a target vector找到最适合目标向量的向量的线性组合
【发布时间】:2021-09-10 20:02:47
【问题描述】:

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

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

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 library,但我不确定如何将这个问题转化为像这样的求解器所需的形式。谁能指出我正确的方向?

【问题讨论】:

  • 对系数是否有任何限制(例如,全为正数、总和为 1 等)?与维度相比,有多少向量可以组合?
  • 是的,系数都应该是非负的。理想情况下,它们的总和应为 1,尽管打开和关闭此约束的能力会更好。每个向量的长度会超过向量的个数。

标签: python linear-programming quadratic-programming quadprog


【解决方案1】:

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

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

通过添加您提到的约束来扩展cvxpy least square example

# 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 不是我只是停留在 cvxpy 文档中的示例。我编辑了答案并使用帖子中的数据添加了示例
【解决方案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.]))

您可以在documentation 中查看矩阵 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 确实是一个很好的开始方式!)

【讨论】:

    猜你喜欢
    • 2011-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-06
    • 2014-04-10
    • 1970-01-01
    • 1970-01-01
    • 2022-08-14
    相关资源
    最近更新 更多