# Import potrebných balíčkov
import pandas as pd
import numpy as np
from keras.models import Model
from keras.layers import Dense, Input, Activation
from keras.callbacks import Callback
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from keras.utils import plot_model
from IPython.display import Image
# Uistíme sa, že máme všetky potrebné dáta
!mkdir -p data
!wget -nc -O data/iris.csv https://www.dropbox.com/s/v3ptdkv5fvmx5zk/iris.csv?dl=1
# Pomocný kód
class NEpochLogger(Callback):
"""
Trieda na menej časté zobrazovanie priebehu učenia.
"""
def __init__(self, n_epochs=100):
super(NEpochLogger, self).__init__()
self.n_epochs = n_epochs
def on_epoch_end(self, epoch, logs=None):
logs = logs or {}
if epoch % self.n_epochs == 0:
curr_loss = logs.get('loss')
curr_acc = logs.get('acc') * 100
print("epoch = {}; loss = {}; acc = {}".format(
epoch, curr_loss, curr_acc))
Tento notebook ukazuje, ako sa dá neurónová sieť zostrojená pomocou pythonového balíčka keras
aplikovať na jednoduchú klasifikačnú úlohu. Ukážeme, ako sa dá taká sieť vytvoriť a natrénovať. Budeme používať veľmi jednoduchú architektúru – bez konvolučných vrstiev, dávkovej normalizácie a iných podobných špeciálnych vrstiev.
Ako prvý krok načítame dátovú množinu IRIS:
df = pd.read_csv("data/iris.csv")
df.head()
Dáta rozdelíme na tréningové a testovacie. 75% dát použijeme na učenie a 25% na testovanie. Aplikujeme tiež stratifikáciu podľa stĺpca species
, ktorý obsahuje označenie triedy (pomer tried v oboch častiach dátovej množiny zostane rovnaký, ako bol v pôvodnej dátovej množine).
df_train, df_test = train_test_split(df, test_size=0.25,
stratify=df['species'],
random_state=4)
Prvé 4 stĺpce sú vstupy, posledný výstup:
inputs = df.columns[:4]
output = df.columns[-1:]
X_train_raw = df_train[inputs]
Y_train_l = df_train[output]
X_test_raw = df_test[inputs]
Y_test_l = df_test[output]
Vytvoríme pipeline na predspracovanie. Všetky 4 vstupy budeme štandardizovať.
input_preproc = StandardScaler()
X_train = input_preproc.fit_transform(X_train_raw)
X_test = input_preproc.transform(X_test_raw)
Triedy prekódujeme do reprezentácie 1 z n (one-hot encoding).
output_preproc = OneHotEncoder(sparse=False)
Y_train = output_preproc.fit_transform(Y_train_l)
Y_test = output_preproc.transform(Y_test_l)
Sieť bude mať toľko vstupov, koľko je stĺpcov v X. Výstupov bude zase toľko, koľko je tried (čo je to isté ako počet stĺpcov v Y).
num_inputs = X_train.shape[1]
num_outputs = Y_train.shape[1]
Teraz začneme vytvárať samotnú sieť. Začneme vstupnou vrstvou, ktorá bude mať num_inputs
neurónov:
y = x = Input(shape=(num_inputs, ))
Ďalej pridáme niekoľko úplne prepojených vrstiev s aktivačnou funkciou ReLU. Všimnite si, ako dávame y
na vstup každej vrstvy a tiež doňho priraďujeme výstup. Takýmto spôsobom vrstvy zreťazujeme.
# Prvá úplne prepojená vrstva + ReLU.
y = Dense(3)(y)
y = Activation('relu')(y)
# Druhá úplne prepojená vrstva + ReLU.
y = Dense(3)(y)
y = Activation('relu')(y)
Ďalej pridáme výstupnú vrstvu. Ako vieme, potrebujeme použiť aktivačnú funkciu softmax, aby sa všetky výstupy sčítali na 1 a dali sa interpretovať ako pravdepodobnosti.
y = Dense(num_outputs)(y)
y = Activation('softmax')(y)
Napokon sme pripravení vytvoriť aj samotný model. Povieme, aké sú jeho vstupy a výstupy. Následne ho skompilujeme, pričom špecifikujeme chybovú funkciu a optimalizačnú metódu, ktorú treba použiť. Pridaním 'accuracy' (správnosti) medzi metriky docielime, že sa nám počas učenia bude správnosť zobrazovať.
model = Model(x, y)
model.compile(loss='categorical_crossentropy',
optimizer="adam", metrics=['accuracy'])
S použitím pomocnej funkcie plot_model
si môžeme vizualizovať architektúru vytvorenej siete:
plot_model(model, "model.png", )
Image(retina=True, filename='model.png')
Potom ako sme skonštruovali model, môžeme pristúpiť ku samotnému učeniu z tréningových dát. Špecifikujeme počet epoch učenia a veľkosť minidávok.
So sieťou a dátovou množinou týchto rozmerov by učenie nemalo trvať príliš dlho. Na väčšie siete a dátové množiny bude ale treba použiť GPU, ktoré vie učenie značne urýchliť.
model.fit(X_train, Y_train, epochs=2000, batch_size=64,
verbose=0, callbacks=[NEpochLogger()])
Keď sme model natrénovali, potrebujeme ho ešte otestovať na testovacích dátach, aby sme verifikovali, či správne zovšeobecňuje. Spustíme teda model na testovacích dátach.
y_test = model.predict(X_test)
Výsledné pravdepodobnosti transformujeme späť na označenia triedy:
y_test_l = output_preproc.inverse_transform(y_test)[:, 0]
Y_test_l = output_preproc.inverse_transform(Y_test)[:, 0]
Zobrazíme maticu zámen a vypočítame správnosť.
cm = pd.crosstab(Y_test_l, y_test_l,
rownames=['actual'],
colnames=['predicted'])
print(cm)
print("Správnosť: {}.".format(accuracy_score(
Y_test_l, y_test_l
)))