Python 中的像素最小二乘法

问题描述 投票:0回答:1

我有一个非线性前向模型,它计算每个像素参数w的灰度图像。我还可以使用 scipys 优化函数 反转模型。我目前遇到的唯一问题是图像的大小使得这个解决方案非常慢...比如 7% 的像素在 40 分钟内计算得很慢。我使用 for 循环遍历所有像素并按像素应用模型。我尝试过 least_squaresleastsqroot 函数,但它们都非常慢。我还实现了导数值,因为我听说通过提供雅可比矩阵可以更快,但无济于事。

我认为 leastsq 可能是解决方案,因为它的描述中有以下声明:

x = arg min(sum(func(y)**2,axis=0))
         y

如果我将图像重塑为

1xn
,它应该沿着
axis=0
最小化。但不知何故,我最终得到了一个大小为 2 的数组作为我的输入参数
y
,而且我无法调试它。

我特别关注最小二乘优化,因为将来,我想提供多个图像,这些图像应该由相同的参数生成w(其他参数不同)。

除了scipy之外,还有其他库可以为这个问题提供更优雅的方法吗?

我还计划尝试root 函数的 numba 实现,但它有它自己的问题。或者使用 Google 的 LM JAX 实现,但到目前为止我还没有 JAX 的实际经验...

编辑 这是我的问题的一个小例子: 假设我有一个模型定义为

f(n) = a*n**2 + b*n + c
,其中
f(n)
是每个像素的图像值
n
。对于不同的三元组
(a,b,c)
我可以生成图像
I=f(n)
。现在,我有一组具有不同参数
I1, I2, ...
的图像,但
(a1, b1, c1), (a2, b2, c2),...
在每个像素上并没有不同。
最简单的情况是只有一张图像

n

,并且我有参数

I1
,并且可以使用根方法或最小化器来计算所需的
(a1, b1, c1)
n

循环每个像素需要相当长的时间,并且我已经尝试仅使用一个和模块和整数除法来计算索引来减少双for循环
def my_model(n, a, b, c, img=0): return a * n**2 + b * n + c - img # load img1, a1, b1, c1 from a file n = np.zeros_like(img1) for i in range img1.shape[0]: for j in range img1.shape[1]: x0 = 1/3 args = { "a": a1, "b": b1, "c": c1, "img": img1[i,j], } res = least_squares(my_model, x0, kwargs=args) n[i, j] = res.x[0]

如果我可以做得更快,多个图像也不会那么难实现,因为我只需要为参数提供一个数组。

python scipy numba scipy-optimize jax
1个回答
0
投票

加速最小二乘拟合的一个技巧是提供接近函数实际根的起始值。

如果图像的像素彼此相关,一种方法是获取解决上一个最小二乘问题得到的 n 值,并将其作为 x0 提供给下一次调用。我观察到由此加速了大约 10 倍。

另一种方法是尝试找到一种更快的方法来计算 f

-1

(x)。您可以使用多种方法,但一种方法是在一堆点处评估 f(x),并拟合从 f(x) 到 x 的样条曲线。 如果您只转换一个像素,则需要更长的时间来拟合样条线,但优点是在进行多次评估时可以节省时间。

这是一个例子。我获取了您的代码,并将其与以下图像

测试模式

一起使用。 (将此图像保存为同一目录中的grayscale.png以进行测试。) 然后我比较了两种方法:逐像素方法,以及将样条曲线拟合到函数反函数。我发现样条方法大约快 100 倍。

样条方法有两点好处:识别逆矩阵需要更少的计算,并且可以以矢量化方式完成更多计算。这大约快了 100 倍。

i,j

	
© www.soinside.com 2019 - 2024. All rights reserved.