Least squares#

We use interpolation and fitting by polynomial as an example.

%config InlineBackend.figure_format = 'svg'
import numpy as np
import matplotlib.pyplot as plt

Let us generate the data as in the book.

m = 11
x = np.linspace(0.0, 1.0, m)
y = (np.abs(x-0.4) < 0.2)*1.0 + 0.0
plt.plot(x,y,'o')
plt.xlabel("x"); plt.ylabel("y"); plt.grid(True);
../_images/48625a4159e87cf35ac136a7caa6c5090df87eb4870f33320231604037a79351.svg

Polynomial interpolation#

We solve the matrix problem using numpy.linalg.solve.

A = np.empty((m,m))
for i in range(m):
    A[i,:] = x[i]**np.arange(0,m)
cint = np.linalg.solve(A,y)

The following function evaluates the polynomial with coefficients in the array c.

# c = polynomial coefficients, m = len(c)
# Computes degree m-1 polynomial
#    y = sum(i=0,m-1) c[i] * x**i
def p(c,x):
    m = len(c)
    y = 0*x
    for i in range(m):
        y += c[i] * x**i
    return y

Let us plot the polynomial on a finer set of points.

xc = np.linspace(0.0, 1.0, 100)
plt.plot(x,y,'o',label='Data')
plt.plot(xc,p(cint,xc),label='Interp deg='+str(m-1))
plt.xlabel("x"); plt.ylabel("y")
plt.legend()
plt.grid(True)
plt.savefig("sqwave_interp.pdf")
../_images/39b4fe557fe09c2a368b3adb680ca1fa3387deabde6ddd384ff81b3ec4c75c81.svg

Polynomial least squares fit#

We solve the least squares problem using numpy.linalg.lstsq.

n = 8
A = np.empty((m,n))
for i in range(m):
    A[i,:] = x[i]**np.arange(0,n)
cls,res,rank,s = np.linalg.lstsq(A,y,rcond=None)

Let us plot the interpolating and least squares polynomials.

plt.plot(x,y,'o',label='Data')
plt.plot(xc,p(cint,xc),label='Interp deg='+str(m-1))
plt.plot(xc,p(cls,xc),label='LS, deg='+str(n-1))
plt.xlabel("x"); plt.ylabel("y")
plt.legend()
plt.grid(True)
plt.savefig("sqwave_fit.pdf")
../_images/5ca7b8bb8cd1c368e1479039b0ae7a544755cb49396373d617d7de37cd8027b6.svg

Fitting a straight line#

We have some data \((x_i, y_i)\) and we expect a linear relationship between \(x\) and \(y\)

\[ y = c_0 + c_1 x \]

But the data \(y_i\) possibly has some error.

c0 = 1.0
c1 = 2.0

m = 10
x = np.linspace(0.0, 1.0, m)
yt = c0 + c1 * x
plt.plot(x, yt, '--',label='True')
y = yt + 0.2 * (2 * np.random.rand(m) - 1)
plt.plot(x, y, 'o',label='Data')
plt.legend(); plt.grid(True)
plt.xlabel("x"); plt.ylabel("y");
../_images/4b6e50206ec6273fad933ecd4bbef83ec030dc54a19272ae64dd73fef1d8525d.svg

Let us estimate \(c_0, c_1\) using least squares fitting.

n = 2
A = np.empty((m,n))
A[:,0] = 1.0
A[:,1] = x
c,res,rank,s = np.linalg.lstsq(A,y,rcond=None)
print('c0 = ', c[0])
print('c1 = ', c[1])
c0 =  1.0229585444774352
c1 =  1.9823138862703176

Plot the fitted line and compare with data and true function.

yf = c[0] + c[1] * x
plt.plot(x, yt, '--', label='True')
plt.plot(x, y, 'o',label='Data')
plt.plot(x, yf, '-', label='Fit')
plt.legend(); plt.grid(True)
plt.xlabel("x"); plt.ylabel("y");
../_images/b88cb84cbb4e9132790f5f3fe98e452bf1b8a477861bfcb7c6e672ab104003b6.svg