<jupyter_start><jupyter_text>Úkol č. 2 - předzpracování dat a binární klasifikace (do 10. listopadu)  * Cílem thoto úkolu je vyzkoušet si naučit prediktivní model pro binární klasifikaci.  * Budete se muset vypořádat s příznaky, které jsou různých typů a které bude třeba nějakým způsobem převést do číselné reprezentace.    > **Úkoly jsou zadány tak, aby Vám daly prostor pro invenci. Vymyslet _jak přesně_ budete úkol řešit, je důležitou součástí zadání a originalita či nápaditost bude také hodnocena!** Zdroj datBudeme se zabývat predikcí přežití pasažérů Titaniku.K dispozici máte trénovací data v souboru **data.csv** a data na vyhodnocení v souboru **evaluation.csv**. Seznam příznaků:* survived - zda přežil, 0 = Ne, 1 = Ano, **vysvětlovaná proměnná**, kterou chcete predikovat* pclass - Třída lodního lístku, 1 = první, 2 = druhá, 3 = třetí* name - jméno* sex - pohlaví* age - věk v letech* sibsp	- počet sourozenců / manželů, manželek na palubě* parch - počet rodičů / dětí na palubě* ticket - číslo lodního lístku* fare - cena lodního lístku* cabin	- číslo kajuty* embarked	- místo nalodění, C = Cherbourg, Q = Queenstown, S = Southampton* home.dest - Bydliště/Cíl Pokyny k vypracování**Základní body zadání**, za jejichž (poctivé) vypracování získáte **8 bodů**:  * V Jupyter notebooku načtěte data ze souboru **data.csv**. Vhodným způsobem si je rozdělte na trénovací, testovací a případně i validační množinu (preferujeme ale použití cross-validation).  * Projděte si jednotlivé příznaky a transformujte je do vhodné podoby pro použití ve vybraném klasifikačním modelu.  * Podle potřeby si můžete vytvářet nové příznaky (na základě existujících), například tedy můžete vytvořit příznak měřící délku jména. Některé příznaky můžete také úplně zahodit.  * Nějakým způsobem se vypořádejte s chybějícími hodnotami.  * Následně si vyberte vhodný klasifikační model z přednášek. Najděte vhodné hyperparametry a určete jeho přesnost (accuracy) na trénovací množině. Také určete jeho přesnost na testovací/vaidační množině.  * Načtěte vyhodnocovací data ze souboru **evaluation.csv**. Napočítejte predikce pro tyto data (vysvětlovaná proměnná v nich již není). Vytvořte **results.csv** soubor, ve kterém tyto predikce uložíte do dvou sloupců: ID, predikce přežití. Tento soubor nahrajte do repozitáře.**Další body zadání** za případné další body  (můžete si vybrat, maximum bodů za úkol je každopádně 12 bodů):  * (až +4 body) Aplikujte všechny klasifikační modely z přednášek a určete (na základě přesnosti na validační množině), který je nejlepší. Přesnost tohoto nejlepšího modelu odhadněte pomocí testovací množiny. K predikcím na vyhodnocovacích datech využijte tento model.  * (až +4 body) Zkuste použít nějaké (alespoň dvě) netriviální metody doplňování chybějících hodnot u věku. Zaměřte na vliv těchto metod na přesnost predikce výsledného modelu. K predikcím na vyhodnocovacích datech využijte ten přístup, který Vám vyjde jako nejlepší. Poznámky k odevzdání  * Řiďte se pokyny ze stránky https://courses.fit.cvut.cz/BI-VZD/homeworks/index.html.  * Odevzdejte nejen Jupyter Notebook, ale i _csv_ soubor(y) s predikcemi pro vyhodnocovací data.  * Opravující Vám může umožnit úkol dodělat či opravit a získat tak další body. **První verze je ale důležitá a bude-li odbytá, budete za to penalizováni**  Podpůrné funkcePodpůrné funkce na práci s daty<jupyter_code>from sklearn.model_selection import cross_val_score

def ConvertNameToVector(name):
    titles = ['Sir.','Master.','Mr.','Mrs.','Miss.']
    tmp = -1
    for i in range(len(titles)):
        if titles[i] in name:
            tmp = i
    return [len(name),tmp]

def ConvertEmbarkedToVector(embarked):
    if embarked == 'C':
        return [1,0,0]
    if embarked == 'Q':
        return [0,1,0]
    if embarked == 'S':
        return [0,0,1]
    return [0,0,0]
    
def ConvertEmbarkedToVector(embarked):
    if embarked == 'C':
        return [1,0,0]
    if embarked == 'Q':
        return [0,1,0]
    if embarked == 'S':
        return [0,0,1]
    return [0,0,0]


