MATLAB: multiple function fitting - matlab

I have a function, sum of three exponents:
F = f1*exp1 + f2*exp2 + f3*exp3
exactly:
F=1-((1-f(2)-f(3)).*(exp(-abs(data)./a(1)))+((1-f(1)-f(3)).*(exp(-abs(data)./a(2))))+((1-f(1)-f(2)).*(exp(-abs(data)./a(3)))));
where f1, f2, f3 is a fraction and each exp has one parameter, call it a1, a2 and a3.
So, fitting this function to experimental data gives six parameters (f1, f2, f3, a1, a2, a3).
Note, that
a1 > a2 > a3
and
f1 + f2 + f3 = 1
The fitting is done for several timelags (call it t1, t2, t3....). So for each timelag there is one set of six parameters.
Parameters a1, a2 and a3 are increasing with timelag in linear way ( a1(t1) < a1(t2) < a1(t3)... and so on). Fractions are the same for each timelag.
What I need is slope of a1(t), a2(t), a3(t) and fractions.
The problem is, that when I am fitting the function for each timelag, I often have a situation that a1 and a2 are nicely going up (perfect linear fits) but a3 is going down.
Also I have a problem with fractions - I can't take mean of each fraction because when I add f1(t) + f2(t) + f3(t) its never equal to 1.
Is there any (simple) way to fit it all 'at once'? How to do that?
Thanks!

