#!/usr/bin/env python
# coding: utf-8
#
Metode najmanjih kvadrata
# Često se pri raznim mjerenjima pojavljuje veliki broj podataka. Da bi lakše protumačili te podatke pribjegava se grafičkom predstavljanju tih podataka. Na primjer pri izvodjenju nekog eksperimenta dobijeni su podaci
# $$(x_0,y_0),\,(x_1,y_1),\dots,(x_7,y_7).$$
#
# Ovakve podatke moguće je predstaviti grafikom, na primjer kao na sljedećoj slici.
#
#
#
# Podaci iz prethodne tabele predstavljeni grafički
#
#
# Na prvi pogled grafik linearne funkcije najbolje bi odgovara ovim eksperimentalnim podacima. Sljedeći korak bi bio da odredimo linearnu funkciju
#
# $$y=ax+b,$$
#
# odnosno koeficijente $a$ i $b.$ Postavlja se pitanje: Koja je to prava koja je najbliže prolazi predstavljenim tačkama $(x_0,y_0)-(x_7,y_7)?$ ili u opštem slučaju tačkama $(x_0,y_0)-(x_n,y_n)?$ Pretpostavimo da su $a$ i $b$ tražene vrijednosti. Neka je $(x_k,y_k)$ jedna od datih tačaka i neka kroz ovu tačku ne prolazi prava $y=ax+b,$ tada je $y_k\neq ax_k+b,$ tj. $y_k-a x_k-b\neq 0.$
#
#
# Da bi izračunali $a$ i $b$ posmatrajmo funkciju
# $$\varphi(a,b)=\sum_{k=0}^{n}(ax_k+b-y_k)^2. \:(\star)$$
#
#
# Ako greška ima normalnu statističku raspodjelu, onda minimizacijom funkcije $\varphi$ dobijamo najbolje procjena za $a$ i $b.$ Računanje parametara $a$ i $b$ na ovakav način, odnosno linearne funkcije kojom ćemo aproksimirati naziva se $l_2$ aproksimacija.
#
#
#
# Napomena. Norma $l_p$ definisana je na sljedeći način
# $$ || x ||_p=\left\{ \sum_{i=1}^{n}|x_i|^p \right\}^{1/p},\:1\leqslant p<\infty,$$
# za neki vektor $x=(x_1,\ldots,x_n)^T.$
#
#
# Odredimo sada minimum funkcije $\varphi.$ Potrebni uslovi za minimum funkcije $\varphi$ su
#
# $$ \frac{\partial \varphi}{\partial a}=0,\quad \frac{\partial \varphi}{\partial b}=0,$$
#
# računajući prethodne uslove dobijamo
#
# \begin{align*}
# \sum_{k=0}^{n}{2(ax_k+b-y_k)x_k}=&0\\
# \sum_{k=0}^{n}{2(ax_k+b-y_k)}=&0 ,
# \end{align*}
#
# Prethodne jednačine su po nepoznatim $a$ i $b$ i možemo ih napisati u obliku
#
#
# \begin{align}
# \left(\sum_{k=0}^{n}{x^2_k}\right)a+ \left(\sum_{k=0}^{n}{x_k}\right)b=&\sum_{k=0}^{n}{x_k y_k}\\
# \left(\sum_{k=0}^{n}{x_k}\right)a+ (n+1)b=&\sum_{k=0}^{n}{y_k},
# \end{align}
#
#
# gdje je $\sum_{k=0}^{n}{1}=n+1.$
#
#
# Rješenje prethodnog sistema je
#
#
#
# \begin{align*}
# a=& \frac{1}{d}\left[(n+1)\sum_{k=0}^{n}{x_k y_k}-\left(\sum_{k=0}^{n}{x_k}\right)\left(\sum_{k=0}^{n} {y_k}\right) \right] \\
# b=&\frac{1}{d}\left[\left(\sum_{k=0}^{n} {x^2_k}\right)\left(\sum_{k=0}^{n} {y_k}\right)
# -\left(\sum_{k=0}^{n}{x_k}\right)\left(\sum_{k=0}^{n} {x_ky_k}\right) \right],
# \end{align*}
#
#
# gdje je $$d=(n+1)\sum_{k=0}^{n}{x^2_k}-\left(\sum_{k=0}^{n}{x_k^2 }\right)^2.$$
#
#
#
#
#
#
# Zadatak. Izračunati za podatke
# $(0.5,2.25),(1,3.7),\,(2,4.1),\,(2.5,4.3),\,(3,5);$ linearnu funkciju $y=ax+b $ metodom najmanjih kvadrata.
#
# In[1]:
from IPython import get_ipython; # briše varijable, funkcije ...
get_ipython().magic('reset -sf') #
import numpy as np
from matplotlib import pyplot
from numpy import linalg
from numpy import polynomial
from matplotlib import pyplot
from matplotlib import rc
pyplot.style.use('tableau-colorblind10')
newparams={'figure.figsize':(15,8),'font.size': 13,'axes.grid': True,'lines.markersize':10, 'lines.linewidth':2,'figure.dpi':300}
pyplot.rcParams.update(newparams)
xdata=[.5,1,2,2.5,3]
ydata=[2.25,3.7,4.1,4.3,5]
#xdata=np.linspace(1,15,200)
#def f1(x):
# return 4*np.sin(3*x)*np.cos(14*x)+x
#ydata=f1(xdata)
broj=len(xdata)
def lin(x):
xzbir=0; yzbir=0; xyzbir=0; xkvadrat=0; d=0; a=0; b=0;
for i in range(broj):
xzbir=xzbir+xdata[i]
yzbir=yzbir+ydata[i]
xyzbir=xyzbir+xdata[i]*ydata[i]
xkvadrat=xkvadrat+(xdata[i])**2
d=(broj)*xkvadrat-xzbir**2
a=((broj)*xyzbir-xzbir*yzbir)/d
b=(xkvadrat*yzbir-xzbir*xyzbir)/d
print('Koeficijenti su a=%f i'%a, 'b=%f.'%b)
return a*x+b
iks=np.linspace(np.min(xdata)-.25,np.max(xdata)+.25,1000)
fig=pyplot.figure()
pyplot.plot(xdata,ydata,'o',markersize=10)
pyplot.plot(iks,lin(iks),linewidth=3)
pyplot.legend(('Podaci','Linearna funkcija'))
pyplot.savefig('/home/samir/Dropbox/Python/Zadaci/Slike/najmanji2a.pdf')
pyplot.close(fig)
pyplot.show()
#
# Konstrukcija linearne funkcije za uzorak od 5 tačaka
#
#
#
# Konstrukcija linearne funkcije za uzorak od 200 tačaka
#
# Generalni slučaj
# Umjesto računanja linearne funkcije $y=ax+b,$ metoda najmanjih kvadrata može se poopštiti na računanje funkcije $$y=\sum_{j=0}^{m}{c_jg_j(x)}$$ kojom ćemo predstaviti podatke koji su nam na raspolaganju. Funkcije $g_0,\ldots,g_m$ su poznate, fiksirane i linearno nezavisne. Koeficijente $c_0,\ldots,c_m$ ponovo treba izračunati koristeći prethodno izloženi princip najmanjih kvadrata. Drugim riječima, ponovo su poznate kordinate tačaka $(x_k,y_k),\,i=0,\ldots,n;$ koje smo dobili mjerenjem, eksperimentalno ili na neki drugi način, i cilj nam je izračunati koeficijente $c_0,\ldots,c_m;$ tako da funkcija
# \begin{equation}
# \varphi(c_0,\ldots,c_m)=\sum_{k=0}^{n}{\left[ \sum_{j=0}^{m}{c_jg_j(x_k)-y_k}\right]^2 }
# \label{funkcija1}
# \end{equation}
# ima što je moguće manju vrijednost. Potrebni uslovi za dobijanje minimuma funkcije $\varphi$ su
# $$ \frac{\partial \varphi}{\partial c_i}=0,\:i=0,\ldots,m$$
# gdje su
# $$\frac{\partial \varphi}{\partial c_i}=\sum_{k=0}^{n}{2\left[\sum_{j=0}^{m}{c_jg_j(x_k)-y_k} \right]}g_i(x_k),\:i=0,\ldots,m.$$
# Na kraju dobijamo
# $$ \sum_{j=0}^{m}{\left[ \sum_{k=0}^{n}{g_i(x_k)g_j(x_k)}\right]c_j}= \sum_{k=0}^{n}{y_kg_i(x_k)},\:i=0,\ldots,m.$$
#
# Zadatak. Izračunati za podatke $(-1.5,2.3),\, (-1,1.1),\,(-0.5,0.24),\,(0,0.01),\,(0.5,0.26),\,(1,1.2),\,(1.5,2.25)$ kvadratnu funkciju $y=c_2x^2+c_1x+c_0$ metodom najmanjih kvadrata.
#
# In[8]:
from IPython import get_ipython; # briše varijable, funkcije ...
get_ipython().magic('reset -sf') #
import numpy as np
from matplotlib import pyplot
from numpy import linalg
from numpy import polynomial
from matplotlib import rc
pyplot.style.use('tableau-colorblind10')
newparams={'figure.figsize':(15,8),'font.size': 13,'axes.grid': True,'lines.markersize':10, 'lines.linewidth':2,'figure.dpi':300}
pyplot.rcParams.update(newparams)
xdata=np.array([-1.5,-1,-.5,0,.5 ,1,1.5])
ydata=np.array([2.3,1.1,.24,.01,.26,1.2,2.25])
brojTacaka=len(xdata)
brojBaznih=3
matricaBaznih=np.zeros((brojBaznih,brojTacaka))
matricaSistema=np.zeros((brojBaznih,brojBaznih))
vektorSlob=np.zeros(brojBaznih)
def bazne(x,stepen):
return x**stepen
for i in range(brojBaznih):
for j in range(brojTacaka):
matricaBaznih[i,j]=bazne(xdata[j],i)
for i in range(brojBaznih):
for j in range(brojBaznih):
for k in range(brojTacaka):
matricaSistema[i,j]=matricaSistema[i,j]+matricaBaznih[i,k]*matricaBaznih[j,k]
for i in range(brojBaznih):
for k in range(brojTacaka):
vektorSlob[i]=vektorSlob[i]+ydata[k]*matricaBaznih[i,k]
koeficijenti=linalg.solve(matricaSistema,vektorSlob)
pol=np.polynomial.Polynomial(koeficijenti)
iks=np.linspace(min(xdata),max(xdata),250)
y=pol(iks)
fig=pyplot.subplot()
pyplot.plot(xdata,ydata,'o',markersize=10)
pyplot.plot(iks,y)
pyplot.legend(('Podaci','polinom $p_{10}$'),loc='upper center');
pyplot.savefig('/home/samir/Dropbox/Python/Zadaci/Slike/najmanji4d.png')
#pyplot.xlabel(' Broj tačaka je %i'%len(xdata));
#pyplot.show()
pyplot.close()
#
# Konstrukcija polinoma $p_2(x)=c_2x²+c_1x+c_0$ za uzorak od 7 tačaka
#
#
# Konstrukcija polinoma $p_2(x)=c_2x²+c_1x+c_0$ za uzorak od 200 tačaka
#
#
# Konstrukcija polinoma $p_3(x)=c_3x^3+c_2x^2+c_1x+c_0$ za uzorak od 200 tačaka
#
#
# Konstrukcija polinoma $p_4(x)=c_4x^4+c_3x^3+c_2x^2+c_1x+c_0$ za uzorak od 200 tačaka
#
#
# Konstrukcija polinoma $p_5(x)=c_5x^5+c_4x^4+c_3x^3+c_2x^2+c_1x+c_0$ za uzorak od 200 tačaka
#
#
#
#
#
#
# Konstrukcija polinoma $p_{10}$ za uzorak od 500 tačaka
#
#
# Napomena 1. Kao bazne funkcije umjesto $1,x,\ldots,x^n$ mogu se koristiti i druge funkcije.
#
#
# Napomena 2. Ovdje je predstavljena najjednostavija metoda. Druge metode i detaljnija analiza može se vidjeti na primjer u [J97] ili [TB97].
# Literatura
#
# [CD04] W. Cheney, D. Kincaid, Numerical Mathematics and Computing, Brooks/Cole-Thompson Learning, USA, 2004. ISBN: 053489937.
# [J97] J.W. Demmel, Applied Numerical Linear Algebra, SIAM, USA, 1997. ISBN: 0-89871-389-7.
#
# [TB97] L.N.Trefethen, D.Bau III, Numerical Linear Algebra, SIAM, USA, 1997. ISBN: 0-89871-361-7.