def ConvertFile(path): #Write missing values as -1
    with open(path,'r') as f:
        lines = [line.rstrip('\n') for line in f]
    X = []
    Y = []
    for line in lines[1:]:
        cnt = 0
        tmpArr = line.split(',')
        if not 'evaluation' in path:
            Y.append(int(tmpArr[1]))
        else:
            cnt -= 1
            Y.append(int(tmpArr[0]))
        tmpX = []
        
        pClass = -1 if tmpArr[2+cnt] == '' else (int(tmpArr[2+cnt]))
        
        name = ''
        while tmpArr[3+cnt] != 'male' and tmpArr[3+cnt] != 'female' and tmpArr[3+cnt] != '':
            name += tmpArr[3+cnt]
            cnt += 1
        
        tmpX.extend(ConvertNameToVector(name))
        cnt -= 1
        
        maleXFemale = -1 if tmpArr[4+cnt] == '' else (1 if tmpArr[4+cnt] == 'male' else 0)
        tmpX.append(pClass)
        tmpX.append(maleXFemale)
        for i in range(5+cnt,10+cnt):
            try:
                val = -1 if tmpArr[i] == '' else (float(tmpArr[i]))
            except Exception as ex: # cabin with string at the beginning
                tmp = tmpArr[i].split(' ')
                if len(tmp) == 1:
                    val = -1
                else:
                    val = float(tmp[-1])
            tmpX.append(val)
        tmpX.extend(ConvertEmbarkedToVector(tmpArr[11+cnt]))
        X.append(tmpX)
        
    return X, Y<jupyter_output><empty_output><jupyter_text>Odhad chybějících hodnot věků lidíFunkce FixMissingAges1 a FixMissingAges2 jsou dvě netriviální metody doplňování chybějících hodnot u věku.  * Funkce FixMissingAges1 určuje chybějící hodnotu věku takovým způsobem, aby měla množina doplněných věku podobnou distribuci věku jako původní již vyplněná množina věků.   * Funkce FixMissingAges2 predikuje chybějící hodnotu věku regresním modelem. Regresní model byl naučený na datech (příznacích) které obsahovali hodnotu věku.Z těchto dvou funkcí měli klasifikační modeli větši přesnost s použitím funkce FixMissingAges1<jupyter_code>currentAges = []
# This one achieved higher accuracy
def FixMissingAges1(X, test=False): # Predict missing ages using distribution of current ages
    import random
    if not test:
        for i in range(len(X)):
            if X[i][4] != -1:
                currentAges.append(X[i][4])

    for i in range(len(X)):
        if X[i][4] == -1:
            X[i][4] = currentAges[random.randrange(0,len(currentAges))]
    return X
    
def FixMissingAges2(X): # Predict missing ages using regression
    from sklearn.ensemble import RandomForestRegressor
    regressionArr, y = [],[]
    regressionTestArr = []
    for i in range(len(X)):
        if X[i][4] != -1:
            tmp = []
            for j in range(len(X[i])):
                if j!=4:
                    tmp.append(X[i][j])
                    
            regressionArr.append(tmp)
            y.append(X[i][4])
    for i in range(len(X)):
        if X[i][4] == -1:
            tmp = []
            for j in range(len(X[i])):
                if j!=4:
                    tmp.append(X[i][j])
                    
            regressionTestArr.append(tmp)
    
    rfRegressor = RandomForestRegressor(100)
    rfRegressor.fit(regressionArr,y)
    predictions = rfRegressor.predict(regressionTestArr)
    
    counter = 0
    for i in range(len(X)):
        if X[i][4] == -1:
            X[i][4] = predictions[counter]
            counter += 1
    return X<jupyter_output><empty_output><jupyter_text>Normalizace datFunkce myNorm nejprve doplní množinu dat o chybějící a pak normalizuje data. Funkce jsou normalizována tak aby každý příznak měl hodnotu mezi 0 a 1. Toho je docíleno tak, že pro každý příznak je nalezena maximální hodnota v trénovací množině a tímto polem nejvyšších hodnot příznáků je pak dělena celá trénovací množina.Toto pole nejvyšších hodnot příznáků trénovací množiny (pole "myMaxes") je pak použito na normalizaci testovací množiny<jupyter_code>myMaxes = []
def myNorm(X, test=False):
    FixMissingAges1(X,test)
    if not test:
        for i in range(len(X[0])):
            myMaxes.append(0)
        for item in X:
            for i in range(len(item)):
                if item[i] > myMaxes[i]:
                    myMaxes[i] = item[i]
    
    for j in range(len(X)):
        for i in range(len(X[j])):
            X[j][i] /= float(myMaxes[i])

    return X<jupyter_output><empty_output><jupyter_text>Načtení dat<jupyter_code>x_train, y_train = ConvertFile('data.csv')
