127
Ajzenhamer Nikola Naučno izračunavanje — Kroz programski jezik Python — 17. jun 2018.

AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

Page 1: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

Ajzenhamer Nikola

Naučno izračunavanje— Kroz programski jezik Python —

17. jun 2018.

Page 2: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu
Page 3: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

Sadržaj

Predgovor iii

1 Uvod 11.1 Uvod u programski jezik Python . . . . . . . . . . . . . . . . . . . . . . . . 11.2 Biblioteka NumPy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91.3 Biblioteka Matplotlib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111.4 Biblioteka Pandas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141.5 Zadaci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

2 Aproksimacija funkcija 212.1 Linearna algebra kroz modul numpy.linalg . . . . . . . . . . . . . . . . . . 212.2 Kriterijumi kvaliteta aproksimacija funkcija i metod najmanjih kvadrata 25

2.2.1 Aproksimacija polinomima . . . . . . . . . . . . . . . . . . . . . . . 282.2.2 Dodatni primeri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

2.3 Linearna regresija . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312.3.1 Biblioteka scikit-learn . . . . . . . . . . . . . . . . . . . . . . . . . . 332.3.2 Regularizacija . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 432.3.3 Grebena regresija . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

2.4 Odabir modela . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 442.5 Evaluacija modela i unakrsna validacija . . . . . . . . . . . . . . . . . . . 472.6 Zadaci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

3 Furijeove transformacije 513.1 Uzorkovanje signala . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 533.2 Spektrogram . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

3.2.1 Prozorske funkcije . . . . . . . . . . . . . . . . . . . . . . . . . . . . 583.3 Obrada slika . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61

3.3.1 Zamućivanje slike odsecanjem visokih frekvencija . . . . . . . . . 643.3.2 Određivanje kontura odsecanjem niskih frekvencija . . . . . . . . 643.3.3 Konvolucija . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 663.3.4 Postavljanje vodenog žiga . . . . . . . . . . . . . . . . . . . . . . . . 68

3.4 Zadaci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70

4 Numerička linearna algebra 714.1 Dekompozicija matrica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71

4.1.1 LU dekompozicija . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 714.2 Čoleski dekompozicija . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 734.3 SVD dekompozicija . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75

4.3.1 Kompresovanje slika pomoću SVD dekompozicije . . . . . . . . . . 764.3.2 Rešavanje problema najmanjih kvadrata pomoću SVD dekompo-

zicije . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78

i

Page 4: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

SADRŽAJ ii

4.4 Reprezentacija teksta pomoću retkih matrica . . . . . . . . . . . . . . . . 794.5 Analiza glavnih komponenti . . . . . . . . . . . . . . . . . . . . . . . . . . . 81

4.5.1 Primena PCA na skup podataka breast_cancer . . . . . . . . . . . . 824.5.2 Primena PCA za prepoznavanje lica — sopstvena lica . . . . . . . 84

4.6 Određivanje sopstvenih vrednosti i sopstvenih vektora . . . . . . . . . . 874.6.1 Ugrađena bibliotečka podrška . . . . . . . . . . . . . . . . . . . . . 884.6.2 Metod stepenovanja . . . . . . . . . . . . . . . . . . . . . . . . . . . 884.6.3 Metod iscrpljivanja . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89

4.7 Problem rangiranja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 904.7.1 PageRank algoritam . . . . . . . . . . . . . . . . . . . . . . . . . . . 904.7.2 TextRank algoritam . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92

5 Matematička optimizacija 995.1 Metode lokalne optimizacije prvog reda bez ograničenja . . . . . . . . . 995.2 Metode lokalne optimizacije drugog reda bez ograničenja . . . . . . . . 1025.3 Metode lokalne optimizacije sa ograničenjima . . . . . . . . . . . . . . . 1045.4 Primer primene matematičke minimizacije — određivanje parametra

restauracije fotogra je . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1085.5 Zadaci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110

6 Rešenja zadataka 1116.1 Uvod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1116.2 Aproksimacija funkcija . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1116.3 Furijeove transformacije . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1116.4 Optimizacija . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113

Literatura 115

A Liste slika i tabela 117

B Lista resursa 121

Page 5: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

Predgovor

Ovaj tekst predstavlja skriptu iz kursa ‚‚Naučno izračunavanje'', na 5. godinismerova Informatika i Raǔnarstvo i informatika naMatematičkom fakultetu Univer-ziteta u Beogradu, zasnovanu na materijalima Anđelke Zečević, beleškama sa ča-sova vežbi i skripti ‚‚Naučno izračunavanje'' profesora Mladena Nikolića i AnđelkeZečević [1]. Skripta je prateći materijal pre svega studentima koji ovaj kurs slušajuu okviru svojih studija, ali i svima Vama koji biste želeli da se upoznate sa ovom te-matikom. Ovaj materijal ne može zameniti pohađanje vežbi niti drugu preporučenuliteraturu.

Ovaj tekst je u ranoj fazi formiranja. Ukoliko ste pažljivi čitalac ove skripte,i ukoliko uočite bilo kakvu grešku ili propust, možete se javiti autoru na [email protected]. Svi komentari, sugestije, kritike, ali i pohvale ve-zane za ovaj materijal su dobrodošli.

Autor

iii

Page 6: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu
Page 7: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

Glava 1

Uvod

Naučno izračunavanje predstavlja multidisciplinarnu oblast koja se bavi rešava-njem praktičnih problema u naučnim i inženjerskim disciplinama. Ono što je karak-teristično za ovu oblast jeste da se za rešavanje raznih problema koriste pre svegametodi čije je poreklo oblast numeričke matematike, ali i mnogi drugi. Značajnostove oblasti se ogleda kroz ogroman (i sve veći) broj primena u različitim oblastima[1].

U ovom tekstu biće reči o praktičnim primenama metoda naučnog izračunava-nja u programskom jeziku Python, kao vodećem programskom jeziku u ovoj oblasti.Zbog toga, u prvom poglavlju biće dat kratak pregled elemenata programskog je-zika Python [2], a zatim će biti reči o elementima biblioteka NumPy (skraćeno odNumerical Python) [3], Matplotlib [4] i Pandas [5], koje će biti intenzivno korišćeneu daljem tekstu.

1.1 Uvod u programski jezik PythonPython1 je netipizirani (ponekad se kaže i dinamički tipizirani) programski jezik

koji objedinjuje elemente različitih programskih paradigmi, kao što su procedural-na, objektno-orijentisana i skript paradigma. Python izvorni kôd se interpretirapomoću Python interpretera, koji se može pokrenuti iz komandne linije:

$ python

Nakon pokretanja dobijamo informacije o verziji jezika, interpreteru i slične in-formacije, koje se razlikuju zavisno od načina na koji smo instalirali Python sistem.Jedan takav sistem koji je dostupan je Anaconda2, koji osim interpretera donosi i ve-liki broj korisnih paketa kojima se proširuje osnovna funkcionalnost jezika Python.Tako se, na primer, pokretanjem Python interpretera iz komandne linije ispisujenaredna poruka:

Python 3.6.4 |Anaconda, Inc.| (default, Jan 16 2018, 10:22:32) [MSC v.1900 64 bit(AMD64)] on win32Type "help", "copyright", "credits" or "license" for more information.

Nakon ove poruke stoji oznaka da je interpreter spreman da prihvati sledeću na-redbu:

>>>

1Već na samom početku skrećemo pažnju čitaocu da će u ovoj skripti biti korišćena verzija jezika 3.6.2Više informacija na https://www.anaconda.com/.

1

Page 8: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 1. UVOD 2

Direktnim unošenjem naredbi moguće je komunicirati sa interpreterom. Postoje idrugi načini za izvršavanje kôdova, kao što je pisanje Python skripti (koji podrazu-mevano imaju ekstenziju .py), a zatim njihovim izvršavanjem pozivanjem interpre-tera i prosleđivanjem imena skripta. Na primer, poziv$ python lokacija/do/mog/skripta/moj_skript.py

izvršiće sadržaj skript datoteke moj_skript.py. U nastavku će biti izloženi odabranielementi programskog jezika Python, i to oni koji će nam biti neophodni za rešavanjeproblema u ostatku teksta.

Korišćenje Python paketa Osnova programskog jezika Python se jednostavnoproširuje dobavljanjem, a zatim uvoženjem (engl. import) dodatnih programskihbiblioteka koji su organizovani kroz pakete (engl. package). Postoje dva načina zauvoženje biblioteka u radno okruženje: (1) uvoženje celokupnog paketa i (2) uvože-nje određenih bibliotečkih koncepata3. Sintaksa i primeri upotrebe oba načina datisu u tabeli 1.1.

Tabela 1.1: Načini na koje je moguće uvesti dobavljene pakete u radno okruženjeu programskom jeziku Python.

Način uvoženja Sintaksa Komentar

Celokupanpaket

importime_paketa

Uvozi se celokupan paket, naprimer, math, čime postaju dostupnenaprednije matematičke funkcije ikonstante. Svaki koncept de nisanu uvezenom paketu je dostupannavođenjem math.ime_koncepta.

Određenikoncepti

fromime_paketaimport

ime_koncepta1,...,

ime_konceptaN

Na primer, naredbom from mathimport sin, cos uvoze se samo

funkcije sin i cos iz paketa math. Ovefunkcije su dostupne bez navođenjaimena paketa; na primer, umesto

math.sin navodimo sin.

Veoma često su imena paketa i koncepata de nisanih u njima prilično dugačka,što značajno otežava programiranje – svaki put je potrebno navesti puno ime kon-cepta prilikom njegovog korišćenja. U tu svrhu, na raspolaganju nam je ključna rečas, kojom se uvode pseudonimi (engl. alias). Korišćenje ključne reči as demonstri-ramo sledećim dvama naredbama:>>> import numpy as np>>> from matplotlib import pyplot as plt

čime se uvode nova imena za pakete i koncepte. U ovom konkretnom slučaju, ume-sto numpy možemo koristiti np i umesto matplotlib.pyplot možemo koristiti plt.

Da bismo saznali koji sve koncepti se uvoze u radno okruženje iz nekog paketa,možemo iskoristiti ugrađenu funkciju dir, čiji je argument naziv paketa. Na primer,ukoliko želimo da saznamo sadržaj pomenutog paketa math, korišćenjem naredbe>>> import math>>> dir(math)

3Između ostalog, koncepti mogu biti: globalne promenljive, klase i funkcije.

Page 9: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 1. UVOD 3

dobijamo izlaz

['__doc__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh','asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh','degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod','frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf','isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan','pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc']

Python funkcija ima veliki broj i uvoženjem novih paketa taj broj značajno raste.Pri svakodnevnom radu mi se upoznajemo sa sve većim brojem funkcija. Među-tim, nemoguće je zahtevati od nekoga da zapamti precizno ponašanje svake Pythonfunkcije. Stoga, na raspolaganju nam stoji funkcija help, koja nam prikazuje doku-mentaciju za funkciju koju prosledimo kao argument. Na primer, naredba

>>> help(dir)

proizvodi naredni izlaz

Help on built-in function dir in module builtins:

dir(...)dir([object]) -> list of strings

If called without an argument, return the names in the current scope.Else, return an alphabetized list of names comprising (some of) the attributesof the given object, and of attributes reachable from it.If the object supplies a method named __dir__, it will be used; otherwisethe default dir() logic is used and returns:

for a module object: the module's attributes.for a class object: its attributes, and recursively the attributesof its bases.

for any other object: its attributes, its class's attributes, andrecursively the attributes of its class's base classes.

Promenljive i tipovi Uvođenje nove promenljive se vrši dodeljivanjem vrednostiidenti katoru koji označava tu novu promenljivu. Kao što smo već pomenuli, uprogramskom jeziku Python jedna promenljiva može biti različitog tipa u zavisnostiod toga koja vrednost joj je dodeljena. Na primer, naredba

>>> x = 1

uvodi promenljivu x čija je vrednost celi broj 1, te je i njen tip celi broj, preciznije,int. Ovo se može proveriti korišćenjem izraza

>>> type(x)

čime se dobija rezultat

<class 'int'>

Pored tipa int, osnovni tipovi koje ćemo koristiti su float (brojevi u pokretnomzarezu), complex (kompleksni brojevi), boolean (Bulove promenljive) i str (niske).Primeri vrednosti ovih tipova dati su u tabeli 1.2, a neke od operacija nad njimadate su u tabeli 1.3. Informacije o ovim tipovima možemo dobiti uvoženjem paketasys, a zatim korišćenjem odgovarajućih koncepata. Na primer, ukoliko želimo dasaznamo više o tipu float, možemo izvršiti naredbu

Page 10: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 1. UVOD 4

>>> sys.float_info

čime dobijamo naredni izlaz

sys.float_info(max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308, min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307, dig=15, mant_dig=53, epsilon=2.220446049250313e-16, radix=2, rounds=1)

Tabela 1.2: Primeri literala odgovarajućih osnovnih tipova u programskom jezikuPython.

Tip Primeri literala datog tipa

int 0, 3, -5, …float -3.2415, 17.3, 2.3e3, …complex complex(2,3), 2+3j, …boolean True, False

str

"Niska koja dozvoljava umetanje jednostrukih navodnika",'Niska koja dozvoljava umetanje dvostrukih navodnika',"""Niska sa dvostrukim navodnicimakoja može da se prelamau više linija""",'''Niska sa jednostrukim navodnicimakoja može da se prelamau više linija''',r'Niska u kojoj se ne obrađuju escape sekvence, tzv. sirova niska',…

Tabela 1.3: Primeri operacija nad odgovarajućim tipovima u programskom jezikuPython.

Tip Primeri operacija nad datim tipom

int, float +, -, *, / (deljenje u pokretnom zarezu), // (celobrojno deljenje), % (ostatakpri celobrojnom deljenju), <, <=, >, >=, ==, !=, …

complex +, -, *, / (deljenje kompleksnih brojeva), ==, !=, .real (realni deo),.imag (imaginarni deo), …

boolean and (logička konjukcija), or (logička disjunkcija), ! (logička negacija),== (logička ekvivalencija), ^ (logička ekskluzivna disjunkcija)

str belina između dve niske (nadovezivanje), + (nadovezivanje), * (umnožavanjeniske skalarom, videti tabelu 1.5), …

Konverzije Eksplicitna konverzija između tipova se vrši pomoću operatora kon-verzije (engl. cast), čija je sintaksa ciljni_tip(izraz). Na primer, niz naredbi

>>> a = 0>>> b = -3.65>>> c = '42'>>> float(a)>>> int(b)>>> int(c)>>> float(c)

Page 11: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 1. UVOD 5

proizvodi izlaz

0.0-34242.0

Napomenimo da ukoliko pokušamo da izvršimo konverziju između tipova kojinisu kompatibilni, ispaliće se TypeError, a ukoliko pokušamo da izvršimo konver-ziju između str u int ili float, pri čemu niska ne predstavlja celi broj, odnosno,broj u pokretnom zarezu, onda će biti ispaljen ValueError. U programskom jezikuPython izvršava se i implicitna konverzija užih tipova u širi tip, pri korišćenju ope-racija nad različitim tipovima. Na primer, pri izračunavanju izraza x+y, pri čemuje x celobrojna vrednost i y vrednost u pokretnom zarezu, prvobitno će se izvršitiimplicitna konverzija celobrojne vrednosti x u odgovarajuću vrednost u pokretnomzarezu (float(x)), a zatim će se izvršiti sabiranje dve vrednosti u pokretnom zare-zu (float(x) + y). Pri implicitnoj konverziji se mogu ispaliti iste greške kao i prieksplicitnoj konverziji. Očekivano, rezultat će biti vrednost u pokretnom zarezu.

Kontrole toka (i funkcije), ispravno nazubljivanje i komentari Programskijezik Python dozvoljava korišćenje standardnih konstrukcija za kontrolu toka. Jed-na važna karakteristika jeste da se umesto vitičastih zagrada { i } za označavanjetela kontrole toka koristi nazubljivanje. Preciznije, telo kontrole toka mora biti zatačno jedan tabulator nazubljeno u odnosu na nazubljivanje te kontrole toka. Podkontrolama toka ćemo smatrati i de nisanje funkcije. Primeri kontrola toka datisu u tabeli 1.4. Ukoliko želimo da koristimo kontrole toka u interaktivnom Pythonokruženju, interpreter nam neće parcijalno izvršiti kontrolu toka nakon što pritisne-mo taster ENTER, već će nam prikazati oznaku ... nakon koje možemo da nastavimosa konstrukcijom kontrole toka. Naglasimo još jednom da se ceo kod tela kontro-le toka mora nazubiti jednim tabulatorom. U programskom jeziku Python postojeisključivo jednolinijski komentari koji počinju karakterom #.

Tabela 1.4: Primeri korišćenja kontrola toka u programskom jeziku Python.

Kontrola toka Primer korišćenja

if-elif-else

if x < 0:print('Negativno x')

elif x > 0:print('Pozitivno x')

else:print('X je jednako 0')

whilewhile (n > 0):

print(n)n = n-1

for for n in range(10, 0, -1)4:print(n)

de nisanje funkcijeidenti katora nzd

sa dva argumenta a i b

def nzd(a, b):if b == 0:

return aelse:

return nzd(b, a%b)

Page 12: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 1. UVOD 6

Liste Liste u programskom jeziku Python predstavljaju sekvence vrednosti kojene moraju nužno biti istog tipa. Sintaksa listi je oblika [ vrednost1, vrednost2, …,vrednostN ]. Indeksiranje u listama počinje indeksom 0. Liste su veoma korisnastruktura podataka i, pored operacija koje se mogu izvršiti nad svakim sekvencijal-nim tipom podataka (koje su prikazane u tabeli 1.5)), nad listama se posebno moguizvršiti i operacije koje su predstavljene u tabeli 1.6. Kažemo da se ove operacijeizvršavaju u mestu (engl. in place), odnosno, ne pravi se kopija objekta kao rezultatizvršavanja operacije, već se menja objekat nad kojim se izvršila operacija. U da-tim tabelama smatramo da se operacije izvršavaju u mestu osim ako nije eksplicitnonaznačeno drugačije.

Tabela 1.5: Operacije koje se mogu izvršiti nad proizvoljnom sekvencom (koja ćebiti referisana kao seq ili više njih, koje će biti referisane kao seq1 i seq2) i njihoviopisi.

Operacija Opis operacije

obj in seq Proverava da li obj pripada sekvenci.obj not in seq Proverava da li obj ne pripada sekvenci.

seq1 + seq2 Nadovezuje drugu sekvencu na kraj prve sekvence.Nije operacija u mestu.

n * seq ili seq * n Umnožava sekvencu n puta, pri čemu je n tipa int. Nijeoperacija u mestu.

len(seq) Određuje dužinu sekvence.

seq[i]

Izračunava element liste na poziciji i. Neka jen = len(seq). Ukoliko je −n ≤ i ≤ −1, tada se izračunavaelement koji se nalazi na poziciji −i od kraja sekvence.Ukoliko je i ≥ n ∨ i ≤ −(n+ 1), tada se ispaljujeIndexError.

seq[i:j:step]

Izračunava sekvencu elemenata na pozicijamai, i+ step, . . ., pri čemu se u rezultujućoj sekvenci nenalazi element na poziciji j. Nijedan od i, j, step ne morada bude naveden. Podrazumevana vrednost za step je1, tako da se u tom, specijalnom slučaju izračunavapodsekvenca list[i], list[i+ 1], . . . , list[j− 1]. Ukoliko nenavedemo i, onda se za početni indeks smatra 0.Ukoliko ne navedemo j, onda se za krajnji indekssmatra j+ 1.

seq.count(obj) Prebrojava sva pojavljivanja obj u sekvenci.

seq.index(obj)Izračunava se indeks prvog pojavljivanja obj u sekvenci.Ukoliko se obj ne nalazi u sekvenci, ispaljuje seValueError.

min(seq)

Izračunava se najmanji objekat u sekvenci. Operacijazahteva da operator < bude de nisan za svaki parelemenata u sekvenci. U suprotnom se ispaljujeTypeError i operacija se zaustavlja.

max(seq)

Izračunava se najveći objekat u sekvenci. Operacijazahteva da operator < bude de nisan za svaki parelemenata u sekvenci. U suprotnom se ispaljujeTypeError i operacija se zaustavlja.

4O klasi range će biti više reči u nastavku teksta.

Page 13: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 1. UVOD 7

Tabela 1.6: Operacije koje se mogu izvršiti nad proizvoljnom listom (koja će bitireferisana kao list) i njihovi opisi.

Operacija Opis operacije

list.append(obj) Dodaje na kraj liste element obj.

list.insert(pos, obj)

Dodaje se obj na poziciju pos u listi, a svi elementi na(prethodnim) pozicijama pos,pos+ 1, . . . ,n− 1 sepomeraju za jedno mesto udesno. Ukoliko je pos ≥ n,tada se element dodaje na kraj liste, a ukoliko jepos ≤ −(n+ 1), tada se element dodaje na početak liste.

del list[pos]

Briše se element na poziciji pos iz liste, a svi elementina (prethodnim) pozicijama pos+ 1,pos+ 2, . . . ,n− 1 sepomeraju za jedno mesto ulevo. Važe ista pravila zaispaljivanje IndexError kao i za operaciju list[i].

list.sort()

Uređuje elemente liste koristeći operator <.Napomenimo da je uspešno izvršavanje uređenjaneophodno da operator < bude de nisan za svaki parelemenata u listi. U suprotnom se ispaljuje TypeError ioperacija uređivanja se zaustavlja. U ovom slučaju, listamože biti parcijalno uređena.

list.reverse() Izračunava se lista u obrnutom poretku.

Generisanje listi Ponekad nam je neophodno da na jednostavan način generiše-mo liste čiji elementi imaju neke karakteristike. Na primer, voleli bismo da generi-šemo liste iz nekog intervala, liste čiji elementi zadovoljavaju neko svojstvo ili listekoje konstruišemo od već postojećih listi. U programskom jeziku Python imamo ovemogućnosti.

Generisanje sekvence čiji su elementi celi brojevi iz intervala [i, j−1] sa korakomstep može se izvršiti pomoću klase range, čiji je konstruktor oblika range(i,j,step).Ukoliko navedemo dva parametra i i j, onda se pravi sekvenca sa korakom 1. Uko-liko navedemo samo jedan parametar j, onda podrazumevano sekvenca počinje od0 (odnosno, i = 0). Iako kroz objekat klase range možemo iterirati, range nije lista,te nam nisu dostupne sve operacije iz tabele 1.6. Da bismo od objekta klase rangedobili listu, dovoljno je izvršiti eksplicitnu konverziju u tip list.

Videli smo da možemo koristiti klasu range za generisanje jednostavnih listi čijisu elementi celi brojevi iz nekog intervala. Međutim, često nam ovo nije dovoljno,već nam je potreban mehanizam koji može da generiše liste koje mogu biti znatnokompleksnije, na primer, generisanje kvadrata svih prostih brojeva (do nekog una-pred zadatog broja, da bismo ograničili listu). Da bismo generisali ovakve liste, naraspolaganju nam je koncept svojstvenih listi (engl. list comprehensions). Svojstve-ne liste predstavljaju koncept za generisanje lista čiji elementi zadovoljavaju nekosvojstvo (otuda i ime ovog koncepta5). Sintaksa svojstvenih lista je oblika

[ φ(elem) for elem in sekvenca if uslov ].

Ovom konstrukcijom se generiše lista od elemenata elem koji pripadaju sekvenca(što može biti druga lista, objekat klase range, ili bilo koji drugi iteratibilni obje-kat), koji ispunjavaju opcioni uslov, na koje se zatim primeni svojstvo φ. Svojstvene

5Prevod sa engleskog jezika je odabir autora; kao i većina drugih prevoda u domenu informacionihtehnologija, ovaj prevod nije jedini ni najbolji.

Page 14: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 1. UVOD 8

liste u potpunosti odgovaraju matematičkoj skupovnoj notaciji6, te se prethodnakonstrukcija može zapisati u skupovnoj terminologiji kao

{φ(elem) | elem ∈ sekvenca ∧ uslov}.

Da bismo dodatno pojasnili svojstvene liste, prikažimo nekoliko primera. Nekaje data sekvenca seq = range(5,15). Naredni fragment koda prikazuje korišćenjesvojstvenih listi u cilju izračunavanja: (1) liste koja sadrži sve dvostruko uvećaneelemente sekvence seq, (2) liste koja sadrži sve parne elemente sekvence seq i (3)vrednosti sinusne funkcije u svim tačkama sekvence seq koji su parni i veći od 10:>>> [2*elem for elem in seq]>>> [elem for elem in seq if elem % 2 == 0]>>> [math.sin(elem) for elem in seq if elem % 2 == 0 and elem > 10]

Rezultat izvršavanja prethodnog fragmenta koda je[10, 12, 14, 16, 18, 20, 22, 24, 26, 28][6, 8, 10, 12, 14][-0.5365729180004349, 0.9906073556948704]

Iako ovde nećemo govoriti detaljnije o tome, napomenimo da se svojstvene listemogu ulančavati, pa samim tim i koristiti za konstruisanje izraza koji mogu biti vrlonapredni, ali i značajno teži za razumevanje.

Torke Često su podaci organizovani preko svojih atributa, odnosno, kao elemen-ti dekartovog proizvoda skupova atributa, pa u tom slučaju govorimo o torkama(engl. tuple). Sintaksa torki slična je sintaksi listi, sa tom razlikom da se umestouglastih zagrada [ i ] koriste obične zagrade ( i ). Na primer, ako za neki artikalčuvamo njegov naziv, cenu i kategoriju, onda bi primer takvog artikla mogao da seu terminima torki zapiše na sledeći način>>> artikal1 = ('Naucno izracunavanje kroz programski jezik Python', 0, 'knjiga')

Što se tiče operacija koje se mogu vršiti nad torkama, dostupne su nam sveoperacije iz tabele 1.5. Kao i kroz dve druge sekvence, kroz torke se može iterirati,pa se mogu koristiti u svojstvenim listama.

Heš mape Heš mape predstavljaju strukturu podataka koje mapiraju vrednostkoju nazivamo ključ (engl. key) u objekat koji nazivamo vrednost (engl. value).Heš mape se drugačije zovu i rečnici (engl. dictionary), te otuda se u programskomjeziku Python na ovu strukturu referiše kao dict. Vrednostima se pristupa isključivopreko ključa, na primer:>>> d = {'x':5, 'y':1, 'z':-17}>>> d['x']5

Ovaj primer prikazuje i kako se formira literal tipa dict. Pristupanje vrednostiprema ključu koji ne postoji u rečniku ispaljuje KeyError. Tipovi ključeva ne morajubiti jednaki, na primer:>>> d[100] = ['a', 'b', 'c']>>> d[100]['a', 'b', 'c']

6Naravno, ova notacija odgovara skupovima, čije se karakteristike razlikuju od karakteristika struk-ture podataka list u programskom jeziku Python.

Page 15: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 1. UVOD 9

Na ovom mestu nećemo dati punu speci kaciju operacija nad heš mapama. Višeo ovoj strukturi podataka može se pronaći u [2]. Napomenimo samo da je mogućeiterirati kroz heš mape korišćenjem operacije iter. Na primer, naredni fragmentkoda ispisuje sve ključeve prethodno de nisane heš mape d:>>> for kljuc in iter(d):... print(kljuc)...xyz100

1.2 Biblioteka NumPyPrilikom korišćenja različitih metoda oblasti numeričkog izračunavanja, posta-

vlja se nekoliko ključnih pitanja. Jedno od njih je na koji način se ulazni podacičuvaju u memoriji. Iako postoji veliki broj struktura podataka, videćemo da su ma-trice (engl. multidimensional array ilimultiarray) dominirajuća struktura podataka.Takođe, svaki pojedinačan podatak matrice mora biti odgovarajućeg tipa. Možemokoristiti ugrađene u programski jezik Python tipove int, float i druge, ali često namto nije dovoljno – od značaja nam je da znamo da li su, na primer, podaci zapisani upokretnom zarezu smešteni u 16, 32 ili 64 bita. Čim govorimo o tipovima podata-ka (kao i o strukturama podataka), odmah bi trebalo da se setimo i operacija kojemožemo izvršiti nad njima. Potrebno nam je, dakle, da koristimo širok dijapazontipova podataka sa mnoštvom operacija de nisanim nad njima. Upravo iz ovih ra-zloga je biblioteka NumPy praktično postala nezaobilazna biblioteka pri rešavanjuproblema metodima numeričkog izračunavanja. Kao i ostale biblioteke, NumPy seuvozi u radno okruženje pomoću>>> import numpy as np

pri čemu je pseudonim np standardni u zajednici numeričkog izračunavanja.

Matrice Matrice se u biblioteci NumPy konstruišu pomoću funkcije np.array, čijije argument homogena sekvencijalna struktura podataka (interno, ta sekvencijalnastruktura podataka bude transformisana u listu). Tako, na primer, naredne dvenaredbe>>> a = np.array([1,2,3])>>> a = np.array((1,2,3))

proizvode istu matricu, tj. vektor-kolonu (jednodimenzionalni niz) sa tri elementa.Ovu informaciju dobijamo ili izračunavanjem vrednosti promenljive a ili korišćenjemfunkcije np.shape:>>> aarray([1, 2, 3])>>> a.shape(3,)

Page 16: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 1. UVOD 10

Višedimenzionalne matrice se formiraju iz listi lista. Na primer,

>>> b = np.array([[1,2,3], [4,5,6]])>>> barray([[1, 2, 3],

[4, 5, 6]])>>> b.shape(2, 3)

Tipovi elemenata matrica se izračunavaju dinamički. Ipak, ukoliko mi želimo daeksplicitno označimo tip, to možemo učiniti navođenjem parametra dtype (skraćenood data type). Za izračunavanje tipa elemenata matrice može se iskoristiti operator.dtype. Na primer:

>>> b = np.array([[1,2,3], [4,5,6]], dtype='float32')>>> barray([[1., 2., 3.],

[4., 5., 6.]], dtype=float32)>>> b.dtypedtype('float32')

Operacije nad matricama biblioteke NumPy date su u tabeli 1.7. Za većinu ovihoperacija moguće je de nisati da se izračunavaju po vrstama ili po kolonama. Utom slučaju kažemo da se izračunavanje izvršava po osama (engl. axis) i koristimoargument axis, čija je vrednost 0 ako se operacija izvršava duž kolona, a 1 ako seoperacija izvršava duž vrsti. Na primer:

>>> np.sum(b, axis=0)array([5., 7., 9.], dtype=float32)

Tabela 1.7: Operacije nad matricama (M, M1 i M2) u biblioteci NumPy i njihovi opisi.

Operacija Opis operacije

M + n ili n + M Pokoordinatno sabiranje skalarom n.M * n ili n * M Pokoordinatno množenje skalarom n.

np.sin(M)Pokoordinatno izračunavanje vrednosti sinusne funkcije.Slično važi i za ostale elementarne matematičke funkcijede nisane u biblioteci NumPy.

np.sum(M) Izračunavanje sume svih elemenata.M1 + M2 Pokoordinatno sabiranje matrica.M1 * M2 Pokoordinatno množenje matrica.

M1.dot(M2)

Matrično množenje matrica. Matrice moraju bitiodgovarajućih dimenzija da bi se uspešno izvršilomatrično množenje, odnosno, mora da važi uslovM1.shape[1] == M2.shape[0]. U suprotnom,ispaljuje se ValueError. U slučaju da su M1 i M2vektor-kolone, matrično množenje se svodi naskalarno množenje dve vektor-kolone.

M.T ili M.transpose() Izračunavanje transponovane matrice MT.np.min(M) Izračunava najmanji element.np.max(M) Izračunava najveći element.

Page 17: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 1. UVOD 11

Tabela 1.7: Operacije nad matricama (M, M1 i M2) u biblioteci NumPy i njihovi opisi(nastavak).

Operacija Opis operacije

M.reshape(n, m)Pretvaranje matrice M u matricu dimenzija n×m.U slučaju da je nemoguće izvesti pretvaranje,ispaljuje se ValueError.

np.hstack([M1, M2, …])Horizontalno nadovezivanje matrica M2, … na matricu M1.Ukoliko je nemoguće izvesti nadovezivanje matrica,ispaljuje se ValueError.

np.vstack([M1, M2, …]) Slično kao i np.hstack, samo što je nadovezivanjevertikalno.

np.arange(i, j, step) Generiše vektor-kolonu sa elementima i, i+ step, . . .do najviše j− 1.

np.linspace(start, stop,num, endpoint)

Generiše vektor-kolonu – jednodimenzionalnu mrežuekvidistantnih tačaka iz intervala [start, stop),odnosno [start, stop] u zavisnosti od vrednostiBulove promenljive endpoint (podrazumevano je True),veličine num (podrazumevano je 50).

np.ones((n, m))

Matrica dimenzije n×m čiji su svi elementi jedinice.Primetimo da je argument funkcije uređeni par(dvočlana torka). Moguće je proslediti bilo kojudvočlanu sekvencu, ali ne i dva cela broja.Alternativno, prosleđivanje jednog argumenta nproizvodi vektor-kolonu dimenzije n.

