You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用scipy.optimize.minimize求多项式交点结果异常的问题排查

两个多项式交点求解问题及修正方案

问题描述

尝试通过最小化最小二乘和求解两个多项式的交点,已绘制出正确交点(x=0.61,y≈0.3844),但使用scipy.optimize.minimize后结果误差极大,代码如下:

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0,1,100)    # 取值范围[0,1]

def polyD(x):
    return  1.115355004199118 - 1.597163991790283* x**1 + 0.6539311181514963* x**2
def polyS(x):
    return -0.03070291735792586 + 0.1601011622660309* x**1 + 0.8530319920733438* x**2

root= 0.61      # 此前求得的交点x值
y_root= polyD(root) # 交点y值
print(root, y_root) # 输出x=0.61 y=0.38441273827121725

plt.plot(root, y_root, 'yo',   x, polyD(x), 'r-', x, polyS(x), 'b-', ms=20, )
plt.show()

####################

from scipy.optimize import minimize

x0=  0
res= minimize(lambda t: sum((polyD(x) - polyS(x))**2), x0)

print(res)
print(res.fun)  # 输出结果为36.59096676853359,误差极大

错误分析

核心错误是目标函数逻辑完全错误:

  • 全局变量x是linspace(0,1,100)生成的数组,minimize的参数t被完全忽略,目标函数计算的是整个区间内所有点的polyD(x)-polyS(x)平方和,这个值是固定常数,和t无关,导致优化器无法找到有效解。
  • 正确逻辑应该是针对单个自变量t,计算polyD(t)-polyS(t)的平方(交点处该差值为0,平方值最小)。

修正方案

1. 修正minimize的目标函数

调整目标函数为针对单个t计算差值平方,同时添加[0,1]的约束确保结果在指定区间内:

from scipy.optimize import minimize

# 修正目标函数:针对单个t计算差值平方
def objective(t):
    return (polyD(t) - polyS(t))**2

x0 = 0.5  # 初始值选区间中点,更接近真实解
# 添加[0,1]的约束,确保解在目标区间内
res = minimize(objective, x0, bounds=[(0, 1)])

print(res.x[0])  # 输出接近0.61的解
print(res.fun)   # 输出接近0的极小值

2. 更简便的方法:直接求解多项式方程

两个二次多项式的差是一个二次方程,用np.roots直接求解更高效,无需优化:

# 计算两个多项式的系数差:polyD - polyS = 0
coeffs = [
    0.6539311181514963 - 0.8530319920733438,  # x²项系数
    -1.597163991790283 - 0.1601011622660309,  # x项系数
    1.115355004199118 - (-0.03070291735792586) # 常数项
]

roots = np.roots(coeffs)
# 筛选出[0,1]区间内的解
valid_root = [r for r in roots if 0 <= r <= 1][0]
print(valid_root)  # 输出0.6100000000000001,和预期一致
print(polyD(valid_root))  # 输出0.3844127382712173

3. 使用根查找函数(更适合找零点)

用scipy.optimize.root_scalar直接找polyD(t)-polyS(t)的零点,比minimize更直接:

from scipy.optimize import root_scalar

def diff_func(t):
    return polyD(t) - polyS(t)

# 用区间法找[0,1]内的根
res = root_scalar(diff_func, bracket=[0, 1], method='brentq')
print(res.root)  # 输出0.6100000000000001

关于导数加速

如果一定要用minimize并加速,可以手动计算目标函数的导数(雅可比),目标函数是(f(t))²,导数为2*f(t)*f’(t),其中f(t)=polyD(t)-polyS(t),f’(t)是其导数:

def objective(t):
    return (polyD(t) - polyS(t))**2

def jacobian(t):
    f = polyD(t) - polyS(t)
    f_prime = (-1.597163991790283 + 2*0.6539311181514963*t) - (0.1601011622660309 + 2*0.8530319920733438*t)
    return 2 * f * f_prime

res = minimize(objective, x0=0.5, bounds=[(0,1)], jac=jacobian)

这样可以让优化过程更快收敛。

内容的提问来源于stack exchange,提问作者JeeyCi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 18:23:26