Create least squares fit for linear combinations

8 views (last 30 days)
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!

Answers (3)

Bruno Luong
Bruno Luong on 13 Apr 2022
first write
a2 = 1 - a1
replace in the first equation with y, solve for a1, then a2

Matt J
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
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)
a1 = 0.1290
% total least-square
[~,~,V] = svd([dx(:) dxy(:)], 0); % find the SVD of Z.
a1 = -V(1,2) / V(2,2)
a1 = 0.1332
%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]);
Minimum found that satisfies the constraints. Optimization completed because the objective function is non-decreasing in feasible directions, to within the value of the optimality tolerance, and constraints are satisfied to within the value of the constraint tolerance.
a=a(1:2)/a(3);
a(1)
ans = 0.1305
Bruno Luong
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)
a1 = 0.1453
% total least-square
[~,~,V] = svd([dx(:) dxy(:)], 0); % find the SVD of Z.
a1 = -V(1,2) / V(2,2)
a1 = 0.1462
%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]);
Minimum found that satisfies the constraints. Optimization completed because the objective function is non-decreasing in feasible directions, to within the value of the optimality tolerance, and constraints are satisfied to within the value of the constraint tolerance.
a=a(1:2)/a(3)
a = 2×1
0.1833 0.8167

Sign in to comment.


Bruno Luong
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]
a = 2×1
0.1102 0.8898
  1 Comment
Bruno Luong
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).

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!