np.zeros((n, m)) Matrica dimenzije n×m čiji su svi elementi nule.Važe slična pravila kao i za funkciju np.ones.

np.eye(n) Proizvodi jediničnu matricu reda n.

np.diag(seq)Proizvodi dijagonalnu matricu reda len(seq) čiji jeelement na poziciji (i, i) jednak vrednosti seq[i],gde je seq sekvenca.

np.random.rand(n) Izračunava vektor-kolonu od n elemenataiz uniformne raspodele U [0,1).

M[i][j] Izračunava element na poziciji (i, j).

M[i:j:v_step] Izračunava matricu koja se sastoji od vrsta i,i+ v_step, . . . do najviše j− 1 matrice M.

M[i:j:v_step, k:l:k_step]Slično kao u prethodnom slučaju, sa razlikom da seuzimaju u obzir samo kolone k,k+ k_step, . . . donajviše j− 1.

1.3 Biblioteka MatplotlibVizualizacija podataka je prikazivanje informacija u vidu gra ka ili tabela. Uspe-

šna vizualizacija zahteva da se podaci prebace u vizualni format kako bi karakteri-stike podataka ili veze između pojedinačnih podataka ili atributa mogle da se ana-liziraju. Cilj vizualizacije je interpretacija vizualiziranih informacija od strane nekeosobe i formiranje umnog modela informacija.

U tu svrhu, biblioteka Matplotlib nudi veliki broj načina za vizualizaciju podata-ka, kao što su: opšti gra ci (engl. plot), histogrami (engl. histogram), kutije-nacrti(engl. box plot), tačkasti nacrti (engl. scatter plot), i mnogi drugi. Na ovom mestućemo prikazati osnovni rad sa opštim gra cima, za šta će nam biti korisan modul

Page 18: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 1. UVOD 12

pyplot iz paketa matplotlib:>>> import numpy as np>>> from matplotlib import pyplot as plt

Najjednostavniji rad sa opštim gra cima nam je dostupan kroz funkciju plt.plot.Njeni argumenti su:

• x i y, sekvence x- i y-koordinata tačaka od kojih se konstruiše opšti gra k,

• niska kojom se označava na koji način će tačke biti prikazane,

• color, boja opšteg gra ka,

• linewidth, debljina linije u pikselima,

• linestyle, stil iscrtavanja linije,

• label, naziv opšteg gra ka,

• …

Nakon de nisanja nacrta pozivom funkcije plt.plot, da bi se proizveo prikazpotrebno je izvršiti poziv funkcije plt.show. Sada ćemo dati dva primera iscrtavanjanarednih koordinata tačaka:>>> x = np.linspace(0, 3, 20)>>> y = np.linspace(0, 9, 20)

Na slici 1.1 data su dva primera korišćenja funkcije plt.plot nad prethodno sku-pom tačaka S = {(xi,yi) | xi ∈ x,yi ∈ y, i = 0,1, . . . ,19}, gde su x i y gore de nisanivektori-kolone. Prikaz levo, odnosno, prikaz desno, dobijeni su narednim pozivima,redom:>>> plt.plot(x, y)>>> plt.show()>>> plt.plot(x, y, '+')>>> plt.show()

Slika 1.1: Dva primera korišćenja funkcije plt.plot nad istim skupom tačaka u rav-ni.

Ono što nam plt omogućava jeste slaganje više opštih gra ka na jedan prikaz.Ovo se postiže jednostavno pozivanjem više funkcija plt.plot sekvencijalno. U tusvrhu, često se prikazi dodatno okarakterišu, na primer, naslovima, nazivima osa

Page 19: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 1. UVOD 13

i opštih gra ka, legendom i slično. Neke od ovih karakterizacija prikaza dati su utabeli 1.8.

Na slici 1.2 demonstrirane su dve stvari: (1) slaganje više gra ka na jednomprikazu (u ovom slučaju, to su dva gra ka) i (2) operacije koje su de nisane u tabeli1.8. Naredni fragment koda generiše dati prikaz:

>>> x = np.linspace(-np.pi, np.pi, 256)>>> sinValues = np.sin(x)>>> cosValues = np.cos(x)>>> plt.plot(x, sinValues, color='purple', label='y1')>>> plt.plot(x, cosValues, color='green', label='y2')>>> plt.title('Grafik sinusne i kosinusne funkcije u 256 tacaka na intervalu [-pi, pi)')>>> plt.xlabel('Mreza 256 ekvidistantnih tacaka na intervalu [-pi, pi)')>>> plt.ylabel('y1 = sin(x), y2 = cos(x)')>>> plt.show()

Tabela 1.8: Dodatne karakteristike PyPlot prikaza.

Operacija Opis operacije

plt.title(naslov) Dodaje nisku naslov kao naslov prikaza.plt.xlabel(x_naziv) Dodaje nisku x_naziv kao naziv x-ose.plt.xlabel(y_naziv) Dodaje nisku y_naziv kao naziv y-ose.

plt.legendDodaje legendu na prikaz. Legenda zahteva dasvaki pojedinačan poziv plt.plot funkcije bude označen,odnosno, da svaki poziv ima argument label.

Slika 1.2: Primer slaganja dva različita opšta gra ka na jednom prikazu. Na ovomprikazu su demonstrirane i operacije iz tabele 1.8.

Page 20: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 1. UVOD 14

1.4 Biblioteka PandasPandas je biblioteka koja se koristi u analizi podataka. Ona raspolaze visoko

performantnim strukturama podataka koje su jednostavne za korišćenje. U daljemtekstu ćemo koristiti dve strukture podataka:

1. Series — jednodimenzionalni označeni nizovi, ne nužno homogenih podataka,i

2. DataFrames — tabelarni podaci, čiji su redovi i kolone označeni.

Standardna konvencija za uvoženje paketa Pandas izgleda:

>>> import pandas as pd

Serije Serije predstavljaju jednodimenzionalnu strukturu podataka koje sadržesekvencu vrednosti (sličnih tipova kao što su NumPy tipovi) i asocijativni niz oznakakoji se naziva indeks (engl. index). Često ćemo u nastavku teksta elemente indeksanazivati indeksima umesto oznakama, ali ne bi trebalo biti teško razumeti o čemuje reč iz konteksta. Najjednostavnija serija se formira od liste podataka, na primer:

>>> s = pd.Series([(1,1), (2,2), (3,3)])>>> s0 (1, 1)1 (2, 2)2 (3, 3)dtype: object

Prikazivanjem serije možemo primetiti njene elemente (ispis desno) i odgova-rajuće indekse pridružene podacima (ispis levo). Ukoliko ne navedemo drugačije,tipovi indeksa su podrazumevano celi brojevi, pri čemu se njihove vrednosti inkre-mentiraju počevši od 0 do N−1, gde je N broj podataka. U suprotnom, elementimamozemo de nisati indekse korišćenjem parametra index, na primer:

>>> s = pd.Series([(1,1), (2,2), (3,3)], index = ['x', 'y', 'z'])>>> sx (1, 1)y (2, 2)z (3, 3)dtype: object

Iako se nećemo upuštati u detalje operacija nad strukturom podataka serija, pri-kažimo ipak neke jednostavne operacije koje se mogu primeniti nad njima u tabeli1.9. Na ovom mestu objasnićemo samo poslednju operaciju iz tabele. Za početak,konstruišimo nešto jednostavniju seriju:

>>> s = pd.Series([1344, 252, 187, 150, 105],index = ['Beograd', 'Novi Sad', 'Nis', 'Kragujevac', 'Subotica']

)

Elementi ove serije su brojevi stanovnika u nekim gradovima Srbije koji su datiodgovarajućim indeksima, u stotinama hiljada (sa odgovarajućim zaokruživanjimana cele brojeve). Ukoliko bismo želeli da izračunamo sve gradove koje imaju višeod 150 hiljada stanovnika, to možemo izvesti postavljanjem odgovarajućeg uslova:

Page 21: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 1. UVOD 15

>>> s[s > 150]Beograd 1344Novi Sad 252Nis 187dtype: int64

Ono što je zanimljivo primetiti jeste struktura uslova koji se zadaje: operator >prolazi kroz sve elemente serije s i time konstruiše lista Bulovih vrednosti (True,ako je uslov ispunjen za taj element, a False u suprotnom); zatim se ta lista koristiza pristupanje samo onim elementima čije su odgovarajuće oznake konstruisanevrednosti True. Ovi uslovi mogu biti znatno komplikovaniji, što ćemo videti većkada budemo prešli na narednu strukturu podataka.

Tabela 1.9: Jednostavne operacije nad strukturom podataka Series (koja će bitireferencirana oznakom s) i njihovi opisi.

Operacija Opis operacije

s[label] Pristupa elementu sa oznakom/indeksom label.

s[[label1, ..., labelM]]

Pristupa skupu elemenata koji su datilistom oznaka/indeksa [label1, ..., labelM].Čak i u slučaju kad su oznake tipa str umesto int,ova lista se interpretira kao lista indeksa.

s.values Izračunava niz svih vrednosti.s.index Izračunava indeks.obj in s Proverava da li je obj element s.

obj not in s Proverava da li obj nije element s.

s[φ(s)] Izdvaja sve elemente serijekoji zadovoljavaju uslov dat sa φ(s).

Tabele podataka Struktura podataka DataFrame predstavlja tabelarnu organiza-ciju podataka i sadrži uređenu kolekciju kolona, pri čemu svaka kolona može imatielemente tipa različitog u odnosu na druge kolone. Ova struktura podataka se naj-češće koristi za smeštanje višedimenzionalnih podataka iako je u istu svrhu mogućekoristiti i serije. Tabele podataka imaju dva indeksa — jedan za vrste i drugi za ko-lone.

Iako je moguće konstruisati tabele podataka na različite načine, počnimo odugrađenog tipa dict u programskom jeziku Python:

>>> osobe = {'ime' : ['Ana', 'Pera', 'Laza'],'godine' : [28, 23, 14],'lokacija' : ['Beograd', 'London', 'Pariz']

}>>> df_osobe = pd.DataFrame(osobe)>>> df_osobe

godine ime lokacija0 28 Ana Beograd1 23 Pera London2 14 Laza Pariz

Kao što vidimo, rezultujuća tabela podataka ima podrazumevano dodeljene ce-lobrojne indekse vrstama, kao što je bio slučaj kod serija, a kolone su uređene.

Page 22: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 1. UVOD 16

Ukoliko želimo da pristupimo određenoj koloni, dovoljno je da referišemo na njuodgovarajućim indeksom kolone, na primer:>>> df_osobe['ime']0 Ana1 Pera2 LazaName: ime, dtype: object

Sa druge strane, pristup vrsti, odnosno pojedinacnom podatku, možemo izvršitikorišćenjem funkcije loc i referisanjem odgovarajućeg indeksa vrste, na primer:>>> df_osobe.loc[1]godine 23ime Peralokacija LondonName: 1, dtype: object

Nadalje, mozemo izračunati vrednosti atributa pojedinačnog podatka, na pri-mer:>>> df_osobe.loc[1]['lokacija']'London'

Alternativa ovom pristupu je moguća ukoliko je indeks kolone, tj. atributa ko-ji želimo da izračunamo u pogodnom obliku, tj. ako indeks kolone čini ispravanidenti kator u programskom jeziku Python. Na primer, prethodno izračunavanje jemoglo da se alternativno napiše i kao>>> df_osobe.loc[1].lokacija'London'

Primetimo da je ovo moguće zato što je lokacija validan identi kator u program-skom jeziku Python. Ipak, korišćenje prvog pristupa je sigurnije jer ga je mogućeizvršiti za proizvoljan indeks kolone. Spisak značajnih operacija dat je u tabeli 1.10,ali zbog njihovog značaja, daćemo detaljniji prikaz nekih od njih.

Pri analizi podataka često radimo sa velikom količinom podataka. Ovakvi podacise najčešće nalaze u datotekama i zapisani su u formatu koji se naziva vrednostirazdvojene zapetom (engl. comma-separated values, akraćeno CSV), ili u formatukoji se relativno jednostavno može svesti na CSV. Kao što i sam naziv sugeriše, zaproizvoljni podatak (koji se nalazi u zasebnoj vrsti), vrednosti njegovih atributa surazdvojeni zapetom. Ovaj opis predstavlja kostur ovog formata, a dodatno se moguobezbediti i, na primer, indeksi vrsta i kolona. Za ucitavanje podataka iz datoteke,zapisanih u CSV formatumožemo iskoristiti funkciju read_csv, čiji je argument nazivdatoteke, na primer:>>> df_languages = pd.read_csv('languages.csv')

gde je languages.csv datoteka koji sadrzi informacije o jezicima. Ovaj skup podata-ka sadrži informacije o ugrozenim jezicima, tj. o onim jezicima koji su u procesunestajanja. Više informacija o resursu se može pronaći u dodatku B.

Nekada će nam biti od značaja da imamo uvid u podatke koje obrađujemo. Pozi-vom funkcija head i tail nad tabelom podatakamožemo dobiti uvid u prvih, odnosno,poslednjih nekoliko podataka, redom. Na primer, prikaz prvih 5 podataka iz skupapodataka koje smo prethodno učitali, dobijamo narednim pozivom7:

7Primetimo da je izlaz formatiran tako da sve informacije staju u prozor komandne linije iz koje jepozvan Python interpreter. Razna okruženja nude različite mogućnosti, pa je tako moguće da se ovajizlaz formatira u vidu HTML tabele u, na primer, Jupyter Notebook okruženju.

Page 23: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 1. UVOD 17

>>> df_languages.head()ID Name in English Name in French Name in Spanish \

0 1022 South Italian italien du sud napolitano-calabrés1 1023 Sicilian sicilien siciliano2 383 Low Saxon bas-saxon bajo sajón3 335 Belarusian biélorusse bielorruso4 382 Lombard lombard lombardo

Countries \0 Italy1 Italy2 Germany, Denmark, Netherlands, Poland, Russian...3 Belarus, Latvia, Lithuania, Poland, Russian Fe...4 Italy, Switzerland

Country codes alpha 3 \0 ITA1 ITA2 DEU, DNK, NLD, POL, RUS3 BRB, LVA, LTU, POL, RUS, UKR4 ITA, CHE

ISO639-3 codes Degree of endangerment0 nap Vulnerable1 scn Vulnerable2 act, drt, frs, gos, nds, sdz, stl, twd, vel, wep Vulnerable3 bel Vulnerable4 lmo Definitely endangered

Alternate names Name in the language \0 Neapolitan; Neapolitan-Calabrese; ????????????... NaN1 NaN NaN2 Low German, Niedersächsisch, Nedersaksisch, Ni... Neddersassisch3 NaN NaN4 NaN NaN

Number of speakers Sources \0 7500000.0 NaN1 5000000.0 NaN2 4800000.0 NaN3 4000000.0 Hienadz Cychun: Weißrussisch. — Lexikon der Sp...4 3500000.0 NaN

