如何权衡散点图中的点以进行拟合?

How to weigh the points in a scatter plot for a fit?

所以,我在Python中查找了有关polyfit(numpy.polynomial.polynomial.polyfit)函数中权重参数的信息,它似乎与与各个点相关的错误有关。 (How to include measurement errors in numpy.polyfit)

然而,我正在尝试做的与错误无关,而是权重。我有一个 numpy 数组形式的图像,它指示检测器中沉积的电荷量。我将该图像转换为散点图,然后进行拟合。但我希望这种拟合能够为电荷沉积较多的点赋予更多权重,而对电荷较少的点赋予较少的权重。这就是权重参数的作用吗?

这是一个示例图片: 这是我的代码:

def get_best_fit(image_array, fixedX, fixedY):
    weights = np.array(image_array)
    x = np.where(weights>0)[1]
    y = np.where(weights>0)[0]
    size = len(image_array) * len(image_array[0])
    y = np.zeros((len(image_array), len(image_array[0])))
    for i in range(len(np.where(weights>0)[0])):
        y[np.where(weights>0)[0][i]][np.where(weights>0)[1][i]] = np.where(weights>0)[0][i]
    y = y.reshape(size)
    x = np.array(range(len(image_array)) * len(image_array[0]))
    weights = weights.reshape((size))
    b, m = polyfit(x, y, 1, w=weights)
    angle = math.atan(m) * 180/math.pi
    return b, m, angle

我给你解释一下代码:

第一行分配存放在称为权重的变量中的电荷。接下来的两行获取电荷沉积 > 0 的点,因此沉积了一些电荷以捕获散点图的坐标。然后我得到整个图像的大小,稍后转换为一个一维数组用于绘图。然后,我浏览图像并尝试获取电荷沉积点的坐标(请记住,电荷的 数量 存储在变量 weights 中)。然后我重塑 y 坐标以获得一维数组并从图像中获取所有相应 y 坐标的 x 坐标,然后将权重的形状也更改为一维。

编辑:如果有一种使用 np.linalg.lstsq 函数执行此操作的方法,那将是理想的,因为我也在尝试使拟合通过绘图的顶点。我可以重新定位图,使顶点为零,然后使用 np.linalg.lstsq,但这不允许我使用权重。

所以我可能误解了问题,但我只是尝试将直线拟合到散点图,然后使用权重参数更改拟合以优先考虑特定点。
我用 np.polyfit and np.polynomial.polynomial.polyfit 尝试了这个,我希望它们的行为相同,因为它们都最小化了平方误差(至少那是我的理解)。
然而,配合是完全不同的,见下文。不太确定该怎么做。

代码

import numpy as np
import matplotlib.pyplot as plt

def func(p1, p2, x):
    return  p1 * x + p2

y = np.array([1.0, 3.3, 2.2, 4.25, 4.8, 5.1, 6.3, 7.5])
x = np.arange(y.shape[0])

plt.scatter(x, y)

w = np.ones(x.shape[0])
w[1] = 12
# p1, p2 = np.polyfit(x, y, 1, w=w)
p1, p2 = np.polynomial.polynomial.polyfit(x, y, 1, w=w)
print(p1, p2, w)

plt.plot(x, func(p1, p2, x))

plt.show()

np.polyfit

没有配重(或全部设置 1)

第2点权重设置为12,其他权重均为1

np.polynomial.polynomial.polyfit

没有权重

第2点权重设置为12,其他权重均为1

所以 np.polyfit 的行为符合我的预期,但是我真的不知道 np.polynomial.polynomial.polyfit 是怎么回事,即使没有任何权重的合身对我来说也没有任何意义。
但我认为 np.polyfit 做你想要的?更改权重参数显然会为更高权重的点赋予更多权重。

您可以使用 sklearn.linear_model.LinearRegression。它允许您不适合截距(即线穿过原点,或者通过一些欺骗,您选择的点)。它还处理加权数据。

例如(大部分是从@Hiho的回答中无耻的偷来的)

import numpy as np
import matplotlib.pyplot as plt
import sklearn.linear_model

y = np.array([1.0, 3.3, 2.2, 4.25, 4.8, 5.1, 6.3, 7.5])
x = np.arange(y.shape[0]).reshape((-1,1))
w = np.linspace(1,5,y.shape[0])

model = sklearn.linear_model.LinearRegression(fit_intercept=False)
model.fit(x, y, sample_weight=w)

line_x = np.linspace(min(x), max(x), 100).reshape((-1,1))
pred = model.predict(line_x)

plt.scatter(x, y)
plt.plot(line_x, pred)

plt.show()