Create least squares fit for linear combinations
8 views (last 30 days)
Show older comments
Hi, I'm trying to create an unmixing alogirthm and want help in doing so.
To start off, I have 2 values (let's say x1 and x2) that make up an unknown (let's say y1). I'm trying to figure out what combination of these values make up the unknown, so the equation would be:
y1 = (a1 * x1) + (a2 * x2)
where a1 + a2 = 1, as they're percentages of each x value.
I'm trying to understand how to create a function that would find a value of a1 and a2 to minimize the difference between the unknown and the combination. In essence, I'm trying to minimize using the least squares fit:
y1 - (a1*x1) + (a2*x2)
Any help would be appreciated, thanks!
1 Comment
Answers (3)
Bruno Luong
on 13 Apr 2022
first write
a2 = 1 - a1
replace in the first equation with y, solve for a1, then a2
0 Comments
Matt J
on 15 Apr 2022
I'm assuming x1,x2, and y1 are all equal-sized column vectors.
LHS=x1(:)-x2(:);
RHS=y1(:)-x2(:);
a1=min(max(LHS\RHS,0),1);
a2=1-a1;
a=[a1,a2];
9 Comments
Matt J
on 17 Apr 2022
Edited: Matt J
on 17 Apr 2022
x1=zeros(1,1000);
x2=ones(1,1000);
y=0.1*x1+0.9*x2;
x1=x1+0.2*randn(size(x1));
x2=x2+0.2*randn(size(x2));
y=y+0.02*randn(size(y));
dx = x1-x2;
dxy = y-x2;
% leastsquare
a1=dot(dxy,dx)./dot(dx,dx)
% total least-square
[~,~,V] = svd([dx(:) dxy(:)], 0); % find the SVD of Z.
a1 = -V(1,2) / V(2,2)
%total least square constrained
C=[x1(:),x2(:),-y(:)];
d=zeros(size(C,1),1);
a=lsqlin(C,d,[],[], [1,1,-1],0,[0;0;0]);
a=a(1:2)/a(3);
a(1)
Bruno Luong
on 17 Apr 2022
Better but I don't think what you call lsqlin is Total Least squares according to Wikipedia, where the Frobenius norm of the augmented error matrix
% norm([E F],'fro')
is minimize, not
% norm(C*aa,2)
Your solution and mine clearly differ if you run smaller numerical example.
x1=zeros(1,10);
x2=ones(1,10);
y=0.1*x1+0.9*x2;
x1=x1+0.1*randn(size(x1));
x2=x2+0.1*randn(size(x2));
y=y+0.01*randn(size(y));
dx = x1-x2;
dxy = y-x2;
% leastsquare
a1=dot(dxy,dx)./dot(dx,dx)
% total least-square
[~,~,V] = svd([dx(:) dxy(:)], 0); % find the SVD of Z.
a1 = -V(1,2) / V(2,2)
%total least square constrained
C=[x1(:),x2(:),-y(:)];
d=zeros(size(C,1),1);
a=lsqlin(C,d,[],[], [1,1,-1],0,[0;0;0]);
a=a(1:2)/a(3)
Bruno Luong
on 17 Apr 2022
Edited: Bruno Luong
on 17 Apr 2022
I also make a flawed code of total leat squares earlier (under comment of Matt's answer), since dx and dxy are correlated so my TLSQ implement on those vectors is not the appropriate. The better implementation is
n=1000;
x1=zeros(1,n);
x2=ones(1,n);
y=0.1*x1+0.9*x2;
x1=x1+0.1*randn(size(x1));
x2=x2+0.1*randn(size(x2));
y=y+0.1*randn(size(y));
% total least-square
% assuming ccov([x1(:) x2(:) y(:)]) is sigma*eye(3)
v = (y+x1-2*x2)/sqrt(6);
w = (y-x1)/sqrt(2);
[~,~,V] = svd([v(:) w(:)], 0);
V22 = V(2,2)*sqrt(6);
V12 = V(1,2)*sqrt(2);
a1 = (V22-V12)/(V22+V12);
a1 = min(max(a1,0),1);
a2 = 1-a1;
a = [a1; a2]
1 Comment
Bruno Luong
on 17 Apr 2022
Doing some montecarlo to evaluate the precision of each method (script attached). LSQ and LSQLIN seems to have some systematic errors (bias).

See Also
Categories
Find more on Linear Least Squares in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!