Latitude Longitude Description of the location0 40.9798 15.2490 Campania, Lucania (Basilicata), Abruzzi (Abruz...1 37.4399 14.5019 Sicily (Sicilia), southern and central Calabri...2 53.4029 10.3601 northern Germany, the north-eastern part of th...3 53.9560 27.5756 Belarus except the Polesian-speaking south-wes...4 45.7215 9.3273 the region of Lombardy (except the southernmos...

Neke analize zahtevaju upotrebu selekcije (engl. selection) podataka pre sa-me obrade. Sintaksnom konstrukcijom df[φ(df)] izvršava se selekcija podataka iztabele podataka df, koji zadovoljavaju uslov φ(df). Na primer, ukoliko želimo da

Page 24: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 1. UVOD 18

izdvojimo imena (na engleskom jeziku) i nazive zemalja u kojima se govore oni jezicikoji imaju više od 3 miliona govornika, onda to možemo izvesti na sledeći način:

>>> df_languages[df_languages['Number of speakers'] > 3000000][... ['Name in English', 'Countries']... ]Name in English Countries

0 South Italian Italy1 Sicilian Italy2 Low Saxon Germany, Denmark, Netherlands, Poland, Russian...3 Belarusian Belarus, Latvia, Lithuania, Poland, Russian Fe...4 Lombard Italy, Switzerland5 Romani Albania, Germany, Austria, Belarus, Bosnia and...

Uređivanje vrednosti u tabeli podataka može se izvršiti pozivanjem funkcijesort_values(by, axis, ascending, inplace). Obavezan parametar by predstavlja ni-sku ili listu niski kojima se opisuje po čemu se vrši uređivanje po osi axis (koja jepodrazumevano 0). Podrazumevano se uređivanje vrši rastuće, ali se može prome-niti postavljanjem parametra ascending na False ili zadavanjem liste Bulovih vredno-sti čija veličina mora da odgovara listi by, radi de nisanja smera uređenja za svakukolonu/vrstu. Takođe, podrazumevano se pri uređivanju tabele podataka konstrui-še nova tabela. Ukoliko želimo da uređujemo u mestu, možemo postaviti parametarinplace na vrednost True.

Nije neobično da za neke objekte u skupu podataka ne znamo vrednosti jednogili više atributa. Staviše, ovo je možda najčešći problem sa kojim se možemo su-sresti u analizi podataka. U nekim slučajevima možda jednostavno nismo uspeli daprikupimo podatke. Na primer, neki ljudi odbijaju da daju informaciju o broju ličnekarte. U nekim drugim slučajevima atributi nisu primenljivi za sve objekte. Rukova-nje nedostajućim vrednostima se može uraditi na više načina. Eliminacija podatakapredstavlja jednostavan i efektivan način rešavanja problema nedostajućih vredno-sti — jednostavno odbacimo sve objekte koji imaju "nedostatke". U programskomjeziku Python, nedostajuće vrednosti se označavaju vrednošću np.NaN (nadalje samoNaN).

Eliminisanje podataka sa nedostajućim vrednostima u tabelama podataka se iz-vršava pozivom funkcije dropna(axis, how, thresh, subset, inplace), kojom se do-bija tabela podataka iz koje su eliminisani atributi koji predstavljaju nedostajućevrednosti. Eliminacija se vrši po parametru axis, što može biti jedna osa i sekvencaosa, ukoliko želimo po više osa da vršimo eliminaciju. Parametar how može uzimativrednosti iz skupa {'any', 'all'}, u zavisnosti od toga da li želimo da eliminišemoukoliko je barem jedna vrednost NaN, ili ukoliko su sve vrednosti takve. Parametarthresh označava celobrojnu granicu kojom zahtevamo najmanji broj ne-NaN vred-nosti. Parametar subset predstavlja sekvencu koja sadrži oznake koje razmatramona suprotnoj osi; na primer, ako vršimo eliminaciju vrsta, onda se ovim predsta-vlja sekvenca kolona koje se uključuju. Podrazumevano se konstruiše nova tabelapodataka, ali ukoliko želimo da vršimo eliminaciju direktno nad zadatom tabelompodataka, onda treba postaviti parametar inplace na vrednosti True.

Do sada smo videli da programski jezik Python ima izuzetnu moć u analizi i ob-radi različitih podataka. Međutim, njegova prava upotrebna vrednost se najboljeogleda kombinovanjem različitih biblioteka koje smo do sada upoznali. Na primer,možemo generisati stubičasti dijagram (engl. bar plot) koji prikazuje apsolutni brojpojavljivanja neke vrednosti. Što se tiče našeg skupa podataka o jezicima u nesta-janju, ovo nam može biti korisno da steknemo uvid u, na primer, raspodelu stepenaugroženosti jezika (što je predstavljeno atributom 'Degree of endangerment'). Na-redni fragment koda generiše stubičasti dijagram prikazan na slici 1.3 sa kojeg

Page 25: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 1. UVOD 19

Tabela 1.10: Operacije nad strukturom podataka DataFrame (koja će biti referenci-rana oznakom df) i njihovi opisi.

Operacija Opis operacije

df.read_csv(file, sep)Učitava podatke iz datoteke file, pri čemu supodaci zadati u CSV formatu i razdvojeniseparatorom sep. Podrazumevano je: sep=','.

df.head(n) Prikazuje prvih n vrsta. Podrazumevano je: n=5.df.tail(n) Prikazuje poslednjih n vrsta. Podrazumevano je: n=5.df.index Izračunava se indeks vrsta.

df.columns Izračunava se indeks kolona.df.values Izračunava se matrica podataka.

df[i:j:step] Izračunavaju se kolone i, i+ step, . . . do najviše j− 1,ukoliko i i j nisu niske, a u suprotnom do najviše j.

df.loc[n] Izračunava se n-ta vrsta.df[[naslov1,

..., naslovM]]Izračunavaju se kolone čiji indeksi odgovarajuzadatoj listi oznaka.

df[φ(df)] Izračunava se selekcija po vrednostima kolone iizdvajaju se sve vrste koje zadovoljavaju uslov φ(df).

df[naslov].value_counts() Grupisanje po vrednostima u koloni indeksa naslov.

df.sort_values(by, axis,ascending, inplace)

Uređuju se vrednosti u tabeli podataka.Podrazumevano je: axis=0, ascending=True,inplace=False.

df.dropna(axis, how,thresh, subset, inplace)

Eliminišu se podaci koji sadrže NaN vrednosti.Podrazumevano je: axis=0, how='any', thresh=None,subset=None, inplace=False.

možemo zaključiti da je broj jezika koji su nestali (tj. koji imaju vrednost Extinctodgovarajućeg atributa) u odnosu na broj jezika koji su, na primer, pred nestaja-njem (tj. koji imaju vrednost Severely endangered odgovarajućeg atributa) manji oko2.4 puta.>>> df_languages['Degree of endangerment'].value_counts().plot(kind='bar')>>> plt.show()

1.5 ZadaciNaredni zadaci se odnose na prethodno opisani skup podataka o ugroženim je-

zicima.

Zadatak 1.1 Izračunati imena jezika koji se nalaze na pozicijama od 100 do 120.

Zadatak 1.2 Izračunati ukupan broj jezika o kojima postoji informacija o broju go-vornika.

Zadatak 1.3 Izračunati broj jezika koji imaju više od 10000 govornika.

Zadatak 1.4 Izračunati imena prvih 5 jezika sa najviše govornika.

Zadatak 1.5 Izračunati imena jezika koji se govore u Austriji.

Zadatak 1.6 Izračunati imena kritički ugroženih jezika i njihov broj.

Page 26: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 1. UVOD 20

Slika 1.3: Stubičasti dijagram atributa "stepen ugroženosti" jezika u nestajanju.

Page 27: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

Glava 2

Aproksimacija funkcija

Pod aproksimacijom funkcije f, podrazumeva se određivanje neke funkcije g, kojaje funkciji f bliska u nekom unapred de nisanom smislu. Razlozi za aproksimaci-ju mogu biti različiti. Nekada je to zato što je funkcija f previše komplikovana zadirektnu upotrebu, pa se aproksimacijom pojednostavljuje (na primer, zamena po-linomom), nekada nema poželjna matematička svojstva, pa se zamenjuje funkcijomkoja ih ima (na primer, konveksnom funkcijom), a najčeší razlog je što su vredno-sti funkcije f poznate samo na diskretnom, najčešće konačnom, skupu tačaka, apotrebno je koristiti njene vrednosti na širem domenu [1].

U ovom poglavlju biće prvobitno dat kratak podsetnik na osnovne pojmove i me-tode linearne algebre. Način na koji će tekst biti izložen jeste prvobitno kroz uvođe-nje odgovarajućeg pojma, a zatim ilustrovanjem odgovarajućih funkcija u program-skom jeziku Python. Za de nisanje pojmova, kao literatura su korišćeni izvori [6] i[1]. Kao i do sada, uobičajene konvencije za uvoženje biblioteka i dalje važe.

2.1 Linearna algebra kroz modul numpy.linalgU ovoj sekciji ćemo govoriti o različitim metodama linearne algebre. U program-

skom jeziku Python, veliki broj ovih metoda dostupan nam je kroz modul linalgbiblioteke NumPy. Usvajamo konvenciju da se uvoženje ovog modula vrši uz pseu-donim LA:>>> from numpy import linalg as LA

Metodi linearne algebre operišu nad matricama. De nišemo primer jedne ma-trice:>>> A = np.array([... [1,2,4],... [6,11,9],... [2,1,1]]... )

Jedna od prvih operacija nad matricama koja se uvodi jeste izračunavanje de-terminante matrice. Ipak, pre samog uvodđenja pojma determinante, potrebno jeuvesti neke dodatne pojmove.

Bijekciju π : {1, . . . ,n} −→ {1, . . . ,n} nazivamo permutacijom (engl. permutation)skupa {1, . . . ,n}. Skup svih permutacija skupa {1,2, . . . ,n} označavamo oznakomΠn. Uređeni par (π(i), π(j)) čini inverziju (engl. inverse) u permutaciji π kada jei < j, a π(i) > π(j). Za permutaciju kažemo da je parna (engl. even) kada ima paran

21

Page 28: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 2. APROKSIMACIJA FUNKCIJA 22

broj inverzija i kažemo da je neparna (engl. odd) kada ima neparan broj inverzija.De nišimo funkciju sgn na skupu permutacija kao

sgn(π) ={

1, ako je π parna;−1, ako je π neparna;

Sada konačno možemo de nisati pojam determinante. Neka jeMn prostor ma-trica dimenzija n× n i neka je A = (aij)n×n ∈ Mn. Determinantu matrice A, u oznacidet(A), ili samo |A|, de nišemo kao realan broj∑

π∈Πn

sgn(π)a1π(1)a2π(2) · · ·anπ(n).

Za razliku od nešto dužeg matematičkog zasnivanja pojma determinante, za ra-čunanje vrednosti determinante matrice A može se iskoristiti funkcija LA.det(A).Vrednost determinante gore de nisane matrice A iznosi:

>>> LA.det(A)-37.99999999999999

Pored izračunavanja determinante, jedna od najznačajnijih operacija nad matri-cama jeste računanje njene inverzne matrice. Neka je A ∈Mn. Ako za neku matricuA−1 ∈Mn važi da je A ·A−1 = In = A−1 ·A, gde je I ∈Mn jedinična matrica i · operacijamnoženja matrica, tada kažemo da je A−1 inverzna matrica (engl. inverse matrix)matrici A.

Kažemo da je matrica singularna (engl. singular) ukoliko je njena determinan-ta jednaka 0. U suprotnom, matrica je nesingularna (engl. nonsingular). Možese pokazati da je matrica invertibilna akko je nesingularna. Poput izračunavanjadeterminante, izračunavanje inverzne matrice matrice A se u programskom jezikuPython jednostavno izračunava pozivanjem funkcije LA.inv(A). Na primer,

>>> LA.inv(A)array([[-0.05263158, -0.05263158, 0.68421053],

[-0.31578947, 0.18421053, -0.39473684],[ 0.42105263, -0.07894737, 0.02631579]])

Inverzne matrice i determinante se nalaze u posebnoj vezi. Razmotrimo narednumatricu:

>>> B = np.array([... [-1, 1.5],... [0.667,-1]... ])

Njena inverzna matrica izgleda:

>>> LA.inv(B)array([[2000., 3000.],

[1334., 2000.]])

Zapitajmo se da li nas iznenađuje što su vrednosti inverzne matrice relativnodrastično skočile u odnosu na vrednosti polazne matrice B. Odgovor možemo dobitiizračunavanjem determinante polazne matrice:

>>> LA.det(B)-0.0005000000000001671

Page 29: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 2. APROKSIMACIJA FUNKCIJA 23

Sada bi trebalo da nam stvari budu nešto jasnije. Što je determinanta matricebliža vrednosti 0, njen "singularitet raste", a to se direktno odražava na njenu in-verznu matricu. Ovo opažanje ima veze sa pojmom uslovljenosti matrica sa kojimćemo se upoznati u nastavku teksta. Uvedimo prvo pojam norme.

Norma (engl. norm) predstavlja preslikavanje || · || : V −→ R, gde je V vektorskiprostor1 i R skup realnih brojeva, sa sledećim karakteristikama:1. ||x|| ≥ 0,∀x ∈ V;

2. ||x|| = 0 akko x = 0;

3. ||λx|| = λ · ||x||; i

4. ||x+ y|| ≤ ||x||+ ||y||.Postoje različite vrste normi. U programskom jeziku Python, na raspolaganju

nam stoji funkcija LA.norm(x, ord, axis) za izračunavanje vrednosti norme vektorax. Parametar ord nam de niše koja konkretna norma se izračunava. Tabela 2.1 pri-kazuje moguće vrednosti za parametar ord i njihova značenja ukoliko se primenjujuna matrice, odnosno, na vektore. Podrazumevano je da se izračunava Frobeniusovanorma (zadata vrednošću 'fro'):

||A||Fro =

√√√√ n∑i=1

n∑j=1

a2ij.

Tabela 2.1: Moguće vrednosti parametra ord funkcije LA.norm.

Vrednost ord Matrična norma Vektorska norma

None Frobenijusova norma 2-norma'fro' Frobenijusova norma --'nuc' Nuklearna norma --

inf max1≤i≤n

{n∑j=1|aij|

}max1≤i≤n

{|xi|}

-inf min1≤i≤n

{n∑j=1|aij|

}min1≤i≤n

{|xi|}

0 -- sum(x != 0)

1 max1≤j≤n

{ n∑i=1|aij|

}kao ispod

-1 min1≤j≤n

{ n∑i=1|aij|

}kao ispod

2 2-norma (najveća singularna vrednost) kao ispod-2 najmanja singularna vrednost kao ispod

ostalo --( n∑i=1|xi|ord

)1/ord

Za matricu kažemo da je numerički stabilna (engl. numerically stable) ukolikomale promene u vrednostima njenih elemenata rezultuju u malim promenama vred-nosti rezultata u čijim izračunavanjima učestvuje ta matrica. Numerička stabilnostmatrica je u uskoj vezi sa njenom uslovljenošću.

1Primetimo da smo privremeno prešli sa pojma matrice na pojam vektora. Iako se u većini slučajevao vektorima može govoriti kao o matricama dimenzija 1×n (vektori-vrsta) ili n×1 (vektori-kolona), kadase razmatraju norme, prirodno se govori u terminima vektora. Ipak, ovo ne bi trebalo da nam zbunjujes obzirom da podjednako razmatramo vektore i matrice.

Page 30: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 2. APROKSIMACIJA FUNKCIJA 24

Uslovljenost problema se kvanti kuje merom koja se tako i naziva — uslovlje-nost. Neka α predstavlja sve ulazne podatke problema P, a x(α) rešenje tog proble-ma. Tada se uslovljenost (engl. conditional number) problema P, u oznaci Cond(P),de niše kao odnos relativne greške rešenja i relativne greške ulaznih podataka:

Cond(P) = R(x(α),x(α))R(α, α) =

||x(α)− x(α)||/||x(α)||||α − α||/||α|| .

U slučaju problema P, rešavanja sistema jednačina Ax = b važi

Cond(P) = ||A−1Δb||||Δb|| · ||Ax||

||x|| .

De nisemo uslovljenost matrice A kao maksimalnu vrednost uslovljenosti pro-blema rešavanja sistema jednačina Ax = b, kada se maksimum uzima po svim ne-nula vrednostima Δb i x. Prema de niciji matričnih normi, važi

Cond(A) = ||A|| · ||A||−1.

Ako je matrica singularna, tada je

Cond(A) = + inf .

Možemo zaključiti da je donja granica za uslovljenost matrice:

||A|| · ||A||−1 ≥ ||A · A−1|| = ||I|| = 1.

Dajmo jedan ilustrativni primer. Neka je potrebno (posebno) rešiti naredna dvasistema jednačina: [

1 22 3.999

]·[xy

]=

[9

7.999

][1.001 2.0012.001 3.998

]·[xy

]=

[9

7.999

]Rešenje svakog od ovako zadatih sistema glasi x = A−1b. Umesto da računamo

sami rešenje ovih sistema, prepustićemo programskom jeziku Python da to uradiumesto nas. Napomenimo da je prilikom kontrukcije vektora b neophodno transpo-novati rezultat funkcije np.array da bi se množenje izvršilo ispravno. Pogledajmorešenje prvog sistema:>>> A = np.array([... [1, 2],... [2, 3.999]... ])>>> b = np.array([4, 7.999]).T>>> x = LA.inv(A).dot(b)>>> xarray([2., 1.])

Pogledajmo sada rešenje drugog sistema:>>> A = np.array([... [1.001, 2.001],... [2.001, 3.998]... ])>>> b = np.array([4, 7.999]).T>>> x = LA.inv(A).dot(b)>>> xarray([6.98901648, -1.49725412])

Page 31: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 2. APROKSIMACIJA FUNKCIJA 25

Vidimo da su male promene u matrici A rezultovale u velikim promenama u re-šenju. Proverimo da li možemo okriviti njenu visoku uslovljenost za ovo opažanje.Na raspolaganju nam je funkcija LA.cond(x, p) koja računa uslovljenost matrice,odnosno, vektora x pri vrsti norme koja se zadata parametrom p. Kao i ranije, pod-razumevano se koristi Frobinijusova norma. Uslovljenost matrice A iz prethodnogprimera je:

>>> LA.cond(A)12478.285990729695

što nam deluje kao da je relativno visoka vrednost, pa možemo zaključiti da matricaA nije numerički stabilna.

Iako smo ranije rekli da je vrednost determinante matrice A u bliskoj vezi sa nje-nom inverznommatricom, sada ćemo pokazati da ipak ne postoji tesna veza izmeđuvrednosti determinante matrice A i njene uslovljenosti. Za početak, primetimo davaži

det(kA) = kn · det(A).

Međutim,

Cond(kA) = ||kA|| · ||(kA)−1|| == ||A|| · ||A−1|| == Cond(A)

Dakle, rast u vrednostima matrice A direktno rezultuje u (eksponencijalnom)rastu vrednosti njene determinante, ali ne i u rastu njene uslovljenosti.

2.2 Kriterijumi kvaliteta aproksimacija funkcija imetod najmanjih kvadrata

Za funkciju f može postojati više različitih funkcija koje je aproksimiraju. Krite-rijumi kvaliteta aproksimacije mogu biti različiti i voditi različitim najboljim aprok-simacijama. Kriterijumi se mogu razlikovati u zavisnosti od toga šta se želi postići.Ukoliko je bitno da funkcija g uglavnom dobro aproksimira funkciju f, ali je prihva-tljivo i da se negde više razlikuju, kao kriterijum aproksimacije je moguće koristitisredinu kvadrata razlike između te dve funkcije:

||f− g||22 =

n∑i=1

(f(xi)− g(xi))2.

Drugim rečima, minimizacioni problem koji nas interesuje je

minn∑i=1

(f(xi)− g(xi))2. (2.1)

Vektorski prostor koji je kompletan (svaki Košijev niz elemenata vektorskog pro-stora konvergira elementu tog prostora) u odnosu na metriku indukovanu skalar-nim proizvodom d(x,y) = ||x−y|| =

√(x− y) · (x− y) naziva seHilbertovim prostorom

(engl. Hilbert space). Ako se za Hilbertov prostor H uzme prostor funkcija L2[a,b],

Page 32: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 2. APROKSIMACIJA FUNKCIJA 26

odnosno prostor funkcija integrabilnih sa kvadratom na intervalu [a,b], u kome jenorma de nisana integralom

||f||2 =

∫ b

af2(x)dx, f ∈ L2[a,b],

onda se element najbolje aproksimacije naziva elementom najbolje srednjekvadrat-ne aproksimacije. Ako je funkcija f de nisana samo na konačnom skupu tačakax0, . . . ,xm iz intervala [a,b], integral se zamenjuje sumom, pa su skalarni proizvod iodgovarajuća norma dati jednakostima:

f · g =

m∑i=1

f(xi)g(xi)

||f|| = f · f =m∑i=1

f2(xi).

Metoda koja odgovara srednjekvadratnoj aproksimaciji u ovom slučaju se nazivametodom najmanjih kvadrata (engl. least squares method).

Dajmo jedan primer. Neka treba resiti sistem jednačina Ax = b, gde je

A =

2 0−1 10 2

, b =

−101

S obzirom da ne možemo izvršiti inverziju matrice A, moramo pronaći rešenje naneki drugi način. Pomnožimo sistem jednačina Ax = b matricom AT sa leve strane.Time dobijamo sistem

ATAx = ATb.Primetimo da je ATA kvadratna matrica, odnosno, njen inverz je moguće pronaći(ukoliko je nesingularna). Množenjem prethodne jednakosti matricom (ATA)−1,dobijamo rešenje sistema

x = (ATA)−1ATb.U programskom jeziku Python, ovo se jednostavno kodira narednim program-

skim fragmentom koda:>>> A = np.array([[2,0], [-1,1], [0,2]])>>> b = np.array([-1,0,1]).T>>> x = LA.inv(A.T.dot(A)).dot(A.T).dot(b)

Neka je x približno rešenje pravog resenja x. Potrebno je rešiti naredni minimi-zacioni problem

min ||x− x||.U našem primeru, ocena greške u smislu metode najmanjih kvadrata glasi

||b− b|| =

√√√√ n∑i=1

(bi − bi)2

U programskom jeziku Python, ovo se jednostavno kodira narednim program-skim fragmentom koda:>>> b_approx = A.dot(x)>>> np.sqrt(np.sum((b - b_approx)*(b - b_approx)))0.816496580927726

Page 33: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 2. APROKSIMACIJA FUNKCIJA 27

Primetimo da smo mogli iskoristiti i funkciju normiranja modula linearne algebre:

>>> b_approx = A.dot(x)>>> LA.norm(b - b_approx)0.816496580927726

Dajmo još jedan primer. Neka je data duž AD na kojoj se nalaze tačke B i C,tako da je A − B − C − D i A = B = C = D. Ako su poznate dužine segmenata|AD| = 89, |AC| = 67, |BD| = 53, |AB| = 35 i CD = 20, odrediti dužinu segmenta BC.Ukoliko označimo |AB| = x1, |BC| = x2 i |CD| = x3, tada dobijamo naredni sistemjednačina

x1 + x2 + x3 = 89x1 + x2 = 67

x2 + x3 = 53x1 = 35

x3 = 20

što se može matrično zapisati u programskom jeziku Python na sledeći način:

>>> A = np.array([>>> [1,1,1],>>> [1,1,0],>>> [0,1,1],>>> [1,0,0],>>> [0,0,1]>>> ])>>> b = np.array([89, 67, 53, 35, 20]).T

Ovog puta, umesto da sami implementiramo računanje sistema jednačina i oce-njivanje greške, iskoristićemo funkciju LA.lstsq(A, b, rcond). Ova funkcija izraču-nava rešenje linearnog sistema jednačina sa najmanjom greškom u smislu metodanajmanjih kvadrata. Argumenti funkcije su: matrica koe cijenata A, vektor slobod-nih članova b i parametar odsecanja rcond malih singularnih vrednosti matrice A,koji je podrazumevano postavljen na -1. Preciznije rečeno, funkcija izračunava:rešenje, aproksimaciju greške, rang matrice A i singularne vrednosti matrice A. Po-zivom ove funkcije nad prethodno de nisanim matricama A i b daje:

>>> rezultat = LA.lstsq(A, b)>>> # Resenje sistema linearnih jednacina... rezultat[0]array([35.125, 32.5 , 20.625])>>> # Aproksimacija resenja u smislu metode najmanjih kvadrata... rezultat[1]array([1.375])>>> # Rang matrice A... rezultat[2]3>>> # Singularne vrednosti matrice A... rezultat[3]array([2.5243378 , 1.41421356, 0.79228699])

Dakle, kao najbolje rešenje za dužinu segmenta BC uzimamo vrednost 32.5, uzaproksimaciju greške 1.375.

Page 34: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 2. APROKSIMACIJA FUNKCIJA 28

2.2.1 Aproksimacija polinomimaNeka su date su tacke (xi,yi). Želimo da aproksimiramo funkciju f polinomom P

stepena n, pri čemu je P(xi) = yi. Određujemo tačke p0,p1, . . . ,pn, tako da vršimominimizaciju

minn∑i=0

(yi − P(xi))2.

Jednakosni uslovi koje traženi polinom mora da zadovoljava mogu se matričnozapisati na sledeći način:

1 x1 x21 . . . xn11 x2 x22 . . . xn2...

...... . . .

...1 xn x2n . . . xnn

p0p1...pn

=

y1y2...yn

(2.2)

Matrica sa leve strane prethodne jednakosti naziva se Vandermondova matri-ca. Dajmo jedan jednostavan primer kojim ćemo ilustrovati aproksimaciju funkcijepolinomom.

Neka je zadato n = 5 tačaka, na sledeći način:

>>> n = 5>>> x = np.linspace(0, 1, n)>>> y = np.random.rand(n)

Za izračunavanje polinoma P koji zadovoljava jednakost P(xi) = yi za svako i =1, . . . ,nmože se iskoristiti funkcija np.polyfit(x, y, deg). Ova funkcija, čiji su argu-menti vektori tačaka x i y i stepen polinoma deg, izračunava traženi polinom u smi-slu minimizacije metodom najmanjih kvadrata. Rezultat izračunavanja ove funkcijepredstavlja niz koe cijenata p0,p1, . . . ,pn narednog polinoma stepena n:

P(x) = p0xn + p1xn−1 + . . .+ pn.

Izračunajmo sada koe cijente traženog polinoma korišćenjem opisane funkcije.S obzirom da nam je na raspolaganju n tačaka, formiramo polinom stepena n− 1:

>>> coef1 = np.polyfit(x, y, n-1)>>> coef1array([-11.10716719, 29.26514694, -24.00021412, 6.62169741,

0.1839524 ])

Primetimo da se u prethodnoj jednakosti prvi koe cijent nalazi uz najveći ste-pen, a da poslednji koe cijent predstavlja slobodan član. Zbog toga ćemo uglavnomobrtati redosled rezultujućeg niza koe cijenata u našim izračunavanjima. Prome-na redosleda elemenata niza tipa np.ndarray može se izvršiti funkcijom np.flip(m,axis), gde je m niz čiji redosled elemenata menjamo.

Izračunajmo koe cijente polinoma korišćenjem jednakosti 2.2, odnosno, prime-nomVandermondovematrice. Izračunavanje Vandermondovematrice se jednostav-no izvodi korišćenjem funkcije np.vander(x, N, increasing), gde je x vektor tačaka,N dimenzija Vandermondove matrice i increasing Bulova promenljiva koja određu-je redosled stepena (ovu vrednost postavljamo na True ukoliko želimo da dobijemoredosled stepena kao u jednakosti 2.2).

>>> V = np.vander(x, n, increasing=True)

Page 35: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 2. APROKSIMACIJA FUNKCIJA 29

Za rešavanje jednakosti 2.2 iskoristićemo sada već poznatu funkciju LA.lstsq.Na ovom mestu ćemo uvesti pojam čuvar mesta (engl. placeholder). Čuvar mestapredstavlja simboličku vrednost koja se može iskoristiti umesto stvarne vrednostiukoliko nam ona nije od značaja. U programskom jeziku Python se čuvari mestaoznačavaju podvlakom _.

Govorili smo da funkcija LA.lstsq ima (u određenom smislu) četiri povratne vred-nosti. S obzirom da je nama trenutno od značaja, samo prva vrednost (rezultatsistema linearnih jednačina), to možemo iskoristiti čuvare mesta za preostale trivrednosti, odnosno:

coef2, _, _, _ = LA.lstsq(V, y)

Sadamožemo pristupiti koe cijentima polinoma dobijenim na ovaj način i uvidetida je rezultat identičan prethodnom postupku (naravno, uz adekvatnu operacijupromene redosleda, o čemu je bilo reči):

>>> np.flip(coef2, axis=0)array([-11.10716719, 29.26514694, -24.00021412, 6.62169741,

0.1839524 ])

2.2.2 Dodatni primeriDo sada smo videli različite pristupe rešavanja problema čiji je zadatak odre-

đivanje aproksimacije funkcija i to kroz korišćenje metoda linearne algebre. Kaokriterijum aproksimacije razmatrali smo metod najmanjih kvadrata 2.1. Pre negošto pređemo na sledeći metod koji nam može služiti kao alat za aproksimaciju funk-cija, daćemo dva primera radi dodatne ilustracije i rezimiranja onoga što smo dosada videli.

Prvi primer bi sada već trebalo da bude jednostavan za rešavanje. Neka je datskup tačaka {(−10,2.11), (7.4,2.05), (3,2.18), (−4.11,1.99), (5.32,2.05)}. Potrebno jepronaći funkciju f(x) = c, gde je c konstanta, koja najbolje aproksimira funkcijuzadatu datim tačkama. Jasno je da optimizacioni problem glasi

min∑i(yi,c)2.

Jedan način jeste da pronađimo u kojoj tački funkcija pod minimumom dostiženajmanju vrednost:

f(c) =∑i(yi − c)2

f′(c) =∑i2(yi − c)(−1)

Važi

f′(c) = 0⇔n∑i=1

(yi − c) = 0.

Odavde zaključujemo da je c = 1n∑n

i=1 yi. Drugi način jeste da rešimo sistemjednačina (zadat u matričnom obliku):

Page 36: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 2. APROKSIMACIJA FUNKCIJA 30

11...1

[c] =

y1y2...yn

Uporedimo rešenja dobijena pomoću oba načina. Narednim fragmentom koda

možemo zaključiti da su rešenja (ako primenimo odgovarajuće zaokruživanje) ekvi-valentna:>>> data = [(-10, 2.11), (7.4, 2.05), (3, 2.18), (-4.11, 1.99), (5.32, 2.05)]>>> x = np.array([d[0] for d in data])>>> y = np.array([d[1] for d in data])

>>> c1 = np.mean(y)>>> print('c1 = ', c1)c1 = 2.0759999999999996>>> rss1 = np.sum((y-c1)*(y-c1))>>> print('rss1 = ', rss1)rss1 = 0.020720000000000044

>>> n = len(data)>>> A = np.ones(n).reshape((5, 1))>>> b = y.copy()>>> rezultat = LA.lstsq(A, b, rcond = None)>>> print('c2 = ', rezultat[0])c2 = [2.076]>>> print('rss2 = ', rezultat[1])rss2 = [0.02072]

Pređimo na drugi primer. Društveni domet (engl. social reach) predstavlja merubroja ljudi koje možemo da obuhvatimo ako plasiramo neku informaciju. Ova merase najčešće pominje u oblasti marketinga i reklamiranja na društvenim mrežama,poput Facebook-a. Ukoliko naša informacija dođe do nekog korisnika, verovatnoćada ona nastavi da se plasira je veća ukoliko taj nalog ima više "prijatelja".

Na raspolaganju nam je skup podataka koji se može predstaviti tabelom 2.2.Kolone ove tabele predstavljaju različite veb portale (ukupno 3) na kojima želimoda plasiramo našu reklamu, a vrste predstavljaju zemlje u kojima želimo da izvršimoreklamiranje. Označimo ovu tabelu matricom A = (aij)10×3.

Tabela 2.2: Prikaz skupa podataka social_reach.

veb1 veb2 veb3zemlja1 a11 a12 a13zemlja2 a21 a22 a23

......

......

zemlja10 a10,1 a10,2 a10,3

Vrednost aij predstavlja cenu reklame za 1000 klikova u zemlji i, na portalu j.Cilj nam je da raspodelimo budžet koji nam je na raspolaganju na svaki od portalatako da ostvarimo idealno milion pregleda ukupno. Drugim rečima, potrebno jepronaći vrednosti ulaganja u svaki portal, sa ciljem da da budu što manje, takoda u idealnom slučaju ostvarimo milion pregleda. Ukoliko oznakom invj označimoinvesticiju u portal j, onda naš zadatak možemo matrično zapisati na sledeći način:

Page 37: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 2. APROKSIMACIJA FUNKCIJA 31

a11 a12 a13a21 a22 a23...

......

an1 an2 an3

[inv1 inv2 inv3]=

10001000...

1000

Naredni fragment koda prikazuje rešenje prethodnog sistema jednačina:

>>> investments, _, _, _ = LA.lstsq(data, 1000*np.ones(10))>>> investmentsarray([ 62.07662454, 99.98500403, 1442.83746254])

Odredimo sada vrednost društvenog dometa. Da bismo ovo uradili, dovoljno jeda izračunamo sumu proizvoda date matrice cena i dobijenih vrednosti investicija.Iz narednog izračunavanja vidimo da čak i u najboljem slučaju nismo u mogućnostida ostvarimo željeni domet od milion pregleda, te je dalje potrebno odlučiti da li jevredno sprovesti plasiranje ili ne.>>> social_reach_vec = data.dot(investments)>>> np.sum(social_reach_vec)*10009824071.104836853

Kako je rezultat datog proizvoda vektor vrednosti društvenog dometa po zemlja-ma, prethodno sumiranje zapravo predstavlja zbir koordinata tog vektora. Ukolikonas zanima vrednost date mete po zemljama, možemo rezultat vizualizovati u oblikuhistograma, što je prikazano na slici 2.1.

Slika 2.1: Histogram vrednosti društvenog dometa za svaku od zemalja.

2.3 Linearna regresijaLinearna regresija predstavlja jedan od najjednostavnijih i najčešće korišćenih

modela za predviđanje. Sa probabilističke tačke gledišta, osnovna pretpostavkaje pretpostavka normalne raspodele ciljne promenljive y, pri datim vrednostimaatributa x. Odnosno, važi

p(y|x) = N (f(x),σ2),

Page 38: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 2. APROKSIMACIJA FUNKCIJA 32

gde je f funkcija koja uspostavlja vezu izmedu atributa i očekivanja ciljne promen-ljive. U zavisnosti od forme ove funkcije, moguće je dobiti vrlo različite modele.Tehnički najjednostavnija forma modela je linearna:

fβ(x) = β0 + β1x+ . . .+ βmxm, (2.3)

pri čemu ćemo često koristiti formu za m = 1, odnosno,

fβ(x) = β0 + β1x. (2.4)

Reklamiranje u medijima Dajmo jedan primer. Na raspolaganju nam je skuppodataka advertising. Atributi ovih podataka su veličine uloženih sredstava u TV,radio i novinske medije, kao i veličina koja određuje ukupnu prodaju proizvoda kojise reklamirao na datim medijima. Treba oceniti model koji kombinuje sva tri atribu-ta — TV, radio i novinske medije — da predvidi vrednost prodaje. Drugim rečima,vršimo predviđanje prodaje y u odnosu na atribute xTV,xRadio,xNewspaper. Model li-nearne regresije u ovom slučaju izgleda

y = β0 + β1xTV + β2xRadio + β3xNewspaper.

Za početak, pogledajmo kako se svaki atribut ponaša sa ciljnom promenljivom.Za vizualizaciju ovog zadatka korisno je upotrebiti tačkaste nacrte (engl. scatterplot). Naredni fragment programskog koda generiše tačkaste nacrte na slici 2.2— zavisnosti ciljne promenljive od atributa TV, radio i novinskih medija, redom.

>>> import pandas as pd>>> from matplotlib import pyplot as plt

>>> data = pd.read_csv('advertising.csv')

>>> # Ciljna promenljiva>>> sales = data['Sales']

>>> tvData = data['TV']>>> plt.scatter(tvData, sales)>>> plt.show()

>>> radioData = data['Radio']>>> plt.scatter(radioData, sales, color='red')>>> plt.show()

>>> newspaperData = data['Newspaper']>>> plt.scatter(newspaperData, sales, color='magenta')>>> plt.show()

Ono što se odmah uočava posmatranjem ovih nacrta jeste da je linearna zavi-snost Sales od TV najveća, a da je linearna zavisnost Sales od Newspaper najmanja.Iako je naša inicijalna analiza podataka u ovom slučaju dala neke odgovore koje setiču zavisnosti atributa i ciljne promenljive, uočavamo jednu bitnu činjenicu — tač-kasti nacrti su pogodni za vizualizaciju zavisnosti u dvodimenzionalnom (eventu-alno, trodimenzionalnom) prostoru, dok je ovakva analiza u visokodimenzionalnimprostorima nezamisliva. Zato nam je potreban drugi analitički metod, na primer,linearna regresija.

Page 39: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 2. APROKSIMACIJA FUNKCIJA 33

Slika 2.2: Tačkasti nacrti zavisnosti cilje promenljive Sales od atributa TV, Radio iNewspaper, redom (sleva).

2.3.1 Biblioteka scikit-learnBiblioteka scikit-learn (sklearn) predstavlja skup alata, jednostavnih za korišće-

nje, koje možemo iskoristiti u različitim kontekstima pri analizi podataka, istraži-vanju podataka i mašinskom učenju [7]. Neki od modula ove biblioteke su: klasi-kacioni, regresioni, izbor modela, pretprocesiranje i drugi. Ovu biblioteku ćemo

intenzivno koristiti pri radu sa svimmodelima mašinskog učenja, kao što je linearnaregresija, koja se nalazi u modulu linear_model:

>>> from sklearn import linear_model

Da bismo konstruisali model linearne regresije, neophodno je konstruisati obje-kat klase LinearRegression(fit_intercept, normalize, ...). Njegov parametar fit_interceptkoji je podrazumevano postavljen na True određuje da li se izračunava slobodni članza taj model. S obzirom da mi podrazumevamo formu modela 2.3, želimo da seslobodni član (β0) izračunava. Parametar normalize, podrazumevano postavljen naFalse, određuje da li će skup podataka biti normalizovan pre izvođenja regresije. Sobzirom da ćemo pretprocesiranje podataka raditi mi2, želimo da ovaj parametarostane na svojoj podrazumevanoj vrednosti. Konstruišimo sada naš model:

>>> model = linear_model.LinearRegression()

Pre samog treniranja modela, potrebno je pripremiti skup podataka na kojima ćemodel izvršiti treniranje. Drugim rečima, izdvajamo one kolone koje su nam bitneza regresiju, u ovom slučaju:

>>> allData = data[['TV', 'Radio', 'Newspaper']]

Sada možemo trenirati naš model. Ovo izvodimo pozivanjem metoda fit(X, y,sample_weight=None) koji na osnovu skupa za obučavanje X vrši obučavanje ciljnepromenljive y, pri čemu možemo dodeliti težine instancama korišćenjem parametrasample_weight. U našem slučaju, obučavanje linearnog modela izgleda:

>>> model.fit(allData, sales)

Nakon obučavanja, dostupni su nam atributi intercept_ i coef_ koji sadrže vred-nosti slobodnog člana β0 i koe cijenata β1, . . . , βm, redom. U našem slučaju, koe -cijenti linearnog modela koji se dobijaju su:

>>> print('Slobodni clan:', model.intercept_)Slobodni clan: 2.9388893694594085>>> print(pd.Series(model.coef_, index=['TV', 'Radio', 'Newspaper']))TV 0.045765

2U ovom slučaju nije neophodno izvršiti normalizaciju podataka. Ubrzo ćemo se upoznati sa pojmomnormalizacije i primerom kada ju je neophodno izvršiti.

Page 40: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 2. APROKSIMACIJA FUNKCIJA 34

Radio 0.188530Newspaper -0.001037dtype: float64

Ocenimo sada prediktivnu moć našeg modela. Postoje različite ocene regresio-nih modela; mi ćemo sada predstaviti jedan od njih. Neka su nam dati podaci (xi,yi) ineka je y = 1

n∑n

i=1 yi. Koe cijent determinacije (engl. coe icient of determination),u oznaci R2, predstavlja vrednost

R2 = 1−∑n

i=1(yi − yi)2∑ni=1(yi − y)2

. (2.5)

Na osnovu prethodne jednakosti vidimo da su za ocenjivanje modela potrebnistvarni podaci yi i podaci koje naš model predviđa y. Za početak, napravimo kopijunaših vrednosti ciljne promenljive. Dodatno, izvršićemo i predimenzioniranje tihpodataka (odnosno, koristićemo funkciju reshape) da bismomogli oceniti naš model.Drugim rečima,>>> sales_real = sales.copy().values.reshape((200, 1))

Sada je potrebno da odredimo podatke koje naš model predviđa. Za to namkoristi funkcija predict(X), čiji je parametar skup za obučavanje. U našem slučaju:>>> sales_predicted = model.predict(allData)

Kada imamo sve neophodne podatke, možemo izvršiti ocenjivanje koe cijen-tom determinacije 2.5. Funkcija kojom ćemo izračunati ocenu je r2_score(y_true,y_pred, ...) modula metrics biblioteke sklearn. Kao što i sami nazivi parametaragovore, y_true predstavlja skup stvarnih vrednosti ciljne promenljive yi, dok y_predpredstavlja predviđene vrednosti y. Ocena našeg modela iznosi:>>> from sklearn import metrics>>> metrics.r2_score(sales_real, sales_predicted)0.8972106381789522

S obzirom da najbolja ocena koja može da se dobije koe cijentom determinaci-je iznosi 1.0, pri čemu ona može biti negativna (model može biti proizvoljno loš),zaključujemo da naš model relativno dobro predviđa.

Procena cena domova u Bostonu Jedan izuzetno koristanmodul biblioteke sklearnjeste modul datasets. Ovaj modul sadrži različite skupove podataka koji se mogu ko-ristiti u najrazličitijim analizama, poput regresije i klasi kacije. Jedan od skupovapodataka koji se nalazi u njemu sadrži informacije vezane o domovima u Bostonu.Pored različitih atributa koji ih opisuju, domovi imaju i svoje cene. Svaki skup poda-taka dobijamo kao rezultat poziva odgovarajuće funkcije iz modula, pa tako opisaniskup podataka dobijamo pozivom funkcije:>>> from sklearn import datasets>>> data = datasets.load_boston()

Da bismo dobili više informacija o ovom skupu podataka, možemo prikazi svoj-stvo DESCR objekta koji sadrži skup podataka. Neke od informacija od značaja kojevidimo su: broj instanci, broj atributa, informacije o atributima i postojanje nedo-stajućih vrednosti. Značajno je uvek pogledati ove informacije kako bismo mogliunapred da odredimo osnovne korake u pretprocesiranju i analizi podataka. Sa-da ćemo prikazati detaljan sadržaj ovog svojstva, a u daljim primerima ćemo samonapomenuti koje informacije smo dobili na osnovu njegovog analiziranja.

Page 41: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 2. APROKSIMACIJA FUNKCIJA 35

>>> print(data.DESCR)Boston House Prices dataset===========================

Notes------Data Set Characteristics:

:Number of Instances: 506

:Number of Attributes: 13 numeric/categorical predictive

:Median Value (attribute 14) is usually the target

:Attribute Information (in order):- CRIM per capita crime rate by town- ZN proportion of residential land zoned for lots over 25,000 sq.ft.- INDUS proportion of non-retail business acres per town- CHAS Charles River dummy variable (= 1 if tract bounds river; 0 otherwise)- NOX nitric oxides concentration (parts per 10 million)- RM average number of rooms per dwelling- AGE proportion of owner-occupied units built prior to 1940- DIS weighted distances to five Boston employment centres- RAD index of accessibility to radial highways- TAX full-value property-tax rate per $10,000- PTRATIO pupil-teacher ratio by town- B 1000(Bk - 0.63)^2 where Bk is the proportion of blacks by town- LSTAT % lower status of the population- MEDV Median value of owner-occupied homes in $1000's

:Missing Attribute Values: None

:Creator: Harrison, D. and Rubinfeld, D.L.

This is a copy of UCI ML housing dataset.http://archive.ics.uci.edu/ml/datasets/Housing

This dataset was taken from the StatLib library which is maintained at CarnegieMellon University.

The Boston house-price data of Harrison, D. and Rubinfeld, D.L. 'Hedonicprices and the demand for clean air', J. Environ. Economics & Management,vol.5, 81-102, 1978. Used in Belsley, Kuh & Welsch, 'Regression diagnostics...', Wiley, 1980. N.B. Various transformations are used in the table onpages 244-261 of the latter.

The Boston house-price data has been used in many machine learning papers thataddress regression problems.

**References**

- Belsley, Kuh & Welsch, 'Regression diagnostics: Identifying Influential Data and

Page 42: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 2. APROKSIMACIJA FUNKCIJA 36

Sources of Collinearity', Wiley, 1980. 244-261.- Quinlan,R. (1993). Combining Instance-Based and Model-Based Learning. InProceedings on the Tenth International Conference of Machine Learning, 236-243,University of Massachusetts, Amherst. Morgan Kaufmann.- many more! (see http://archive.ics.uci.edu/ml/datasets/Housing)

Samim skupom podataka pristupamo svojstvom data objekta skupa podataka.Svojstvom feature_names dobijamo indeks kolona atributa na osnovu kojih vršimopredviđanje. Korišćenjem ova dva svojstva možemo formirati objekat tipa DataFramena sledeći način:

>>> x = pd.DataFrame(data.data, columns=data.feature_names)

Svojstvo target sadrži vrednosti ciljnih promenljivih:

>>> y = data.target

Ovim smo kompletirali obradu ulaznih podataka. Sada treba izvršiti konstrukci-ju modela i njegovo treniranje. Kao i u prethodnom primeru, i ovde ćemo koristitilinearni model sa slobodnim članom kao model predviđanja. Međutim, treniranjećemo izvršiti na nešto drugačiji način. Prisetimo se da smo u tom primeru treniranjemodela vršili nad svim podacima. Ovo je sasvim očekivano jer želimo da iscrpimošto je više informacija moguće ne bi li naš model bio treniran upravo sa svim in-formacijama koje možemo izvući iz podataka. Mesto gde nastaje problem jeste uevaluaciji modela. Mi smo računali vrednost koe cijenta determinacije na osnovupodataka koje smo predviđali, ponovo na osnovu celog skupa podataka. Drugim re-čima, koristili smo iste podatke i za trening modela i za evaluaciju modela. Ovimesmo prekršili prvo i osnovno načelo evaluacije modela koje glasi:

Podaci korišćeni u evaluaciji modela ni na koji način ne smeju bitikorišćeni prilikom njegovog obučavanja.

Kršenjem ovog načela ocene koje dobijamo pri (pogrešnoj) evaluaciji modela suoptimistične, odnosno, ne daju realnu sliku stanja kako će se naš model ponašatiprema budućim podacima. Zbog toga, ukoliko želimo da ispravno izvršimo evalua-ciju modela, potrebno je skup podataka podeliti na dva skupa:

1. skup za obučavanje (engl. training set), nad kojim ćemo izvršiti treniranjemodela;

2. skup za evaluaciju (engl. testing set), koji ćemo iskoristiti za dobijanje ocenepredviđanja našeg modela.

Napomenimo sada još jednom, a kasnije ćemo dodatno skrenuti pažnju, sve dokne dođemo do faze evaluacije modela, ne smemo koristiti nijednu informaciju dobi-jenu iz podataka koji pripadaju skupu za evaluaciju, bilo implicitno ili eksplicitno.

Iako bismo mogli i mi sami da izvršimo podelu skupa, u modulu model_selectionbiblioteke sklearn dostupna nam je funkcija train_test_split(*arrays, **options)koja ovo može da izvrši za nas. Njeni argumenti su sekvence podataka — ulaznihvrednosti i ciljne promenljive — i opcije kojima možemo dodatno okarakterisati štaje to što podela podataka mora da ispunjava. Neke od opcija koje možemo precizi-rati su:

• train_size, apsolutan (ako je tipa int) ili relativan (ako je tipa float) broj po-dataka koji ulazi u skup za obučavanje. Ukoliko se ne navede, podrazumevase komplement vrednosti parametra test_size;

Page 43: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 2. APROKSIMACIJA FUNKCIJA 37

• test_size, apsolutan (ako je tipa int) ili relativan (ako je tipa float) broj po-dataka koji ulazi u skup za evaluaciju. Ukoliko se ne navede, podrazumeva sekomplement vrednosti parametra train_size;

• random_state, inicijalizator generatora pseudo-slučajnih brojeva.

Povratna vrednost ove funkcije je lista dužine 2·len(arrays)—podela prosleđenihnizova na skup za obučavanje i skup za evaluaciju, i to onim redom kojim su oninavedeni. Rad ove funkcije se najbolje shvata kroz primer, te prikažimo na kojinačin možemo izvršiti podelu naših skupova x i y:>>> x_train, x_test, y_train, y_test = model_selection.train_test_split(... x, y, train_size=0.67, test_size=0.33, random_state=7... )

Odavde vidimo da smo podelili skup podataka u razmeri bliskoj 2 : 1, što je jednamoguća podela koja se koristi u praksi, ali nije i jedina. Od sada ćemo postavljativrednost parametra random_state na broj 73, kako bi čitalac pri izvršavanju fragme-nata kodova mogao dobiti iste vrednosti kao one koje su date u tekstu.

Ostatak procesa je gotovo isti kao i u prethodnom primeru: model prvo trenira-mo (ovoga puta nad skupom za obučavanje), a zatim vršimo evaluaciju (ovoga putanad skupom za evaluaciju). Ovoga puta ćemo kao meru kvaliteta uzeti srednjekva-dratnu grešku (engl. mean square error), koja je data formulom

MSE =1N

N∑i=1

(yi − f(xi))2. (2.6)

Što se tiče procene kvaliteta na osnovu vrednosti ove greške, model predviđanajbolje ukoliko je vrednost ocene nula. Inače, ocena može dati proizvoljnu nene-gativnu vrednost — što je model lošiji, to je vrednost veća. Izračunajmo vrednostMSE za linearni model nad ovim podacima:>>> # Obucavanje modela nad skupom za obucavanje>>> model = linear_model.LinearRegression()>>> model.fit(x_train, y_train)>>> # Dobijene vrednosti modela>>> model.coef_array([-1.06282809e-01, 2.57340451e-02, 1.00723142e-02, 2.59140195e+00,

-1.57091327e+01, 5.34155336e+00, -1.39519386e-02, -1.30702759e+00,2.67953424e-01, -1.12531878e-02, -9.70043443e-01, 1.01801820e-02,-3.88405487e-01])

>>> model.intercept_24.713159262931597

>>> # Evaluacija modela nad skupom za evaluaciju>>> y_pred = model.predict(x_test)>>> metrics.mean_squared_error(y_test, y_pred)25.290803639932545

Iako nećemo ulaziti u interpretaciju rezultata ocena, izračunajmo i vrednost ko-e cijenta determinacije u ovom slučaju:>>> metrics.r2_score(y_test, y_pred)0.6667241096456478

3Broj 7 je odabran jer je to autorov omiljeni broj.

Page 44: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 2. APROKSIMACIJA FUNKCIJA 38

Ono što bi moglo biti značajno proveriti jeste da li je linearni model uopšte pogo-dan za predviđanje u ovom primeru. Reziduali (engl. residuals) predstavljaju vred-nosti razlika između stvarnih vrednosti i predviđenih vrednosti. Podsetimo se da seu linearnom modelu pretpostavlja normalna raspodela reziduala, odnosno, greša-ka pri predviđanju modela. Naredni fragment koda iscrtava histogram reziduala,koji je prikazan na slici 2.3, a čijim analiziranjem se možemo uveriti u korektnostodabira linearnog modela.

>>> plt.hist(y_pred - y_test)>>> plt.show()

Slika 2.3: Histogram reziduala linearnog modela u primeru procene cena domovau Bostonu.

Pokušajmo da popravimo ocenemodela biranjem samo nekih atributa, na primer,stope kriminala i odnos učenika i nastavnika. Kao i do sada, primenjujemo istipostupak:

>>> x_train_2 = x_train[['CRIM', 'PTRATIO']]>>> y_train_2 = y_train.copy()>>> x_test_2 = x_test[['CRIM', 'PTRATIO']]>>> y_test_2 = y_test.copy()

>>> model2 = linear_model.LinearRegression()>>> model2.fit(x_train_2, y_train_2)

>>> y_pred_2 = model2.predict(x_test_2)

>>> metrics.mean_squared_error(y_test_2, y_pred_2)54.1579297830717

>>> metrics.r2_score(y_test_2, y_pred_2)0.28632033504452725

Vidimo da se u ovom slučaju dobila još veća greška, te zaključujemo da je ovajmodel lošiji.

Page 45: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 2. APROKSIMACIJA FUNKCIJA 39

Ono što može biti interesantno prilikom inicijalne analize podataka jeste određi-vanje korelacije između atributa. Ukoliko imamo mnogo visoko koreliranih atribu-ta, sva je prilika da će model predviđati lošije. U takvim situacijama, možda trebarazmisliti o eliminisanju jednog od dva visoko korelirana atributa.

Jedna pogodna tehnika vizualizacije korelacije između atributa jeste korišćenjetoplotnih mapa (engl. heat map). Toplotna mapa se oslanja na vrednosti u matriciod koje se konstruiše i prikazuje svetlije boje tamo gde je vrednost u matrici ve-ća, a tamnije bolje tamo gde je vrednost u matrici manja. Ova tehnika se odličnokombinuje samatricom korelacije, u oznaci Corr, čiji je element na poziciji (i, j) jed-nak vrednosti (na primer, Pirsonovog) koe cijenta korelacije između atributa i i j,odnosno

Corr(i, j) =

1n−1

N∑k=1

(ik − i)(jk − j)

si · sj,

gde su i, j, si, sj vrednosti proseka za atribut i, proseka za atribut j, standardne devi-jacije za atribut i i standardne devijacije za atribut j, redom. Matrica korelacije seizračunava korišćenjem funkcije corr() biblioteke pandas nad objektom čiju matricukorelacije želimo da izračunamo. Iscrtavanje toplotne mape nad matricom kore-lacije može se izvršiti pozivom funkcije plt.imshow(X), gde je X matrica korelacije.Naredni fragment koda iscrtava toplotnu mapu sa slike 2.4.>>> # Priprema podataka za iscrtavanje toplotne mape>>> data_hm = pd.DataFrame(data.data)>>> num_of_columns = len(data1.columns)

>>> # Postavljanje vrednosti tacaka na x-osi na imena atributa>>> plt.xticks(np.arange(num_of_columns), list(data.feature_names),... rotation='vertical')

>>> # Postavljanje vrednosti tacaka na y-osi na imena atributa>>> plt.yticks(np.arange(num_of_columns), list(data.feature_names))

>>> # Racunanje matrice korelacije i prikazivanje toplotne mape>>> corr_data_hm = data_hm.corr()>>> plt.imshow(corr_data_hm)

>>> # Prikazivanje legende za toplotnu mapu>>> plt.colorbar()

>>> plt.show()

Analiziranjem toplotne mape zaključujemo da, na primer, između atributa RAD iTAX ima visoke pozitivne korelacije, a da, na primer, između atributa DIS i AGE, DIS iNOX, i LSTAT i RM ima visoke negativne korelacije.

Page 46: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 2. APROKSIMACIJA FUNKCIJA 40

Slika 2.4: Toplotna mapa matrice korelacije atributa u primeru procene cena do-mova u Bostonu.

Procena plata bejzbol igrača U ovom primeru ćemo pokušati da konstruiše-mo linearni model koji predviđa plate bejzbol igrača na osnovu nekih informacijao njihovom igranju u karijeri (skup podataka Hitters, videti B). Videćemo neke odmetoda koje se koriste u pretprocesiranju podataka, kao što su standardizacija po-dataka, rukovanje nedostajućim vrednostima i izbor atributa. Nadalje ćemo istiskup podataka koristiti da prikažemo još jedan model i napredne tehnike izboramodela i evaluacije.>>> data = pd.read_csv('hitters.csv')

Prvo ćemo raditi analizu nedostajućih vrednosti. Za to nam može poslužiti funk-cija isnull() paketa pandas koju primenjujemo nad data. Rezultat funkcije je objekatBulovih vrednosti iste dimenzije koji označava da li je vrednost nedostajuća ili ne.Sumiranjem ovih vrednosti po koloni možemo videti za svaki atribut koliko ima ne-dostajućih vrednosti:>>> data_isnull = np.sum(data.isnull(), axis=0)>>> data_isnull[data_isnull > 0]Salary 59dtype: int64

Jedini atribut koji ima nedostajuće vrednosti jeste upravo ciljna promenljiva Salary.Vidimo da imamo 59 nedostajućih vrednosti (od 322 ukupno). Postoji više načinaza rukovanje nedostajućim vrednostima, a jedna od najosnovnijih jeste eliminisa-nje instanci koje imaju nedostajuće vrednosti. To možemo izvršiti pozivom funkcijedropna() o kojoj je već bilo reči. Druga mogućnost je da ih na neki način predviđa-mo, među tim, o tome neće biti reči u ovom tekstu. Dakle, naš skup podataka je zasada:>>> data = data.dropna()

Pomoću funkcije info() paketa pandas primenjene na datamožemo videti tipovevrednosti po kolonama:>>> data.info()<class 'pandas.core.frame.DataFrame'>

Page 47: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 2. APROKSIMACIJA FUNKCIJA 41

Int64Index: 263 entries, 1 to 321Data columns (total 21 columns):Player 263 non-null objectAtBat 263 non-null int64Hits 263 non-null int64HmRun 263 non-null int64Runs 263 non-null int64RBI 263 non-null int64Walks 263 non-null int64Years 263 non-null int64CAtBat 263 non-null int64CHits 263 non-null int64CHmRun 263 non-null int64CRuns 263 non-null int64CRBI 263 non-null int64CWalks 263 non-null int64League 263 non-null objectDivision 263 non-null objectPutOuts 263 non-null int64Assists 263 non-null int64Errors 263 non-null int64Salary 263 non-null float64NewLeague 263 non-null objectdtypes: float64(1), int64(16), object(4)memory usage: 45.2+ KB

Vidimo da su kolone Player, League, Division i NewLeague nešto što nisu numeričkevrednosti. U našem slučaju, u pitanju su niske koje određuju upravo ono što im isamo ime govori. Pretprocesiranje ovakvih podataka se takođe može uraditi na dru-gačije načine, ali s obzirom da mi za sada baratamo samo numeričkim podacima,odlučujemo da i takve atribute eliminišemo. To možemo izvesti pozivanjem funkci-je drop(labels=None, axis=0, ..., inplace=False, ...) paketa pandas primenjen nadata, čiji su parametri: labels — sekvenca oznaka atributa koje eliminišemo, axis— osa po kojoj vršimo eliminisanje, inplace — Bulova vrednost koja određuje da lise eliminacija vrši u mestu ili ne, i dr. Naredni poziv funkcije drop eliminiže dateoznake po kolonama4:>>> data.drop(['Player', 'League', 'Division', 'NewLeague'], axis=1, inplace=True)

Sada možemo da izvršimo izdvajanje atributa i ciljne promenljive. Kao i do sada,skup vrednosti atributa (sve kolone osim Salary) biće čuvan u promenljivoj x, a skupciljne promenljive (kolona Salary) u vektoru y:>>> x = data.drop(['Salary'], axis=1)>>> y = data['Salary']

Ukoliko pogledamo naš skup podataka, primetićemo da različiti atributi merevrednosti na različitim skalama. Ova pojava je nešto što se često javlja u praksi,posebno u medicinskim istraživanjima. Ako imamo, na primer, informacije o teži-ni osobe, visini krvnog pritiska i količini minerala u organizmu, sve te vrednostise mere na različitim skalama. Standardizacija podataka je svođenje podataka sakojima radimo na iste skale. Standardizaciju podataka najčešće vršimo na interval

4Iako smo rekli da je vrednost 0 parametra axis rezervisana za kolone, funkcija drop radi malo dru-gačije. Zapravo, ona ima parametre columns i index kojima možemo proslediti oznake koje treba eli-misati. Poziv data.drop(labels, axis=1) ekvivalentan je pozivu data.drop(columns=labels), dok je pozivdata.drop(labels, axis=0) ekvivalentan pozivu data.drop(index=labels).

Page 48: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 2. APROKSIMACIJA FUNKCIJA 42

[0,1] tako što oduzimamo prosečnu vrednost i podelimo disperzijom. Ukoliko vrši-mo standardizaciju podataka, moramo biti oprezni da ne napravimo propust. Naslici 2.5 prikazan je originalni skup podataka, zatim skup podataka standardizovanna ispravan i neispravan način. Ispravan postupak standardizacije podrazumevada se prvobitno podele podaci na skup za obučavanje i skup za evaluaciju, zatimda se odrede parametri za standardizaciju podataka na skupu za obučavanje, i nakraju koristimo srednju vrednost i standardnu devijaciju za normalizaciju skupa zaevaluaciju.

Do pogrešne standardizacije dolazi kada parametre za standardizaciju računa-mo nad celim skupom podataka, a zatim njih koristimo posebno nad podeljenih sku-povima. Ovime smo prekršili primarno načelo evaluacije modela jer smo koristiliinformaciju iz skupa za evaluaciju u fazi obučavanja modela5.

Slika 2.5: Gra čki prikaz primera skupa podataka (levo) i dva načina vršenja stan-dardizacije podataka — ispravno (sredina) i neispravno (desno). Pri ispravnoj stan-dardizaciji, podaci čuvaju prvobitnu strukturu, dok pri neispravnoj standardizacijidolazi do promene strukture podataka u skupu za evaluaciju.

Naredni fragment programskog koda prikazuje ceo postupak ispravne standar-dizacije:>>> x_train, x_test, y_train, y_test = model_selection.train_test_split(... x, y, test_size=0.33, random_state=7... )

>>> # Racunamo srednju vrednost i st. dev. na nivou kolona skupa za obucavanje>>> train_mean = x_train.mean(axis=0)>>> train_std = x_train.std(axis=0)

>>> # Koristimo dobijene parametre na oba skupa>>> x_train_norm = (x_train - train_mean)/train_std>>> x_test_norm = (x_test - train_mean)/train_std

Standardizacija podataka se može izvršiti i primenom klase StandardScaler izmodula preprocessing paketa sklearn. Objekat ove klase treba prvo trenirati nadskupom za obučavanje, a zatim ga iskoristiti za pretprocesiranje kao što smo touradili na prethodni način:

5Preciznije, u fazi pretprocesiranja podataka, ali svakako, pre faze evaluacije modela.

Page 49: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 2. APROKSIMACIJA FUNKCIJA 43

>>> from sklearn import preprocessing>>> scaler = preprocessing.StandardScaler()

>>> # Objekat scaler prvo treba da nauci srednju vrednost i st. dev. iz skupa za obucavanje>>> scaler.fit(x_train)

>>> # Primenjujemo standardizaciju>>> x_train = scaler.transform(x_train)>>> x_test = scaler.transform(x_test)

Sada prelazimo na obučavanje linearnog modela i njegovo ocenjivanje:>>> model = linear_model.LinearRegression()>>> model.fit(x_train, y_train)>>> y_pred = model.predict(x_test)>>> score = metrics.r2_score(y_test, y_pred)>>> print('R^2(linear):', score)R^2(linear): 0.44196328363432236

2.3.2 RegularizacijaDo sada smo razmatrali linearni model oblika 2.3. Algebarska forma rešenja pro-

blema linearne regresije (ATA)−1ATb jasno ukazuje na potencijalni problem. Matri-ca ATA ne mora biti invertibilna. Postoji više načina rešavanja ovog problema, ajedan od njih je regularizacija, odnosno rešavanje optimizacionog problema:

minβ

1N

N∑i=1

(fβ(xi)− yi)2 + λ ·Reg, (2.7)

gde je Reg izraz koji nazivamo regularizacioni izraz. Parametar α, koji nazivamoregularizacioni parametar, određuje značaj regularizacije u ovoj optimizaciji. Zavrednost λ = 0, regularizacija ne postoji. Povećavanjem vrednosti parametra λ,invertovana matrica postaje sve bolje uslovljena, ali se naravno regularizovani pro-blem udaljava od polaznog problema.

U zavisnosti od oblika regularizacionog izraza Reg dobijamo različite modele.Na primer, ako je

Reg = ||β||2,onda govorimo o klasičnom linearnom modelu sa regularizacijom.

2.3.3 Grebena regresijaRegularizacioni izraz oblika

Reg = β21 + β22 + . . .+ β2m, (2.8)

naziva se Grebeni regularizacioni izraz. Ako se rešava optimizacioni problem 2.7uz Grebeni regularizacioni izraz 2.8, tada govorimo o Grebenoj regresiji. Obično seβ0 se stavlja da bude podložan regularizaciji. Grebeni regresioni model je dostupankroz klasu Ridge(alpha=1.0, ...) modula linear_model paketa sklearn. Parametaralpha u ovoj implementaciji predstavlja recipročnu vrednost regularizacionog para-metra u izrazu 2.7, tako da treba biti oprezan pri interpretaciji modela.

Obučavanjem Grebenog regresionog modela nad skupom podataka Hitters saparametrom alpha=0.5 dobijamo nešto bolju evaluacionu ocenu od običnog linear-nog modela:

Page 50: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 2. APROKSIMACIJA FUNKCIJA 44

>>> ridge_model = linear_model.Ridge(alpha=0.5)>>> ridge_model.fit(x_train, y_train)>>> y_ridge_pred = ridge_model.predict(x_test)>>> score_ridge = metrics.r2_score(y_test, y_ridge_pred)>>> print('R^2(ridge):', score_ridge)R^2(ridge): 0.4473033820119713

2.4 Odabir modelaPitanje koje se prirodno postavlja jeste zašto smo za parametar alpha odabrali

baš vrednost 0.5. Možda bi se drugim odabirom vrednosti dobili bolji rezultati?Odgovor je — možda. Vrednosti regularizacionih parametra se određuju metodompokušaja dok se ne pronađu oni koji su najpodesniji.

Razni modeli imaju različite metaparametre. Do sada smo videli samo regula-rizacioni parametar kao metaparametar modela, ali postoje i drugi. Na primer,parametar tolerancije kod metoda potpornih vektora za regresiju, parametara ker-nela, izbor podskupa atributa, pa čak i izbor konkretnog algoritma. Sve mogućevrednosti ovih parametara određuju mrežu metaparametara (pri čemu se mi ogra-ničavamo na diskretan broj vrednosti). Svaki konkretan odabir vrednosti parame-tara iz mreže određuje jednu kon guraciju modela. Dakle, govorimo o načinu nakoji biramo model podešavanjem njegovih metaparametara, odnosno, određujemokon guraciju modela.

Vratimo se na prethodni primer sa Grebenom regresijom i parametrom alpha.Želimo da probamo razne vrednosti za regularizacioni parametar i na neki način daodredimo sa kojim parametrom alpha naš model predviđa najbolje. U tu svrhu ćemonapraviti (jednodimenzionalnu) mrežu metaparametara, za svaku od kon guracijaproceniti koji model daje najbolje predviđanje, a zatim evaluirati model sa upravotom kon guracijom:>>> # Formiranje mreze metaparametara>>> alphas = 10**np.linspace(10, -2, 100)*0.5>>> # Niz u kojem cuvamo procenjene greske za svaku konfiguraciju>>> errors = np.empty(0)

>>> # Za svaku konfiguraciju>>> for alpha in alphas:

... # Treniramo model

... r_model = linear_model.Ridge(alpha=alpha)

... r_model.fit(x_train, y_train)

... # Vrsimo ocenu greske

... y_pred_r = r_model.predict(x_test)

... error = metrics.mean_squared_error(y_test, y_pred_r)

... errors = np.append(errors, error)

>>> plt.xscale('log')>>> plt.plot(alphas, errors)>>> plt.show()

Na slici 2.6 prikazan je gra k zavisnosti grešaka od metaparametra alpha. Odre-dimo sada vrednost regularizacionog parametra koji daje najbolje rešenje i evalui-rajmo tu kon guraciju.

Page 51: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 2. APROKSIMACIJA FUNKCIJA 45

Slika 2.6: Gra k zavisnosti greške predviđanja i izbora metaparametra alpha.

>>> index = np.argmin(errors)>>> best_alpha = alphas[index]>>> best_alpha21.643806405415308

>>> final_model = linear_model.Ridge(alpha=best_alpha)>>> final_model.fit(x_train, y_train)>>> y_pred_fm = final_model.predict(x_test)>>> metrics.r2_score(y_test, y_pred_fm)0.43502694773837924

Primećujemo da smo dobili veću grešku nego kad smo trenirali model sa vred-nošću metaparametra 0.5. Gde smo pogrešili? Ono na šta bi uvek trebalo prvoda pomislimo jeste da li smo možda u nekom trenutku upotrebili podatke iz skupaza evaluaciju u fazi obučavanja modela. Model je zaista treniran nad skupom zaobučavanje i evaluiran nad skupom za evaluaciju. Dakle, tu nema pogreške. Među-tim, ako pogledamo fragment programskog koda u kojem smo određivali najboljukon guraciju, tu smo zaista koristili podatke iz skupa za evaluaciju. Isto kao štou fazi pretprocesiranja (na primer, kad smo radili standardizaciju podataka) nismosmeli da koristimo nikakvu informaciju iz skupa za evaluaciju, tako ni u fazi izboramodela ne smemo da prekršimo osnovno načelo evaluacije modela.

Rešenje se nalazi u podeli skupa podataka na tri skupa. Pored skupa za obučava-nje i skupa za evaluaciju, dodajemo skup za validaciju. Upravo pomoću ovog skupaćemo ocenjivati kon guracije u fazi izbora modela. Slika 2.7 prikazuje ispravan tokkonstrukcije modela sa tri skupa.

Sada prikazujemo celokupan, ispravan tok konstrukcije najboljeg kon gurabil-nog modela. Prvo radimo pretprocesiranje podataka:

>>> # Podela na tri skupa>>> x_train_validation, x_test, y_train_validation, y_test = model_selection.train_test_split(... x, y, test_size=0.33, random_state=7... )>>> x_train, x_validation, y_train, y_validation = model_selection.train_test_split(... x_train_validation, y_train_validation, train_size=0.66, test_size=0.34, random_state=7... )

Page 52: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 2. APROKSIMACIJA FUNKCIJA 46

Slika 2.7: Prikaz ispravnog toka faza izbora, obučavanja i evaluacije modela kori-šćenjem skupova za obučavanje, validaciju i evaluaciju.

>>> # Standardizacija za faze obucavanja i evaluacije>>> scaler1 = preprocessing.StandardScaler()>>> scaler1.fit(x_train_validation)>>> x_train_validation = scaler1.transform(x_train_validation)>>> x_test = scaler1.transform(x_test)

>>> # Standardizacija za fazu izbora modela>>> scaler2 = preprocessing.StandardScaler()>>> scaler2.fit(x_train)>>> x_train = scaler2.transform(x_train)>>> x_validation = scaler2.transform(x_validation)

Zatim vršimo izbor modela:>>> alphas = 10**np.linspace(10, -2, 100)*0.5>>> errors = np.empty(0)

>>> for alpha in alphas:... r_model = linear_model.Ridge(alpha=alpha)... r_model.fit(x_train, y_train)... y_pred_r = r_model.predict(x_validation)... error = metrics.mean_squared_error(y_validation, y_pred_r)... errors = np.append(errors, error)

>>> index = np.argmin(errors)>>> best_alpha = alphas[index]>>> best_alpha16.372745814388658

Page 53: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 2. APROKSIMACIJA FUNKCIJA 47

Konačno, vršimo obučavanje modela i njegovu evaluaciju:

>>> final_model = linear_model.Ridge(alpha=best_alpha)>>> final_model.fit(x_train_validation, y_train_validation)>>> y_pred_fm = final_model.predict(x_test)>>> metrics.r2_score(y_test, y_pred_fm)0.4868181789718439

Primećujemo da je konačna ocena poboljšana, ali ne zato što je to optimističnaocena, već upravo zato što smo vršili izbor modela i evaluaciju modela na ispravannačin.

2.5 Evaluacija modela i unakrsna validacijaDo sada smo videli najjednostavniju metodu za evaluaciju modela koja se na-

ziva evaluacija pomoću skupa za evaluaciju. Prisetimo se još jednom celokupnogpostupka. Ukupni podaci se dele na dva skupa — skup za obučavanje i skup zaevaluaciju. Skup za obučavanje je obićno veći — ugrubo dve trećine (ali ne nužno) ina njemu se odreduje model, koji se potom primenjuje na skup za evaluaciju, čimese dobijaju njegova predvidanja, koja se onda nekom merom kvaliteta mogu ocenitiu odnosu na tačne vrednosti ciljne promenljive.

Mana ovakvog pristupa ima više. Prvo, neke instance su izabrane da budu uskupu za obučavanje, a neke da budu u skupu za evaluaciju. Od načina na koji jeizvršena podela zavisiće i ocena kvaliteta. Za različite podele, ova ocena može zna-čajno varirati. Pritom, greška ocene može biti vrlo velika ako se skup za testiranjepristrasno izabere. Na primer, ako sadrži samo instance jedne klase ili, u sluča-ju regresije, ako sadži samo instance sa najvišom (ili najnižom) vrednošću ciljnepromenljive.

Odgovor na neke od prethodnih problema je tehnika K-struke unakrsne valida-cije (engl. K-fold cross-validation). Sprovodi se na sledeći način:

Procedura: UnakrsnaValidacija(D, K)Ulaz: D (skup podataka), K (broj slojeva)Izlaz: Score (ocena kvaliteta na celom skupu podataka)Započni

Slojevi ← Podeli podatke D na K približno jednakih slojeva6;for all Sloj in Slojevi do

Obučiti model na preostalih K− 1 slojeva;Izvršiti predviđanja dobijenim modelom na izabranom sloju Sloj;

end forScore ← Izračunata ocena kvaliteta na osnovu svih predviđanja na celom skupu D;

Završi proceduru

Očigledna prednost unakrsne validacije u odnosu na prethodni metod je manjavarijansa ocene greške usled toga što se ocena greške računa na većoj količini po-dataka. Drugim rečima, ocena je pouzdanija. S druge strane, model se ne obučavajednom, već K puta, što može biti vremenski zahtevno. Takode, postavlja se pitanjei izbora broja K. U praksi se za K koriste vrednosti 5 i 10.

Umodulu model_selection paketa sklearn dostupna nam je funkcija cross_val_score(estimator, X, y=None, ..., scoring=None, cv=None, ...), čiji su parametri: estimator

6Slojevi (engl. fold) predstavljaju disjunktne podskupove.

Page 54: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 2. APROKSIMACIJA FUNKCIJA 48

— objekat koji predstavlja model učenja, X — skup atributa, y — vektor ciljne pro-menljive, scoring — niska koja označava koja ocena kvaliteta se računa, i cv — brojslojeva (K u proceduri UnakrsnaValidacija).

Napomenimo da se ocena kvaliteta računa tek nakon što su izračunata sva pred-viđanja. U praksi se često pravi greška da se mere kvaliteta računaju na svakomsloju pojedinačno, pa se na kraju uproseče. To može biti podjednako dobro u slu-čaju nekih mera poput MSE koje predstavljaju zbirove, ali u slučaju drugih, poputR2, ne.

Ipak, s obzirom da funkcija cross_val_score vraća ocenu kvaliteta na svakomsloju, nama ne preostaje ništa drugo nego da uprosečimo MSE grešku dobijenu naslojevima. U narednom fragmentu koda vidimo da ova funkcija za grešku koristinegativne vrednosti MSE, te je zato rezultatu potrebno dodati predznak minus:>>> scores = model_selection.cross_val_score(... estimator=final_model, X=x, y=y, cv=10, scoring='neg_mean_squared_error'... )

>>> final_score = np.average(-scores)>>> final_score118697.5670924411

Vidimo da model pravi dosta veliku grešku u proseku, ali to ne bi trebalo da naszačudi, s obzirom da ni ocena kvaliteta dobijena R2 greškom nije dobra.

2.6 ZadaciZadatak 2.1 Proveriti da li je sistem[

1 22 3

] [xy

]=

[47

]numerički stabilan.

Zadatak 2.2 Odrediti vrednosti koe cijenata α i β tako da je funkcija f(x) = α +βsin(x) u smislu metode najmanjih kvadrata aproksimira skup tačaka {(2,2.6),(−1.22,−1.7), (8.32,2.5), (4.23,−1.6)}. Dati ocenu greške. Prikazati skup tačaka inacrtati rezultujuću funkciju.

Zadatak 2.3 Odrediti koe cijente c1, c2 i c3 funkcije f(x,y) = c1xy+c2x+c3 tako dau smislu metode najmanjih kvadrata aproksimira skup tačaka {((3,3),−1), ((5,3),1),((3,4),2)}. Dati ocenu greške.

Zadatak 2.4 Odrediti koe cijente a i b funkcije f(x) = a+bx ako je poznat skup pa-rova vrednosti {(0,1.2), (0.5,2.05), (1,2.9), (−0.5,0.1)}. Dati ocenu greške. Prikazatizadate parove vrednosti i nacrtati rezultujuću funkciju.

Zadatak 2.5 Odrediti da li se skup tačaka {(2.1,30.4), (0.5,1.51), (0.21,1.6),(−0.34,2.66), (−0.5,2.72)} bolje aproksimira polinomom trećeg ili četvrtog stepena.Odrediti vrednost tako dobijene aproksimacije u tački x = 1.23.

Zadatak 2.6 U primeru reklamiranja u medijima, uporediti ocenu modela predvi-đanja koji kombinuje sva tri atributa sa onim koji kombinuju neka dva atributa. Dali je moguće dobiti bolju ocenu predviđanja u smislu koe cijenta determinacije 2.5ako se koriste dva od tri atributa?

Page 55: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 2. APROKSIMACIJA FUNKCIJA 49

Zadatak 2.7 U odnosu na linearni regresioni model koji daje ocenu cene domovana osnovu odnosa broja učenika po nastavniku (PTRATIO) i ocene stope kriminala(CRIM), proveriti sledeće:

• da li se dobija bolji model predviđanja cena domova ukoliko se uzme u obzirsamo stopa kriminala?

• da li se dobija bolji model predviđanja cena domova ukoliko se uzme u obzir irastojanje od radnih centara (DIS)?

Zadatak 2.8 U primeru ocena cene domova, oceniti da li se dobija linearni modelkoji bolje predviđa ukoliko se prvobitno izvrši standardizacija podataka.

Zadatak 2.9 Odrediti grebeni regresioni model kojim se na osnovu svih karakteri-zacija doma predviđa njegova cena. Vrednost regularizacionog parametra odabratiiz mreže {0,0.01,0.1,1,10} tako da srednjekvadratna greška regresionogmodela navalidacionom skupu bude manja od zadate tacnosti eps = 27. Korišćenjem izraču-natog parametra oceniti grešku modela na test skupu.

Zadatak 2.10 Korišćenjem K-struke unakrsne validacije, uporediti modele koji surazmatrani u zadatku 2.7. Koji od ovih modela daje najbolju ocenu?

Page 56: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu
Page 57: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

Glava 3

Furijeove transformacije

Jedan od tipičnih primera Furijeovog reda je trigonometrijski Furijeov red, ko-ji počiva na sistemu sinusa i kosinusa različitih frekvencija (cos(kx) i sin(kx) zak = 0,1, ...). Staviše, periodične funkcije pod određenim uslovima mogu biti pro-izvoljno dobro aproksimirane linearnim kombinacijama funkcija iz ovog sistema.Furijeovi koe cijenti funkcije omogućavaju analizu signala u odnosu na frekvenci-je koje su u njemu zastupljene, odnosno spektar signala. Furijeova transformaci-ja upravo omogućava prevođenje reprezentacije funkcije iz vremenskog domena ufrekvencijski domen. Obrnuto se postiže inverznom Furijeovom transformacijom.Ilustracija je data na slici 3.1.

Slika 3.1: Ilustracija analiza signala (kojeg posmatramo u vremenskom domenu)pomoću Furijeove transformacije (u frekvencijskom domenu).

Neka je funkcija f integrabilna sa kvadratom i periodična na intervalu [a,b]. Tadase može razviti u Furijeov red:

f(t) = a02 +

∞∑k=1

(ak cos

(2πktb− a

)+ bk sin

(2πktb− a

)), (3.1)

gde važi

ak =2

b− a

∫ b

af(t)cos

(2πktb− a

)dt, k = 0,1,2, . . .

51

Page 58: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 3. FURIJEOVE TRANSFORMACIJE 52

bk =2

b− a

∫ b

af(t) sin

(2πktb− a

)dt, k = 1,2, . . .

Naravno, u praktičnim primenama, dostupne su nam konačne vrednosti tačaka,te Furijeov red u formuli 3.1 aproksimiramo konačnim Furijeovim redom, a inte-grale u formulama za koe cijente zamenjujemo odgovarajućim sumama.

Vazni pojmovi koji se susreću u literaturi koja pokriva ovu oblast su:

• fundamentalna (osnovna) kruzna frekvencija:

c(t) = cos(w0t), s(t) = sin(w0t)

• fundamentalna (osnovna) frekvencija:

c(t) = cos(2πf0t), s(t) = sin(2πf0t)

• harmonici:c(t) = cos(2πkf0t), s(t) = sin(2πkf0t)

Neka je funkcija f, periodična na periodu T0, tj. f(t + T0) = f(t). Harmonici sutalasi kod kojih su frekvencije umnošci neke fundamentalne frekvencije. Važi da seperiod T0 skraćuje kako se frekvencija povećava. Na slici 3.2 prikazan je osnovnitalas i odgovarajući drugi i treći harmonik.

Slika 3.2: Primer talasa i njegovog drugog i trećeg harmonika.

Kompleksni brojevi, kakve su i vrednosti Furijeove transformacije, su određenisvojim modulom i argumentom iliti fazom, odnosno, intenzitetom radijus vektora iuglom u kompleksnoj ravni, redom. Modul predstavlja intenzitet iliti amplitudu ne-ke frekvencije u nekom signalu, dok faza predstavlja pomeraj sinusne ili kosinusnefunkcije te frekvencije duž vremenske ose. Određivanje modula (ck) i faze (dk) datoje narednim formulama:

ck =√a2k + b2k, dk = arctan bk

ak.

Page 59: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 3. FURIJEOVE TRANSFORMACIJE 53

3.1 Uzorkovanje signalaU praksi se zbog diskretne prirode većine računskih mašina najčešće operiše sa

diskretnim reprezentacijama signala. Da bi se dobile ovakve reprezentacije, neop-hodno je proći kroz proceduru uzorkovanja signala i njegove kvantizacije. Ukolikoje, recimo, reč o zvučnim signalima, uzorkovanje predstavlja odabir vremenskihtrenutaka u kojima će se meriti jačina zvuka, a kvantizacija odabir numeričke ska-le za predstavljanje izmerenih vrednosti (na primer, vrednosti se mogu zapisivatipomoću jednog bajta, pomoću dva, itd).

Ako se na svakih Ts sekundi vrši odabir uzorka signala, tj. merenje relevantnihparametara signala, govori se o uzorkovanju signala sa frekvencijom uzorkovanjaFs. Veličina Ts se naziva period uzorkovanja. Veza koja važi između frekvencijeuzorkovanja i perioda uzorkovanja je Fs = 1/Ts. Ova veličina se izražava u Hercima.Ako je broj uzoraka jednak N, tada je ukupno vreme uzorkovanja T = N · Ts.

Uvedimo još dva pojma: frekvencijska rezolucija predstavlja razliku u frekven-cijama između svaka dva susedna uzorka, odnosno veličinu Δf = Fs/N, a k-ta fre-kvencijska korpica predstavlja k-ti podeok na gra ku zavisnosti amplitude od fre-kvencije, pri čemu važi da k-tom podeoku odgovara frekvencija Δf · k.

Ukoliko postoji neka frekvencija fb za koju važi fb > f gde f predstavlja frekven-ciju signala izraženu u Hercima, kaže se da je signal ograničen, a frekvencija fbse zove granična frekvencija. Informacija o ograničenosti signala je osobito važnapri izboru frekvencije uzorkovanja jer se prema Najkvistovoj teoremi signal moževerodostojno reprodukovati samo ako je frekvencija uzorkovanja više od dva putaveća od granične frekvencije.

Jednostavan primer Posmatrajmo signal s(t) = 2 · sin(2πt) + 3 · sin(2 · 22πt) + ϵ,gde je ϵ šum. Odavde možemo da zaključimo da je f0 = 1 i f1 = 22. Takođe, jasnoje da imamo vrhove u tačkama 1 i 22 visine 2 i 3, redom. Slično važi za tačke −1i −22. Neka treba pokriti frekvencije do 30Hz. I neka ukupno vreme uzorkovanjasignala iznosi 100 sekundi. Treba uraditi sledeće:

• nacrtati signal s(t) u vremenskom domenu,

• nacrtati signal s(t) u frekvencijskom domenu,

• konstruisati lter koji otklanja šum i primenom njega rekonstruisati signal uvremenskom domenu.

Za početak, uvedimo osnovne biblioteke u okruženje:>>> import numpy as np>>> from matplotlib import pyplot as plt

De nisaćemo signal kao funkciju od t na osnovu zadate formule, pri čemu ćemošum generisati iz normalne raspodele N (0,1). Na gra ku koji prikazuje signal s(t)u vremenskom domenu postavljamo limit na 5 sekundi zbog pogodnijeg prikaza.Rezultat izvršavanja narednog programskog koda dat je na slici 3.3.def signal(t):

n = t.shape[0]noise = 2*np.random.randn(n)return 2*np.sin(2*np.pi*t) + 3*np.sin(2*22*np.pi*t) + noise

Fs = 60T = 100

Page 60: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 3. FURIJEOVE TRANSFORMACIJE 54

N = Fs * Tt = np.linspace(0, 100, N)s = signal(t)

# Skracujemo prikazivanje na 5 sekundi zbog prikazaplt.xlim(0, 5)plt.plot(t, s)plt.show()

Slika 3.3: Gra k vremenskog domena signala s(t) = 2 · sin(2πt)+3 · sin(2 ·22πt)+ ϵ,gde je ϵ ∼ N (0,1).

Da bismo prikazali zadati signal u frekvencijskom domenu, morati izračunativrednosti Furijeovih koe cijenata. U tu svrhu nam koristi funkcija fft(a, ...) mo-dula fft paketa numpy. Njen argument predstavljaju vrednosti signala čiju transfor-maciju treba izvršiti. Rezultat ove funkcije je niz kompleksih brojeva — Furijeovihkoe cijenata:

from numpy import fft

c = fft.fft(s)

U našem primeru, niz c određuje vrednosti na y-osi. Vrednosti na x-osi možemodobiti pozivanjem funkcije fftfreq(n, d=1.0), koja vraća vrednosti frekvencijskihkorpica koji odgovaraju koe cijentima dobijenim pozivom funkcije fft. Njeni ar-gumenti su broj uzoraka n i recipročna vrednost frekvencije uzorkovanja d. Ovogaputa, umesto korišćenja funkcije plt.plot, za prikaz signala s(t) u frekvencijskomdomenu koristićemo repićasti dijagram (engl. stem plot) na kojem su eksplicitnooznačene tačke koje odgovaraju visinama za svaki podeok na x-osi1. Rezultat izvr-šavanja narednog programskog koda dat je na slici 3.4.

freq = fft.fftfreq(N, 1.0/Fs)

1Ovakvo označavanje tačaka daje utisak kraja "repa" vrednosti funkcije u odgovarajućem podeoku,te otuda ovakav naziv dijagrama.

Page 61: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 3. FURIJEOVE TRANSFORMACIJE 55

# Prikazujemo amplitudu za svaki stoti Furijeov koeficijent# zbog velike gustine niskoamplitudnih koeficijenataplt.stem(freq[::100], np.abs(c)[::100])plt.show()

Slika 3.4: Gra k frekvencijskog domena signala s(t) = 2·sin(2πt)+3·sin(2·22πt)+ϵ,gde je ϵ ∼ N (0,1).

Napomenimo da smo na isti način mogli generisati repićasti dijagram zavisnostifaze od frekvencije tako što bismo koristili funkciju np.angle(c) umesto np.abs(c) uprethodnom fragmentu koda.

Iz gra ka na slici 3.4 možemo zaključiti da bi naš lter za otklanjanje šuma mo-gao da sačuva samo one amplitude koje su iznad, na primer, 1000. Takođe, dabismo vratili funkciju nazad u vremenski domen, moramo izvršiti inverznu Furije-ovu transformaciju. To je moguće izvršiti pozivanjem funkcije ifft(a, ...), čiji jeargument niz Furijeovih koe cijenata. Povratna vrednost ove funkcije je niz kom-pleksnih brojeva, ali mi možemo ignorisati njihove imaginarne delove jer je inver-zna Furijeova transformacija od Furijeove transformacije realne funkcije, zapravorealna funkcija. Rezultat izvršavanja narednog programskog koda dat je na slici3.5.# filter za odsecanje sumamask = np.abs(c) > 1000filtered_c = c * mask

# inverzna fftc_inv = fft.ifft(filtered_c)

plt.xlim(0, 5)plt.plot(t, s)plt.plot(t, c_inv.real, color='purple')plt.show()

Page 62: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 3. FURIJEOVE TRANSFORMACIJE 56

Slika 3.5: Gra k frekvencijskog domena signala s(t) = 2·sin(2πt)+3·sin(2·22πt)+ϵ,gde je ϵ ∼ N (0,1) (plavo) i signala dobijenog od signala s(t) eliminacijom šuma(ljubičasto).

3.2 SpektrogramSpektrogram je vizualna reprezentacija spektra frekvencija zvuka ili drugih sig-

nala kako variraju kroz vreme. Spektrogrami se intenzivno koriste u muzičkom,radarskom, seizmološkom domenu, u domenu procesiranja govora i drugim. Poka-zaćemo kako se može konstruisati spektrogram korišćenjem Furijeove transforma-cije. U našem primeru, na x-osi će biti prikazane frekvencije, a na y-osi vreme. Unekim drugim implementacijama ose su obrnute, te treba voditi računa. U ovomprimeru biće korišćena zvučna datoteka bonobo_towers.wav dužine 30 sekundi, uzor-kovana na 44100Hz.

Prvo, uvedimo neke biblioteke u okruženje koje će nam biti od značaja. Poredonih koje smo do sada uvodili, biće nam neophodanmodul signal biblioteke scipy, zaobradu signala. Zatim, modul wavfile biblioteke scipy.io koristićemo za učitavanjezvučnog signala u .wav formatu. Konačno, koristićemo displaymodul paketa IPythonda bismo mogli da predamo kontrole zvučnog zapisa okruženju2:>>> # obrada signala>>> from scipy import signal>>> # rad sa wav formatima>>> from scipy.io import wavfile>>> # prikazivanje raznih formata>>> from IPython import display

Predavanje kontrole radnom okruženjumože se izvršiti pozivanjem funkcije display.Audio(...,url=None, ...), koja učitava zvučni signal sa lokacije zadate parametrom url. Na-redni poziv funkcije u Jupyter Notebook okruženju generiše kontrolu zvučnog zapi-sa prikazanu na slici 3.6.

2U zavisnosti od okruženja, kontrole se mogu prikazati na različite načine. Ukoliko želimo da iskori-stimo ovu funkcionalnost, potrebno je da pokrenemo odgovarajući fragment koda u, na primer, JupyterNotebook okruženju. Nažalost, nećemo biti u mogućnosti da proizvedemo kontrole u komandnoj liniji.

Page 63: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 3. FURIJEOVE TRANSFORMACIJE 57

>>> display.Audio(url='bonobo_towers.wav')

Slika 3.6: Prikaz kontrola u Jupyter Notebook okruženju nakon učitavanja zvučnogsignala pomoću funkcije IPython.display.Audio.

Učitavanje zvučnog signala za obradu (umesto za puštanje) može se obaviti pozi-vanjem funkcije wavfile.read(filename, ...), čiji je argument lokacija datoteke kojasadrži zvučni zapis. Povratne vrednosti ove funkcije su frekvencija uzorkovanja i(potencijalno višedimenzioni) niz koji sadrži zvučne podatke:>>> Fs, data = wavfile.read('bonobo_towers.wav')>>> Fs44100>>> data.shape(1323000, 2)

Primetimo da je niz podataka dvodimenzionalan, što je slučaj ukoliko je zvukstereo tipa. S obzirom da ćemo mi raditi na jednom kanalu, možemo uprosečitipodatke na oba kanala, po vrstama:>>> data = data.mean(axis=1)

Za dalje će nam biti potrebne neke informacije iz podataka. Odredimo broj uzo-raka, trajanje zvučnog signala, i dužinu fragmenata:>>> # Broj uzoraka (potreban nam je samo za odredjivanje duzine trajanja)>>> N = data.shape[0]>>> # Duzina trajanja signala (vazna nam je zbog podeoka na y-osi)>>> duration = N/Fs>>> duration30.0>>> # Fragmenti su po pola sekunde>>> # Koristimo istu promenljivu N jer nam broj uzoraka vise nije potreban>>> N = Fs // 2>>> N22050

Naredni fragment koda prikazuje odgovarajuće izračunavanje koje vršimo zajedan fragment. Takođe, opredeljujemo se za skup do 1000 frekvencija, i prikazujerepićasti dijagram (slika 3.7):>>> t = np.linspace(0, 0.5, N)>>> samples = data[:N]>>> c = fft.fft(samples)>>> freq = fft.fftfreq(N, 1/Fs)

>>> # Operator * deluje kao pokoordinatna logicka konjunkcija>>> # nad vektorima Bulovih promenljivih>>> mask = (freq > 0) * (freq < 1000)>>> c_filtered = c[mask]>>> freq_filtered = freq[mask]>>> plt.stem(freq_filtered[::100], np.abs(c_filtered[::100]))>>> plt.show()

Page 64: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 3. FURIJEOVE TRANSFORMACIJE 58

Slika 3.7: Prikaz jednog fragmenta zvučnog zapisa bonobo_towers.wav u frekvencij-skom domenu, ltriran na skup do 1000 frekvencija.

Podatke koje ćemo vizualizovati ćemo čuvati u matrici, koju ćemo zatim popuniti.Matricu takođe možemo shvatiti kao niz fragmenata, te ćemo izračunavanja i vršitiza svaki fragment. Za početak, konstruišimo matricu adekvatnih dimenzija:

>>> spectrogram_frequencies = freq_filtered.size>>> time_segment = 0.5>>> spectrogram_time = duration // time_segment

>>> spectrogram = np.zeros((spectrogram_time, spectrogram_frequencies))

3.2.1 Prozorske funkcije

Razvoj u Furijeov red i diskretna Furijeova transformacija pretpostavljaju peri-odičnost signala i diksretan frekvencijski domen. Realističnost ovih pretpostavki upraksi je upitna. Signal najčešće nije periodičan. Cak i ako jeste, ǎko nije savrše-no uzorkovan u dužini perioda, dobijeni uzorak neće imati neprekidno periodičnoponašanje i očekuju se prekidi ukoliko se uzorak periodično nadoveže. Ovo je prika-zano slikom 3.8. Ti prekidi dovode do pojave visokih frekvencija u frekvencijskomspektru, koje nisu zaista prisutne u spektru originalnog signala.

Kako bi se ovaj problem ublažio, pribegava se modi kovanju signala. Jedan na-čin za to predstavljaju prozorske funkcije (engl. window functions), kojima se uvremenskom domenu množi polazni signal tako da se u krajevima potiskuje ka nuli.Prozorske funkcije obično zadovoljavaju određena jednostavna svojstva kao da susvuda izvan nekog intervala jednake nuli i da maksimum dostižu na polovini togintervala na kojem su različite od nule. Neke od prozorskih funkcija koje se koristeu praksi su prikazane na slici 3.9, pri čemu je prikaz generisan narednim program-skim kodom:

Page 65: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 3. FURIJEOVE TRANSFORMACIJE 59

Slika 3.8: Primer savršenog (gore) i nesavršenog (dole) uzorkovanja signala.

Slika 3.9: Primer prozorskih funkcija: Blekmanova funkcija (crveno), Hanova funk-cija (plavo), Hamingova funkcija (zeleno) i Kaizerova funkcija (žuto).

Page 66: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 3. FURIJEOVE TRANSFORMACIJE 60

>>> plt.plot(np.arange(0, N), signal.windows.blackman(N), color='red')>>> plt.plot(np.arange(0, N), signal.windows.hann(N), color='blue')>>> plt.plot(np.arange(0, N), signal.windows.hamming(N), color='green')>>> plt.plot(np.arange(0, N), signal.windows.kaiser(N, 5), color='yellow')>>> plt.show()

Za naše potrebe može poslužiti bilo koja prozorska funkcija. Neka je to, na pri-mer, Hamingova funkcija. Sve funkcije u modulu signal.windows imaju parametarM koji određuje širinu prozora, odnosno, broj tačaka uzorkovanja. Kako mi radimopo fragmentima, to prozorsku funkciju konstruišemo sa argumentom N:

>>> window = signal.windows.hamming(N)

Sada, konačno, prelazimo na izračunavanje spektrograma i njegovo iscrtavanje(slika 3.10):

>>> # Sada radimo za sve fragmente da popunimo matricu, tj. niz fragmenata>>> for n in range(spectogram_time):... # Vrsimo isecanje uzoraka iz skupa podataka koji se odnosi na vremenski domen n... samples = data[n*N : (n+1)*N]... c = fft.fft(samples) * window... c_filtered = c[mask]... # Na nivou spektrograma se vidja logaritamska skala... fragment = np.log(np.abs(c_filtered))... # Popunjavamo matricu za dati fragment... spectrogram[n, :] = fragment

>>> # Parametar extent odredjuje donji levi i gornji desni ugao prikaza>>> # Redosled elemenata u torki je (left, right, bottom, top)>>> # Parametar aspect postavljamo na 'auto' da bi parametar extent dosao do izrazaja>>> plt.imshow(spectogram, extent=(0, 1000, 0, duration), aspect='auto')>>> plt.show()

Slika 3.10: Spektrogram zvučnog zapisa bonobo_towers.wav.

Page 67: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 3. FURIJEOVE TRANSFORMACIJE 61

Očekivano, modul signal poseduje ugrađenu funkciju spectrogram(x, fs=1.0, window=('tukey',0.25), ...) kojom možemo postići isti efekat. Njeni parametri su: x — vremenskaserija izračunatih vrednosti signala, fs — frekvencija uzorkovanja, window — vre-menska funkcija, zadata kao niska ili sekvenca (u slučaju da prozorska funkcija imadodatne parametre). Funkcija izračunava spektrogram koristeći Furijeove trans-formacije i ima tri povratne vrednosti: f — niz frekvencija uzorkovanja, t — nizvremenskih segmenata i Sxx — spektrogram signala x. Naredni fragment program-skog koda izračunava spektrogram zvučnog zapisa bonobo_towers.wav i prikazuje gatoplotnom mapom (slika 3.11):>>> f, t, s = signal.spectrogram(data, Fs)>>> plt.pcolormesh(t, f, np.log(s))>>> plt.colorbar()>>> plt.show()

Slika 3.11: Spektrogram zvučnog zapisa bonobo_towers.wav dobijen korišćenjemfunkcije scipy.signal.spectrogram.

3.3 Obrada slikaFurijeova transformacija se intenzivno koristi u obradi slika. U tom slučaju je

potrebno de nisati je u dve dimenzije. U diskretnom slučaju, de niše se kao:

f(l,m) =1PQ

P−1∑j=0

Q−1∑k=0

f(j,k) · e2πi(jl/P+km/Q) (3.2)

f(j,k) =P−1∑l=0

Q−1∑m=0

f(l,m) · e−2πi(jl/P+km/Q) (3.3)

Za učitavanje slika biće nam potreban modul Image paketa PIL. Jednostavno uči-tavanje slike može se postići pozivom funkcije Image.open(fp, mode='r'), čiji je argu-

Page 68: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 3. FURIJEOVE TRANSFORMACIJE 62

ment fp naziv slike koju učitavamo. Funkcija vraća objekat tipa PIL.Image.Image, nakoji ćemo u nastavku referisati samo kao Image. Nad ovim tipom su de nisane ope-racije iz tabele 3.1. U ovoj sekciji ćemo raditi sa dve slike, dance.jpg i keep_calm.png,koje su prikazane na slici 3.12.

Tabela 3.1: Neke operacije de nisane nad tipom PIL.Image.Image.

Operacija Primeri operacija nad datim tipom

show() Pokreće podrazumevani pregledač slika.size Izračunava veličinu slike.

resize(size, ...) Pravi kopiju slike nove veličine zadate sekvencom size.

histogram()Izračunava histogram za sliku.Histogram se izračunava kao lista broja piksela,jedan za svaki piksel u originalnoj slici.

convert(mode, ...) Izračunava konvertovanu verziju slike u modu mode.

Slika 3.12: Slike dance.jpg (levo) i keep_calm.png (desno).

Kao i do sada, navikli smo da radimo sa numeričkim podacima, tako da je za po-trebe obrade naših slika potrebno da se one konvertuju u odgovarajuće sekvencenumeričkih vrednosti. Srećom, ovo se jednostavno postiže eksplicitnim kastova-njem u, na primer, np.array:

>>> import numpy as np>>> from matplotlib import pyplot as plt>>> from PIL import Image

>>> img = np.array(Image.open('dance.jpg'))>>> img.shape(407, 570, 3)

Page 69: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 3. FURIJEOVE TRANSFORMACIJE 63

S obzirom da je naša slika u modu RGB, to je niz img trodimenzionalan. Za svakipiksel se pamte vrednosti crvene, zelene i plave boje. Mi ćemo za početak raditisa crno-belim slikama, te je potrebno nakon učitavanja slike izvršiti odgovaraju-ću konverziju u crno-beli mod. To se može postići pozivanjem funkcije convert saargumentom 'L':

>>> img = np.array(Image.open('dance.jpg').convert('L'))>>> img.shape(407, 570)

Primećujemo da smo informacije o bojama zameniti količinom crne boje u sva-kom od piksela. Kao što se može primetiti iz formula 3.2, rezultat primene Furijeo-ve transformacije nad slikom je, takođe, slika. Pokažimo ovo na primeru prethodnoučitane slike dance.jpg. Furijeova transformacija za dvodimenzionalni signal se do-bija pozivom funkcije fft.fft2(a), čiji je smisao isti kao i kod funkcije fft.fft, sarazlikom da se transformacija vrši u dve dimenzije.

>>> from numpy import fft

>>> c = fft.fft2(img)>>> plt.imshow(20*np.log(np.abs(c)), cmap='gray')>>> plt.show()

Logaritamsku skalu množimo brojem 20 da bismo dobili skalu u decibelima. Re-zultat primene se nalazi na slici 3.13 (levo). Ipak, češće se ovaj prikaz modi kujetako da se vrednost koe cijenta f(0,0) nađe u centru slike. Da bismo ovo postigli,koristićemo funkciju fft.fftshift(x), čiji je argument x niz vrednosti koe cijenatadobijenih funkcijom fft.fft2. Rezultat primene se nalazi na slici 3.13 (desno).

>>> c_shifted = fft.fftshift(c)>>> plt.imshow(20*np.log(np.abs(c_shifted)), cmap='gray')>>> plt.show()

Slika 3.13: Furijeova transformacija slike dance.jpg u crno-belom modu: slika dobi-jena samo primenom funkcije fft.fft2 (levo) i ista slika sa transliranim koe cijen-tima tako da se vrednost koe cijenta f(0,0) nalazi u centru slike (desno).

Primetimo da smo u oba slučaja koristili module koe cijenata umesto vredno-sti njihovih faza. Za rad sa slikama se najčešće koristi spektar amplituda, iako jemoguće raditi nad spektrom faza.

Page 70: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 3. FURIJEOVE TRANSFORMACIJE 64

3.3.1 Zamućivanje slike odsecanjem visokih frekvencijaOdsecanje koe cijenata u slučaju obrade slika se izvršava postavljanjem vred-

nosti odgovarajućih koe cijenata na vrednost 0. Zbog toga, prvi korak koji trebauraditi jeste kreiranje matrice istih dimenzija kao i Furijeova transformacija pola-zne slike, pri čemu su njene vrednosti 0 tamo gde se vrši odsecanje, a 1 u ostalimvrednostima. Recimo da smo odabrali da sačuvamo one koe cijente koji su na uda-ljenosti 50 od centra, po osama:>>> mask = np.zeros(img.shape)>>> x_center = img.shape[0] // 2>>> y_center = img.shape[1] // 2

>>> number_of_ones = 50>>> mask[x_center-number_of_ones : x_center+number_of_ones,... y_center-number_of_ones : y_center+number_of_ones] = 1

Sada ćemo iskoristiti dobijenu matricu da bismo dobili ltrirane koe cijente.Kao što je funkcija fft.ifft vršila inverznu Furijeovu transformaciju funkcije fft.fftu jednodimenzionalnom slučaju, tako i funkcija fft.ifft2(a) vrši inverznu Furijeovutransformaciju funkcije fft.fft2 u dvodimenzionalnom slučaju. Važno je napome-nuti da funkcija fft.ifft2 očekuje raspored koe cijenata kao na slici 3.13 (levo),tako da je neophodno izvršiti inverznu transformaciju transliranja pomoću funkcijefft.ifftshift(x). Rezultat primene se nalazi na slici 3.14.>>> # Prisetimo se da je * pokoordinatno mnozenje matrica>>> c_shifted_filtered = c_shifted * mask>>> c_filtered = fft.ifftshift(c_shifted_filtered)>>> c_final = fft.ifft2(c_filtered)

>>> # Konstruisemo objekat tipa Image da bismo ga prikazali>>> blured_image = Image.fromarray(np.abs(c_final))>>> blured_image.show()

Ovako konstruisan objekat Image moramo da konvertujemo u crno-beli mod dabismo mogli da ga sacuvamo kao sliku u .png formatu. Ukoliko želimo samo da gaprikažemo pomoću funkcije show, onda nije potrebno da vršimo konverziju. Inače,možemo iskoristiti funkciju Image.save(fp), na primer:>>> blured_image.convert('L').save('dance_blured.png')

3.3.2 Određivanje kontura odsecanjem niskih frekvencijaIsti postupak ćemo iskoristiti, sa razlikom da ćemo vršiti odsecanje niskih fre-

kvencija, u cilju određivanja kontura, odnosno, ivica na slici. Rezultat primene senalazi na slici 3.15.>>> mask = np.ones(img.shape)

>>> x_center = img.shape[0] // 2>>> y_center = img.shape[1] // 2

>>> number_of_zeros = 50>>> mask[x_center-number_of_zeros : x_center+number_of_zeros,... y_center-number_of_zeros : y_center+number_of_zeros] = 0

Page 71: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 3. FURIJEOVE TRANSFORMACIJE 65

>>> c_shifted_filtered = c_shifted * mask>>> c_filtered = fft.ifftshift(c_shifted_filtered)>>> c_final = fft.ifft2(c_filtered)

>>> strong_image = Image.fromarray(np.abs(c_final))>>> strong_image.show()

Slika 3.14: Zamućena crno-bela verzija slike dance.jpg dobijena odsecanjem visokihfrekvencija.

Slika 3.15: Prikaz kontura crno-bele verzije slike dance.jpg dobijen odsecanjem ni-skih frekvencija.

Page 72: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 3. FURIJEOVE TRANSFORMACIJE 66

3.3.3 KonvolucijaSvaka operacija ∗ koja se može de nisati kao

(f ∗ g)(i) =n−1∑j=0

f(j)g(i− j) i = 0,1, . . . ,n− 1,

pri čemu se podrazumeva da je gk = gn+k, ukoliko je k < 0, naziva se konvolucija(engl. convolution). Takode, konvolucija se može de nisati u više dimenzija, naprimer dve:

(f ∗ g)(i, j) =m−1∑k=0

n−1∑l=0

f(k, l)g(i− k, j− l),

sa istom konvencijom indeksiranja kao u jednodimenzionalnom slučaju.Konvolucija se intenzivno koristi u obradi signala. Jedna funkcija u konvoluciji

predstavlja signal, a druga je obično jednostavnija i predstavlja speci čnu funkcijukojom se postiže neki efekat transformacije signala i naziva se lterom. Konvolucijase može jednostavno shvatiti na sledeći način. Filter se predstavlja jednostavnommatricom koja deluje na svaki piksel. Delovanje se vrši tako da vrednosti u matriciltera otežavaju vrednosti piksela na slici koje lter pokriva. Zatim se nad takvim,

otežanim vrednostima primeni neka operacija agregacije, na primer, sumiranje iliuprosečavanje, i dobijena vrednost predstavlja vrednost piksela nad kojim je matri-ca postavljena, odnosno vrednost središnjeg piksela (videti sliku 3.16).

Slika 3.16: Konvolucija u obradi slika.

Veliki broj prede nisanih ltera nam je dostupan kroz modul ImageFilter paketaPIL. Na primer, lter zamućivanjamožemo dobiti na naredni način (rezultat primenese nalazi na slici 3.17 (levo)):

Page 73: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 3. FURIJEOVE TRANSFORMACIJE 67

>>> from PIL import ImageFilter

>>> img = Image.open('keep_calm.png').convert('L')>>> blur_filter = ImageFilter.BLUR()>>> img_filtered = img.filter(blur_filter)>>> img_filtered.show()

Takođe, neke prede nisane ltere možemo dobiti i kroz modul ndimage paketascipy. Na primer, poznat je Sobelov lter koji određuje konture na slici (rezultatprimene se nalazi na slici 3.17 (desno)):>>> from scipy import ndimage

>>> img_sobel = ndimage.filters.sobel(img)>>> img_sobel = Image.fromarray(img_sobel)>>> img_sobel.show()

Slika 3.17: Primena nekih bibliotečkih ltera nad crno-belom verzijom slikekeep_calm.png — PIL.ImageFilter.BLUR() (levo) i scipy.ndimage.filters.sobel (de-sno).

Ukoliko želimo da primenimo lter koji smo mi de nisali, to možemo učiniti ko-rišćenjem funkcije ndimage.convolve(input, weights, output=None, mode='reflect',cval=0.0, origin=0). Njeni parametri su:

• input — ulazni signal (slika) koji se ltrira;

• weights — lter koji želimo da primenimo;

• output — ndarray sekvenca u koju se čuvaju vrednosti nakon ltriranja;

• mode—način na koji se tretiraju ivični pikseli nad kojima nemože direktno da seprimeni lter. Podrazumevano se re ektuju vrednosti u ulaznom signalu u od-nosu na ivicu ose. Može uzeti vrednosti iz skupa 'reflect', 'constant', 'nearest', 'mirror', 'wrap';

Page 74: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 3. FURIJEOVE TRANSFORMACIJE 68

• cval — vrednost kojom će popunjavaju pikseli izvan ivica ulaznog signala uko-liko se za vrednost parametra mode odabere 'constant';

• origin — sekvenca kojom se određuje na koji piksel se smešta vrednost lte-ra u odnosu na piksel nad kojim je lter postavljen (tj. u odnosu na centar).Podrazumevana vrednost 0 je ekvivalentna vrednosti (0,)*input.ndim.

Povratna vrednost ove funkcije je rezultat primene konvolucije input i weights.Uglavnom su nam ta dva parametra i dovoljna, dok drugi služe za no podešavanje.

3.3.4 Postavljanje vodenog žigaPretpostavimo da imamo neku sliku koju želimo da zaštitimo od neodobrenog

korišćenja drugih ljudi. Ovakav zahtev je vrlo čest i jedan od rešenja jeste posta-vljanje vodenog žiga (engl. watermark) na sliku. Postoje dve vrste vodenog žiga:vidljivo utisnut i utisnut u frekvencijski domen. Vodeni žig koji je vidljivo utisnut sejasno vidi na slici, odnosno, utiče na izgled slike u domenu u kojem se ona i najče-šće posmatra3. Vodeni žig utisnut u frekvencijski domen ne utiče4 na vidljivi domenslike.

U ovom primeru, primenićemo vodeni žig utisnut u frekvencijski domen nadcrno-belom verzijom slike keep_calm.png. Biramo da vodeni žig bude niz nasumičnihtačaka u formi diskretnog kruga. De nisaćemo tri funkcije:

• random_vector(seed, length), koja generiše niz od kojeg konstruišemo vodenižig;

• make_watermark(image_shape, radius, seed, length=50, intensity=1), koja gene-riše vodeni žig veličine image_shape, u formi kruga poluprečnika radius sa cen-trom u sredini slike. Parametri seed i length se koriste za primenu prethodnefunkcije. Parametar intensity određuje vidljivost vodenog žiga u frekvencij-skom domenu. Na slici 3.18 dat je primer vodenog žiga koji se dobija pozivomfunkcije make_watermark(img.shape, 100, 17, intensity=255), gde je img objekattipa Image koji sadrži sliku keep_calm.png.

• add_watermark(img, watermark, alpha), koja dodaje vodeni žig watermark na sli-ku img u intenzitetu alpha.

Narednim fragmentom koda utiskamo prethodno opisani vodeni žig nad slikomkeep_calm.png. Rezultat primene se nalazi na slici 3.18 (levo). Primetimo da nemavidljive razlike u zaštićenoj slici.>>> def random_vector(seed, length):... np.random.seed(seed)

... return np.array([np.random.choice([0,1]) for _ in range(length)])

>>> def make_watermark(image_shape, radius, seed, length=50, intensity=1):... watermark = np.zeros(image_shape)... center_x = image_shape[0] // 2... center_y = image_shape[1] // 2... vector = random_vector(seed, length)

3Za zvuk smo ovaj domen nazivali vremenski; za slike je nešto teže tako jednostavno imenovati odgo-varajući domen. U daljem tekstu ćemo ovaj domen nazivati vidljivi domen.

4Preciznije, utiče dovoljno malo da ga prosečno ljudsko oko ne primeti.

Page 75: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 3. FURIJEOVE TRANSFORMACIJE 69

... for i in range(length):

... # Moramo da kastujemo vrednosti u tip int

... # jer na nivou slike imamo int vrednosti

... x = center_x + int(radius * np.cos(2*np.pi*i/length))

... y = center_y + int(radius * np.sin(2*np.pi*i/length))

... if vector[i] == 1:

... watermark[x, y] = intensity

... return watermark

>>> watermark = make_watermark(img.shape, 100, 17, intensity=200)

>>> def add_watermark(img, watermark, alpha):... c = fft.fft2(img)... c_shifted = fft.fftshift(c)... c_protected = c_shifted + alpha*watermark

... # Modifikovane koeficijente vracamo u odgovarajuci zapis,

... # primenjujemo inverznu Furijeovu transformaciju

... # i uzimamo vrednosti amplituda da bismo mogli da konvertujemo u Image tip

... return np.abs(fft.ifft2(fft.ifftshift(c_protected)))

>>> img_protected = add_watermark(img, watermark, 100)>>> img_protected = Image.fromarray(img_protected)>>> img_protected.show()

Slika 3.18: Prikaz vodenog žiga generisanog funkcijom make_watermark (levo) i nje-gova primena nad crno-belom verzijom slike keep_calm.png (desno).

Page 76: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 3. FURIJEOVE TRANSFORMACIJE 70

3.4 ZadaciZadatak 3.1 Ako je frekvencija uzorkovanja signala 10KHz i ako je dobijeno N =1024 uzoraka, odrediti frekvencijsku rezoluciju i najveću frekvenciju koja se poja-vljuje u spektru.

Zadatak 3.2 Na osnovu uzorkovanja signala oblika x(t) = cos(2πft) u trajanju od0.5 sekundi dobijene su 32 vrednosti ciji je gra k prikazan u gornjem delu slike 3.19,a diskretnom Furijeovom transformacijom signala, dobijena je spektralna analizaprikazana na donjem delu iste slike.

1. Kolika je frekvencija uzorkovanja fs signala x(t)?

2. Kolika je osnovna (fundamentalna) frekvencija signala f?

3. Nacrtati frekvencijski spektar za signal čija je osnovna frekvencija f+1 i obja-sniti promene do kojih se dolazi.

Slika 3.19: Slika uz zadatak 3.2.

Zadatak 3.3 Napraviti lter koji odseca 10% najvećih i najmanjih frekvencija sig-nala x(t) = 2 · sin(200πt) koji se uzorkuje frekvencijom od 800Hz u trajanju od 2sekunde.

Zadatak 3.4 Uporediti rezultate dobijene primenom Sobelovog ltera (slika 3.17(desno)) i primenom Laplasovog ltera zadatog matricom0 1 0

1 −4 10 1 0

.

Page 77: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

Glava 4

Numerička linearna algebra

U poglavlju 2 dali smo uvod u elementarne pojmove linearne algebre i prika-zali smo njihove osnovne načine korišćenja za rešavanje različitih problema. Ciljovog poglavlja jeste da predstavimo neke naprednije probleme i metode njihovogrešavanja. Započnimo ovo poglavlje temom o dekompoziciji matrica.

4.1 Dekompozicija matricaDekompozicije matrica igraju veliku ulogu u numeričkom rešavanju osnovnih

problema linearne algebre. Često pružaju veću brzinu, ali i veću numeričku stabil-nost metoda u odnosu na druge pristupe. U nastavku ćemo razmotriti LU i Čoleskidekompozicije.

4.1.1 LU dekompozicijaLU dekompozicija kvadratne matrice A se sastoji u njenom predstavljanju u vidu

proizvoda dve matrice

A = LUgde je matrica L donjetrougaona sa jedinicama na dijagonali, a matricaU gornje-

trougaona. U okviru paketa scipy dostupan je modul linalg u kojem su implemen-tirane različite vrste dekompozicija, kao što je, na primer, LU. Obratiti pažnju da jeovaj modul različit od modula numpy.linalg. Dakle, prvo ćemo uvesti ovaj paket uradno okruženje>>> from scipy import linalg as LAs

Prikažimo sada korišćenje ovog paketa na jednostavnom primeru LU dekompo-zicije naredne matrice

A =

1 −2 32 −5 120 2 −10

U navedenom paketu pronalazimo funkciju LAs.lu(a, permute_l=False, ...), ko-

ja za nas izračunava LU dekompoziciju zadate matrice a. Tačnije, ukoliko bismopogledali u dokumentaciji opis ove funkcije, videli bismo da ova funkcija zapra-vo vraća različite vrednosti u zavisnosti od parametra premute_l. Podrazumevano,funkcija vraća tri matrice — P,L i U, gde su L i U gore opisane matrice, a P tzv.

71

Page 78: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 4. NUMERIČKA LINEARNA ALGEBRA 72

matrica permutacije. Ona označava koje vrste su zamenile mesta u matrici L. Tadabismo matricu A mogli predstaviti

A = PLUU slučaju da parametar permute_l postavimo na True, funkcija vraća permutovanu

matricu L i matricu U. Tako se, na primer, pozivom>>> P, L, U = LAs.lu(A)

dobijaju matrice čijim se množenjem dobija matrica A.

P =

0 0 11 0 00 1 0

, L =

1 0 00 1 00.5 0.25 1

, U =

2 −5 120 2 −100 0 −0.5

,

Ukoliko je LU dekompozicija poznata, može se upotrebiti za rešavanje sistemajednačina Ax = b. Naime, važi

Ax = (LU)x = L(Ux) = bOdavde se vidi da je rešavanjem sistema

Ly = b

a potom sistema

Ux = ymoguće dobiti rešenje polaznog sistema. Pokažimo ovaj postupak na primeru

rešavanja sistema

2x1 + x2 + x3 = 4x1 + 3x2 + 2x3 = 5

x1 = 6

>>> A = np.array([... [2, 1, 1],... [1, 3, 2],... [1, 0, 0]... ])>>> b = np.array([4, 5, 6])>>> P, L, U = LAs.lu(A)>>> y = LAs.inv(L).dot(b)>>> x = LAs.inv(U).dot(y)>>> xarray([ 6., 15., -23.])

Rešimo sada isti problem pomoću ugrađene funkcije za rešavanje sistema line-arnih jednačina Ax = b pomoću LU dekompozicije matrice A. U tu svrhu, dostupnanam je funkcija LAs.lu_solve(lu_and_piv, b, ...), čiji su argumenti lu_and_piv=(lu,piv), faktorizacijamatrice koe cijenataA, koja se dobija pozivom funkcije LAs.lu_factor(a,...), i vektor b.>>> x = LAs.lu_solve(LAs.lu_factor(A), b)>>> xarray([ 6., 15., -23.])

Vidimo da oba načina daju identična rešenja.

Page 79: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 4. NUMERIČKA LINEARNA ALGEBRA 73

4.2 Čoleski dekompozicijaUkoliko je kvadratna matrica A simetrična i pozitivno de nitna, postoji moguć-

nost njene e kasnije trougaone dekompozicije. Podsetimo se, matrica je pozitivnode nitna ukoliko za sve vektore x odgovarajuće dimenzije, različite od nule, važi

xTAx > 0Čoleski dekompozicija koju je moguće izvesti u pomenutom slučaju predstavlja

dekompoziciju matrice u obliku

A = LLT

gde je L donjetrougaona matrica sa strogo pozitivnim dijagonalnim elementima.Čoleski dekompozicija matrice dimenzija n× n se izračunava narednim formulama

lii =(aii −

i−1∑k=1

lik

) 12

, i = 1, . . . ,n

lji =1lii

(aij −

i−1∑k=1

likljk

), i = 1, . . . ,n− 1,

j = i+ 1, . . . ,n

(4.1)

Ako je poznata Čoleski dekompozicija, rešavanje sistema jednačina se vrši takošto se prvo reši sistem

Ly = ba potom sistem

LTx = ySada ćemo pokazati kako je moguće izvršiti Čoleski dekompoziciju kroz modul

scipy.linalg, ali ćemo prikazati i jednu implementaciju. Za početak de nišimo funk-cije koje ispituju uslove pod kojima je moguće izvršiti Čoleski dekompoziciju.

Funkcija is_symetric(A) proverava da li je zadata matrica A simetrična. Matricaje simetrična ako je jednaka svojoj transponovanoj matrici. Rad ove funkcije se osla-nja na ugrađenu funkciju numpy.allclose(a, b, rtol=1e-05, atol=1e-08, ...) kojaispituje jednakost matrica do na zadatu tačnost.>>> def is_symetric(A):... return np.allclose(A, A.T)

Funkcija is_positive_definite(A, n) proverava da li je zadata kvadratna matricaA dimenzije n pozitivno de nitna. Matrica A je pozitivno de nitna ako i samo akosu determinante svih kvadratnih podmatrica koje uključuju element a11 — odnosno,svi glavni minori — pozitivni. Ovaj uslov je poznat kao Silvestrov kriterijum.>>> def is_positive_definite(A, n):... for i in range(1, n+1):... matrix_minor = A[:i,:i]... minor = LAs.det(matrix_minor)... if minor <= 0:... return False

... return True

Page 80: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 4. NUMERIČKA LINEARNA ALGEBRA 74

Naš naredni korak jeste da upotrebimo napisane funkcije za proveru da li jenaredna matrica simetrična i pozitivno de nitna. 4 12 −16

12 37 −43−16 −43 98

>>> A = np.array([... [4, 12, -16],... [12, 37, -43],... [-16, -43, 98]... ])

>>> is_symetric(A) and is_positive_definite(A, A.shape[0])True

S obzirom da jeste, hajmo da odredimo njenu Čoleski dekompoziciju koristeci bi-bliotečku funkciju LAs.cholesky(a, lower=False, ...). Pored obaveznog parametrakoji predstavlja matricu A čiju dekompoziciju želimo da izračunamo, treba napome-nuti i parametar lower, čijim se podrazumevanim postavljanjem vrednosti na Falseračuna gornjetrougaona matrica L. Ipak, kako smo mi matricu L u ovoj dekompozi-ciji de nisali kao donjetrougaonu, postavićemo vrednost ovog parametra na True.>>> L = LAs.cholesky(A, lower=True)>>> Larray([[ 2., 0., 0.],

[ 6., 1., 0.],[-8., 5., 3.]])

Sada ćemo dati jednu implementaciju izračunavanja Čoleski dekompozicije kojase zasniva na formulama 4.1.>>> def cholesky(A):... n = A.shape[0]... L = np.zeros(A.shape)

... if not (isSymetric(A, n) and IsPositiveDefinite(A, n)):

... print('Matrix is not symetric and positive definite')

... return

... for i in range(n):

... L[i, i] = np.sqrt(A[i,i] - np.sum(L[i, :i]**2))

... for j in range(i+1, n):

... second_sum = np.sum(L[i, :i]*L[j, :i])

... L[j, i] = 1/L[i,i] * (A[i, j] - second_sum)

... return L

Primenimo funkciju cholesky na početnu matricu A.>>> c = cholesky(A)>>> carray([[ 2., 0., 0.],

[ 6., 1., 0.],[-8., 5., 3.]])

Vidimo da smo dobili istu dekompoziciju kao i primenom bibliotečke funkcije.

Page 81: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 4. NUMERIČKA LINEARNA ALGEBRA 75

4.3 SVD dekompozicijaU slučaju matrica koje su bliske singularnim, prethodne metode ipak imaju svo-

ja ograničenja u kontekstu rešavanja sistema jednačina — problem je sam po sebiloše uslovljen. U slučaju singularnih matrica, pomoću njih nije moguće doći ni dokakvih rešenja. Singularna dekompozicija (engl. singular value decomposition), iliskraćeno SVD, pruža mogućnost za smisleno baratanje ovakvim sistemima jedna-čina, bilo u cilju njihovog rešavanja, bilo u cilju razumevanja problema koji ih čineproblematičnim za rešavanje.

Neka je A matrica dimenzija m × n. Za bilo koju takvu matricu A, postoje or-togonalna matrica U dimenzija m × m, dijagonalna matrica Σ dimenzija m × n iortogonalna matrica V dimenzija n× n, takve da važi

A = UΣVT (4.2)Matrica Σ ima m − n vrsta koje se sastoje isključivo od nula i koje se mogu za-

nemariti. Stoga, matricu A je moguće razložiti i na matricu ortonormiranih kolonaU′ dimenzija m×n, dijagonalnu matricu Σ′ dimenzija n×n i ortogonalnu matricu Vdimenzija n× n, tako da važi

A = U′Σ′VT

U okviru modula numpy.linalg dostupna je funkcija svd(a, ...) koja izračunavaSVD dekompoziciju de nisanu formulom 4.2. Prikažimo jedan jednostavan primernam matricom

1 0 0 0 20 0 3 0 00 0 0 0 00 2 0 0 0

>>> A = np.array([... [1, 0, 0, 0, 2],... [0, 0, 3, 0, 0],... [0, 0, 0, 0, 0],... [0, 2, 0, 0, 0]... ])>>> U, S, V = LA.svd(A)

Rezultat izvršavanja su matrice

U =

0 1 0 01 0 0 00 0 0 −10 0 1 0

S =

3

2.2360679820

V =

0 0 1 0 0

0.4472136 0 0 0 0.894427190 1 0 0 00 0 0 1 0

−0.89442719 0 0 0 0.4472136

Primetimo da ova funkcija vraća matricu S kao vektor umesto kao dijagonalnu

matricu. Jasno je da bismo mogli dobiti baš dijagonalnu matricu pozivanjem funk-cije np.diag(S).

SVD dekompozicija ima mnogobrojna svojstva, a mi ćemo ovde navesti samoneka:

• Kolone matrice U su sopstveni vektori matrice AAT i nazivaju se levim singu-larnim vektorima matrice A.

Page 82: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 4. NUMERIČKA LINEARNA ALGEBRA 76

• Kolone matrice V predstavljaju sopstvene vektore matrice ATA i nazivaju sedesnim singularnim vektorima matrice A.

• Dijagonalni elementi matrice Σ, koji će biti označavani σi za i = 1,2, . . . ,n,nazivaju se singularnim vrednostima matrice A.

• Rang matrice A je jednak broju singularnih vrednosti koje nisu jednake nuli.

4.3.1 Kompresovanje slika pomoću SVD dekompozicijeU nekim slučajevima se aproksimacija matrice matricom nižeg ranga smatra

poželjnijom od originalne matrice, pošto se prilikom odsecanja članova sume kojiodgovaraju najnižim singularnim vrednostima može eliminisati šum ili neki manjebitni elementi signala.

Jedna od mogućih primena singularne dekompozicije je u aproksimaciji slika.Prikazaćemo kako se moguće aproksimirati sliku 4.1 matricom manjeg ranga.

Slika 4.1: Originalna slika tiger_bw.jpg koju želimo da aproksimiramo SVD dekom-pozicijom.

>>> from PIL import Image>>> image = Image.open('tiger_bw.jpg')>>> image.size(1600, 1000)

Kao što vidimo, originalna slika je dimenzija 1600×1000. Dakle, ona je opisanapomoću 1600000 brojeva.

>>> image_array = np.array(image)>>> U, S, V = np.linalg.svd(image_array)>>> print(U.shape, S.shape, V.shape)(1000, 1000) (1000,) (1600, 1600)>>> np.count_nonzero(S)1000

SVD dekompozicijom vidimo da slika ima 1000 sopstvenih vrednosti. Uradimo ivizualnu analizu dobijenih vrednosti. Na slici 4.2 (levo) prikazan je gra k sopstve-nih vrednosti slike 4.1. Na istoj slici (desno) prikazan je gra k kumulativne sumevektora S, normalizovan na interval [0,1]. Kumulativna suma vektora v predstavljavektor cumsum(v) čiji je element na i-toj poziciji jednak sumi

∑ik=1 vk. Analizom

Page 83: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 4. NUMERIČKA LINEARNA ALGEBRA 77

ovog gra ka možemo vršiti izbor ranga aproksimativne matrice — što je rang ve-ći, to se vrše informacija zadržava. Možemo videti da se izborom ranga 400 čuvapribližno 96.5% informacija.

>>> log_S = np.log10(S)>>> plt.plot(log_S)

>>> normalized_cumsum = np.cumsum(S)/np.sum(S)>>> plt.plot(normalized_cumsum)

>>> normalized_cumsum[400]0.96568835154453825

Slika 4.2: Gra čki prikaz vektora sopstvenih vrednosti (levo) i kumulativne sumevektora sopstvenih vrednosti (desno) dobijenih SVD dekompozicijom slike 4.1.

Da bismo prikazali rezultate različitih aproksimacija, de nisaćemo funkcijucreate_approx_image(image_array, rank), koja odmatrične reprezentacije image_arraypočetne slike konstruiše sliku koja se dobija aproksimacijommatrice ranga rank. Naslici 4.3 prikazane su aproksimacije ranga 5,20,50,100,175 i 280, redom.

>>> def create_approx_image(image_array, rank):... U, S, V = np.linalg.svd(image_array)

... # Potrebna nam je dijagonalna matrica,

... # konstruisana od vektora sopstvenih vrednosti

... S_approx = np.diag(S[:rank])

... # U matrici U zadrzavamo sve vrste, a odsecamo kolone

... U_approx = U[:, :rank]

... # U matrici V zadrzavamo sve kolone, a odsecamo vrste

... V_approx = V[:rank, :]

... image_approx_array = np.dot(np.dot(U_approx, S_approx), V_approx)

... image_approx = Image.fromarray(image_approx_array).convert('L')

... image_approx.save('image_approx_' + str(rank) + '.jpg')

>>> ranks = np.cumsum([5*i for i in np.cumsum(range(1, 7))])>>> for rank in ranks:... create_approx_image(image_array, rank)

Page 84: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 4. NUMERIČKA LINEARNA ALGEBRA 78

Slika 4.3: Aproksimacije slike 4.1 ranga 5,20,50,100,175 i 280, redom.

4.3.2 Rešavanje problema najmanjih kvadrata pomoću SVDdekompozicije

Sada ćemo demonstrirati kako se može iskoristiti SVD dekompoziciju za rešava-nje sistema jednačina ax+ by+ c = 0, gde su x i y zadati vektori koordinata tačaka.Matrično, zapisujemo x1 y1 1

......

...xn yn 1

abc

= 0

odnosno,

Ax = 0

Skup svih vektora x za koje vazi prethodna jednakost čini jedan vektorski prostori u slucaju SVD dekompozicije matrice, bazu tog vektorskog prostora čine vektori-kolone matrice V koji odgovaraju nula-singularnim vrednostima. Ako se rešava si-stem Ax = 0 i traži se njegovo netrivijalno rešenje, onda može da se posmatra isistem

ATAx = 0

Ovo je sistem koji ima netrivijalno rešenje samo ako postoji sopstvena vrednostmatrice ATA koja je nula, a zbog veze koja važi između sopstvenih vektora i singu-larnih vrednosti, ovo je ujedno i uslov kojim kažemo da tražimo singularnu vrednostmatrice A koja je nula. Drugim rečima, tražimo poziciju koja u matrici S ima najma-nju singularnu vrednost takvu da njoj odgovara vektor-kolona u matrici V. Naravno,jasno je da ovakvim pristupom možemo praviti grešku jer zapravo vršimo aproksi-maciju rešenja.

Zadajmo vektore x i y na naredni način. Gra čki prikaz podataka dat je na slici4.4

>>> np.random.seed(7)

>>> intercept = -10>>> slope = 3>>> number_of_points = 50

Page 85: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 4. NUMERIČKA LINEARNA ALGEBRA 79

>>> noise = 80

>>> x = 10 + np.random.randn(number_of_points, 1) * 90>>> y = slope * x + intercept + np.random.randn(number_of_points, 1) * noise

Slika 4.4: Prikaz generisanih podataka za primer rešavanja sistema linearnih jed-načina pomoću SVD dekompozicije.

Prvo je potrebno da formiramo matricu A. Zatim, kao što smo rekli, potražiće-mo indeks najmanje singularne vrednosti matrice A i izdvojiti odgovarajuću vektorkolonu kao rešenje sistema.

>>> A = np.hstack([x, y, np.ones((number_of_points, 1))])>>> _, s, v = LA.svd(A)>>> solution = v.T[s.argmin()]>>> solutionarray([ -3.79355732e-05, -9.39291623e-04, -9.99999558e-01])

4.4 Reprezentacija teksta pomoću retkih matricaNumerička linearna algebra se može koristiti i za obradu teksta. Pre nego što

kažemo nešto više o ovome, predstavimo kako je to moguće zapisati neki tekst uobliku pogodnom za metode linearne algebre. Za početak, upoznajmo se sa ret-kim matricama. Retke matrice su one matrice koje imaju veliki broj nula. Kao štovidimo, ne postoji precizna de nicija kojom se one određuju, ali mi ćemo ih tako,intuitivno, i shvatati.

U okviru paketa scipy dostupan je modul sparse u kojem se nalazi veliki brojmetoda za rad sa retkim matricama. Ovaj modul sadrži različite klase za rad saretkim matricama.

>>> from scipy import sparse as sps

Među ovim klasama nalazi se i dok_matrix, koja zapravo predstavlja mapu klju-čeva koje imaju ne-nula vrednosti1. Pri kreiranju objekta ove klase potrebno jeproslediti dimenzije matrice kao i postaviti tip vrednosti.

1Ime potiče od sintagme Dictionary of Keys.

Page 86: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 4. NUMERIČKA LINEARNA ALGEBRA 80

>>> m = sps.dok_matrix((5, 5), dtype=np.float64)>>> m<5x5 sparse matrix of type '<class 'numpy.float64'>'

with 0 stored elements in Dictionary Of Keys format>

Vrednosti se jednostavno dodaju, na primer, korišćenjem indeksnog operatora.

>>> for i in range(5):... m[i,i] = 1

>>> m<5x5 sparse matrix of type '<class 'numpy.float64'>'

with 5 stored elements in Dictionary Of Keys format>

Broj ne-nula vrednosti je moguće dobiti pozivom funkcije getnnz(). Pretvaranjeu gustu ndarraymatricu moguće je izvesti pozivom funkcije toarray(), a pretvaranjeu gustu numpy.matrixmatricu moguće je izvesti pozivom funkcije todense(). Sve ovefunkcije se pozivaju nad objektom tipa nekog od retkih matrica iz modula sparse.Dodatno, napomenimo da su dostupne sve funkcije sa rad sa matricama koje smodo sada videli.

Pokažimo sada kako je moguće sačuvati tekst u formi retke matrice. Radi jed-nostavnosti, posmatrajmo tekst koji se sastoji od samo dve rečenice:

We like Python. he likes apples.

Napomenimo da je reč he namerno stavljena malim slovima. Ovo je u vezi sainicijalnim pretprocesiranjem teksta. Naime, ono što se prvo radi u obradi tekstajeste formiranje rečnika, odnosno, izdvajanje jedinstvenih reči, pri čemu se rečina neki način normalizuju — na primer, sve reči se prebacuju u mala slova, odglagolskih oblika se čuvaju samo in nitivi, i sl. Dakle, prvo bismo formirali nizrečenica.

>>> text = ['We like Python.', 'he likes apples.']

Zatim bismo, na neki način, procesirali rečenice i formirali rečnik.

>>> vocabulary = ['we', 'like', 'python', 'he', 'apples']

Dalje, svakoj reči pridružujemo vektor koji ima jedinicu na poziciji reči u vokabu-laru, a nulu inače. Tada, rečenice dobijamo kao zbirove vektora reči koje se nalazeu toj rečenici.

>>> words_encoded = {... 'we': [1, 0, 0, 0, 0],... 'like': [0, 1, 0, 0, 0],... 'python': [0, 0, 1, 0, 0],... 'he': [0, 0, 0, 1, 0],... 'apple': [0, 0, 0, 0, 1],... }>>> first_sentence = words_encoded['we'] + \... words_encoded['like'] + \... words_encoded['python']>>> first_sentencearray([1, 1, 1, 0, 0])>>> second_sentence = words_encoded['he'] + \... words_encoded['like'] + \... words_encoded['apple']

Page 87: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 4. NUMERIČKA LINEARNA ALGEBRA 81

>>> second_sentencearray([0, 1, 0, 1, 1])>>> test_encoded = {... 'We like Python.': first_sentence,... 'he likes apples.': second_sentence:... }

Očigledno, ovo je primer jedne retke reprezentacije teksta2 koja se naziva bagof words. Sada ćemo ovaj postupak ponoviti korišćenjem bibliotečkih funkcija.

U modulu sklearn.feature_extraction nalazi se veliki broj metoda za obradu siro-vih podataka. Nas zanimamodul text, u kojemmožemo pronaći klasu CountVectorizer.Ova klasa pretvara sekvencu tekstualnih dokumenata u retku reprezentaciju. Obu-čavanje se vrši pozivom funkcije fit(raw_documents, ...) kojoj se prosleđuje korpusteksta. Nakon toga, obučeni rečnik je dostupan kroz atribut vocabulary_.>>> vectorizer = feature_extraction.text.CountVectorizer()>>> vectorizer.fit(text)>>> vectorizer.vocabulary_{'apples': 0, 'he': 1, 'like': 2, 'likes': 3, 'python': 4, 'we': 5}

Primetimo da je CountVectorizer, zbog neuključivanja dodatnog pretprocesira-nja, uključio obe reprezentacije glagola like.

Konačno, primenom funkcije transform(raw_documents), dobijamo bag of wordsreprezentaciju početnog teksta.>>> bag_of_words = vectorizer.transform(text)>>> bag_of_words<2x6 sparse matrix of type '<class 'numpy.int64'>'

with 6 stored elements in Compressed Sparse Row format>

Pogledajmo i konačan izgled vektorske reprezentacije teksta.>>> bag_of_words.toarray()array([[0, 0, 1, 0, 1, 1],

[1, 1, 0, 1, 0, 0]])

4.5 Analiza glavnih komponentiU primenama, podaci se često predstavljaju visokodimenzionalnim vektorima.

Primera radi, slike se često sastoje iz velikog broja piksela. Ipak, iako je prostorvisokodimenzionalan, većina vektora podataka često leži u niskodimenzionalnoj po-vrši unutar tog prostora ili vrlo blizu neke takve površi. Ukoliko bi se podaci pro-jektovali na nju, izgubio bi se deo informacije, ali bi se dimenzionalnost podatakamogla, često i drastično, smanjiti. Na primer, u skupu svih mogućih slika, skup licačini prostor manje dimenzije. Ovakva transformacija je poželjna kako zbog skla-dištenja podataka, tako i zbog toga što statistički algoritmi i algoritmi mašinskogučenja često daju bolje rezultate ukoliko podaci imaju nižu dimenzionalnost. U ne-kim slučajevima olakšava i razumevanje podataka.

Jedno od zapažanja na kojem se zasnivaju metode analize podataka je da varijaci-ja promenljivih nosi informaciju. S druge strane, koreliranost promenljivih znači dapromenljive nose manje informacije nego što njihova brojnost sugeriše. Stoga, raci-onalan pristup je naći skup vektora duž kojih je varijacija podataka najveća, takvihda projekcije podataka na njih nisu korelirane, izabrati ih za novu bazu prostora

2Naravno, opažana retkost se ogleda tek na većem korpusu teksta, a ne na ovako uskom skupu reči.

Page 88: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 4. NUMERIČKA LINEARNA ALGEBRA 82

podataka i zanemariti one koordinate kojeodgovaraju vektorima duž kojih je varija-cija podataka najmanja. Kako bi projekcije bile nekorelirane, konstruisani vektoritreba da budu ortogonalni. Ovi vektori, koji se nazivaju glavnim komponentama semogu pronaći tako što se pronade, prvo vektor duž kojeg podaci najviše variraju,tako što se varijabilnost podataka duž tog vektora ukloni, a potom se proces nastavi.Ovaj postupak se naziva analizom glavnih komponenti (engl. Principal ComponentAnalysis, skr. PCA).

Standardni PCA koraci su:

• centriranje skupa podataka — po svakoj dimenziji se računa aritmetička sre-dina i oduzima se od pojedinačnih podataka;

• kreiranje matrice kovarijanse;

• određivanje sopstvenih vrednosti i sopstvenih vektora matrice kovarijanse;

• uređivanje skupa sopstvenih vrednosti i izbor odgovarajućeg broja sopstvenihvektora (tzv. glavne komponente);

• izvođenje novog skupa podataka;

• vizuelizacija;

• po potrebi vraćanje na polazni skup podataka.

Sada ćemo pokazati kako se može primeniti PCA na dvama skupa podataka.Napomenimo da ćemo u oba primera za primenu PCA algoritma iskoristiti ugra-đenu bibliotečku klasu sklearn.decomposition.PCA. Čitalac se ohrabruje da sam im-plementira algoritam PCA kao primer dobre vežbe za razumevanje postupka, uzkonsultovanje sa [1].

4.5.1 Primena PCA na skup podataka breast_cancerU ovom primeru podrazumevamo naredna uvoženja paketa

>>> from sklearn import datasets>>> from sklearn import preprocessing>>> from sklearn.decomposition import PCA>>> import numpy as np>>> import matplotlib.pyplot as plt

Za početak, izdvojimo skup podataka i izvršimo standardizaciju.

>>> data = datasets.load_breast_cancer()>>> x = data.data>>> y = data.target>>> scaler = preprocessing.StandardScaler()>>> scaler.fit(x)>>> x = scaler.transform(x)

Naredni korak predstavlja kreiranje objekta klase PCA(n_components=None, ...),kojem se prosleđuje broj glavnih komponenti koje će činiti novi prostor u koji želimoda ,,prezapišemo'' podatke. U našem primeru, odabraćemo svega 2 glavne kompo-nente, radi jednostavne vizualizacije rezultata. Nakon kreiranja, potrebno je obučitiPCA model nad zadatim podacima i izvršiti transformaciju. Nekada može biti kori-sno imati uvid u matricu kovarijanse, koja se može dobiti pozivom get_covariance()nad objektom tipa PCA.

Page 89: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 4. NUMERIČKA LINEARNA ALGEBRA 83

>>> pca = PCA(n_components=2)>>> pca.fit(x)PCA(copy=True, iterated_power='auto', n_components=2, random_state=None,svd_solver='auto', tol=0.0, whiten=False)

>>> x_pca = pca.transform(x)

Dakle, kao što smo rekli, novi prostor obrazuju prva i druga glavna komponenta.Sada možemo vizualno prikazati podatke na sledeći način. Prikazaćemo transfor-misane podatke u ravni u novim koordinatama, pri čemu ćemo svakoj klasi (kojih,ako se prisetimo ima dve — 0 ili 1) dodeliti drugačiju boju. Rezultat ove vizuali-zacije, dobijene narednim fragmentom programskog koda, prikazan je na slici 4.5.Zanimljivo je videti da su klase u novom prostoru gotovo potpuno linearno razdvo-jive.>>> plt.xlabel("I PCA component")>>> plt.ylabel("II PCA component")>>> colors = np.where(y==0, 'blue', 'red')>>> plt.scatter(x_pca[:, 0], x_pca[:, 1], c=colors)>>> plt.show()

Slika 4.5: Prikaz skupa podataka breast_cancer u novom prostoru koji razapinjuprve dve glavne komponente datog skupa podataka.

Ono što bi bilo zanimljivo videti jeste koliko koji atribut u početnom prostorupodataka utiče na svaku glavnu komponentu, ali i obrnuto, koliko svaka glavnakomponenta objašnjava varijaciju početnih podataka.

U prvu svrhu, podatke o glavnim komponentamamožemo dobiti iz atributa components_objekta PCA. Ove vektore ćemo prikazati po vrstama, a kolone će činiti atributi pola-znog prostora. Ovakav prikaz se može prikladno prikazati toplotnom mapom, kojaje prikazana na slici 4.6.>>> plt.matshow(pca.components_, cmap='viridis')>>> plt.xticks(np.arange(30), data.feature_names, rotation=60, ha='left')>>> plt.yticks([0, 1], ['I PCA component', 'II PCA component'])

Page 90: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 4. NUMERIČKA LINEARNA ALGEBRA 84

Slika 4.6: Prikaz toplotne mape odnosa atributa skupa podataka breast_cancer upočetnom prostoru i atributa u novom prostoru koji razapinju prve dve glavne kom-ponente datog skupa podataka.

>>> plt.colorbar()>>> plt.show()

U drugu svrhu, na raspolaganju su nam atributi explained_variance_ iexplained_variance_ratio_, koji prikazuju koliku količinu varijanse podataka svakiod glavnih komponenti objašnjava. Prvi atribut predstavlja apsolutne, dok drugipredstavlja relativne vrednosti. Narednim fragmentom programskog koda vidimoda drugi atribut govori o tome da prve dve glavne komponente objašnjavaju ugrubo63% ukupne varijanse podataka.>>> pca.explained_variance_array([ 13.30499079, 5.7013746 ])>>> pca.explained_variance_ratio_array([ 0.44272026, 0.18971182])>>> np.sum(pca.explained_variance_ratio_)0.63243207651559397

Značajno je znati kako možemo podatak u novom prostoru predstaviti u koor-dinatama početnog prostora. Za to nam služi funkcija inverse_transform(X) nadobjektom tipa PCA.>>> pca.inverse_transform([2, 4])array([-0.49762364, -0.0313752 , -0.40565086, -0.48231687, 1.02963148,

1.08613715, 0.75746241, 0.38263751, 1.037729 , 1.59502858,-0.01025106, 0.39477478, 0.0648229 , -0.20343124, 0.84678472,1.27165049, 1.09600871, 0.88812103, 0.82038884, 1.32550475,-0.42347225, 0.02706946, -0.32623435, -0.42766637, 0.94512253,0.99456445, 0.84939152, 0.468743 , 0.81334251, 1.36492576])

4.5.2 Primena PCA za prepoznavanje lica — sopstvena licaU ovom primeru podrazumevamo naredna uvoženja paketa

>>> import numpy as np>>> import matplotlib.pyplot as plt>>> from sklearn import datasets>>> from sklearn import neighbors>>> from sklearn import model_selection>>> from sklearn.decomposition import PCA

Slike licamožemo dobiti pozivanjem funkcije datasets.fetch_lfw_people(..., resize=0.5,min_faces_per_person=0, ...), koja će za nas dohvatiti skup podataka. Parametrom

Page 91: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 4. NUMERIČKA LINEARNA ALGEBRA 85

resize određujemo veličinu slike, dok postavljanjem parametra min_faces_per_personsadržavamo samo one slike osoba koje imaju barem toliko slika.

>>> dataset = datasets.fetch_lfw_people(resize=0.7, min_faces_per_person=20)

Pogledajmo sada neke informacije o klasa, odnosno, u ovom primeru, o ljudimačije slike analiziramo.

>>> target = dataset.target.tolist()>>> target_names = dataset.target_names.tolist()>>> len(target_names)62>>> bush_index = target_names.index('George W Bush')>>> bush_count = target.count(bush_index)>>> bush_count530>>> serena_index = target_names.index('Serena Williams')>>> serena_count = target.count(serena_index)>>> serena_count52

Kao što vidimo, ukupno imamo 62 osobe na slikama, pri čemu različite osobeimaju različit broj svojih slika. Na slici 4.7 dati su primeri slika nekoliko osoba sanjihovim imenima.

>>> figure, axis = plt.subplots(2, 5, figsize=(15, 8), \... subplot_kw={'xticks':(), 'yticks':()})

>>> for target, image, ax in zip(dataset.target, dataset.images, axis.ravel()):... ax.imshow(image, cmap='gray')... ax.set_title(dataset.target_names[target])

>>> plt.show()

Slika 4.7: Primeri slika osoba i njihova imena.

Page 92: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 4. NUMERIČKA LINEARNA ALGEBRA 86

S obzirom da ćemo vršiti klasi kaciju lica, želeli bismo da vršimo testiranje kla-si katora, te je potrebno izvršiti podelu skupa podataka na skupove za obučavanjei testiranje.>>> x_people = dataset.data>>> y_people = dataset.target

>>> x_train, x_test, y_train, y_test = model_selection.train_test_split( \... x_people, y_people, test_size=0.33, stratify=y_people, random_state=7 \... )

U ovom primeru ćemo iskoristiti neighbors.KNeighborsClassifier klasi kator zaprepoznavanje lica. Prvo ćemo koristiti analizu bez korišćenja PCA. Broj susedakoji uzimamo u obzir je 1.>>> classifier = neighbors.KNeighborsClassifier(n_neighbors=1)>>> classifier.fit(x_train, y_train)KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',

metric_params=None, n_jobs=1, n_neighbors=1, p=2,weights='uniform')

