<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Sveučilište u Zagrebu
Fakultet elektrotehnike i računarstva  
Strojno učenje 2019/2020
http
Step1:  1. Ansambli (glasovanje)
(a)
Vaš je zadatak napisati razred VotingClassifierDIY koji implementira glasački ansambl. Konstruktor razreda ima dva parametra
Step2:  (b)
Uvjerite se da Vaša implementacija radi jednako onoj u razredu ensemble.VotingClassifier, i to pri oba načina glasovanja (parametar voting). Parametar weights ostavite na pretpostavljenoj vrijednosti. Za ovu provjeru koristite tri klasifikatora logističke regresije s različitom stopom regularizacije i brojem iteracija. Koristite skup podataka dan u nastavku. Ekvivalentnost implementacije najlakše je provjeriti usporedbom izlaza funkcije predict (kod prebrojavanja) i funkcije predict_proba (kod usrednjavanja).
NB
Step3:  Q
Step4:  Razred koji implementira stablo odluke jest tree.DecisionTreeClassifier. Prvo naučite stablo odluke (engl. decision tree) na skupu za učenje, ali tako da je taj model presložen. To možete postići tako da povećate najveću moguću dubinu stabla (parametar max_depth). Ispišite pogrešku na skupu za ispitivanje (pogrešku 0-1; pogledajte paket metrics).
Step5:  Sada isprobajte algoritam slučajnih šuma (dostupan u razredu ensemble.RandomForestClassifier) za različit broj stabala $L \in [1, 30]$. Iscrtajte pogrešku na skupu za učenje i na skupu za ispitivanje u ovisnosti o tom hiperparametru. Ispišite najmanju pogrešku na skupu za ispitivanje.
Step6:  Q
Step7:  (a)
Boosting, kao vrsta ansambla, također se temelji na kombinaciji više klasifikatora s ciljem boljih prediktivnih sposobnosti. Međutim, ono što ovakav tip ansambla čini zanimljivim jest to da za osnovni klasifikator traži slabi klasifikator (engl. weak classifier), odnosno klasifikator koji radi tek malo bolje od nasumičnog pogađanja. Često korišteni klasifikator za tu svrhu jest panj odluke (engl. decision stump), koji radi predikciju na temelju samo jedne značajke ulaznih primjera. Panj odluke specijalizacija je stabla odluke (engl. decision tree) koje smo već spomenuli. Panj odluke stablo je dubine 1. Stabla odluke implementirana su u razredu tree.DecisionTreeClassifier.
Radi ilustracije, naučite ansambl (AdaBoost) koristeći panj odluke kao osnovni klasifikator, ali pritom isprobavajući različit broj klasifikatora u ansamblu iz skupa $L \in {1, 2, 3, 50}$. Prikažite decizijske granice na danom skupu podataka za svaku od vrijednosti korištenjem pomoćne funkcije mlutils.plot_2d_clf_problem.
NB
Step8:  Q
Step9:  Iscrtajte krivulje pogrešaka na skupu za učenje i ispitivanje u ovisnosti o hiperparametru $L \in [1,80]$. Koristite pogrešku 0-1 iz paketa metrics. Ispišite najmanju ostvarenu pogrešku na skupu za ispitivanje, te pripadajuću vrijednost hiperparametra $L$.
Step10:  Q
Step11:  Q
Step12:  (b)
Prikažite funkciju $\mathcal{L}(\mu|N,m)$ za (1) $N=10$ i $m=1,2,5,9$ te za (2) $N=100$ i $m=1,10,50,90$ (dva zasebna grafikona).
Step13:  Q
Step14:  Q
Step15:  Q
Step16:  Q
Step17:  (g)
Pročitajte ove upute o učitavanju oglednih skupova podataka. Učitajte skup podataka Iris. Taj skup sadrži $n=4$ značajke i $K=3$ klase. Odaberite jednu klasu i odaberite sve primjere iz te klase, dok ostale primjere zanemarite (u nastavku radite isključivo s primjerima iz te jedne klase). Vizualizirajte podatke tako da načinite 2D-prikaze za svaki par značajki (šest grafikona; za prikaz je najjednostavnije koristiti funkciju scatter).
NB
Step18:  (h)
Pogledajte opis modul stats te proučite funkciju norm. Implementirajte funkciju log-izglednosti za parametre $\mu$ i $\sigma^2$ normalne distribucije.
Step19:  (i)
Izračunajte ML-procjene za $(\mu, \sigma^2)$ za svaku od $n=4$ značajki iz skupa Iris. Ispišite log-izglednosti tih ML-procjena.
Step20:  Q
Step21:  (k)
Proučite funkciju cov te izračunajte ML-procjenu za kovarijacijsku matricu za skup Iris. Usporedite pristranu i nepristranu procjenu. Pokažite da se razlika (srednja apsolutna i kvadratna) smanjuje s brojem primjera (npr. isprobajte za $N/4$ i $N/2$ i $N$ primjera).
<ASSISTANT_TASK:>
Python Code:
# Učitaj osnovne biblioteke...
import sklearn
import mlutils
import numpy as np
import matplotlib.pyplot as plt
%pylab inline
Explanation: Sveučilište u Zagrebu
Fakultet elektrotehnike i računarstva  
Strojno učenje 2019/2020
http://www.fer.unizg.hr/predmet/su
Laboratorijska vježba 4: Ansambli i procjena parametara
Verzija: 0.4
Zadnji put ažurirano: 27. rujna 2019.
(c) 2015-2019 Jan Šnajder, Domagoj Alagić  
Objavljeno: 30. rujna 2019.
Rok za predaju: 16. prosinca 2019. u 07:00h
Upute
Četvrta laboratorijska vježba sastoji se od četiri zadatka. Kako bi kvalitetnije, ali i na manje zamoran način usvojili gradivo ovog kolegija, potrudili smo se uključiti tri vrste zadataka: 1) implementacija manjih algoritama, modela ili postupaka; 2) eksperimenti s raznim modelima te njihovim hiperparametrima, te 3) primjena modela na (stvarnim) podatcima. Ovim zadatcima pokrivamo dvije paradigme učenja: učenje izgradnjom (engl. learning by building) i učenje eksperimentiranjem (engl. learning by experimenting).
U nastavku slijedite upute navedene u ćelijama s tekstom. Rješavanje vježbe svodi se na dopunjavanje ove bilježnice: umetanja ćelije ili više njih ispod teksta zadatka, pisanja odgovarajućeg kôda te evaluiranja ćelija. 
Osigurajte da u potpunosti razumijete kôd koji ste napisali. Kod predaje vježbe, morate biti u stanju na zahtjev asistenta (ili demonstratora) preinačiti i ponovno evaluirati Vaš kôd. Nadalje, morate razumjeti teorijske osnove onoga što radite, u okvirima onoga što smo obradili na predavanju. Ispod nekih zadataka možete naći i pitanja koja služe kao smjernice za bolje razumijevanje gradiva (nemojte pisati odgovore na pitanja u bilježnicu). Stoga se nemojte ograničiti samo na to da riješite zadatak, nego slobodno eksperimentirajte. To upravo i jest svrha ovih vježbi.
Vježbe trebate raditi samostalno. Možete se konzultirati s drugima o načelnom načinu rješavanja, ali u konačnici morate sami odraditi vježbu. U protivnome vježba nema smisla.
End of explanation
from collections import Counter
class VotingClassifierDIY(object):
    
    SCHEME_COUNTING = "counting"
    SCHEME_AVERAGING = "averaging"
    
    def __init__(self, clfs, voting_scheme=SCHEME_COUNTING):
        # Vaš kôd ovdje
        pass
        
    def fit(self, X, y):
        # Vaš kôd ovdje
        pass
    
    def predict_proba(self, X):
        # Vaš kôd ovdje
        pass
    
    def predict(self, X):
        # Vaš kôd ovdje
        pass
