Using matlab fit object as a function - matlab

Matlab fit is no doubt useful but it is not clear how to use it as a function
apart from trivial integration and differentiation given on the official website:
http://uk.mathworks.com/help/curvefit/example-differentiating-and-integrating-a-fit.html
For example given a fit stored in the object 'curve' one can evaluate
curve(x) to get a number. But how one would, e.g. integrate |curve(x)|^2 (apart from clumsily creating a new fit)? Trying naively
curve = fit(x_vals,y_vals,'smoothingspline');
integral(curve(x)*curve(x), 0, 1)
gives an error:
Output of the function must be the same size as the input. If FUN is an array-valued integrand, set the 'ArrayValued' option to true.
I have also tried a work around by definining a normal function and an implicit function for the integrand (below) but both give the same error.
func=#(x)(curve(x))...; % trial solution 1
function func_val=func(curve, x)...; % trial solution 2

Defining function for the integrand followed by integration with option 'ArrayValued' set to 'true' works:
func=#(x)(curve(x)*curve(x));
integral(func,0,1,'ArrayValued',true)

You need to have the function vectorized, i.e use element-wise operations like curve(x).*curve(x) or curve(x).^2.
Also make sure that the shape of the output matches the input, i.e a row input gives a row output, similarly a column comes out as a column. It seems that evaluating the fit object always returns a column vector (e.g. f(1:10) returns a 10x1 vector not 1x10).
With that said, here is an example:
x = linspace(0,4*pi,100)';
y = sin(x);
y = y + 0.5*y.*randn(size(y));
f = fit(x, y, 'smoothingspline');
now you can integrate as:
integral(#(x) reshape(f(x).^2,size(x)), 0, 1)
in this case, it can be simplified as a simple transpose:
integral(#(x) (f(x).^2)', 0, 1)

Related

MATLAB - integral function vectorization warning

When trying to use the integral2 function, I get the following warning:
"Integrand function outputs did not match to the required tolerance when the same input values were supplied in two separate calls with different size input matrices. Check that the function is vectorized properly."
My code is:
z1=0; z2=5;
t1=0; t2=10;
a=1:500;
b=linspace(0.15,0.02,length(a));
c=[a;b];
d=4.9e-07;
func = #(z,t) my_func((z + t),c) .* exp(-d.*t);
int_x = integral2(func,z1,z2,t1,t2,'RelTol',1e-3,'AbsTol',1e-3) ./ (z2 - z1);
my_func is:
function out = my_func(z_in,c)
z=reshape(z_in,1,numel(z_in));
for i=1:length(z)
if (z(i)<0.0)
z(i)=0.0;
end
end
expfactor=exp(-z/150);
sB=5.5*0.9*4*expfactor;
mB=0.9*interpolate(c(1,:),c(2,:),z);
out=sB+mB;
out=reshape(out,size(z_in,1),size(z_in,2));
end
z1=0, z2=9.6, t1=0, t2=3000 (i.e. all have the size (1,1)), and I have used element-wise operations, so not sure what the problem is.
When debugging, my_func is called three times, with z and t having different sizes each time (although same as each other; (14,14), (2,3) and (14,14)). When sizes are (14,14), the values of z are unique for each column, but the same for each row (e.g. [3,2,1;3,2,1]), and vice versa for t (e.g. [4,4,4;5,5,5]). But when sizes are (2,3), all values in the z and t matrices are unique. The warning comes after the second and third call.
What could be the reasons for the warning?
Edit: to accommodate the dimension requirements in my_func, I've reshaped z to a vector at the start, then reshaped the output back to matrix at the end, copying a similar function I've seen. But this returns the warning:
"Non-finite result. The integration was unsuccessful. Singularity likely."
Thanks

Integral of an integral

Why does the error message of this code return: "Subscript indices must either be real positive integers or logicals.", when I am using ceil for every subscript?
A=1:1:100;
B=1:1:100;
C=1;
D=1:1:100;
E=2;
F=1:1:100;
G=1:1:100;
H=0.1:0.1:10;
fun_1=#(t)integral(#(ti)G(ceil(ti)).*H(ceil(t-ti)),0.1,t-1);
fun_2=#(t)integral(#(ti)G(ceil(ti)).*B(ceil(ti)).*(C.*D(t).^E)./F(t).*...
exp(-integral(#(x)(C.*D(ceil(x)).^E)./F(ceil(x)),ti,5)-K.*(t-ti)),0.1,t-
1,'ArrayValued',true);
I=500;
J=1000;
K=2;
fun_3=#(t)I*integral(#(ti)min(fun_2(ceil(ti)),J).*exp(-(K+I).*(t-ti)),0.1,t-
1);
t=1:1:5;
figure(1)
fplot(fun_1,t);
figure(2)
fplot(fun_2,t);
figure(3)
fplot(fun_3,t);
fplot see documentation Called as fplot(f,xinterval) evaluates your function handle f over the interval xinterval. IT will evaluate f at automatically determined steps along that given interval.
From the docs:
xinterval — Interval for x [–5 5] (default) | two-element vector of
form [xmin xmax]
You seem to be trying to specify exactly where you want your functions evaluated
t=1:1:5;
...
fplot(fun_1,t);
But it doesn't work that way. What is happening is that fplot is evaluating the function from 1 to 2 (the first 2 elements of t). So for example it might feed values of t = 1, 1.05, 1.1,... ,2 into your fun_# functions.
You can tell this because you first function which does work actually plots over the x-range of 1 to 2.
The reason you are getting a subscript indices error is because in fun_2 you have this ...(C.*D(t).^E)./F(t).*... Since fplot is feeding in values for t which are spaced between 1 and 2 (ex. 1.1) that is not a valid index.
If you really just want the values of your functions at t = 1:1:5 The you probably do not want to use fplot and just want evaluate the functions at those times and plot it.
y = feval(fun_1,t);
plot(t,y)
EDIT: The above code doesn't work
You will need to do something like the code below. This is because the 2nd & 3rd trems to the intergral function need to be scalar (1x1). If you feed them an array for t then they crash. So evaluate at each t not all at once.
figure(1)
y_1 = arrayfun(fun_1,t);
plot(t,y_1);
figure(2)
y_2 = arrayfun(fun_2,t);
plot(t,y_2);
figure(3)
y_3 = arrayfun(fun_3,t);
plot(t,y_3);
Note: the Third function still errors ... and I'm not 100% sure why. I didn't really look at it.

trying to understand scipy's optimize.minimize function, getting indexerror

I'm trying to write code that will optimize a multivariate function using sklearn's optimize function, but it keeps returning an IndexError, and I'm not sure where to go from here.
The code is this:
revcoeff = coefficients[::-1]
xdot = np.zeros(0)
normfeat1 = normfeat1.reshape(-1,1)
xdot = np.append(normfeat1, normfeat2.reshape(-1,1), axis=1)
a = revcoeff[1:3]
b = xdot[0, :]
seed = np.zeros(5) #does seed need to be the coefficients? not sure
fun = lambda x: np.multiply((1/666), np.power(np.sum(np.dot(a, xdot[x, :])-medianv[x]),2)) #costfunction
optsol = optimize.minimize(fun, seed)
where there are two features I'm using in my nearest neighbors algorithm. Coefficients for the fitted regression model are given into the array "coefficients".
What I'm having trouble understanding is 1) why my code is throwing a "IndexError: arrays used as indicies must be of integer or boolean type"....and also partially I'm confused by the optimize.minimize function itself. It takes in two input values, the function and x0 (an ndarray with initial guesses). What should x0 be, the coefficients values? Or do I pick random values, and how many are necessary?
np.zeros() does not return integers by default. Try, for example, np.zeros(5, dtype=int) instead. It won't solve all of the problems with your code, though. You'll see some other error message.
Also, notice, that 1/666 returns 0 instead of 0.00150150. You probably want 1/666.0.
It would be helpful if you could clean up your code as half of it is of no use.

Octave fminsearch: Problems with minimization and options

I am trying to use Octave's fminsearch function, which I have used in MATLAB before. The function seems not sufficiently documented (for me at least), and I have no idea how to set to options such that it would actually minimize.
I tried fitting a very simple exponential function using the code at the end of this message. I want the following:
I want the function to take as input the x- and y-values, just like MATLAB would do. Furthermore, I want some control over the options, to make sure that it actually minimizes (i.e. to a minimum!).
Of course, in the end I want to fit functions that are more complicated than exponential, but I want to be able to fit exponentials at least.
I have several problems with fminsearch:
I tried handing over the x- and y-value to the function, but a matlab-style thing like this:
[xx,fval]=fminsearch(#exponential,[1000 1],x,y);
or
[xx,fval]=fminsearch(#exponential,[33000 1],options,x,y)
produces errors:
error: options(6) does not correspond to known algorithm
error: called from:
error: /opt/local/share/octave/packages/optim-1.0.6/fmins.m at line 72, column 16
error: /opt/local/share/octave/packages/optim-1.0.6/fminsearch.m at line 29, column 4
Or, respectively (for the second case above):
error: `x' undefined near line 4 column 3
error: called from:
error: /Users/paul/exponential.m at line 4, column 2
error: /opt/local/share/octave/packages/optim-1.0.6/nmsmax.m at line 63, column 6
error: /opt/local/share/octave/packages/optim-1.0.6/fmins.m at line 77, column 9
error: /opt/local/share/octave/packages/optim-1.0.6/fminsearch.m at line 29, column 4
Apparently, the order of arguments that fminsearch takes is different from the one in MATLAB. So, how is this order??
How can I make fminsearch take values and options?
I found a workaround to the problem that the function would not take values: I defined the x- and y values as global. Not elegant, but at least then the values are available in the function.
Nonetheless, fminsearch does not minimize properly.
This is shown below:
Here is the function:
function f=exponential(coeff)
global x
global y
X=x;
Y=y;
a= coeff(1);
b= coeff(2);
Y_fun = a .* exp(-X.*b);
DIFF = Y_fun - Y;
SQ_DIFF = DIFF.^2;
f=sum(SQ_DIFF);
end
Here is the code:
global x
global y
x=[0:1:200];
y=4930*exp(-0.0454*x);
options(10)=10000000;
[cc,fval]=fminsearch(#exponential,[5000 0.01])
This is the output:
cc =
4930.0 5184.6
fval = 2.5571e+08
Why does fminsearch not find the solution?
There is an fminsearch implementation in the octave-forge package "optim".
You can see in its implementation file that the third parameter is always an options vector, the fourth is always a grad vector, so your ,x,y invocations will not work.
You can also see in the implementation that it calls an fmins implementation.
The documentation of that fmins implementation states:
if options(6)==0 && options(5)==0 - regular simplex
if options(6)==0 && options(5)==1 - right-angled simplex
Comment: the default is set to "right-angled simplex".
this works better for me on a broad range of problems,
although the default in nmsmax is "regular simplex"
A recent problem of mine would solve fine with matlab's fminsearch, but not with this octave-forge implementation. I had to specify an options vector [0 1e-3 0 0 0 0] to have it use a regular simplex instead of a 'right-angled simplex'. The octave default makes no sense if your coefficients differ vastly in scale.
The optimization function fminsearch will always try to find a minimum, no matter what the options are. So if you are finding it's not finding a minimum, it's because it failed to do so.
From the code you provide, I cannot determine what goes wrong. The solution with the globals should work, and indeed does work over here, so something else on your side must be going awry. (NOTE: I do use MATLAB, not Octave, so those two functions could be slightly different...)
Anyway, why not do it like this?
function f = exponential(coeff)
x = 0:1:200;
y = 4930*exp(-0.0454*x);
a = coeff(1);
b = coeff(2);
Y_fun = a .* exp(-x.*b);
f = sum((Y_fun-y).^2);
end
Or, if you must pass x and y as external parameters,
x = [0:1:200];
y = 4930*exp(-0.0454*x);
[cc,fval] = fminsearch(#(c)exponential(c,x,y),[5000 0.01])
function f = exponential(coeff,x,y)
a = coeff(1);
b = coeff(2);
Y_fun = a .* exp(-x.*b);
f = sum((Y_fun-y).^2);
end

MATLAB Function (Solving an Error)

I have one file with the following code:
function fx=ff(x)
fx=x;
I have another file with the following code:
function g = LaplaceTransform(s,N)
g = ff(x)*exp(-s*x);
a=0;
b=1;
If=0;
h=(b-a)/N;
If=If+g(a)*h/2+g(b)*h/2;
for i=1:(N-1)
If=If+g(a+h*i)*h;
end;
If
Whenever I run the second file, I get the following error:
Undefined function or variable 'x'.
What I am trying to do is integrate the function g between 0 and 1 using trapezoidal approximations. However, I am unsure how to deal with x and that is clearly causing problems as can be seen with the error.
Any help would be great. Thanks.
Looks like what you're trying to do is create a function in the variable g. That is, you want the first line to mean,
"Let g(x) be a function that is calculated like this: ff(x)*exp(-s*x)",
rather than
"calculate the value of ff(x)*exp(-s*x) and put the result in g".
Solution
You can create a subfunction for this
function result = g(x)
result = ff(x) * exp(-s * x);
end
Or you can create an anonymous function
g = #(x) ff(x) * exp(-s * x);
Then you can use g(a), g(b), etc to calculate what you want.
You can also use the TRAPZ function to perform trapezoidal numerical integration. Here is an example:
%# parameters
a = 0; b = 1;
N = 100; s = 1;
f = #(x) x;
%# integration
X = linspace(a,b,N);
Y = f(X).*exp(-s*X);
If = trapz(X,Y) %# value returned: 0.26423
%# plot
area(X,Y, 'FaceColor',[.5 .8 .9], 'EdgeColor','b', 'LineWidth',2)
grid on, set(gca, 'Layer','top', 'XLim',[a-0.5 b+0.5])
title('$\int_0^1 f(x) e^{-sx} \,dx$', 'Interpreter','latex', 'FontSize',14)
The error message here is about as self-explanatory as it gets. You aren't defining a variable called x, so when you reference it on the first line of your function, MATLAB doesn't know what to use. You need to either define it in the function before referencing it, pass it into the function, or define it somewhere further up the stack so that it will be accessible when you call LaplaceTransform.
Since you're trying to numerically integrate with respect to x, I'm guessing you want x to take on values evenly spaced on your domain [0,1]. You could accomplish this using e.g.
x = linspace(a,b,N);
EDIT: There are a couple of other problems here: first, when you define g, you need to use .* instead of * to multiply the elements in the arrays (by default MATLAB interprets multiplication as matrix multiplication). Second, your calls g(a) and g(b) are treating g as a function instead of as an array of function values. This is something that takes some getting used to in MATLAB; instead of g(a), you really want the first element of the vector g, which is given by g(1). Similarly, instead of g(b), you want the last element of g, which is given by g(length(g)) or g(end). If this doesn't make sense, I'd suggest looking at a basic MATLAB tutorial to get a handle on how vectors and functions are used.