我有一个函数compare_images(k, a, b)
,用于比较两个二维数组a
和b
在功能内部,我将gaussian_filter
与sigma=k
一起应用于a
我的想法是估计我必须平滑图像a
以使其成为多少类似于图片b
问题是,我的函数compare_images
只会在k
变体超过0.5
时返回不同的值,如果我fmin(compare_images, init_guess, (a, b)
,它通常会卡在init_guess
上1}}值。
我认为问题是fmin
(并且minimize
)往往以非常小的步骤开始,在我的情况下会重现compare_images
完全相同的返回值,因此方法认为它已经找到了最低限度。它只会尝试几次。
有没有办法强制fmin
或scipy
中的任何其他最小化功能采取更大的步骤?还是有更适合我需要的方法吗?
修改
我找到了临时解决方案。
首先,根据建议,我使用xtol=0.5
和更高版本作为fmin
的参数。
即便如此,我仍然遇到了一些问题,并且有几次fmin
会返回init_guess
。
然后我创建了一个简单的循环,这样如果fmin == init_guess
,我会生成另一个,随机init_guess
并再次尝试。
当然,这很慢,但现在我开始运行了。为我的所有数据运行它需要20个左右,但我不需要再做一次。
无论如何,为那些仍然有兴趣寻找更好解决方案的人更好地解释问题:
A
和B
,其中包含一些科学数据。A
看起来像一个带有可变值的点(它是一个矩阵,其中每个有价值的点代表事件发生的位置和强度)B
看起来像一个平滑的热图(它是观察到的出现密度)B
看起来就像是将高斯滤波器应用于A
并带有一点半随机噪声。B
到sigma
的高斯滤波器来近似A
。这个sigma
是视觉上选择的,但仅适用于某类图像。 sigma
,所以稍后我会发现sigma
的某些关系以及每张图片中显示的事件类别。无论如何,谢谢你的帮助!
答案 0 :(得分:4)
快速检查:您可能真的是fmin(compare_images, init_guess, (a,b))
?
如果gaussian_filter
表现得像你说的那样,你的函数是分段常数,这意味着依赖于导数(即大多数)的优化器都不存在。您可以尝试使用anneal之类的全局优化器,或在k
的合理范围内进行强力搜索。
但是,正如您所描述的那样,如果compare_images
是b
的平滑版本,则通常只有a
的明确全局最小值。如果您想确定a
的平滑量,使两个图像最相似,那么您的方法是有意义的。
如果问题是“图像有多相似”,那么我认为像素化比较(可能有一点平滑)是要走的路。根据我们所谈论的图像,可能需要首先对齐图像(例如,用于比较照片)。请澄清: - )
修改:可能有所帮助的另一个想法:重写compare_images,以便计算两个平滑版本 - a
- 一个使用sigma = floor(k)
,另一个使用{{ 1}}(即将k舍入到下一个较低/较高的int)。然后计算ceil(k)
,其中a_smooth = a_floor*(1-kfrac)+a_ceil*kfrac
是kfrac
的小数部分。这样,比较函数变为连续w.r.t k
。
祝你好运!
答案 1 :(得分:2)
Basin hopping可能会做得更好一些,因为它很有可能在高原停留时无论如何都会继续。
我在这个示例函数中发现它在低温下表现得相当不错:
>>> opt.basinhopping(lambda (x,y): int(0.1*x**2 + 0.1*y**2), (5,-5), T=.1)
nfev: 409
fun: 0
x: array([ 1.73267813, -2.54527514])
message: ['requested number of basinhopping iterations completed successfully']
njev: 102
nit: 100
答案 2 :(得分:2)
我意识到这是一个古老的问题,但是我找不到很多类似主题的讨论。我遇到scipy.optimize.least_squares
的类似问题。我发现xtol
对我没有多大帮助。它似乎根本没有改变步长。产生重大变化的是diff_step
。这设置了根据公式step_size = x_i*diff_step
对Jacobian进行数值估计时所采用的步长,其中x_i
是每个自变量。您正在使用fmin
,所以您没有计算雅可比行列式,但是,如果您针对同一问题使用了另一个minimize
之类的scipy函数,则可能会对您有所帮助。