Curve fitting with 5 parameters in Matlab - matlab

I am working on a curve fitting problem with the input function of the form
n=((xi-xa)-a*cos(theta))^2+(h-a*sin(theta))^2;
d=((xi-xa)+a*cos(theta))^2+(h+a*sin(theta))^2;
v=k*log(n/d) : Input function
Here xa,a,theta,h and k are parameters and we are required to compute v(xi)
The plot looks like this
Here blue dots represent observed value and red line is the theoretical curve obtained from the input function.
This fitting process was done by manually varying the parameters and matching the curves using hit and trial.
Could this be accomplished using any optimization technique in Matlab. if so how ?

You can try to use lsqcurvefit (http://nl.mathworks.com/help/optim/ug/lsqcurvefit.html), e.g.
function F = myfun(x,xdata)
%your parameters xa,a,theta,h,k
%map to parameter vector x(1),x(2),x(3),x(4),x(5)
n = ((xdata-x(1))-x(2)*cos(x(3)))^2+(x(4)-x(2)*sin(x(3)))^2;
d = ((xdata-x(1))+acos(x(3)))^2+(x(4)+asin(x(3)))^2;
F = x(5)*log(n/d);
end
and a call to solver
x0 = [1;1;1;1;1]; % your guess for starting values of the x vector of parameters
x = lsqcurvefit(#myfun,x0,xdata,ydata);

Related

Draw random numbers from a custom probability density function in Matlab

I want to sample R random numbers from a custom probability density function in Matlab.
This is the expression of the probability density function evaluated at x.
I thought about using slicesample
R=10^6;
f = #(x) 1/(2*pi^(1/2))*(1/(x^(3/2)))*exp(-1/(4*x));
epsilon= slicesample(0.3,R,'pdf',f,'thin',1,'burnin',1000);
However, it does not work because I get the error
Error using slicesample (line 175)
The step-out procedure failed.
I tried to change starting value and values of thin and burning parameters but it does not seem to work. Could you advise, either on how to make slicesample work or on alternative solutions to sample random numbers from a custom probability density function in Matlab?
Let X be a random variable distributed according to your target pdf. Applying the change of variable y = 1/x and using the well-known theorem for a function of a random variable, the distribution of Y = 1/X is recognized to be a Gamma distribution with parameters α = 1/2, β = 1/4.
Therefore, it suffices to generate a Gamma random variable (using gamrnd) with those parameters and take the inverse. Note that Matlab's definition of the Gamma distribution uses parameters A = α, B = 1/β.
R = 1e5; % desired sample size
x = 1./gamrnd(1/2, 4, [1 R]); % result
Check:
histogram(x, 'Normalization', 'pdf', 'BinEdges', 0:.1:10)
hold on
f = #(x) 1/2/sqrt(pi)./x.^(3/2).*exp(-1/4./x); % target pdf
fplot(f, 'linewidth', .75)

How to use lsqcurvefit to fit a rational function?

I want to fit a rational function using the curve fitting technique in MATLAB.
I am trying to use lsqcurvefit to reproduce a rational function M, which takes 5 inputs, with the data outputted from the exact function C. I think I am close to getting the plots; however, when I use lsqcurvefit, I keep getting an error saying:
LSQCURVEFIT requires the following inputs to be of data type double: 'YDATA'.
Below is my code:
% Define range for k
k= linspace(1E-10,1.5,100);
% Exact Function C(k)
C= #(k)(0.5*((1i*k+0.135).* (1i*k+0.651)))./((1i*k+0.0965).* (1i*k+0.4555));
% Cget function used to extract real and imaginary numbers and stacks the result
Cget= #(k)[real(C(k)); imag(C(k))];
%Call function Cget(k) to get stacked real and imaginary values
realimag =Cget(k);
% Create an initial guess
x0=[1,1];
% Define parameters
a1=0.2; a2=0.7; b1=0.1; b2=0.5;
% Define approximated function
M= #(a1,a2,b1,b2,k)(0.5*((1i*k+a1).* (1i*k+a2)))./((1i*k+b1).* (1i*k+b2));
Mget1= #(a1,a2,b1,b2,k)[real(M(a1,a2,b1,b2,k)); imag(M(a1,a2,b1,b2,k))];
T=Mget1(a1,a2,b1,b2,k);
%Find best fit curve
x=lsqcurvefit(M,x0,k,C)
How can I fit reproduce M, given the exact function C?
The variable C should be entered as a double array so that the function should get the input range and use it in the calculation.
% Exact Function C(k)- Bessel Function
C0 = (0.5*((1i*k+0.135).* (1i*k+0.651)))./((1i*k+0.0965).* (1i*k+0.4555));
and parameters of x could be entered as an array with 4 values.
M = #(x,k)(0.5*((1i*k+x(1)).* (1i*k+x(2))))./((1i*k+x(3)).* (1i*k+x(4)));
and x0 should have 4 values.
x0 = [1,1,1,1];
%Find best fit curve
x = lsqcurvefit(M,x0,k,C0)

Plot symbolic derivative of a built-in MATLAB function

I am trying to compute the second derivative of the airy function. Only its first derivative is a predefined function in MATLAB (airy(1,x))
Is there a way to compute its symbolic derivative? without resorting to finite differences, etc
I tried this
syms x
aiprime = #(x) airy(1,x);
aisecond = diff(airy(1,x));
plot(-10:0.01:10,aiprime,aisecond)
But didn't work.
Error using plot
Invalid second data argument
The problem is your plot statement. You specify the desired x-data, but did not evaluate your function in these points:
syms x
aiprime(x) = airy(1,x); % I would define it as a symbolic function instead of a function handle, although it works too.
aisecond(x) = diff(airy(1,x)); % Define as a function, to be able to evaluate the function easily
xs = -10:0.01:10; % define your desired x points
plot(xs,aiprime(xs),xs, aisecond(xs)) % evaluate your functions and plot data

How to write MatLab Code for bimodal Probability Density Functions?

I want to write a bimodal Probability Density Function (PDF with multiple peaks, Galtung S) without using the pdf function from statistics toolbox. Here is my code:
x = 0:0.01:5;
d = [0.5;2.5];
a = [12;14]; % scale parameter
y = 2*a(1).*(x-d(1)).*exp(-a(1).*(x-d(1)).^2) + ...
2*a(2).*(x-d(2)).*exp(-a(2).*(x-d(2)).^2);
plot(x,y)
Here's the curve.
plot(x,y)
I would like to change the mathematical formula to to get rid of the dips in the curve that appear at approx. 0<x<.5 and 2<x<2.5.
Is there a way to implement x>d(1) and x>d(2) in line 4 of the code to avoid y < 0? I would not want to solve this with a loop because I need to convert the formula to CDF later on.
If you want to plot only for x>max(d1,d2), you can use logical indexing:
plot(x(x>max(d)),y(x>max(d)))
If you to plot for all x but plot max(y,0), you just can write so:
plot(x,max(y,0))

Exponential Curve Fitting in Matlab

I have a data-set which is loaded into matlab. I need to do exponential fitting for the plotted curve without using the curve fitting tool cftool.
I want to do this manually through executing a code/function that will output the values of a and b corresponding to the equation:
y = a*exp(b*x)
Then be using those values, I will do error optimization and create the best fit for the data I have.
Any help please?
Thanks in advance.
Try this...
f = fit(x,y,'exp1');
I think the typical objective in this type of assignment is to recognize that by taking the log of both sides, various methods of polynomial fit approaches can be used.
ln(y) = ln(a) + ln( exp(x).^b )
ln(y) = ln(a) + b * ln( exp(x) )
There can be difficulties with this approach when errors such as noise are involved due to the behavior of ln as it approaches zero.
In this exercise I have a set of data that present an exponential curve and I want to fit them exponentially and get the values of a and b. I used the following code and it worked with the data I have.
"trail.m" file:
%defining the data used
load trialforfitting.txt;
xdata= trialforfitting(:,1);
ydata= trialforfitting(:,2);
%calling the "fitcurvedemo" function
[estimates, model] = fitcurvedemo(xdata,ydata)
disp(sse);
plot(xdata, ydata, 'o'); %Data curve
hold on
[sse, FittedCurve] = model(estimates);
plot(xdata, FittedCurve, 'r')%Fitted curve
xlabel('Voltage (V)')
ylabel('Current (A)')
title('Exponential Fitting to IV curves');
legend('data', ['Fitting'])
hold off
"fitcurvedemo.m" file:
function [estimates, model] = fitcurvedemo(xdata, ydata)
%Call fminsearch with a random starting point.
start_point = rand(1, 2);
model = #expfun;
estimates = fminsearch(model, start_point);
%"expfun" accepts curve parameters as inputs, and outputs
%the sum of squares error [sse] expfun is a function handle;
%a value that contains a matlab object methods and the constructor
%"FMINSEARCH" only needs sse
%estimate returns the value of A and lambda
%model computes the exponential function
function [sse, FittedCurve] = expfun(params)
A = params(1);
lambda = params(2);
%exponential function model to fit
FittedCurve = A .* exp(lambda * xdata);
ErrorVector = FittedCurve - ydata;
%output of the expfun function [sum of squares of error]
sse = sum(ErrorVector .^ 2);
end
end
I have a new set of data that doesn't work with this code and give the appropriate exponential fit for the data curve plotted.