Search code examples
algorithmmatlableast-squares

Least Squares Algorithm doesn't work


:) I'm trying to code a Least Squares algorithm and I've come up with this:

function [y] = ex1_Least_Squares(xValues,yValues,x) % a + b*x + c*x^2 = y

points = size(xValues,1); 
A = ones(points,3);  
b = zeros(points,1); 

for i=1:points
    A(i,1) = 1; 
    A(i,2) = xValues(i); 
    A(i,3) = xValues(i)^2; 

    b(i) = yValues(i);
end

constants = (A'*A)\(A'*b);

y = constants(1) + constants(2)*x + constants(3)*x^2;

When I use this matlab script for linear functions, it works fine I think. However, when I'm passing 12 points of the sin(x) function I get really bad results.

These are the points I pass to the function:

xValues = [ -180; -144; -108; -72; -36; 0; 36; 72; 108; 144; 160; 180];

yValues = [sind(-180); sind(-144); sind(-108); sind(-72); sind(-36); sind(0); sind(36); sind(72); sind(108); sind(144); sind(160); sind(180) ];

And the result is sin(165°) = 0.559935259380508, when it should be sin(165°) = 0.258819


Solution

  • MATLAB already contains a least square polynomial fitting function, polyfit and a complementary function, polyval. Although you are probably supposed to write your own, trying out something like the following will be educational:

    xValues = [ -180; -144; -108; -72; -36; 0; 36; 72; 108; 144; 160; 180];
    % you may want to experiment with different ranges of xValues
    yValues = sind(xValues);
    
    % try this with different values of n, say 2, 3, and 4
    p = polyfit(xValues,yValues,n);
    x = -180:36:180;
    y = polyval(p,x);
    
    plot(xValues,yValues);
    hold on
    plot(x,y,'r');
    

    Also, more generically, you should avoid using loops as you have in your code. This should be equivalent:

    points = size(xValues,1); 
    A = ones(points,3);      
    A(:,2) = xValues; 
    A(:,3) = xValues.^2; % .^ and ^ are different
    

    The part of the loop involving b is equivalent to doing b = yValues; either name the incoming variable b or just use the variable yValues, there's no need to make a copy of it.