如何从经BSpline平滑后的Matplotlib图中寻找全局最小值?
问题描述
我有x和y两个数组,最初用以下代码绘制折线图并通过简单逻辑找到全局最小值:
import numpy as np import matplotlib.pyplot as plt x = [1 ,2, 3, 4, 5, 6, 7, 8, 9] y = [ 3,5, 1, 9, 3, 2, 10, 7, 8] plt.plot(x, y) # 寻找全局最小值 minpos = y.index(min(y)) plt.plot(x[minpos], min(y), 'go', label="Minima") plt.show()
但使用BSpline对曲线平滑处理后,原有的找最小值逻辑不再适用,平滑后的全局最小值位置发生了变化,需要找到新的方法来定位平滑曲线上的全局最小值。平滑代码如下:
from scipy.interpolate import make_interp_spline, BSpline # 生成100个插值点 xnew = np.linspace(min(x), max(x), 100) spl = make_interp_spline(x, y, k=2) # 创建2阶B样条插值 power_smooth = spl(xnew) plt.plot(x[minpos], min(y), 'go', label="Minima") plt.plot(xnew, power_smooth) plt.show()
解决方案
要找到平滑后曲线上的全局最小值,直接针对平滑后的power_smooth数组和对应的xnew数组操作即可,步骤如下:
- 获取
power_smooth中的最小值 - 找到该最小值在数组中的索引
- 通过索引匹配对应的
xnew坐标 - 将该最小值点标注在平滑曲线上
修改后的完整代码如下:
import numpy as np import matplotlib.pyplot as plt from scipy.interpolate import make_interp_spline, BSpline x = [1 ,2, 3, 4, 5, 6, 7, 8, 9] y = [ 3,5, 1, 9, 3, 2, 10, 7, 8] # 生成平滑曲线 xnew = np.linspace(min(x), max(x), 100) spl = make_interp_spline(x, y, k=2) power_smooth = spl(xnew) # 寻找平滑曲线的全局最小值 smooth_min_val = np.min(power_smooth) smooth_min_idx = np.argmin(power_smooth) smooth_min_x = xnew[smooth_min_idx] # 绘图展示所有元素 plt.plot(x, y, 'o-', label='原始曲线') plt.plot(xnew, power_smooth, label='平滑曲线') plt.plot(x[y.index(min(y))], min(y), 'go', label='原始最小值') plt.plot(smooth_min_x, smooth_min_val, 'ro', label='平滑后最小值') plt.legend() plt.show()
代码说明
np.min(power_smooth)直接获取平滑后y值的最小值,适配numpy数组的操作逻辑np.argmin(power_smooth)获取最小值在数组中的索引,比Python内置的index方法更适合处理大规模插值数组- 通过索引从
xnew中取出对应x坐标,就是平滑曲线全局最小值的位置 - 同时绘制原始曲线、平滑曲线以及两个最小值点,方便直观对比差异
内容的提问来源于stack exchange,提问作者Sunjaree
相关产品推荐
相关产品推荐