>>> classifier.score(x_test, y_test)0.32364729458917835

Sada ćemo prvo uraditi analizu glavnih komponenti. Kako je svaki podatak nizdužine 5655, mi ćemo pokušati sa biranjem 150 glavnih komponenti.>>> pca = PCA(n_components=150)>>> pca.fit(x_train)PCA(copy=True, iterated_power='auto', n_components=150, random_state=None,svd_solver='auto', tol=0.0, whiten=False)

>>> x_train_pca = pca.transform(x_train)>>> x_test_pca = pca.transform(x_test)

>>> image_shape = dataset.images[0].shape>>> image_shape(87, 65)

Prikaz prvih nekoliko komponenti nalazi se na slici 4.8.>>> figure, axis = plt.subplots(3, 5, figsize=(15, 12), \... subplot_kw={'xticks':(), 'yticks':()})

>>> for i, (component, ax) in enumerate(zip(pca.components_, axis.ravel())):... ax.imshow(component.reshape(image_shape), cmap='gray')... ax.set_title("Component {0}".format(i+1))

>>> plt.show()

Sada ćemo izvršiti testiranje na isti način kao i bez primene PCA.>>> pca_classifier = neighbors.KNeighborsClassifier(n_neighbors=1)>>> pca_classifier.fit(x_train_pca, y_train)KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',

