Matlab中fminsearch优化提前终止问题的解决方法
问题概述
我用fminsearch执行期权数据的优化流程,将某时间段的期权价格与隐含波动率数据划分为x周的区块,针对每个区块求解一组参数以最小化复杂函数的均方误差。设置的优化选项为:
options = optimset('MaxFunEvals',5000, 'TolFun', 1e-2);
调用fminsearch的代码为:
[a,fval,exitflag,options] = fminsearch(fun,x0,options)
优化逻辑嵌入在自定义函数estimate中,通过循环遍历周区块调用该函数:
function [mu,fval,exitflag,options] = estimate(mu_prev, strike, close, m, n, call_prices, x1, options) t2 = tic; pen_fun = @(x) ...; [a,fval,exitflag,options] = fminsearch(pen_fun,x1,options); toc(t2)
遇到的问题:优化总是提前终止,既不遵守设置的最大迭代次数,也不满足容限要求——终止时fval远大于TolFun,迭代次数远小于MaxFunEvals。尝试过在循环或函数内移动options定义,但无效。
解决思路
先明确终止原因:检查exitflag值
fminsearch的exitflag对应不同终止逻辑:- 1:函数值收敛到容限范围内
- 0:达到最大函数评估次数
- -1:用户手动终止
- 2:参数x的变化小于
TolX容限
每次循环后打印exitflag,确定到底是哪种触发了提前终止,这是排查的核心第一步。
循环中必须重置options初始值
fminsearch会修改传入的options结构体,将当前迭代的已用评估次数、收敛状态等写入其中。如果循环中复用同一个options,下一次调用时会基于上一次的剩余评估次数继续,直接导致提前耗尽配额。解决方法:
在每次调用estimate前重新初始化options:% 循环内每次调用前重置 for ... % 遍历周区块的循环 options = optimset('MaxFunEvals',5000, 'TolFun', 1e-2); [mu,fval,exitflag,options] = estimate(mu_prev, strike, close, m, n, call_prices, x1, options); end或者在
estimate函数内部直接覆盖传入的options,确保每次调用都是全新的初始设置。检查目标函数pen_fun的稳定性
- 若pen_fun返回NaN、Inf或突变值,fminsearch会提前终止。在pen_fun中加入调试代码,打印每次输入x对应的函数值,排查是否存在异常输出。
- 检查均方误差的量级:如果初始fval本身就远大于1e-2,当前TolFun设置可能不合理,可尝试放大容限(比如1e-1),或者对目标函数做归一化处理(比如除以初始误差),让容限设置匹配函数尺度。
优化初始值x1的选择
如果x1落在目标函数的平坦区域,fminsearch会误判为收敛。可以:- 尝试更换不同的初始值,观察终止情况是否变化;
- 每次循环基于前一个区块的结果做小幅度扰动(比如加少量噪声),避免陷入局部平坦区。
调整额外的容限参数
默认的TolX(参数变化容限)为1e-4,如果参数空间尺度较大,可能导致fminsearch因参数变化过小提前终止。可以同时调整TolX:options = optimset('MaxFunEvals',5000, 'TolFun', 1e-2, 'TolX', 1e-2);验证pen_fun的输入输出逻辑
确保pen_fun的输入x维度与x1一致,且返回值是标量的均方误差。若返回值不是标量,或输入维度不匹配,可能导致fminsearch的终止逻辑异常。
内容的提问来源于stack exchange,提问作者mirtilla