First, I would suggest to reduce the number of parameters:
Replace f3 by 1-f1-f2
If ai(t) is always linear, replace by ai(t) = ai0 + bi*t. With bi>0, you can ensure that ai(t) is increasing.
That gives you two parameters for each ai(t), plus f1 and f2 for each time point, so a total of 6 + 2 * (# of timepoints) parameters. Depending on the number of timepoints, it may be possible to fit those with fmincon, as suggested by Chris Taylor.
With fmincon, you can add the parameter constraints in quite flexible ways. You probably want to add the constraint 0<=f1<=1 (and the same for f2) to the ones you already have.

Related

Why is this the correct way to do a cost function for a neural network?

So after beating my head against the wall for a few hours, I looked online for a solution to my problem, and it worked great. I just want to know what caused the issue with the way I was originally going about it.
here are some more details. The input is a 20x20px image from the MNIST datset, and there are 5000 samples, so X, or A1 is 5000x400. There are 25 nodes in the single hidden layer. The output is a one hot vector of 0-9 digits. y (not Y, which is the one hot encoding of y) is a 5000x1 vector with the value of 1-10.
Here was my original code for the cost function:
Y = zeros(m, num_labels);
for i = 1:m
Y(i, y(i)) = 1;
endfor
H = sigmoid(Theta2*[ones(1,m);sigmoid(Theta1*[ones(m, 1) X]'))
J = (1/m) * sum(sum((-Y*log(H]))' - (1-Y)*log(1-H]))')))
But then I found this:
A1 = [ones(m, 1) X];
Z2 = A1 * Theta1';
A2 = [ones(size(Z2, 1), 1) sigmoid(Z2)];
Z3 = A2*Theta2';
H = A3 = sigmoid(Z3);
J = (1/m)*sum(sum((-Y).*log(H) - (1-Y).*log(1-H), 2));
I see that this may be slightly cleaner, but what functionally causes my original code to get 304.88 and the other to get ~ 0.25? Is it the element wise multiplication?
FYI, this is the same problem as this question if you need the formal equation written out.
Thanks for any help I can get! I really want to understand where I'm going wrong
Transfer from the comments:
With a quick look, in J = (1/m) * sum(sum((-Y*log(H]))' - (1-Y)*log(1-H]))'))) there is definetely something going on with the parenthesis, but probably on how you pasted it here, not with the original code as this would throw an error when you run it. If I understand correctly and Y, H are matrices, then in your 1st version Y*log(H) is matrix multiplication while in the 2nd version Y.*log(H) is an entrywise multiplication (not matrix-multiplication, just c(i,j)=a(i,j)*b(i,j) ).
Update 1:
In regards to your question in the comment.
From the first screenshot, you represent each value yk(i) in the entry Y(i,k) of the Y matrix and each value h(x^(i))k as H(i,k). So basically, for each i,k you want to compute Y(i,k) log(H(i,k)) + (1-Y(i,k)) log(1-H(i,k)). You can do it for all the values together and store the result in matrix C. Then C = Y.*log(H) + (1-Y).*log(1-H) and each C(i,k) has the above mentioned value. This is an operation .* because you want to do the operation for each element (i,k) of each matrix (in contrast to multiplying the matrices which is totally different). Afterwards, to get the sum of all the values inside the 2D dimensional matrix C, you use the octave function sum twice: sum(sum(C)) to sum both columnwise and row-wise (or as # Irreducible suggested, just sum(C(:))).
Note there may be other errors as well.

Getting real and imaginary parts of complex function in matlab

I've got a following question. I've got function f(t) = C3*exp(t*x*1i) + C4*exp(-t*x*1i) as a solution of a differential equation (as syms). But I need this solution as a real function (C3*cos + C4*sin). How can I do it? And how can I get real and imaginary parts of this function? Is there a function in matlab allowing me to do it?
You can use rewrite to rewrite the expression in terms of cosines and sines, then collect to collect coefficients in terms of i, giving you your real and imaginary terms:
f = C3*exp(t*x*1i) + C4*exp(-t*x*1i);
g = collect(rewrite(f, 'sincos'), i)
g =
(C3*sin(t*x) - C4*sin(t*x))*1i + C3*cos(t*x) + C4*cos(t*x)
You can see from the above that the imaginary term is zero if C3 is equal to C4.
You can rewrite the expression/function in terms of sine and cosine using rewrite. Still you cannot apply the real and imag functions to get the respective parts in as nicer form as you get in case of non-symbolic computations. The trick to get the real and imaginary parts in a complex expression is to substitute i with 0 to get the real part and then subtract the real part from the original expression to get the imaginary part. Use simplify for the surety.
An example:
syms C3 C4 t x
f(t) = C3*exp(t*x*1i) + C4*exp(-t*x*1i);
fsincos = rewrite(f, 'sincos');
realf = simplify(subs(fsincos, i,0));
imagf = simplify(fsincos-realf);
%or you can use the collect function to avoid simplify
>> fsincos
fsincos(t) =
C3*(cos(t*x) + sin(t*x)*1i) + C4*(cos(t*x) - sin(t*x)*1i)
>> realf
realf(t) =
cos(t*x)*(C3 + C4)
>> imagf
imagf(t) =
sin(t*x)*(C3*1i - C4*1i)

Solve equation with exponential term

I have the equation 1 = ((π r2)n) / n! ∙ e(-π r2)
I want to solve it using MATLAB. Is the following the correct code for doing this? The answer isn't clear to me.
n= 500;
A= 1000000;
d= n / A;
f= factorial( n );
solve (' 1 = ( d * pi * r^2 )^n / f . exp(- d * pi * r^2) ' , 'r')
The answer I get is:
Warning: The solutions are parametrized by the symbols:
k = Z_ intersect Dom::Interval([-(PI/2 -
Im(log(`fexp(-PI*d*r^2)`)/n)/2)/(PI*Re(1/n))], (PI/2 +
Im(log(`fexp(-PI*d*r^2)`)/n)/2)/(PI*Re(1/n)))
> In solve at 190
ans =
(fexp(-PI*d*r^2)^(1/n))^(1/2)/(pi^(1/2)*d^(1/2)*exp((pi*k*(2*i))/n)^(1/2))
-(fexp(-PI*d*r^2)^(1/n))^(1/2)/(pi^(1/2)*d^(1/2)*exp((pi*k*(2*i))/n)^(1/2))
You have several issues with your code.
1. First, you're evaluating some parts in floating-point. This isn't always bad as long as you know the solution will be exact. However, factorial(500) overflows to Inf. In fact, for factorial, anything bigger than 170 will overflow and any input bigger than 21 is potentially inexact because the result will be larger than flintmax. This calculation should be preformed symbolically via sym/factorial:
n = sym(500);
f = factorial(n);
which returns an integer approximately equal to 1.22e1134 for f.
2. You're using a period ('.') to specify multiplication. In MuPAD, upon which most of the symbolic math functions are based, a period is shorthand for concatenation.
Additionally, as is stated in the R2015a documentation (and possibly earlier):
String inputs will be removed in a future release. Use syms to declare the variables instead, and pass them as a comma-separated list or vector.
If you had not used a string, I don't think that it would have been possible for your command to get misinterpreted and return such a confusing result. Here is how you could use solve with symbolic variables:
syms r;
n = sym(500);
A = sym(1000000);
d = n/A;
s = solve(1==(d*sym(pi)*r^2)^n/factorial(n)*exp(-d*sym(pi)*r^2),r)
which, after several minutes, returns a 1,000-by-1 vector of solutions, all of which are complex. As #BenVoigt suggests, you can try the 'Real' option for solve. However, in R2015a at least, the four solutions returned in terms of lambertw don't appear to actually be real.
A couple things to note:
MATLAB is not using the values of A, d, and f from your workspace.
f . exp is not doing at all what you wanted, which was multiplication. It's instead becoming an unknown function fexp
Passing additional options of 'Real', true to solve gets rid of most of these extraneous conditions.
You probably should avoid calling the version of solve which accepts a string, and use the Symbolic Toolbox instead (syms 'r')

Math, 2 equations 2 unknowns, and matlab, plot

i am trying to solve these 2 equations with 2 unknowns.
i want to find the angle of a1(alpha1), a2(alpha2) in radians.
however when i solve it in maple i get 0.112 for a2 and 0.089 for a1.
but some other guys used matlab and they get something different with plot and 2 angles..
can someone tell me if i am right or he is?
MY equations:
equation 1: 4/(2*pi)*(cos(2*a1)+cos(2*a2))=0
equation 2: 4/(10*pi)*(cos(10*a1)+cos(10*a2))=0
his matlab:
j=0;
for i=0:pi/100:1
j=j+1;
a2(j)=i;
a1_1(j)=acos(-cos(2*i))/2;
a1_2(j)=acos(-cos(10*i))/10;
end
plot(a2,a1_1,'-k',a2,a1_2,'-b','LineWidth',1.4);
I wanna plot like him..but i am not sure his Equations a1_1 is correct?
by the way the main equation it came from:
bn = 4/(npi)(cos(na1)+cos(na2))=0
bn = 0 and n is 2th and 10th harmonics to be eliminated
cos(A)+cos(B) = 0
happens for
A + B = pi + 2*k*pi or A - B = pi + 2*k*pi
Both of the two original equations could resolve the the same of the two variants or to different variants. Resolving to the same equation, say the first, will produce
7*(a1+a2) = pi + 2*k7*pi and 13*(a1+a2) = pi + 2*k13*pi
which can only hold if
0 = 6*pi + 2*(13*k7-7*k13) <=> 3 = 7*k13-13*k7
which implies a1+a2 = pi + 2*m*pi. .
In the case of different to different variant, one obtains (modula sign variations of a1, a2)
7*(a1+a2) = pi + 2*k7*pi and 13*(a1-a2) = pi + 2*k13*pi
and thus
a1 = (pi/7+pi/13)/2 + k7*pi/7 + k13*pi/13
a2 = (pi/7-pi/13)/2 + k7*pi/7 - k13*pi/13
and all possible sign variations, since cosine is an even function. However, simultaneous sign variations are also covered by variations of k7 and k13. Thus you obtain additionally (up to) 2*7*13=182 solutions to your problem.

Denormalize results of curve fit on normalized data

I am fitting an exponential decay function with lsqvurcefit in Matlab. To do this I first normalize my data because they differ several orders of magnitude. However Im not sure how to denormalize my fitted parameters.
My fitting model is s = O + A * exp(-t/T) where t and s are known and t is in the order of 10^-3 and s in the order of 10^5. So I subtract from them their mean and divide them by their standarddeviation. My goal is to find the best A, O and T that at the given times t will result most near s. However I dont know how to denormalize my resulting A O and T.
Might somebody know how to do this? I only found this question on SO about normalisation, but does not really address the same problem.
When you normalize, you must record the means and standard deviations for each of your featuers. Then you can easily use those values to denormalize.
e.g.
A = [1 4 7 2 9]';
B = 100 475 989 177 399]';
So you could just normalize right away:
An = (A - mean(A)) / std(A)
but then you can't get back to the original A. So first save the means and stds.
Am = mean(A); Bm = mean(B);
As = std(A); Bs = std(B);
An = (A - Am)/As;
Bn = (B - Bm)/Bs;
now do whatever processing you want and then to denormalize:
Ad = An*As + Am;
Bd = Bn*Bs + Bm;
I'm sure you can see that that's going to be an issue if you have a lot of features (i.e. you have to type code out for each feature, what a mission!) so lets assume your data is arranged as a matrix, data, where each sample is a row and each column is a feature. Now you can do it like this:
data = [A, B]
means = mean(data);
stds = std(data);
datanorm = bsxfun(#rdivide, bsxfun(#minus, data, means), stds);
%// Do processing on datanorm
datadenorm = bsxfun(#plus, bsxfun(#times, datanorm, stds), means);
EDIT:
After you have fit your model parameters (A,O and T) using normalized t and f then your model will expect normalized inputs and produce normalized outputs. So to use it you should first normalize t and then denormalize f.
So to find a new f by running the model on a normalized new t. So f(tn) where tn = (t - tm)/ts and tm is the mean of your training (or fitting) t set and ts the std. Then to get your correct magnitude f you must denormalize only f, so the full solution would be
f(tn)*fs + fm
So once again, all you need to do is save the mean and std you used to normalize.