metric_params=None, n_jobs=1, n_neighbors=1, p=2,weights='uniform')

>>> pca_classifier.score(x_test_pca, y_test)

Page 93: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 4. NUMERIČKA LINEARNA ALGEBRA 87

Slika 4.8: Prikaz prvih nekoliko glavnih komponenti koje nazivamo sopstvena lica.

0.33066132264529058

Vidimo da smo uspeli malo popraviti rezultate. Međutim, da li smo i očekivalidrastično veći uspeh ukoliko smo koristiti klasi kator zasnovan na 1-najbližem su-sedu? Čitalac se savetuje da isproba različite metode sa sličnom analizom i uporedidobijene rezultate.

4.6 Određivanje sopstvenih vrednosti i sopstvenihvektora

Kvadratna matrica A ima sopstveni vektor x i sopstvenu vrednost λ, ukoliko važi

Ax = λx x = 0Drugim rečima, matrica A ne menja pravac sopstvenog vektora. Poznato je da

različitim sopstvenim vrednostima odgovaraju linearno nezavisni vektori, kao i dasu sopstvene vrednosti jednake nulama karakterističnog polinoma

det(A− λI)U nastavku ćemo se prvo upoznati sa postojećom Python podrškog za određiva-

nje sopstvenih vrednosti i vektora.