x_train = myNorm(x_train)
x_test, y_test = ConvertFile('evaluation.csv')
x_test = myNorm(x_test, True)<jupyter_output><empty_output><jupyter_text>SVM<jupyter_code>from sklearn import svm
clf = svm.SVC(max_iter=1000,gamma='auto')
print('SVM accuracy:',cross_val_score(clf, x_train, y_train,cv=10).mean())<jupyter_output>SVM accuracy: 0.79<jupyter_text>Extremely randomised trees<jupyter_code>from sklearn.ensemble import ExtraTreesClassifier
trees = ExtraTreesClassifier(100,class_weight='balanced')
print('Extremely randomised trees accuracy:',cross_val_score(trees, x_train, y_train,cv=10).mean())<jupyter_output>Extremely randomised trees accuracy: 0.8109999999999999<jupyter_text>Random forest<jupyter_code>from sklearn.ensemble import RandomForestClassifier
forest = RandomForestClassifier(100)
print('Random Forest accuracy:',cross_val_score(forest, x_train, y_train,cv=10).mean())<jupyter_output>Random Forest accuracy: 0.8320000000000001<jupyter_text>k-nearest neighbors<jupyter_code>from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=5)
print('kNN accuracy:',cross_val_score(knn, x_train, y_train,cv=10).mean())<jupyter_output>kNN accuracy: 0.8089999999999999<jupyter_text>Ladění hyperparametrůJelikož se Random Forest ukázal jako nejpřesnější, budeme hledat které jeho parametry produkují nejlepší klasifikační přesnost<jupyter_code># Find optimal hyper parameters for Random Forest
nOfEstimators = [10,50,100,150]
bestIndexEst = 0
max_depth = [4,8,16,32,64]
bestIndexDepth = 0
max_features = ['log2','sqrt']
bestIndexFeat = 0
bestCurrentVal = 0

for i in range(len(nOfEstimators)):
    for j in range(len(max_depth)):
        for k in range(len(max_features)):
            forest = RandomForestClassifier(n_estimators=nOfEstimators[i],max_depth=max_depth[j],max_features=max_features[k])
            val = cross_val_score(forest, x_train, y_train,cv=10).mean()
            print(str(i*(len(max_depth)*len(max_features)) + j*len(max_features) + k) +'/'+str(len(nOfEstimators)*len(max_depth)*len(max_features))+ ' searching hyperparameters')
            if val > bestCurrentVal:
                bestCurrentVal = val
                bestIndexEst = i
                bestIndexDepth = j
                bestIndexFeat = k
print('Best cross-validation accuracy:',bestCurrentVal)
print('Best parameters:')
print('Estimators:',nOfEstimators[bestIndexEst])
print('Max depth:',max_depth[bestIndexDepth])
print('Max features:',max_features[bestIndexFeat])<jupyter_output>0/40 searching hyperparameters
1/40 searching hyperparameters
2/40 searching hyperparameters
3/40 searching hyperparameters
4/40 searching hyperparameters
5/40 searching hyperparameters
6/40 searching hyperparameters
7/40 searching hyperparameters
8/40 searching hyperparameters
9/40 searching hyperparameters
10/40 searching hyperparameters
11/40 searching hyperparameters
12/40 searching hyperparameters
13/40 searching hyperparameters
14/40 searching hyperparameters
15/40 searching hyperparameters
16/40 searching hyperparameters
17/40 searching hyperparameters
18/40 searching hyperparameters
19/40 searching hyperparameters
20/40 searching hyperparameters
21/40 searching hyperparameters
22/40 searching hyperparameters
23/40 searching hyperparameters
24/40 searching hyperparameters
25/40 searching hyperparameters
26/40 searching hyperparameters
27/40 searching hyperparameters
28/40 searching hyperparameters
29/40 searching hyperparameters
30/40 searching hyperparameters
31/40 searching hy[...]<jupyter_text>Výsledná predikceNyní natrénujeme Random Forest s nalezenými optimálními hyperparametry na celé trénovací množině. Výsledný model použijeme na klasifikaci testovací množiny.<jupyter_code>forest = RandomForestClassifier(n_estimators=nOfEstimators[bestIndexEst],max_depth=max_depth[bestIndexDepth],max_features=max_features[bestIndexFeat])
forest.fit(x_train, y_train)
predictions = forest.predict(x_test)
with open('results.csv','w') as f:
    for i in range(len(predictions)):
        line = str(y_test[i]) + ',' + str(predictions[i]) + '\n'
        f.write(line)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09489860583016477, 'fraction_numerical': 0.02511089987325729, 'mean_word_length': 3.702048417132216, 'pattern_counts': {'":': 0, '<': 36, '<?xml version=': 0, '>': 39, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 3, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '55060', 'license': 'MIT', 'n_tokens_mistral': 4844, 'n_tokens_neox': 4744, 'n_words': 1178, 'path': 'VZD/02/homework_02_B191.ipynb', 'repo_name': 'JahodaPaul/FIT_CTU', 'size': '12624'}