%matplotlib inline
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn

plt.rcParams['figure.figsize'] = 9, 6

"""
Explanation: Feature selection
Obsah

Filter
Wrapper
Embedded

Preco by som mal vyberat len niektore atributy?

redundancia - skryte zavyslosti medzi nimi 
irelevancia - nemusia mat ziadny vplyv na predikovanu hodnotu
pretrenovanie - model sa da natrenovat aj na nahodnych datach a na trenovacej sade bude fungovat. Na testovacej ale bude fungovat uplne strasne
prekliatie dimenzionality - pri velkom pocte atributov potrebujem vela dat na to aby som dostatocne pokryl priestor moznych hodnot
produktivita / rychlost - moja ako analytika a aj mojich modelov (trenovanie aj predikcia)
zrozumitelnost - lahsie sa vysvetluje model, ktory ma menej atributov
End of explanation
"""


from sklearn.feature_selection import VarianceThreshold

X = np.array([[0, 2, 0, 3], [0, 1, 4, 3], [0, 1, 1, 3]])
X

selector = VarianceThreshold(threshold=0.0)
selector.fit_transform(X)

"""
Explanation: Filter
Vyber atributov bez ohladu na model, ktory sa chystame trenovat.

rychle
nezavisle na modeli (to je dobre aj zle)

Najjednoduchsie je vyhodit atributy, ktore maju vsade rovnake hodnoty
pozor, nie malu varianciu. Hlavne pri nevyvazenych triedach mozu byt prave taketo atributy velmi uzitocne
End of explanation
"""


from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2 # daju sa pouzit ine metriky
iris = load_iris()
X, y = iris.data, iris.target
X.shape

X_new = SelectKBest(chi2, k=2).fit_transform(X, y)
X_new.shape

"""
Explanation: Potom mozeme vyberat atributy na zaklade zavislosti atributu a predikovanej hodnoty
Priklad: vyberieme K vlastnosti, s najvyssou zavislostou s predikovanou hodnotou.
End of explanation
"""


from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import load_iris

iris = load_iris()
X = iris.data
y = iris.target
knn = KNeighborsClassifier(n_neighbors=4)

from mlxtend.feature_selection import SequentialFeatureSelector as SFS

sfs1 = SFS(knn, k_features=3, forward=True,  floating=False, verbose=2, scoring='accuracy', cv=0)
# pomocou tejto triedy vieme robit SFS, SFFS, SBS aj SFBS a dokonca aj pridat cross-validaciu

sfs1 = sfs1.fit(X, y)

sfs1.subsets_

"""
Explanation: Daju sa pouzivat rozne metriky

Klasifikacia
* chi2 - nezaporne cisla
* mutual_info_classif - diskretne data
* f_classif - ANOVA medzi predikovanou premennou a atributmi
Regresia
* f_regression - F test medzi predikovanou hodnotou a atributmi
* mutual_info_regression - Mutual information na realnych cislach

Da sa vyberat K najlepsich alebo nejaky percentil alebo nechat pocet atributov na statisticky test

SelectKBest 

SelectPercentile


SelectFpr - false positive rate

SelectFdr - false discovery rate  

SelectFwe - family wise error


GenericUnivariateSelect - Vsetko dohromady a strategia sa da nastavit parametrom


Vlastnosti filtrov

vacsinou rychle
nezavisle na modely (nepotrebujem opakovane trenovat model ale vybrane atributy nemusia byt najvhodnejsie pre kazdy model)
vacsinou sa pozeraju len na vlastnosti dvojic predikovana premenna - atribut, kombinacie viacerych atributov nezohladnuju

Varovanie, PCA sa casto pouziva na redukciu dimenzionality ale nie na vyber atributov
Je to casta chyba
Nemohol som si odpustit tuto poznamku
Preco je to tak sa mozeme porozpravat v diskusii
Wrapper
Zakladna myslienka
haldame podmnozinu atributov, na ktorej bude model davat najlepsie vysledky
Skusame rozne podmnoziny a vyberame tu najlepsiu
Problem
Ak mame dataset s N atributmi, tak pocet roznych podmnozin je $2^N$
To znamena, ze by sme museli nas model natrenovat $2^N$ krat.
Chcelo by to najst proces, ktory minimalizuje pocet pokusov a zaroven maximalizuje uspesnost modelu
Greedy pristupy
Najcastejsie sa pouzivaju greedy pristupy, ktore postupne zvacsuju sadu atributov (alebo zmensuju) tak, ze pridavaju (odoberaju) atribut tak aby sa co najviac zvysila uspesnost.
Mlxtend


Sequential Forward Selection (SFS)

Postupne zvacsuje mnozinu atributov o ton, ktory najviac prispel k zlepseniu



Sequential Backward Selection (SBS)

Postupne zmensuje mnzoinu atributov o ten, ktory najmenej pomahal



Sequential Floating Forward Selection (SFFS)

SFS s pokusom o vyhodenie uz pridanych atributov ak sa ukaze ze velmi nepomahaju 



Sequential Floating Backward Selection (SFBS)

SBS s pokusom o pridanie uz raz vyhodeneho atributu



Scikit-Learn


RFE - Recursive feature elimination

Postupne vyhadzovanie atributov, ktore maju v modeli najnizsiu vahu (potrebujeme aby to model vedel povedat) 



RFECV - RFE with cross-validation

RFE s cross validaciou



Priklad SFS
End of explanation
"""


sfs1.k_feature_idx_

sfs1.k_score_

"""
Explanation: Viem si vytiahnut zoznam najlepsich vlastnosti a uspesnost modelu pri nich
End of explanation
"""


from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectFromModel
iris = load_iris()
X, y = iris.data, iris.target
X.shape

clf = RandomForestClassifier()
clf = clf.fit(X, y)
clf.feature_importances_  

model = SelectFromModel(clf, prefit=True)
X_new = model.transform(X)
X_new.shape  

"""
Explanation: Embedded
Hlavna myslienka
Skombinovat vyhody filtrov a wrapprov
Model, ktory sa trenuje si bude priamo vyberat atributy, ktore su pre neho najlepsie

Linearne modely penalizovnae L1 (Lasso) alebo L1+L2 (Elastic Net) regularizaciou: SVM, Linearna regresia, Logisticka regresia ...
RandomForest
End of explanation
"""