Page 94: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 4. NUMERIČKA LINEARNA ALGEBRA 88

4.6.1 Ugrađena bibliotečka podrškaU okviru modula numpy.linalg dostupna je funkcija LA.eig(a), koja izračunava

vektor w sopstvenih vrednosti i matricu v desnih sopstvenih vektora kvadratne ma-trice a, poređanih po kolonama, redom. Važi da kolona v[:, i] predstavlja sopstvenivektor koji odgovara sopstvenoj vrednosti w[i].

>>> A = np.array([... [0.5, 0.5],... [0.2, 0.8]... ])

>>> values, vectors = LA.eig(A)

>>> for i in range(len(values)):... print('Sopstvena vrednost {0} i sopstveni vektor {1}'.format( \... values[i], vectors[:, i] \... ))Sopstvena vrednost 0.30000000000000004 i sopstveni vektor [-0.92847669 0.37139068]Sopstvena vrednost 1.0 i sopstveni vektor [-0.70710678 -0.70710678]

U nastavku ćemo prikazati delimične metode za pronalaženje sopstvenih vektorai vrednosti.

4.6.2 Metod stepenovanjaDelimične metode omogućavaju traženje samo nekih sopstvenih vektora, po pra-

vilu dominantnog sopstvenog vektora — onog koji odgovara po modulu najvećojsopstvenoj vrednosti. Među njima je najpoznatija metoda stepenovanja (engl. po-wer method).

