为何scipy.optimize.minimize始终返回初始值,无法完成优化?
为什么scipy.optimize.minimize无法完成优化?
主要有两个核心问题:
目标函数非光滑(不连续、不可导)
你写的overlap函数里,通过min(index_range, key=lambda i: abs(data2_x[i]-x1))寻找最近索引的操作,会让函数值随shift的变化出现阶跃跳变——当shift微调时,某个x1对应的最近索引可能突然切换,导致求和结果sum_的数值不连续,也没有定义良好的梯度。而minimize默认的L-BFGS-B算法是基于梯度的光滑优化算法,遇到这种非光滑函数时,会认为初始点附近没有下降方向,直接返回初始值。优化方法选择不当
默认的L-BFGS-B不适合处理非光滑目标函数,需要改用不需要梯度的启发式优化方法。
修复方案
1. 切换优化方法为Nelder-Mead
直接在调用minimize时指定方法为Nelder-Mead,这个方法不需要计算梯度,能处理非光滑函数:
result = opt.minimize(overlap, 40, args=(data1_x, data1_y, data2_x, data2_y), method='Nelder-Mead')
2. (可选)将目标函数改为光滑形式
如果想要更稳定的优化效果,可以用插值替代索引查找,让函数变得可导。比如用numpy.interp对data2做线性插值,直接计算对应位置的y值:
def overlap(shift, data1_x, data1_y, data2_x, data2_y): x1_shifted = np.array(data1_x) + shift[0] # 线性插值得到每个偏移后x对应的data2的y值 y2_interp = np.interp(x1_shifted, data2_x, data2_y) # 筛选出在共同范围内的点 idx = np.searchsorted(data2_x, x1_shifted) idx = np.clip(idx, 1, len(data2_x)-1) # 避免越界 dist_left = x1_shifted - np.array(data2_x)[idx-1] dist_right = np.array(data2_x)[idx] - x1_shifted min_dist = np.minimum(dist_left, dist_right) mask = min_dist <=5 sum_ = np.sum(np.abs(y2_interp[mask] - np.array(data1_y)[mask])) return sum_
修改后目标函数变得光滑,用默认的L-BFGS-B算法也能正常找到最优解。
3. 验证效果
修改后运行代码,result.x会接近真实的50.5,下方的子图也能看到两个数据集成功对齐。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

