【问题标题】:How to use least squares with weight matrix?如何使用权重矩阵的最小二乘?
【发布时间】:2015-01-23 13:45:17
【问题描述】:

我知道如何使用 Python 通过最小二乘法求解 A.X = B:

例子:

A=[[1,1,1,1],[1,1,1,1],[1,1,1,1],[1,1,1,1],[1,1,0,0]]
B=[1,1,1,1,1]
X=numpy.linalg.lstsq(A, B)
print X[0]
# [  5.00000000e-01   5.00000000e-01  -1.66533454e-16  -1.11022302e-16]

但是用一个不是身份的权重矩阵来解决这个相同的方程呢:

A.X = B (W)

例子:

A=[[1,1,1,1],[1,1,1,1],[1,1,1,1],[1,1,1,1],[1,1,0,0]]
B=[1,1,1,1,1]
W=[1,2,3,4,5]

【问题讨论】:

  • 你看过这个链接吗:stackoverflow.com/questions/19624997/…
  • 是的;我在解决之前尝试过: B=numpy.dot(B,W) ,但我有一条消息:numpy.linalg.linalg.LinAlgError: 0-dimensional array given。数组必须是二维的
  • 如果你取两个一维数组的点积,你会得到一个标量。也许您的意思是简单地将 B 的元素乘以 W 的元素?在这里最好使用 numpy 数组而不是 Python 列表。

标签: python numpy matrix least-squares


【解决方案1】:

scikit 包直接提供加权回归.. https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LinearRegression.html#sklearn.linear_model.LinearRegression.fit

import numpy as np
# generate random data
N = 25
xp = [-5.0, 5.0]
x = np.random.uniform(xp[0],xp[1],(N,1))
e = 2*np.random.randn(N,1)
y = 2*x+e
w = np.ones(N)

# make the 3rd one outlier
y[2] += 30.0
w[2] = 0.0

from sklearn.linear_model import LinearRegression
# fit WLS using sample_weights
WLS = LinearRegression()
WLS.fit(x, y, sample_weight=w)

from matplotlib import pyplot as plt
plt.plot(x,y, '.')
plt.plot(xp, xp*WLS.coef_[0])
plt.show()

【讨论】:

    【解决方案2】:

    我找到了另一种方法(使用 W 作为对角矩阵和矩阵乘积):

    A=[[1,1,1,1],[1,1,1,1],[1,1,1,1],[1,1,1,1],[1,1,0,0]]
    B = [1,1,1,1,1]
    W = [1,2,3,4,5]
    W = np.sqrt(np.diag(W))
    Aw = np.dot(W,A)
    Bw = np.dot(B,W)
    X = np.linalg.lstsq(Aw, Bw)
    

    相同的值和相同的结果。

    【讨论】:

    • 矩阵乘积比@xnx 建议的元素乘积更昂贵
    • 可能在计算上更昂贵,但这更容易阅读。 +1 使用线性代数提高代码清晰度
    • 谢谢!为什么使用 sqrt(weight)?
    • @MonsieurBeilto,这是因为在最小二乘法中,平方位移的总和被最小化(y - y0) ** 2,因此如果您将 y 重新缩放为sqrt(w),则会弹出一个因子 w
    • 我对这个答案和 xnx 的答案之间的差异感到困惑。为什么效果一样?您只将权重乘以 A 的某些条目,而 xnx 将它们乘以 A 的所有条目,对吗?
    【解决方案3】:

    我不知道你是如何定义你的权重的,但如果合适的话你可以试试这个:

    import numpy as np
    A=np.array([[1,1,1,1],[1,1,1,1],[1,1,1,1],[1,1,1,1],[1,1,0,0]])
    B = np.array([1,1,1,1,1])
    W = np.array([1,2,3,4,5])
    Aw = A * np.sqrt(W[:,np.newaxis])
    Bw = B * np.sqrt(W)
    X = np.linalg.lstsq(Aw, Bw)
    

    【讨论】:

    • 谢谢。我不太了解 numpy,并且必须意识到 W[:,np.newaxis] (或 W[:,None])给出了一个对角矩阵。 IE。 array([[1],[2],[3],[4],[5]]) 表示一个 5x5 对角矩阵,这些值在对角线上。
    • (是吗?因为结果 Aw 是一个 5x4 数组,所以这是唯一的解释)
    • 对不起,我被 * 运算符弄糊涂了(我不习惯数组)。它不是矩阵乘积,而是逐项。
    • 没错,NumPy 数组使用 * 作为元素乘法运算符。您需要将 W 转换为列数组才能在 A 上正确广播此乘法。还有一个 NumPY 矩阵对象,但它比它的价值更麻烦(IMO)。
    • 谢谢!为什么使用 sqrt(重量)?是因为它会在错误计算中平方吗?
    猜你喜欢
    • 2015-09-26
    • 2023-03-23
    • 2012-07-10
    • 1970-01-01
    • 2016-08-13
    • 1970-01-01
    • 1970-01-01
    • 2015-12-13
    • 2020-09-18
    相关资源
    最近更新 更多