Neka su x1, . . . ,xn sopstveni vektori matrice A ∈ Rn×n. Neka je v0 proizvoljanvektor. Kako sopstveni vektori čine bazu vektorskog prostora, važi

v0 = α1x1 + . . .+ αnxn

Neka je

vk = Akv0, k = 1,2, . . .

Onda važi

vk = λk1α1x1 + . . .+ λknαnxn

Ako važi |λ1| > |λ2| ≥ . . . ≥ |λn| i α1 = 0, onda vektor vk konvergira ka sopstvenomvektoru kolinearnom sa x1. Dodatno, za ovako dobijenu aproksimaciju sopstvenogvektora može se dobiti njegova sopstvena vrednost

vTkAvkvTkvk

Čak i ako važi α1 = 0, u praksi se zbog računaskih grešaka pojavljuje komponentau pravcu sopstvenog vektora x1, što dovodi do konvergencije, ali sporije. Ukolikomatrica ima nekoliko po modulu jednakih sopstvenih vrednosti, konvergencija nijegarantovana.

Page 95: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 4. NUMERIČKA LINEARNA ALGEBRA 89

>>> def power_method(A, max_iterations=50, eps=1e-6):... n = A.shape[0]

... v_old = np.random.randn(n)

... for i in range(1, max_iterations+1):

... v_new = np.dot(A, v_old)

... if np.linalg.norm(v_new - v_old) < eps:

... break

... # normiranje se preporucuje zbog sprecavanja eksplozije vrednosti

... v_new = v_new / np.linalg.norm(v_new)

... v_old = v_new

... print('Power method completed in {0} iterations'.format(i))

... return v_new

4.6.3 Metod iscrpljivanjaPostoje i druge delimične metode, koje takođe izračunavaju dominantni sopstve-

ni vektor, ali o njima neće biti reči. Važnije pitanje je kako izračunati i ostale sop-stvene vektore, koristeći neku od tih metoda. Neka važi |λ1| > |λ2| > . . . > |λn| ineka su y1, . . . ,yn sopstveni vektori matrice AT, skalirani tako da važi xi · yj = δij (štoje pod datim uslovom moguće). Neka je

A1 = AAi+1 = Ai − λixiyTi i = 2, . . . ,n

Sopstveni vektori i vrednosti se dobijaju primenom metoda stepenovanja na ma-trice Ai i AT

i za i = 1, . . . ,n. Ova metoda se naziva metodom iscrpljivanja.>>> def exhausting_method(A, number_of_vectors, max_iterations=50, eps=1e-5):... values = []... vectors = []... A_old = A... A_old_T = A.T...... for i in range(number_of_vectors):... x_curr = power_method(A_old, max_iterations, eps)... y_curr = power_method(A_old_T, max_iterations, eps)... lambda_curr = np.dot(np.dot(x_curr.T, A_old), x_curr) / np.dot(x_curr.T, x_curr)...... values.append(lambda_curr)... vectors.append(x_curr)...... n = len(x_curr)... x_curr = x_curr.reshape(n, 1)... y_curr_T = y_curr.reshape(1, n)... A_old = A_old - lambda_curr*np.dot(x_curr, y_curr_T)... A_old_T = A_old.T...... return values, vectors

Page 96: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 4. NUMERIČKA LINEARNA ALGEBRA 90

4.7 Problem rangiranjaKao što smo do sada videli, korišćenjem metoda numeričke linearne algebre mo-

guće je rešiti najrazličitije probleme. Dva problema koja će biti izložena u nastavkupredstavljaju probleme rangiranja, odnosno, probleme u kojima je potrebno, izvršitirangiranje objekata, pri čemu važe odgovarajući uslovi.

4.7.1 PageRank algoritamJedan od najilustrativnijih primera primene metoda numeričke linearne algebre

je problem rangiranja stranica na internetu i poznati algoritam PageRank, jedanod glavnih elemenata Guglovog pristupa pretrazi. Sam algoritam ne uzima u obzirupit pretrage, već se samo tiče rangiranja stranica po značaju.

Prirodni matematički formalizam kojim se struktura interneta može modelovatije usmereni graf. Neka je skup strana, njegovih čvorova, označen S i neka je |S| = N.Neka je K skup svih čvorova koji ne vode do drugih strana. Takođe, korisnici imajuvektor preferenci v čije koordinate su sve strogo pozitivne, i sumiraju se na 1. Očitovs se može interpretirati kao verovatnoća da korisnik odluči da poseti stranicu s.

Zapitajmo se kako možemo modelirati verovatnoću posete strane s. Jedan načinje da pratimo sve linkove do cvora s, a drugi je da, ako naiđemo na neku stranu kojane vodi nikuda, postoji verovatnoća iz vektora personalizacije v koji vodi do njega.Tako dolazimo do formule

P(s) =∑

r∈N(s)

P(r)nr

+∑r∈K

vsP(r) s ∈ S

gde je nr broj linkova na strani r. Neka je p vektor verovatnoća posete svihstranica, a A matrica takva da važi Aij = 1/nj ukoliko postoji veza sa strane j kastrani i, a 0 u suprotnom. Takođe, neka je k vektor takav da važi ki = 1 ako čvor inema naslednika, a ki = 0 u suprotnom. Onda se prethodna jednakost može izrazitimatrično

p = (A+ vkT)p

Očito, p predstavlja sopstveni vektor matrice A + vkT. Stoga se prethodni pro-blem svodi na problem nalaženja sopstvenih vektora te matrice. Imajući u viduda je matrica A + vkT stohastička matrica, odnosno da je suma svake njene kolo-ne jednaka 1, lako je dokazati da je njena najveća sopstvena vrednost jednaka 1.Stoga, p predstavlja sopstveni vektor matrice A + vkT, koji odgovara najvećoj sop-stvenoj vrednosti. Međutim, ta sopstvena vrednost može biti višestruka, pa p nijejedinstveno određeno.

Ipak, treba imati u vidu da korisnici ne biraju uvek samo strane dostupne sa te-kuće strane koju su posetili, već nekada biraju narednu stranu nezavisno od tekuće.Neka je 0 ≤ α < 1 verovatnoća izbora jedne od veza dostupnih na tekućoj strani.Tada važi

p = α(A+ vkT)p+ (1− α)v = (α(A+ vkT) + (1− α)veT)p

gde je e vektor čiji su svi elementi jednaki 1, pri čemu poslednja jednakost važizahvaljujući tome što važi

eTp =

n∑i=1

pi = 1

Page 97: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 4. NUMERIČKA LINEARNA ALGEBRA 91

U ovom slučaju, p je sopstveni vektor matrice

G = α(A+ vkT) + (1α)veT

koju nazivamo Guglova matrica. Sada ćemo prikazati implementaciju ovog po-stupka. Za početak, generišimo nasumično matricu A i vektor k prateći gore posta-vljene uslove

>>> np.random.seed(21)>>> N = 10>>> A = np.zeros((N, N))>>> k = np.zeros(N)

>>> for i in range(0, N):... number_of_links = np.random.randint(low=0, high=N)... if number_of_links == 0:... k[i] = 1

... column = np.ones(number_of_links)

... column = np.append(column, np.zeros(N-number_of_links))

... np.random.shuffle(column)

... if number_of_links != 0:

... column = column / number_of_links

... A[:, i] = column

>>> k = k.reshape(10, 1)

Takođe, nasumično generišimo i vektor v

>>> v = np.random.rand(N)>>> v = v / np.sum(v) # delimo sumom da bi bio vektor verovatnoca>>> v = v.reshape(10, 1)

Sada, formirajmo Guglovu matricu i pronađimo njen sopstveni vektor p

>>> alpha = 0.85>>> e = np.ones((N,1))>>> G = alpha*(A + np.dot(v, k.T)) + (1-alpha)*np.dot(v, e.T)>>> p = power_method(G, 1000)Power method completed in 14 iterations

Da je Guglova matrica stohastička, možemo pokazati izvršavanjem narednogfragmenta koda

>>> [np.sum(G[:, i]) for i in range(N)][1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]

Ukoliko nas zanima značaj stranica, možemo sortirati indekse vektora p

>>> np.argsort(p)array([7, 2, 3, 8, 9, 0, 4, 1, 5, 6], dtype=int64)

Odavde vidimo da je stranica 7 najznačajnija, dok je stranica 6 najmanje značaj-na.

Page 98: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 4. NUMERIČKA LINEARNA ALGEBRA 92

4.7.2 TextRank algoritamVeć smo ranije govorili o reprezentacijama tekstova na prirodnom jeziku. Jedan

značajan problem jeste izdvajanje važnih (ključnih) reči u datom tekstu. AlgoritamTextRank koji će biti opisan u nastavku predstavlja model za rangiranje zasnovanna grafovima, koji se koristi u procesiranju tekstova. Za početak, upoznaćemo sesa bibliotekom networkx koja nudi podršku za grafove, a zatim ćemo reći nešto višeo samom algoritmu. Nadalje pretpostavljamo naredna uvoženja paketa

>>> import numpy as np>>> import nltk>>> import networkx as nx>>> import io>>> import os>>> import itertools

Biblioteka networkx U osnovi rada sa grafovima korišćenjem paketa networkx, na-lazi se klasa networkx.Graph, koja predstavlja osnovnu klasu za neusmerene grafove

>>> G = nx.Graph()

Prethodnim pozivom, kreiran je objekat tipa nx.Graph, koji predstavlja prazangraf. Najjednostavniji način za dodavanje novih grana u grafu jeste pozivom funkci-je G.add_edge(u_of_edge, v_of_edge, **attr), kojoj se dodaje grana između čvorovau_of_edge i v_of_edge, pri čemu se oba čvora dodaju automatski ukoliko se već nenalaze u grafu. Dodatno, u mogućnosti smo da granama dodeljujemo razne atribu-te od značaja, bilo kao objekat tipa dict ili korišćenjem parova ključ-vrednost. Naprimer,

>>> G.add_edge('a', 'b', weight = 0.6)>>> G.add_edge('a', 'c', weight = 0.2)>>> G.add_edge('c', 'd', weight = 0.1)>>> G.add_edge('c', 'e', weight = 0.7)>>> G.add_edge('c', 'f', weight = 0.9)>>> G.add_edge('a', 'd', weight = 0.3)

Konačno, pokazaćemo kako je moguće prikazati graf korišćenjem plt modula.Neka je potrebno od objekta G nacrtati graf na sledeći način:

• Čvorove obojiti u 2FDEFF , i postaviti veličinu na 400

• Oznake čvorova prikazati crnom bojom u veličini 20, familijom fontova sans-serif

• Grane čija je težina veća od 0.5 obojiti u A9FFF3 i postaviti debljinu na 4

• Grane čija je težina manja ili jednaka od 0.5 obojiti u 114CCC , postaviti de-bljinu na 2 i iscrtati isprekidanom linijom

• Ne prikazivati atribute grana

• Ne iscrtavati ose

Za početak, podelimo grane u dve liste, u zavisnosti od vrednosti težine

Page 99: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 4. NUMERIČKA LINEARNA ALGEBRA 93

>>> edges_large = [(u, v) for (u, v, d) in G.edges(data=True) if d['weight'] > 0.5]>>> edges_large[('a', 'b'), ('c', 'e'), ('c', 'f')]

>>> edges_small = [(u, v) for (u, v, d) in G.edges(data=True) if d['weight'] <= 0.5]>>> edges_small[('a', 'c'), ('a', 'd'), ('c', 'd')]

Da bismo iscrtali graf, potrebno je da pozicioniramo čvorove grafa. U paketunetworkx postoji veliki broj algoritama za raspoređivanje čvorova grafa, a jedan odnjih je nx.spring_layout(G, ...), koji pokušava da pozicionira elemente grafa takoda budu estetski najpogodniji.>>> pos = nx.spring_layout(G)

Sada kada smo dobili informacije o pozicijama elemenata grafa, pozivanjemfunkcija nx.draw_networkx_nodes, nx.draw_networkx_labels i nx.draw_networkx_edges,uz prosleđivanje odgovarajućih parametara, možemo iscrtati željeni prikaz grafa.Rezultat je prikazan na slici 4.9.>>> nx.draw_networkx_nodes(G, pos, node_color='#2FDEFF', node_size=700)>>> nx.draw_networkx_labels(G, pos, font_size=20, font_family='sans-serif')>>> nx.draw_networkx_edges(G, pos, edgelist=edges_large, width=4, edge_color='#A9FFF3')>>> nx.draw_networkx_edges(G, pos, edgelist=edges_small, width=2, edge_color='#114CCC',\... style='dashed')>>> plt.axis('off')>>> plt.show()

Slika 4.9: Primer iscrtavanja objekta tipa nx.Graph.

Pretprocesiranje teksta Pretpostavimo da se u radnomdirektorijumu nalazi pod-direktorijum articles u kojem se nalazi 10 datoteka 1.txt, 2.txt, …, 10.txt sa ra-zličitim člancima. Cilj je da za svaki članak izvršimo rangiranje po značajnosti rečikoje se nalaze u njemu.

Za početak, želimo da izvršimo tokenizaciju reči u tekstu. U sekciji 4.4 videli smojedan jednostavan postupak (čija je najvećamana bila nedostatak automatizacije) za

Page 100: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 4. NUMERIČKA LINEARNA ALGEBRA 94

obavljanje ovog posla. Ovoga puta želimo da taj postupak unapredimo. U tu svrhu,upotrebićemo paket nltk (skr. Natural Language ToolKit), koji služi za procesiranjeprirodnog jezika. Paket dolazi sa mnoštvom alata, među kojima je i Punkt SentenceTokenizer, koji se može dobaviti pomoću

>>> nltk.download('punkt')

Ovaj alat služi za tokenizaciju teksta. Preciznije, on razbija tekst na listu tokena.Na primer,

>>> text = nltk.word_tokenize('''... We want to go to U.S.A. one day.... We really want to go to USA.... ''')

Sadržaj vektora text je ['We', 'want', 'to', 'go', 'to', 'U.S.A.', 'one', 'day','.', 'We', 'really', 'want', 'to', 'go', 'to', 'USA', '.'].

Ono što je nama od značaja jeste da odstranimo tokene koji nam nisu od značajaza kontekst. Takvi su, na primer, interpunkcijski znakovi, prilozi, i drugo. Da bismoto uradili, potrebno je da tokenima pridružimo tagove koji opisuju vrstu reči. Alatkoji nam to omogućava možemo dobaviti pomoću

>>> nltk.download('averaged_perceptron_tagger')

Nakon tagiranja teksta, dobijamo

>>> tagged_text = nltk.pos_tag(text)>>> tagged_text[('We', 'PRP'),('want', 'VBP'),('to', 'TO'),('go', 'VB'),('to', 'TO'),...('to', 'TO'),('go', 'VB'),('to', 'TO'),('USA', 'NNP'),('.', '.')]

Kao što smo rekli, izdvajamo ono što nam je potrebno. U našem slučaju, uzima-ćemo u obzir tokene sa tagovima: (1) NN — imenice, (2) NNP — imenične fraze i (3)JJ— prideve. Napisaćemo i jednostavnu funkciju koja će vršiti ltriranje tokena naosnovu tagova

>>> def filter_tags(tagged_text, tags=['NN', 'NNP', 'JJ']):... return [item for item in tagged_text if item[1] in tags]

Naš ltrirani tekst je u ovom slučaju

>>> filtered_tagged_text = filter_tags(tagged_text)>>> filtered_tagged_text[('U.S.A.', 'NNP'), ('day', 'NN'), ('USA', 'NNP')]

Dodatno, vršićemo normalizaciju teksta, odnosno, sva velika slova pretvorićemou mala i, takođe, eliminisaćemo karakter za tačku

>>> def normalize(tagged_text):... return [(item[0].lower().replace('.', ''), item[1]) for item in tagged_text]

Page 101: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 4. NUMERIČKA LINEARNA ALGEBRA 95

Naš normalizovani tekst je u ovom slučaju

>>> nft_text = normalize(filtered_tagged_text)>>> nft_text[('usa', 'NNP'), ('day', 'NN'), ('usa', 'NNP')]

Poslednja funkcija u nizu pretprocesiranja eliminiše sve duplicirane parove (to-ken, tag)

>>> def unique_pairs(tagged_text):... return list(set(tagged_text))

Naš nalni tekst sada izgleda:

>>> unique_pairs(nft_text)[('usa', 'NNP'), ('day', 'NN')]

Implementacija TextRank algoritma Vreme je da pređemo na sam TextRankalgoritam. Ideja iza algoritma TextRank je sledeća. Prvo, potrebno je izvršiti pret-procesiranje teksta na opisan način. Zatim, konstruišemo graf čiji su čvorovi parovi(token, tag). Sada je potrebno de nisati grane između ovih čvorova. To je mogućeuraditi tako što ćemo za svaki token gledati reči koje se javljaju pre i posle toke-na u tekstu, ali samo određeni broj. Drugim rečima, postoji prozor u okviru kojegposmatramo kontekst jedne reči. Čvor koji predstavlja trenutnu reč spajamo samosa onim rečima koji se nalaze u njenom prozoru. Ovaj postupak je implementirannarednom funkcijom

>>> def build_graph(nft_text, window_size):... G = nx.Graph()... nodes = unique_pairs(nft_text)... node_pairs = list(itertools.combinations(nodes, 2))...... G.add_nodes_from(nodes)...... for pair in node_pairs:... first_word = pair[0]... second_word = pair[1]...... # Podesavanje tezina granama:... # Ne mozemo svim granama dodeliti tezinu 1 jer nije informativno.... # Umesto toga, postavljamo tezine u prozoru oko reci w... indices = [i for i, w in enumerate(nft_text) if w[0] == first_word]...... weight = 0...... for i in indices:... left = i - window_size... right = i + window_size...... if left < 0:... left = 0... if right > len(nft_text):... right = len(nft_text)...... if second_word in [w for (w,tag) in nft_text[left:right]]:

Page 102: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 4. NUMERIČKA LINEARNA ALGEBRA 96

... # Mogu se dodeliti i finija lingvisticka podesavanja,

... # na primer, broj pojavljivanja

... weight = 1

... break

...

... G.add_edge(first_word, second_word, weight=1)

...

... return G

Sledeći korak jeste izračunavanje rangova tokena. U tu svrhu, iskoristićemougrađenu bibliotečku funkciju nx.pagerank(G, ..., weight='weight', ...) koja po-kreće algoritam PageRank nad konstruisanim grafom G. Parametar weight predsta-vlja ključ na osnovu kojeg se pristupa podacima o granama iz grafa G. Podrazumeva-no je postavljen na 'weight', što nama odgovara, a u slučaju da je njegova vrednostNone, uzima se vrednost 1 za sve grane. Rezultat poziva funkcije je objekat tipa dictkoji za ključeve ima čvorove grafa G, a za vrednosti odgovarajuće rangove.>>> def extract_keywords(text, window_size=3):... word_tokens = nltk.word_tokenize(text)... tagged_text = nltk.pos_tag(word_tokens)...... # Zelimo da sacuvamo poredak kakav je bio u tekstu... text_list = [item[0] for item in tagged_text]...... filtered_tagged_text = filter_tags(tagged_text)... nft_text = normalize(filtered_tagged_text)...... G = build_graph(nft_text, window_size)...... page_rank_scores = nx.pagerank(G, weight='weight')...... # Sortiramo recnik po rangovima i biramo prvu trecinu rangiranih reci da sacuvamo... keywords = sorted(page_rank_scores, key=page_rank_scores.get, reverse=True)... one_third = len(text_list) // 3... final_keywords_list = keywords[:one_third]...... return final_keywords_list

Napisaćemo i funkciju kojom ćemo čuvati rezultate algoritma. Podrazumeva sepostojanje direktorijuma keywords u radnom direktorijumu.>>> def write_files(keywords, article, dirname='keywords'):... keywords_file = io.open(os.path.join(dirname, article), 'w', encoding='utf8')...... for keyword in keywords:... keywords_file.write(keyword[0] + '\n')...... keywords_file.close()

Konačno, napisaćemo i funkciju koja učitava članke i izvršava prethodna izraču-navanja>>> def run_algorithm(dirname = 'articles'):... articles = os.listdir(dirname)... for article in articles:... print('Reading' + article)

Page 103: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 4. NUMERIČKA LINEARNA ALGEBRA 97

... article_file = io.open(os.path.join(dirname, article), 'r', encoding='utf8')

... article_text = article_file.read()

... keyword = extract_keywords(article_text)

... write_files(keyword, article)

... article_file.close()

Page 104: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu
Page 105: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

Glava 5

Matematička optimizacija

Matematička optimizacija je jedna od najprimenjenijih grana matematike. Njencilj je de nisanje metoda pronalaženja minimuma i maksimuma funkcija. Opštiproblem optimizacije je obično oblika:

minx∈D

f(x)

pri uslovima gi(x) ≤ 0 i = 1, . . . ,L

pri čemu se funkcija f naziva ciljnom funkcijom, skup D domenom, a uslovi gi,takođe i ograničenjima. Objekat iz domena koji zadovoljava sva ograničenja, nazivase dopustivo rešenje. Potrebno je među svim dopustivim rešenjima naći ono za kojeje vrednost ciljne funkcije najmanja. Ova formulacija obuhvata i pronalaženje mak-simuma, pošto se pronalaženje maksimuma funkcije f može svesti na pronalaženjeminimuma funkcije −f. Zato će u nastavku biti reči isključivo o metodama pronala-ženja minimuma, odnosno minimizacije. Takođe, treba primetiti da se i jednakosnaograničenja lako uklapaju u navedeni okvir. Naime, ograničenje g(x) = 0 se možepredstaviti pomoću dva ograničenja — g(x) ≤ 0 i −g(x) ≤ 0.

5.1 Metode lokalne optimizacije prvog reda bez ogra-ničenja

Metode optimizacije prvog reda koriste vrednosti funkcije i njenih gradijenatau proizvoljnim tačkama pri izračunavanju. Prva i jednostavna tehnika koju ćemoprikazati naziva se gradijentni spust (engl. gradient descent), a zatim ćemo prećina linijske pretrage (engl. line search).

Gradijentni spust Algoritam započinje pretragu od na neki način izabrane počet-ne tačke x0. Zatim, u svakom koraku, pratimo smer suprotan gradijentu funkcije fu trenutnoj tački da bismo odredili naredni korak

xk+1 = xk − αk∇f(xk)

pri čemu je αk parametar kojim se određuje dužina koraka koji se pravi u korakuk i predstavlja hiperparametar algoritma. Što je njegova vrednost veća, algoritamima tendenciju da obilazi minimum, dok je za male vrednosti parametra αk kon-vergencija spora. Postavlja se pitanje izbora dužine koraka αk. Jedna jednostavna

99

Page 106: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 5. MATEMATIČKA OPTIMIZACIJA 100

implementacija podrazumeva ksiranu vrednost α, za svako k. Za kriterijum zausta-vljanja može se uzeti razlika u vrednostima funkcije između dva uzastopna koraka.Potpuna implementacija opisanog metoda data je narednom funkcijom>>> def gradient_descent(f, grad, x0, alpha, eps=0.01, max_iter=1000):... x_old = x0...... for i in range(max_iter+1):... x_new = x_old - alpha * grad(x_old)...... if np.abs(f(x_new) - f(x_old)) < eps:... break...... x_old = x_new...... return {... 'converge' : i != max_iter,... 'number of iterations' : i,... 'result' : x_new,... 'f-value' : f(x_new)... }

Neka je potrebno minimizovati funkciju f(x1,x2) = 12 (x21 + 10x22) metodom gradi-

jentnog spusta uz početnu vrednost (3,5). Neka su dodatni parametri α = 0.1 i ε =0.01. Ograničiti broj koraka na 1000. Gradijent funkcije f je ∇f(x1,x2) = (x1,10 ·x2).>>> def f(args):... x1 = args[0]... x2 = args[1]...... return 0.5*(x1**2 + 10 * x2**2)

>>> def grad(args):... x1 = args[0]... x2 = args[1]...... return np.array([x1, 10*x2])

>>> result = gradient_descent(f, grad, (3, 5), 0.01)>>> result{'converge': True,'number of iterations': 22,'result': array([0.26588814, 0. ]),'f-value': 0.03534825245075526}

Linijska pretraga Ovaj algoritam predstavlja metod za određivanje najveće du-žine koraka αk duž zadatog pravca p. Počinje se od relativno velike dužine, a zatimse vrednost dužine smanjuje iterativno, sve dok se ne primeti adekvatni spust vred-nosti funkcije, u odnosu na već zadatu vrednost funkcije.

Jedna jednostavna varijanta ovog algoritma, pod nazivom bektreking linijska pre-traga, podrazumeva da se vrednost dužine koraka množi faktorom τ ∈ (0,1).>>> def backtracking_line_search(f, xk, pk, fk, tau=0.5):... alpha = 1

Page 107: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 5. MATEMATIČKA OPTIMIZACIJA 101

... number_of_iterations = 1

...

... while f(xk + alpha*pk) >= fk:

... alpha *= tau

... number_of_iterations += 1

...

... return alpha, number_of_iterations

>>> backtracking_line_search(f, (3,5), -grad((3,5)), f((3,5)))(0.125, 4)

Druga varijantna ovog algoritma zasniva se na tzv. Armijo1 pravilu, koji pod-razumeva i postojanje hiperparametra β ∈ (0,1). Preciznije, dužina koraka αk dužpravca pk zadovoljava Armijo pravilo ako važi

f(xk + αkpk) ≤ f(xk) + βαkpTk∇f(xk)

>>> def armijo_line_search(f, xk, pk, gk, fk, beta=0.7, tau=0.5):... alpha = 1... number_of_iterations = 1...... while f(xk + alpha*pk) >= fk + alpha*beta*np.dot(pk.T, gk):... alpha *= tau... number_of_iterations += 1...... return alpha, number_of_iterations

>>> armijo_line_search(f, (3,5), -grad((3,5)), grad((3,5)) f((3,5)))(0.03125, 6)

Implementirajmo sada gradijentni spust uz korišćenje Armijo pravila za određi-vanje vrednosti dužine koraka αk>>> def gradient_descent_armijo(f, grad, x0, eps=0.01, max_iter=1000):... x_old = x0...... for i in range(max_iter+1):... alpha, _ = armijo_line_search(f, x_old, -grad(x_old), grad(x_old), f(x_old))... x_new = x_old - alpha * grad(x_old)...... if np.abs(f(x_new) - f(x_old)) < eps:... break...... x_old = x_new...... return {... 'converge' : i != max_iter,... 'number of iterations' : i,... 'result' : x_new,... 'f-value' : f(x_new)... }

>>> gradient_descent_armijo(f, grad, (3, 5))

1Larry Armijo, američki matematičar.

Page 108: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 5. MATEMATIČKA OPTIMIZACIJA 102

{'converge': True,'number of iterations': 15,'result': array([ 0.2018967, -0.0046595]),'f-value': 0.020489693196783686}

Ugrađena bibliotečka podrška Uokviru paketa scipy dostupan jemodul optimizekoji obuhvata raznovrsne metode za optimizaciju različitih tipova problema. Nada-lje pretpostavljamo uvoženje>>> from scipy import optimize as opt

Za izvršavanje linijske pretrage dostupna nam je funkcija opt.line_search(f,myfprime, xk, pk, gfk=None, old_fval=None, ...) koja izračunava dužinu koraka αkkoja zadovoljava Wolfe2 uslove. Wolfe uslovi predstavljaju dva uslova: (1) Armijouslov i (2) uslov zakrivljenosti (engl. curvature condition), koji su zadati formulama