Explanation: 1. Ansambli (glasovanje)
(a)
Vaš je zadatak napisati razred VotingClassifierDIY koji implementira glasački ansambl. Konstruktor razreda ima dva parametra: clfs koji predstavlja listu klasifikatora (objekata iz paketa sklearn) i voting_scheme koji označava radi li se o glasovanju prebrojavanjem (SCHEME_COUNTING) ili usrednjavanjem (SCHEME_AVERAGING). Glasovanje prebrojavanjem jednostavno vraća najčešću oznaku klase, dok glasovanje usrednjavanjem uprosječuje pouzdanosti klasifikacije u neku klasu (po svim klasifikatorima) te vraća onu s najvećom pouzdanošću. Primijetite da svi klasifikatori imaju jednake težine. O komplementarnosti klasifikatora vodimo računa tako da koristimo jednake klasifikatore s različitim hiperparametrima.
Razred sadržava metode fit(X, y) za učenje ansambla i dvije metode za predikciju: predict(X) i predict_proba(X). Prva vraća predviđene oznake klasa, a druga vjerojatnosti pripadanja svakoj od klasa za svaki od danih primjera iz X.
NB: Jedan od razreda koji bi Vam mogao biti koristan jest collections.Counter. Također vrijedi i za funkcije numpy.argmax i numpy.dstack.
End of explanation
from sklearn.datasets import make_classification
from sklearn.ensemble import VotingClassifier
from sklearn.linear_model import LogisticRegression
X_voting, y_voting = make_classification(n_samples=1000, n_features=4, n_redundant=0, n_informative=3, n_classes=3, n_clusters_per_class=2)
# Vaš kôd ovdje
Explanation: (b)
Uvjerite se da Vaša implementacija radi jednako onoj u razredu ensemble.VotingClassifier, i to pri oba načina glasovanja (parametar voting). Parametar weights ostavite na pretpostavljenoj vrijednosti. Za ovu provjeru koristite tri klasifikatora logističke regresije s različitom stopom regularizacije i brojem iteracija. Koristite skup podataka dan u nastavku. Ekvivalentnost implementacije najlakše je provjeriti usporedbom izlaza funkcije predict (kod prebrojavanja) i funkcije predict_proba (kod usrednjavanja).
NB: Ne koristimo SVM jer njegova ugrađena (probabilistička) implementacija nije posve deterministička, što bi onemogućilo robusnu provjeru Vaše implementacije.
End of explanation
from sklearn.model_selection import train_test_split
X_bag, y_bag = make_classification(n_samples=1000, n_features=20, n_redundant=1, n_informative=17, n_classes=3, n_clusters_per_class=2)
X_bag_train, X_bag_test, y_bag_train, y_bag_test = train_test_split(X_bag, y_bag, train_size=0.7, random_state=69)
Explanation: Q: Kada je prebrojavanje bolje od usrednjavanja? Zašto? A obratno?
Q: Bi li se ovakav algoritam mogao primijeniti na regresiju? Kako?
2. Ansambli (bagging)
U ovom zadatku ćete isprobati tipičnog predstavnika bagging-algoritma, algoritam slučajnih šuma. Pitanje na koje želimo odgovoriti jest kako se ovakvi algoritmi nose s prenaučenošću, odnosno, smanjuje li bagging varijancu modela.
Eksperiment ćete provesti na danom skupu podataka:
End of explanation
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import zero_one_loss
# Vaš kôd ovdje
Explanation: Razred koji implementira stablo odluke jest tree.DecisionTreeClassifier. Prvo naučite stablo odluke (engl. decision tree) na skupu za učenje, ali tako da je taj model presložen. To možete postići tako da povećate najveću moguću dubinu stabla (parametar max_depth). Ispišite pogrešku na skupu za ispitivanje (pogrešku 0-1; pogledajte paket metrics).
End of explanation
from sklearn.ensemble import RandomForestClassifier
# Vaš kôd ovdje
Explanation: Sada isprobajte algoritam slučajnih šuma (dostupan u razredu ensemble.RandomForestClassifier) za različit broj stabala $L \in [1, 30]$. Iscrtajte pogrešku na skupu za učenje i na skupu za ispitivanje u ovisnosti o tom hiperparametru. Ispišite najmanju pogrešku na skupu za ispitivanje.
End of explanation
from sklearn.datasets import make_circles
circ_X, circ_y = make_circles(n_samples=400, noise=0.1, factor=0.4)
mlutils.plot_2d_clf_problem(circ_X, circ_y)
Explanation: Q: Što možete zaključiti iz ovih grafikona?
Q: Kako bagging postiže diverzifikaciju pojedinačnih osnovnih modela?
Q: Koristi li ovaj algoritam složeni ili jednostavni osnovni model? Zašto?
3. Ansambli (boosting)
U ovom zadatku pogledat ćemo klasifikacijski algoritam AdaBoost, koji je implementiran u razredu ensemble.AdaBoostClassifier. Ovaj algoritam tipičan je predstavnik boosting-algoritama.
Najprije ćemo generirati eksperimentalni skup podataka koristeći datasets.make_circles. Ova funkcija stvara dvodimenzijski klasifikacijski problem u kojem su dva razreda podataka raspoređena u obliku kružnica, tako da je jedan razred unutar drugog.
End of explanation
from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
# Vaš kôd ovdje
Explanation: (a)
Boosting, kao vrsta ansambla, također se temelji na kombinaciji više klasifikatora s ciljem boljih prediktivnih sposobnosti. Međutim, ono što ovakav tip ansambla čini zanimljivim jest to da za osnovni klasifikator traži slabi klasifikator (engl. weak classifier), odnosno klasifikator koji radi tek malo bolje od nasumičnog pogađanja. Često korišteni klasifikator za tu svrhu jest panj odluke (engl. decision stump), koji radi predikciju na temelju samo jedne značajke ulaznih primjera. Panj odluke specijalizacija je stabla odluke (engl. decision tree) koje smo već spomenuli. Panj odluke stablo je dubine 1. Stabla odluke implementirana su u razredu tree.DecisionTreeClassifier.
Radi ilustracije, naučite ansambl (AdaBoost) koristeći panj odluke kao osnovni klasifikator, ali pritom isprobavajući različit broj klasifikatora u ansamblu iz skupa $L \in {1, 2, 3, 50}$. Prikažite decizijske granice na danom skupu podataka za svaku od vrijednosti korištenjem pomoćne funkcije mlutils.plot_2d_clf_problem.
NB: Još jedan dokaz da hrvatska terminologija zaista može biti smiješna. :)
End of explanation
from sklearn.model_selection import train_test_split
X_boost, y_boost = make_classification(n_samples=1000, n_features=20, n_redundant=0, n_informative=18, n_classes=3, n_clusters_per_class=1)
X_boost_train, X_boost_test, y_boost_train, y_boost_test = train_test_split(X_boost, y_boost, train_size=0.7, random_state=69)
Explanation: Q: Kako AdaBoost radi? Ovise li izlazi pojedinih osnovnih modela o onima drugih?
Q: Je li AdaBoost linearan klasifikator? Pojasnite.
(b)
Kao što je i za očekivati, broj klasifikatora $L$ u ansamblu predstavlja hiperparametar algoritma AdaBoost. U ovom zadatku proučit ćete kako on utječe na generalizacijsku sposobnost Vašeg ansambla. Ponovno, koristite panj odluke kao osnovni klasifikator.
Poslužite se skupom podataka koji je dan niže.
End of explanation
# Vaš kôd ovdje
Explanation: Iscrtajte krivulje pogrešaka na skupu za učenje i ispitivanje u ovisnosti o hiperparametru $L \in [1,80]$. Koristite pogrešku 0-1 iz paketa metrics. Ispišite najmanju ostvarenu pogrešku na skupu za ispitivanje, te pripadajuću vrijednost hiperparametra $L$.
End of explanation
# Vaš kôd ovdje
Explanation: Q: Može li uopće doći do prenaučenosti pri korištenju boosting-algoritama?
(c)
Kao što je rečeno na početku, boosting-algoritmi traže slabe klasifikatore kako bi bili najefikasniji što mogu biti. Međutim, kako se takav ansambl mjeri s jednim jakim klasifikatorom (engl. strong classifier)? To ćemo isprobati na istom primjeru, ali korištenjem jednog optimalno naučenog stabla odluke.
Ispišite pogrešku ispitivanja optimalnog stabla odluke. Glavni hiperparametar stabala odluka jest njihova maksimalna dubina $d$ (parametar max_depth). Iscrtajte krivulje pogrešaka na skupu za učenje i ispitivanje u ovisnosti o dubini stabla $d \in [1,20]$.
End of explanation
# Vaš kôd ovdje
Explanation: Q: Isplati li se koristiti ansambl u obliku boostinga? Idu li grafikoni tome u prilog?<br>
Q: Koja je prednost boostinga nad korištenjem jednog jakog klasifikatora?
4. Procjena maksimalne izglednosti i procjena maksimalne aposteriorne vjerojatnosti
(a)
Definirajte funkciju izglednosti $\mathcal{L}(\mu|\mathcal{D})$ za skup $\mathcal{D}={x^{(i)}}_{i=1}^N$ Bernoullijevih varijabli. Neka od $N$ varijabli njih $m$ ima vrijednost 1 (npr. od $N$ bacanja novčića, $m$ puta smo dobili glavu). Definirajte funkciju izglednosti tako da je parametrizirana s $N$ i $m$, dakle definirajte funkciju $\mathcal{L}(\mu|N,m)$.
End of explanation
# Vaš kôd ovdje
Explanation: (b)
Prikažite funkciju $\mathcal{L}(\mu|N,m)$ za (1) $N=10$ i $m=1,2,5,9$ te za (2) $N=100$ i $m=1,10,50,90$ (dva zasebna grafikona).
End of explanation
# Vaš kôd ovdje
Explanation: Q: Koja vrijednost odgovara ML-procjenama i zašto?
(c)
Prikažite funkciju $\mathcal{L}(\mu|N,m)$ za $N=10$ i $m={0,9}$.
End of explanation
from scipy.stats import beta
# Vaš kôd ovdje
Explanation: Q: Koja je ML-procjena za $\mu$ i što je problem s takvom procjenom u ovome slučaju?
(d)
Prikažite beta-distribuciju $B(\mu|\alpha,\beta)$ za različite kombinacije parametara $\alpha$ i $\beta$, uključivo $\alpha=\beta=1$ te $\alpha=\beta=2$.
End of explanation
# Vaš kôd ovdje
Explanation: Q: Koje parametere biste odabrali za modeliranje apriornog znanja o parametru $\mu$ za novčić za koji mislite da je "donekle pravedan, ali malo češće pada na glavu"? Koje biste parametre odabrali za novčić za koji držite da je posve pravedan? Zašto uopće koristimo beta-distribuciju, a ne neku drugu?
(e)
Definirajte funkciju za izračun zajedničke vjerojatnosti $P(\mu,\mathcal{D}) = P(\mathcal{D}|\mu) \cdot P(\mu|\alpha,\beta)$ te prikažite tu funkciju za $N=10$ i $m=9$ i nekolicinu kombinacija parametara $\alpha$ i $\beta$.
End of explanation
# Vaš kôd ovdje
Explanation: Q: Koje vrijednosti odgovaraju MAP-procjeni za $\mu$? Usporedite ih sa ML-procjenama.
(f)
Za $N=10$ i $m=1$, na jednome grafikonu prikažite sve tri distribucije: $P(\mu,\mathcal{D})$, $P(\mu|\alpha,\beta)$ i $\mathcal{L}(\mu|\mathcal{D})$.
End of explanation
from sklearn.datasets import load_iris
import itertools as it
# Vaš kôd ovdje
Explanation: (g)
Pročitajte ove upute o učitavanju oglednih skupova podataka. Učitajte skup podataka Iris. Taj skup sadrži $n=4$ značajke i $K=3$ klase. Odaberite jednu klasu i odaberite sve primjere iz te klase, dok ostale primjere zanemarite (u nastavku radite isključivo s primjerima iz te jedne klase). Vizualizirajte podatke tako da načinite 2D-prikaze za svaki par značajki (šest grafikona; za prikaz je najjednostavnije koristiti funkciju scatter).
NB: Mogla bi Vam dobro dući funkcija itertools.combinations.
End of explanation
from scipy.stats import norm
# Vaš kôd ovdje
Explanation: (h)
Pogledajte opis modul stats te proučite funkciju norm. Implementirajte funkciju log-izglednosti za parametre $\mu$ i $\sigma^2$ normalne distribucije.
End of explanation
# Vaš kôd ovdje
Explanation: (i)
Izračunajte ML-procjene za $(\mu, \sigma^2)$ za svaku od $n=4$ značajki iz skupa Iris. Ispišite log-izglednosti tih ML-procjena.
End of explanation
from scipy.stats import pearsonr
# Vaš kôd ovdje
Explanation: Q: Možete li, na temelju dobivenih log-izglednosti, zaključiti koja se značajka najbolje pokorava normalnoj distribuciji? 
(j)
Proučite funkciju pearsonr za izračun Pearsonovog koeficijenta korelacije. Izračunajte koeficijente korelacije između svih četiri značajki u skupu Iris.
End of explanation
# Vaš kôd ovdje
Explanation: (k)
Proučite funkciju cov te izračunajte ML-procjenu za kovarijacijsku matricu za skup Iris. Usporedite pristranu i nepristranu procjenu. Pokažite da se razlika (srednja apsolutna i kvadratna) smanjuje s brojem primjera (npr. isprobajte za $N/4$ i $N/2$ i $N$ primjera).
End of explanation
<END_TASK>