I'm using fminunc. Specifically, I'm using a quasi-newton method with BFGS and a user supplied gradient to minimize a function. It goes for about 3 iterations, then does a bunch of function evaluations. I have the function I am trying to minimize display its value when it is called, and I can see that after a few calls on the 4th iteration it is significantly smaller than it was on the third iteration, but Matlab continues to evaluate the function and I'm not sure why. Is there something I can adjust to tell it to accept the update and move to the next iteration?
Sounds like you understand the optimizer pretty well, let's see if we can help with the optimset settings. From the mathworks docs it calls out how to relax the tolerances to terminate the optimization with the following parameters:
TolFun Termination tolerance on the function value, a positive scalar. The
default is 1e-6.
TolX Termination tolerance on x, a positive scalar. The default value is
1e-6.
Sounds like you have the Optimization Toolbox, in which case I believe you can use optimset to get the optimization parameters and then use the fminunc to initialize it.(The docs for the regular optimset don't call out that you can pass the fminunc as an argument, but I would think it would work for the toolbox version.
options = optimset('fminunc');
% you can try either of these two or both, but I would
% recommend only changing one at a time :-)
options = optimset(options,'TolFun',myNewTolFun)
options = optimset(options,'TolX',myNewTolX)
% then you can make your call to the optimizer
x = fminunc(fun,x0,options)
Excruciating detail on the optim-settings can be found here.
Related
I have a function with the handle #func with initial condition y0 that I want to test over t = [0, tspan]. What, exactly, do I need to do to increase the number of time steps ode45 uses, without changing tspan?
I saw the MATLAB documentation of ode45 and saw that I need to somehow change the options input to ode45. However, I do not really understand how to do this because no example code was provided.
You need to look at odeset which creates an options structure to be used in ODE solvers, like ode45. You're looking at changing the MaxStep parameter.
The documentation for this (MATLAB R2015a) says:
MaxStep - Upper bound on step size [ positive scalar ]
MaxStep defaults to one-tenth of the tspan interval in all solvers.
Therefore, you can make it something smaller than 0.1*tspan... something like 1e-6 or something like that. This depends on what tspan is, so you'll need to make it smaller than 0.1*tspan if you want to increase the total number of time steps / output points.
As such, create an odeset structure and override the MaxStep parameter. The rest of the values will remain as default:
options = odeset('MaxStep', 1e-6);
Now that you're done, call ode45 on your problem:
[tout,yout] = ode45(#func, tspan, y0, options);
Simply play around with the MaxStep until you get the desired granularity.
Minor Note
Though a bit buried, the documentation does tell you on how to change the options. This is the section that talks about how to call ode45 with options. Please take note of what is highlighted in bold. This is the documentation for MATLAB R2015a:
[TOUT,YOUT] = ode45(ODEFUN,TSPAN,Y0,OPTIONS) solves as above with default
integration properties replaced by values in OPTIONS, an argument created
with the ODESET function. See ODESET for details. Commonly used options
are scalar relative error tolerance 'RelTol' (1e-3 by default) and vector
of absolute error tolerances 'AbsTol' (all components 1e-6 by default).
If certain components of the solution must be non-negative, use
ODESET to set the 'NonNegative' property to the indices of these
components.
Im using fminunc to minimize a function with 450 variables, here are the lines
opts = optimset('Display','Iter','MaxIter', 10000000,'MaxFunEvals', 100000000,'TolX', 1e-12,'TolFun', 1e-12);
[x,fval,exitflag] = fminunc(#function,x0,opts);
Note that I dont provide the gradient, so fminunc uses quasi-newton algorithm.
After some iterations it endes with this final message
fminunc stopped because it cannot decrease the objective function
along the current search direction.
But if I restart the code with the new point obtained, it continued decreasing, so Im not in the minimum.
It seems to me that the algorithm its just looking for the minimum simply along one direccion and when it finds it, it stops instead start searching among the other direccions.
Any clue how to modify the problem so that doesnt happen and find the minimum? or other programm I should use in order to do it faster?
Edit: the function is convex
This type of problem can occur if your have numerical noise in your objective function. Then gradient/hessian become noisy and the step is off, and line searching ends with precisely this error.
Try plotting your criterion in an interval around your starting values but change one of the parameters from x0(i) to
linspace(x0(i)(1-1e07, x(i)(1+1e07), 100), one number at the time.
If the function looks very jittery, that may be your problem.
Alternatively, maybe you are starting in a region where the function is not convex? In that case try fminsearch to begin with.
Otherwise, consider using analytic gradients.
Also, perhaps your tolerance are set too fine. Try reducing tolfun and tolx to 1e-08. Your problem is very high dimensional.
I'm trying to have MATLAB integrate a function of two variables, like fun=#(x,y)x+y;
against one variable. I can define, say fun2=#(y)quad(#(x)fun(x,y),1,2); and it'll give me fun2(1), say, no problem. But it gives me errors when I try to evaluate fun2 of a, say, matrix. When I try to integrate fun2 using quad(), which is what I need to do, it gives me the same error.
And I can't just use quad2d() because (a) I need something like fun2 in several different places and (b) the integrals I need to calculate are 4D.
Are there any other ways of doing this?
So you want to use the fun2 for every element of an array. You can do this by using the arrayfun and define fun2.
You can see the info on arrayfun at: http://www.mathworks.com/help/matlab/ref/arrayfun.html.
Instead of quad, use integral with the 'ArrayValued' property set to true.
fun2 = #(y)integral(#(x)fun(x,y),1,2,'ArrayValued',true);
For your four-dimensional problem, you can use integral(#(x)integral3(…)) or arrayfun. See my answer to this question how to do this exactly.
You should use integral instead of quad anyway, because the Matlab quad documentation says:
quad will be removed in a future release. Use integral instead.
In the documentation of integral, you also find options that specify the accuracy of the result ('AbsTol' and 'RelTol').
I need to numerically integrate the following system of ODEs:
dA/dR = f(R,A,B)
dB/dR = g(R,A,B)
I'm solving the ODEs for a Initial-value stability problem. In this problem, the system is initially stable but goes unstable at some radius. However, whilst stable, I don't want the amplitude to decay away from the starting value (to O(10^-5) for example) as this is non-physical since the system's stability is limited to the background noise amplitude. The amplitude should remain at the starting value of 1 until the system destabilises. Hence, I want to overwrite the derivative estimate to zero whenever it is negative.
I've written some 4th order Runge-Kutta code that achieves this, but I'd much prefer to simply pass ODE45 (or any of the built in solvers) a parameter to make it overwrite the derivative whenever it is negative. Is this possible?
A simple, fast, efficient way to implement this is via the max function. For example, if you want to make sure all of your derivatives remain non-negative, in your integration function:
function ydot = f(x,y)
ydot(1) = ...
ydot(2) = ...
...
ydot = max(ydot,0);
Note that this is not the same thing as the output states returned by ode45 remaining non-negative. The above should ensure that your state variables never decay.
Note, however, that that this effectively makes your integration function stiff. You might consider using a solver like ode15s instead, or at least confirming that the results are consistent with those from ode45. Alternatively, you could use a continuous sigmoid function, instead of the discontinuous, step-like max. This is partly a modeling decision.
Im trying to understand why a call like this
G = const * quadv(fun,a,b,tol)
returns different values than
lenB = length(b)
for 1 = 1:lenB
G(i) = const .* quadl(fun,a,b,tol)
end
and how to achieve both calls to return the same values ?
EDIT:
I would like to run the quadl faster for arrays as well. So I would formulate the above question:
If it is possible, how to call quadl also for arrays (similar like the quadv call above), and thus increase performance by the calculations?
Matlab's quadl uses adaptive Lobatto quadrature; quadv uses adaptive Simpson's rule.
The quality of the answer you get might depend on the function you assume. What does your test fun look like?
I'll assume that you're passing the same function, limits, and tolerance to both calls. That will mean the differences are smaller than the tolerance.
The two methods are different - Gaussian quadrature is not the same as Simpson's rule:
http://en.wikipedia.org/wiki/Gaussian_quadrature
If you take a look at the help of quadl and quadv, you see that quadl uses a different algorithm to integrate the function.
Numerical analysis almost never yields perfect results, so you cannot expect to get identical results.