如何找到使给定向量输入的四参数标量函数最小化的y0与y1?
最优求解方法:线性最小二乘的解析解或数值优化
你的函数f本质是线性最小二乘问题——目标函数是关于y0和y1的二次凸函数,存在唯一的全局最小值。下面提供两种最优实现方式,其中解析解是效率最高的,数值优化则更通用(适合扩展到更复杂的场景)。
方法一:解析解(最直接高效)
因为目标函数是平方和形式,我们可以通过求导并令偏导数为0,推导得到y0和y1的闭式解,不需要迭代计算,速度最快。
推导过程
先定义残差项:d_i = y_[i] - y[i],那么函数f可以改写为:
f(y0, y1) = sum( (d_i + y0 + y1 * i)² )
对y0和y1分别求偏导并令其等于0,得到方程组:
sum(d_i) + n*y0 + y1*sum(i) = 0(n是向量长度)sum(d_i*i) + y0*sum(i) + y1*sum(i²) = 0
解这个二元一次方程组,就能得到最优的y0和y1。
代码实现
import numpy as np def f(y_, y, y0, y1): xy1 = [i*y1 for i in range(len(y_))] diff = [(y_[i] + y0 + xy1[i] - y[i])**2 for i in range(len(y_))] return sum(diff) # 给定输入 y_ = [x**2 + 1.4 for x in range(-10,11,1)] y = [x**2 + 1. for x in range(-10,11,1)] n = len(y_) # 计算所需的各项求和 d = np.array(y_) - np.array(y) sum_d = np.sum(d) sum_i = np.sum(range(n)) sum_i2 = np.sum([i**2 for i in range(n)]) sum_di = np.sum(d * np.arange(n)) # 解二元一次方程组:a*y0 + b*y1 = c; d*y0 + e*y1 = f a = n b = sum_i c = -sum_d d_coeff = sum_i e = sum_i2 f_coeff = -sum_di # 计算行列式 det = a*e - b*d_coeff y0_opt = (c*e - b*f_coeff) / det y1_opt = (a*f_coeff - c*d_coeff) / det print(f"最优y0: {y0_opt}, 最优y1: {y1_opt}") print(f"最小函数值: {f(y_, y, y0_opt, y1_opt)}")
运行结果会显示y0_opt约为-0.4,y1_opt约为0——因为你的d_i都是0.4(看给定的y_和y的差值,每个元素都是0.4),所以最优解就是让y0 + y1*i = -0.4,此时每个残差都是0,函数值为0,完全符合预期。
方法二:数值优化(通用型)
如果后续你的函数变得更复杂(比如非线性),可以用Python的scipy.optimize.minimize来求解,它支持多种优化算法,对于这个线性问题也能快速收敛到最优解。
代码实现
from scipy.optimize import minimize # 定义目标函数(只接受y0,y1作为参数,固定y_和y) def objective(params): y0, y1 = params return f(y_, y, y0, y1) # 初始猜测值 initial_guess = [0, 0] # 求解优化问题 result = minimize(objective, initial_guess) print(f"最优y0: {result.x[0]}, 最优y1: {result.x[1]}") print(f"最小函数值: {result.fun}")
这个方法会得到和解析解完全一致的结果,而且不需要手动推导公式,适合快速验证或处理复杂函数。
总结
- 如果你的函数始终是这种线性平方和形式,解析解是最优选择——计算速度最快,结果精确,没有迭代误差。
- 如果函数可能扩展为非线性形式,数值优化更通用,只需要定义目标函数即可求解。
内容的提问来源于stack exchange,提问作者Capo Mestre
相关产品推荐
相关产品推荐