f(xk + αkpk) ≤ f(xk) + c1αkpTk∇f(xk)−pTk∇f(xk + αkpk) ≤ −c2pTk∇f(xk)

(5.1)

pri čemu je 0 < c1 < c2 < 1. Povratne vrednosti ove funkcije su: dužina korakaalpha koja zadovoljava Wolfe uslove 5.1, broj evaluacija funkcije fc, broj evaluaci-ja gradijenta funkcije gc, trenutna vrednost funkcije new_fval, prethodna vrednostfunkcije old_fval i vrednost new_slope lokalnog zakrivljenja u trenutnoj tački dužpravca pretrage.>>> opt.line_search(f, grad, (3,5), -grad((3,5)), grad((3,5)), f((3,5)))(0.10032388340197529,2,1,3.643688272221999,129.5,array([ 2.69902835, -0.1619417 ]))

5.2 Metode lokalne optimizacije drugog reda bezograničenja

Metode optimizacije drugog reda pored vrednosti funkcije i gradijenta, koristehesijan. Kao što prvi parcijalni izvodi pružaju informaciju o brzini promene funkcijeduž različitih koordinatnih pravaca, tako hesijan pruža informaciju o brzini promenegradijenta duž različitih koordinatnih pravaca.

Njutnov metod Najpoznatiji metod drugog reda je Njutnov metod. U slučajufunkcija jedne promenljive, tekuće rešenje se ažurira po pravilu

xk+1 = xk −f′(xk)f′′(xk)

U slučaju funkcija vrše promenljivih, pravilo je analogno

xk+1 = xk −∇2f(xk)−1∇f(xk)

2Philip Wolfe (1927 — 2016), američki matematičar.

Page 109: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 5. MATEMATIČKA OPTIMIZACIJA 103

>>> def newton_method(f, grad, hess, x, eps=0.0001, max_iter=1000):... x_old = x... for i in range(max_iter+1):... x_new = x_old - np.dot(np.linalg.inv(hess(x_old)), grad(x_old))...... if np.abs(f(x_new) - f(x_old)) < eps:... break...... x_old = x_new...... return {... 'converge' : i != max_iter,... 'number of iterations' : i,... 'result' : x_new,... 'f-value' : f(x_new)... }

Neka je potrebno Njutnovom metodom minimizovati funkciju

f(x1,x2) =12 (1− x1)

2 + (x2 − x21)2

Njeni gradijent i hesijan su dati formulama

∇f(x1,x2) =(−1+ x1 − 4x1(x2 − x21),2(x2 − x21)

)∇2f(x1,x2) =

[1− 4x2 + 12x21 −4x1

−4x1 2

]>>> def f(x):... x0 = x[0]... x1 = x[1]... return 0.5*(1-x0)**2 + (x1-x0**2)**2

>>> def grad(x):... x0 = x[0]... x1 = x[1]... return np.array([-1 + x0 - 4*x0*(x1-x0**2), 2*(x1-x0**2)])

>>> def hess(x):... x0 = x[0]... x1 = x[1]... return np.array([... [1-4*x1+12*x0**2, -4*x0],... [-4*x0, 2]... ])

>>> newton_method(f, grad, hess, (2,2)){'converge': True,'f-value': 1.5407444102395282e-15,'number of iterations': 4,'result': array([ 1.00000006, 1.00000011])}

Bibliotečka podrška U okviru paketa scipy.optimize na raspolaganju nam jefunkcija opt.fmin_ncg(f, x0, fprime, ..., fhess=None, ...) koju možemo upotre-biti za optimizaciju Njutnovom metodom. Argumenti su: ciljna funkcija f, početna

Page 110: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 5. MATEMATIČKA OPTIMIZACIJA 104

tačka x0, funkcija gradijenta fprime, funkcija hesijana fhess. Funkcija ispisuje statusoptimizacije po završetku i kao rezultat vraća pronađeni minimum.

>>> opt.fmin_ncg(f, (2,2), grad, fhess=hess)Optimization terminated successfully.

Current function value: 0.000000Iterations: 9Function evaluations: 11Gradient evaluations: 19Hessian evaluations: 9

array([ 1., 1.])

Naravno, postoji i veliki broj drugih metoda optimizacije drugog reda bez ograni-čenja, od kojih ćemo mi spomenuti još jedan popularan metod — BFGS algoritam3.Iako nećemo diskutovati o njemu, pokazaćemo bibliotečku funkciju koja ga imple-mentira. Funkcija opt.fmin_bfgs(f, x0, fprime=None, ...) ne zahteva eksplicitnufunkciju za izračunavanje hesijana, već ga interno, pri svakom koraku optimizacije,aproksimira.

>>> opt.fmin_bfgs(f, (2,2), grad)Optimization terminated successfully.

Current function value: 0.000000Iterations: 8Function evaluations: 9Gradient evaluations: 9

array([ 1.00000582, 1.00001285])

5.3 Metode lokalne optimizacije sa ograničenjimaOgraničenja sužavaju domen namanji skup dopustivih rešenja. Minimum funkci-

je pri datim ograničenjima često nije jednak pravom minimumu funkcije. Dodatno,funkcije koje nemaju minimum, mogu ga imati u prisustvu ograničenja. Problemisa ograničenjima zahtevaju posebne metode rešavanja. Naime, praćenje gradijentafunkcije može lako dovesti do izlaska iz skupa dopustivih rešenja. Metode optimiza-cije u prisustvu ograničenja su raznovrsne i često se konstruišu za speci čne klaseproblema.

Najjednostavnija klasa problema sa ograničenjima su linearni problemi, odnosnoproblemi linearnog programiranja. Pritom, pod pojmom programa se ne podrazu-meva kod u nekom programskom jeziku, već postavka optimizacionog problema.Problemi linearnog programiranja se karakterišu linearnom funkcijom cilja i line-arnim ograničenjima. Pored njih, još jedna jednostavna klasa problema sa ograniče-njima su problemi kvadratnog programiranja, kod kojih je funkcija cilja kvadratna,a ograničenja su linearna.

Linearno programiranje Da bismo iskoristili ugrađenu bibliotečku funkciju zarešavanje problema linearnog programiranja, problem moramo svesti na oblik

minimizovati cT · xuz uslove Aub · x ≤ bub

Aeq · x = beq(5.2)

3Broyden–Fletcher–Goldfarb–Shanno algoritam.

Page 111: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 5. MATEMATIČKA OPTIMIZACIJA 105

Neka je potrebno pronaći minimum funkcije f(x0,x1) = 3x0 + 4x1 uz uslove x0 +2x1 ≤ 14,3x0 − x1 ≥ 0,x0 − x1 ≤ 2 koji treba da budu zadovoljeni. Da bismo sveliovakvu postavku problema na 5.2, potrebno je da sve uslove prezapišemo u odgo-varajućem obliku. Tako uslov 3x0 − x1 ≥ 0 postaje −3x0 + x1 ≤ 0. Dobijamo

c =

[34

]Aub =

1 2−3 11 −1

bub =

1402

Funkcija koju koristimo je opt.linprog(c, A_ub=None, b_ub=None, A_eq=None, b_eq=None,

bounds=None, method='simplex', ...), koja, pored matrica koje opisuju problem uobliku 5.2, kao argument (opciono) prima i sekvencu bounds parova (min, max) zasvaki element vektora x, a koji de nišu ograničenja na tom parametru. Može se ko-ristiti None za min ili max kada ne postoji ograničenje u tom smeru. Podrazumevanoje postavljena (0, None) (nenegativna granica). Ako se prosledi sekvenca sa jednimparom, tada se ta granica upotrebljava za sve promenljive u problemu. Parametarmethod određuje tip rešavača problema i podrazumevano je postavljen na simpleks,što je jedan od popularnijih i dobro poznatih rešavača.

Rezultat izvršavanja minimizatora je objekat tipa scipy.optimize.OptimizeResultkoji sadrži naredna polja: (1) vektor rešenja x, (2) vrednost u pokretnom zarezuciljne funkcije fun, (3) vektor vrednosti slek promenljivih slack, (4) Bulova vrednostsuccess koja opisuje uspešnost optimizacije, (5) celobrojna vrednost status koja opi-suje status završetka optimizacije, (6) broj koraka nit i (7) opis statusa završetkaoptimizacije message. Vrednost status može biti jedna od sledećih:

• 0 — optimizacija se uspešno završila

• 1 — dostignut je najveći broj iteracija

• 2 — problem se čini nedostižnim (engl. infeasible)

• 3 — problem se čini bezograničenim (engl. unbounded)

>>> c = np.array([3, 4])>>> A_ub = np.array([... [1, 2],... [-3, 1],... [1, -1]... ])>>> b_ub = np.array([14, 0, 2])

>>> opt.linprog(c, A_ub, b_ub)fun: -0.0

message: 'Optimization terminated successfully.'nit: 0

slack: array([14., 0., 2.])status: 0

success: Truex: array([0., 0.])

Pogledajmo još jedan primer. Neka su data dva gradilišta, g1 i g2. Da bi seposao uspešno realizovao na gradilištu g1, uvek moraju biti prisutna 4 kamiona,dok gradilište g2 zahteva 7 kamiona. Kamioni se nalaze u stanicama s1 i s2, pričemu stanica s1 raspolaže sa 8 kamiona, a stanica s2 sa 6 kamiona. Rastojanja su

Page 112: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 5. MATEMATIČKA OPTIMIZACIJA 106

data sa: x1 = d(s1,g1) = 8,x2 = d(s1,g2) = 7,x3 = d(g1, s2) = 3,x4 = d(g2, s2) = 5.Koliki treba da bude broj kamiona koji saobraća tako da se minimizuju troškovi?

Resenje se sastoji u minimizaciji ciljne funkcije

f0(x1,x2,x3,x4) = 8x1 + 9x2 + 3x3 + 5x4 (5.3)uz uslove

x1 + x3 = 4 (5.4)x2 + x4 = 7 (5.5)x1 + x2 ≤ 8 (5.6)x3 + x4 ≤ 6 (5.7)x1, ...,x4 ≥ 0 (5.8)

Već ovim je problem dovoljno dobro de nisan za korišćenje bibliotečke funkcijeopt.linprog (pogledati zadatak 5.3). Ipak, prikažimo još jedan način na koji možemorešiti problem.

Jednakosne uslove 5.4 i 5.5 možemo izraziti na sledeći način, redom

x3 = 4− x1x4 = 7− x2

Zamenom ovih jednakosti u nejednakost 5.7 dobija se

4− x1 + 7− x2 ≤ 6odnosno, nejednakost

− x1 − x2 ≤ −5 (5.9)Dodatno, iz jednakosnih uslova 5.4 i 5.5 i nejednakosnih uslova 5.8 dobijamo

nejednakosne uslove

0 ≤ x1 ≤ 40 ≤ x2 ≤ 7

(5.10)

Sada, problem svodimo na minimizaciju ciljne funkcije

f1(x1,x2) = 5x1 + 4x2 + 47odnosno, nakon eliminisanje konstante koja ne utiče na rešenje problema, ciljne

funkcije

f2(x1,x2) = 5x1 + 4x2uz uslove 5.6, 5.9 i 5.10, što se zapisuje

c =

[54

]Aub =

[1 1−1 −1

]bub =

[8−5

]Napomenimo da ćemo uslove 5.10 zapisati kao bounds parametar funkcije opt.linprog.

>>> c = np.array([5, 4])>>> A_ub = np.array([... [1, 1],... [-1, -1]... ])

Page 113: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 5. MATEMATIČKA OPTIMIZACIJA 107

>>> b_ub = np.array([8, -5])

>>> opt.linprog(c, A_ub, b_ub, bounds=[(0, 4), (0, 7)])fun: 20.0

message: 'Optimization terminated successfully.'nit: 3

slack: array([ 3., 0., 2., 0.])status: 0success: True

x: array([ 0., 5.])

Dakle, dobili smo da je x1 = 0 i x2 = 5. Odatle dobijamo da je x3 = 4 i x4 = 2.

Minimizacija nelinearnih funkcija jedne promenljive pod linearnim uslo-vima Neka je sada potrebno minimizovati funkciju f(x) =

√(x− 3)2 + 4 uz uslov

x ∈ [−1.5,1.5]. Kao što vidimo, funkcija f nije linearna po promenljivoj x. Međutim,kako je x skalar, moguće je iskoristiti funkciju opt.fminbound(func, x1, x2, args=(),..., full_output=0, ...), čiji su parametri: (1) ciljna funkcija jedne promenljive f,(2) donja granica x1, (3) gornja granica x2, (4) dodatni argumenti args koji se pro-sleđuju funkciji f i (5) Bulova vrednost full_output koja određuje da li se vraćajudodatna rešenja nakon što se pronađe prvo.

>>> def f(x):... return np.sqrt((x-3)**2 + 4)

>>> opt.fminbound(f, -1.5, 1.5, full_output=0)1.4999965250429437

>>> opt.fminbound(f, -1.5, 1.5, full_output=1)(1.4999965250429437, 2.5000020849757796, 0, 28)

Minimizacija diferencijalnih funkcija pod diferencijabilnim uslovima Ne-ka je potrebno minimizovati funkciju dve promenljive f(x,y) = 2xy + 2x − x2 − y2pod uslovima x3 − y = 0,y − 1 ≥ 0 i početnom tačkom (0,0). Prethodni metod nijeprimenljiv na ovu funkciju jer funkcija nije jedne promenljive, a ni uslovi nisu line-arni. Međutim, ova funkcija je diferencijabilna, kao i njeni uslovi. To je potrebankriterijum za korišćenje funkcije opt.minimize(fun, x0, args=(), method=None, ...,constraints=(), ...). Njeni parametri su: (1) ciljna funkcija oblika fun(x, *args)-> float, pri čemu je x jednodimenzionalni vektor nezavisne promenljive i args op-ciona torka dodatnih parametara, (2) početna tačka minimizacije x0, (3) opcionidodatni argumenti args koji se prosleđuju funkciji fun, (4) tip rešavača method i (5)lista mapa constraints (primenljivo za rešavače 'COBYLA', 'SLSQP' i 'trust-constr')koja de niše uslove pod kojima se vrši minimizacija. Za rešavače 'COBYLA' i 'SLSQP',ključevi mapa koje de nišu vrednosti su: (1) tip uslova type (može biti 'ineq' za ne-negativne nejednakosne uslove ili 'eq' za jednakosne po nuli uslove; za COBYLA jeprimenljiv samo prvi tip), (2) ciljna funkcija uslova fun i (3) jakobijan ciljne funkcijeuslova jac.

>>> def f(x_arg):... x = x_arg[0]... y = x_arg[1]... return 2*x*y + 2*x - x**2 - y**2

Page 114: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 5. MATEMATIČKA OPTIMIZACIJA 108

>>> constraints = [... {... 'type':'eq',... # definise uslov x^3 - y = 0... 'fun': lambda x_arg: np.array([x_arg[0]**3 - x_arg[1]]),... # njegov gradijent... 'jac': lambda x_arg: np.array([3*x_arg[0]**2, -1])... },... {... 'type':'ineq',... # definise uslov y - 1 >= 0... 'fun': lambda x_arg: np.array([x_arg[1] - 1]),... # njegov gradijent... 'jac': lambda x_arg: np.array([0, 1])... }... ]

>>> opt.minimize(f, (0,0), constraints=constraints, method='SLSQP')fun: 2.000000000000418jac: array([1.99999905e+00, 9.53674316e-07])

message: 'Optimization terminated successfully.'nfev: 124nit: 18njev: 18

status: 0success: True

x: array([1., 1.])

5.4 Primer primenematematičkeminimizacije — odre-đivanje parametra restauracije fotogra je

TODO: Dopuniti ovu sekciju sa više teksta i ulepšati kod i ispis.Neka su nam date dve fotogra je — jedna predstavlja originalnu fotogra ju,

a druga predstavlja tu fotogra ju kojoj su pikseli pomereni ulevo ili udesno (kaona slici 5.1). Zadatak je pronaći parametar pomeraja korišćenjem matematičkeoptimizacije.

from matplotlib import pyplot as pltimport numpy as npfrom scipy import optimize as optfrom scipy import ndimage as ndi

from skimage import io, data, color

astronaut = ndi.imread('astronaut.png', 'L')

plt.imshow(astronaut, cmap='gray')

# (0, -340)astronaut_shifted = ndi.shift(astronaut, (0, 50))

Page 115: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 5. MATEMATIČKA OPTIMIZACIJA 109

Slika 5.1: Originalna slika bw_astro.png (levo) i pomerena slika bw_astro_shifted.png(desno).

plt.imshow(astronaut_shifted, cmap='gray')

def mse(original, transformed):return np.mean((original-transformed)**2)

mse(astronaut, astronaut_shifted)

n = astronaut.shape[1]

shifts = np.linspace(-0.9*n, 0.9*n, 181)

mse_cost = []

for shift in shifts:shifted_back = ndi.shift(astronaut_shifted, (0, shift))mse_cost.append(mse(astronaut, shifted_back))

plt.plot(shifts, mse_cost)plt.xlabel('shifts')plt.ylabel('mse')

def astronaut_shift_error(shift, image):corrected = ndi.shift(image, (0, shift))return mse(astronaut, corrected)

result = opt.minimize(astronaut_shift_error, 0, args=(astronaut_shifted), method='Powell')

result

Page 116: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 5. MATEMATIČKA OPTIMIZACIJA 110

5.5 ZadaciZadatak 5.1 Broj otkucaja čovekovog srca u toku njegovog zivota je, kao što zna-mo, konačan. Posmatrajmo sledeći pojednostavljen model. Važi da prosečan pulsčoveka iznosi 80 otkucaja u minuti. Kada se čovek izlaže zičkim aktivnostima, pulsraste na 120 otkucaja u minuti. Međutim, čovek koji je u formi nema prosek od 80otkucaja, već od 50 otkucaja u minuti. Dakle, redovnim vežbanjem smanjujemoprosečan puls (što znači da trošimo manje otkucaja), ali se takođe izlažemo napo-ru (što znači da trošimo više otkucaja). Postavlja se pitanje — kolika je prosečnaoptimalna količina vežbanja u toku dana?

Zadatak 5.2 Njutnovom metodom minimizovati funkciju

g(x) = 2x21 + 3x22Uporediti rezultate dobijene implementiranom funkcijom newton_method i biblio-

tečkom funkcijom opt.fmin_ncg. Za preciznost uzeti vrednost 10−4, za maksimalnibroj iteracija 1000 i za početnu tačku uzeti (1,1).

Zadatak 5.3 Rešiti primer sa gradilištima korišćenjem inicijalne postavke proble-ma (koja uključuje jednakosne uslove).

Page 117: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

Glava 6

Rešenja zadataka

6.1 Uvod

6.2 Aproksimacija funkcija

6.3 Furijeove transformacijeRešenje 6.3.1 Frekvencijska rezolucija se jednostavno dobija deljenjem frekven-cije uzorkovanja i broja uzoraka. Najveća frekvencija je ona koja se postiže u fre-kvencijskoj rezoluciji za uzorak N/2 (prisetimo se da posmatramo frekvencije od−N/2+ 1 do N/2 umesto od 1 do N):Fs = 10000N = 1024

fs = Fs/Nmax_freq = fs * N/2

Rešenje 6.3.2 Frekvencija uzorkovanja se u ovom slučaju direktno može izraču-nati:T = 0.5N = 32

Fs = N // T

Kako se frekvencije beleže na podeocima (Fs/N) ·k, onda je u našem slučaju k-tafrekvencijska korpica oblika 2k. Dakle, za k = 5, zička frekvencija je 10Hz, a zak = 27 dobija se 54Hz, tj. −10Hz. Odavde sledi da je f = 10.

Naredni fragment koda prikazuje frekvencijski spektar za signal čija je osnovnafrekvencija f+ 1, odnosno, x(t) = cos(2π · 11 · t). Rezultat je dat na slici 6.1.N = 32freq = fft.fftfreq(N, 1/64)t = np.linspace(0, 0.5, N)s = np.cos(2 * np.pi * 11 * t)c = fft.fft(s)plt.stem(freq, np.abs(c))plt.show()

111

Page 118: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 6. REŠENJA ZADATAKA 112

Slika 6.1: Frekvencijski spektar za signal čija je osnovna frekvencija f+ 1.

Slika 6.2: Primena Laplasovog ltera nad crno-belom verzijom slike keep_calm.png.

Rešenje 6.3.3

Rešenje 6.3.4 Rešenje ovog zadatka se sastoji od primene bibliotečke funkcijendimage.convolve. Na slici 6.2 prikazan je rezultat primene Laplasovog ltera. Upo-ređivanjem ove slike sa rezultatom dobijenim primenom Sobelovog ltera na slici3.17 (desno), zaključujemo da Laplasov lter daje bolje rezultate u određivanju kon-tura.

Page 119: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 6. REŠENJA ZADATAKA 113

>>> laplacian = np.array([... [0, 1, 0],... [1,-4, 1],... [0, 1, 0]... ])

>>> img = np.array(Image.open('keep_calm.png').convert('L'))>>> img_laplacian = ndimage.convolve(img, laplacian)>>> img_laplacian = Image.fromarray(img_laplacian)>>> img_laplacian.show()

6.4 OptimizacijaRešenje 6.4.1 Neka je x broj minuta koliko vežbamo u proseku (izraženo u pro-centima). Tada opisani model možemo opisati funkcijom

f(x) = 120x+ faktor · (1− x)Vrednost faktor treba da poseduje sledeću karakteristiku — što je x bliže vred-

nosti 1, to je faktor bliži 50, a što je x bliži 0, to je faktor bliži 80. Jedna mogućainterpretacija ove karakteristike data je izrazom

faktor = 50+ 30e−100x

Dakle, zadatak je minimizovanje funkcije

f(x) = 120x+ (50+ 30e−100x)(1− x)Gradijent funkcije je

f′(x) = 120+ (30e−100x(−100))(1− x)− 50− 30e−100x =

= 70− 30e−100x − 300e−100x(1− x)

Možemo iskoristiti gradijentni spust za određivanje najmanje vrednosti x.TODO: implementirati

Rešenje 6.4.2 Funkcija i njeni gradijent i hesijan su dati narednim implementaci-jama>>> def g(x):... x1 = x[0]... x2 = x[1]... return 2*x1**2 + 3*x2**2

>>> def grad_g(x):... x1 = x[0]... x2 = x[1]... return np.array([4*x1, 6*x2])

>>> def hess_g(x):... x1 = x[0]... x2 = x[1]... return np.array([

Page 120: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

GLAVA 6. REŠENJA ZADATAKA 114

... [4, 0],

... [0, 6]

... ])

>>> eps_trial = 1e-4>>> max_iterations = 1000>>> x0 = (1,1)

Upoređivanjem rezultata vidimo da su obe funkcije dobile istu vrednost minimu-ma, sa razlikom da je funkcija newton_method imala manji broj koraka.>>> newton_method(g, grad_g, hess_g, x0, eps_trial, max_iterations){'converge': True,'f-value': 0.0,'number of iterations': 1,'result': array([ 0., 0.])}

>>> opt.fmin_ncg(g, x0, grad_g, fhess=hess_g, epsilon=eps_trial, maxiter=max_iterations)Optimization terminated successfully.

Current function value: 0.000000Iterations: 6Function evaluations: 7Gradient evaluations: 12Hessian evaluations: 6

array([ 0., 0.])

Page 121: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

Literatura

[1] M. Nikolić and A. Zečević, Naučno izračunavanje. Matematički fakultet, 2017.Dostupno u elektronskoj formi na adresihttp://www.ni.matf.bg.ac.rs/materijali/ni.pdf.

[2] Python 3.6.4 documentation. Dostupno na adresi https://docs.python.org/3/.

[3] Numpy and Scipy Documentation. Dostupno na adresihttps://docs.scipy.org/doc/.

[4] User's Guide – Matplotlib 2.1.2 documentation. Dostupno na adresihttps://matplotlib.org/users/index.html.

[5] Python Data Analysis Library. Dostupno na adresi https://pandas.pydata.org/.

[6] Z. Petrić, Linearna algebra. Matematički fakultet, 2013. Dostupno uelektronskoj formi na adresi http://www.mi.sanu.ac.rs/~zpetric/skripta.pdf.

[7] Scikit Learn: Machine Learning in Python. Dostupno na adresihttp://scikit-learn.org/stable/.

115

Page 122: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu
Page 123: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

Dodatak A

Liste slika i tabela

Lista slika1.1 Dva primera korišćenja funkcije plt.plot nad istim skupom tačaka u

ravni. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121.2 Primer slaganja dva različita opšta gra ka na jednom prikazu. Na

ovom prikazu su demonstrirane i operacije iz tabele 1.8. . . . . . . . . . 131.3 Stubičasti dijagram atributa "stepen ugroženosti" jezika u nestajanju. . 202.1 Histogram vrednosti društvenog dometa za svaku od zemalja. . . . . . . 312.2 Tačkasti nacrti zavisnosti cilje promenljive Sales od atributa TV, Radio i

Newspaper, redom (sleva). . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332.3 Histogram reziduala linearnog modela u primeru procene cena domo-

va u Bostonu. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382.4 Toplotna mapa matrice korelacije atributa u primeru procene cena do-

mova u Bostonu. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402.5 Gra čki prikaz primera skupa podataka (levo) i dva načina vršenja

standardizacije podataka — ispravno (sredina) i neispravno (desno).Pri ispravnoj standardizaciji, podaci čuvaju prvobitnu strukturu, dokpri neispravnoj standardizaciji dolazi do promene strukture podatakau skupu za evaluaciju. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

2.6 Gra k zavisnosti greške predviđanja i izbora metaparametra alpha. . . 452.7 Prikaz ispravnog toka faza izbora, obučavanja i evaluacije modela ko-

rišćenjem skupova za obučavanje, validaciju i evaluaciju. . . . . . . . . . 463.1 Ilustracija analiza signala (kojeg posmatramo u vremenskom domenu)

pomoću Furijeove transformacije (u frekvencijskom domenu). . . . . . . 513.2 Primer talasa i njegovog drugog i trećeg harmonika. . . . . . . . . . . . 523.3 Gra k vremenskog domena signala s(t) = 2·sin(2πt)+3·sin(2·22πt)+ϵ,

gde je ϵ ∼ N (0,1). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 543.4 Gra k frekvencijskog domena signala s(t) = 2·sin(2πt)+3·sin(2·22πt)+

ϵ, gde je ϵ ∼ N (0,1). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 553.5 Gra k frekvencijskog domena signala s(t) = 2·sin(2πt)+3·sin(2·22πt)+

ϵ, gde je ϵ ∼ N (0,1) (plavo) i signala dobijenog od signala s(t) elimina-cijom šuma (ljubičasto). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

3.6 Prikaz kontrola u Jupyter Notebook okruženju nakon učitavanja zvuč-nog signala pomoću funkcije IPython.display.Audio. . . . . . . . . . . . . 57

3.7 Prikaz jednog fragmenta zvučnog zapisa bonobo_towers.wav u frekven-cijskom domenu, ltriran na skup do 1000 frekvencija. . . . . . . . . . . 58

3.8 Primer savršenog (gore) i nesavršenog (dole) uzorkovanja signala. . . . 59

117

Page 124: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

DODATAK A. LISTE SLIKA I TABELA 118

3.9 Primer prozorskih funkcija: Blekmanova funkcija (crveno), Hanova funk-cija (plavo), Hamingova funkcija (zeleno) i Kaizerova funkcija (žuto). . 59

3.10Spektrogram zvučnog zapisa bonobo_towers.wav. . . . . . . . . . . . . . . 603.11Spektrogram zvučnog zapisa bonobo_towers.wav dobijen korišćenjem funk-

cije scipy.signal.spectrogram. . . . . . . . . . . . . . . . . . . . . . . . . . 613.12Slike dance.jpg (levo) i keep_calm.png (desno). . . . . . . . . . . . . . . . . 623.13Furijeova transformacija slike dance.jpg u crno-belom modu: slika do-

bijena samo primenom funkcije fft.fft2 (levo) i ista slika sa transli-ranim koe cijentima tako da se vrednost koe cijenta f(0,0) nalazi ucentru slike (desno). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63

3.14Zamućena crno-bela verzija slike dance.jpg dobijena odsecanjem viso-kih frekvencija. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

3.15Prikaz kontura crno-bele verzije slike dance.jpg dobijen odsecanjemniskih frekvencija. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

3.16Konvolucija u obradi slika. . . . . . . . . . . . . . . . . . . . . . . . . . . . 663.17Primena nekih bibliotečkih ltera nad crno-belom verzijom slike keep_calm.png

— PIL.ImageFilter.BLUR() (levo) i scipy.ndimage.filters.sobel (desno). 673.18Prikaz vodenog žiga generisanog funkcijom make_watermark (levo) i nje-

gova primena nad crno-belom verzijom slike keep_calm.png (desno). . . 693.19Slika uz zadatak 3.2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 704.1 Originalna slika tiger_bw.jpg koju želimo da aproksimiramo SVD de-

kompozicijom. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 764.2 Gra čki prikaz vektora sopstvenih vrednosti (levo) i kumulativne sume

vektora sopstvenih vrednosti (desno) dobijenih SVD dekompozicijomslike 4.1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

4.3 Aproksimacije slike 4.1 ranga 5,20,50,100,175 i 280, redom. . . . . . . 784.4 Prikaz generisanih podataka za primer rešavanja sistema linearnih jed-

načina pomoću SVD dekompozicije. . . . . . . . . . . . . . . . . . . . . . . 794.5 Prikaz skupa podataka breast_cancer u novom prostoru koji razapinju

prve dve glavne komponente datog skupa podataka. . . . . . . . . . . . 834.6 Prikaz toplotne mape odnosa atributa skupa podataka breast_cancer u

početnom prostoru i atributa u novom prostoru koji razapinju prve dveglavne komponente datog skupa podataka. . . . . . . . . . . . . . . . . . 84

4.7 Primeri slika osoba i njihova imena. . . . . . . . . . . . . . . . . . . . . . . 854.8 Prikaz prvih nekoliko glavnih komponenti koje nazivamo sopstvena lica. 874.9 Primer iscrtavanja objekta tipa nx.Graph. . . . . . . . . . . . . . . . . . . . 935.1 Originalna slika bw_astro.png (levo) i pomerena slika bw_astro_shifted.png

(desno). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1096.1 Frekvencijski spektar za signal čija je osnovna frekvencija f+ 1. . . . . 1126.2 Primena Laplasovog ltera nad crno-belom verzijom slike keep_calm.png.112

Page 125: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

DODATAK A. LISTE SLIKA I TABELA 119

Lista tabela1.1 Načini na koje je moguće uvesti dobavljene pakete u radno okruženje

u programskom jeziku Python. . . . . . . . . . . . . . . . . . . . . . . . . . 21.2 Primeri literala odgovarajućih osnovnih tipova u programskom jeziku

Python. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41.3 Primeri operacija nad odgovarajućim tipovima u programskom jeziku

Python. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41.4 Primeri korišćenja kontrola toka u programskom jeziku Python. . . . . 51.5 Operacije koje se mogu izvršiti nad proizvoljnom sekvencom (koja će

biti referisana kao seq ili više njih, koje će biti referisane kao seq1 iseq2) i njihovi opisi. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

1.6 Operacije koje se mogu izvršiti nad proizvoljnom listom (koja će bitireferisana kao list) i njihovi opisi. . . . . . . . . . . . . . . . . . . . . . . 7

1.7 Operacije nad matricama (M, M1 i M2) u biblioteci NumPy i njihovi opisi. 101.7 Operacije nad matricama (M, M1 i M2) u biblioteci NumPy i njihovi opisi

(nastavak). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111.8 Dodatne karakteristike PyPlot prikaza. . . . . . . . . . . . . . . . . . . . . 131.9 Jednostavne operacije nad strukturom podataka Series (koja će biti re-

ferencirana oznakom s) i njihovi opisi. . . . . . . . . . . . . . . . . . . . . 151.10Operacije nad strukturom podataka DataFrame (koja će biti referencira-

na oznakom df) i njihovi opisi. . . . . . . . . . . . . . . . . . . . . . . . . . 192.1 Moguće vrednosti parametra ord funkcije LA.norm. . . . . . . . . . . . . . 232.2 Prikaz skupa podataka social_reach. . . . . . . . . . . . . . . . . . . . . . 303.1 Neke operacije de nisane nad tipom PIL.Image.Image. . . . . . . . . . . . 62

Page 126: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu
Page 127: AjzenhamerNikola · 2020. 9. 19. · GLAVA1. UVOD 2 Direktnimunošenjemnaredbimogućejekomuniciratisainterpreterom. Postojei druginačinizaizvršavanjekôdova,kaoštojepisanjePythonskripti(kojipodrazu

Dodatak B

Lista resursa

Naziv resursa Adresa na internetu

Extinct Languages https://www.kaggle.com/the-guardian/extinct-languagesHitters https://www.kaggle.com/ oser/hitters/data

121