Neurale netwerken¶

K. Verbeeck, T. Van den Bossche, J. Maervoet¶

Data Science (Theory) -- OGI03p

1. Inleiding artificiële neurale netwerken (ANN)¶

  • Artificiële neurale netwerken zijn software- (of hardware-)systemen geïnspireerd op biologische neurale netwerken (in de hersenen)

pic1.png

  • Oorspronkelijk idee: problemen oplossen zoals menselijk brein ze zou oplossen

Typische kenmerken ANN¶

  • netwerk van artificiële neuronen
  • signalen op verbindingen voorgesteld als reële getallen
  • output neuron: niet-lineaire functie (vaak threshold) toegepast op som van inputsignalen
  • verbindingen hebben gewichten die aangepast worden tijdens het leerproces
  • gewichten bepalen in welke mate het signaal wordt doorgegeven aan de input

ArtificialNeuronModel_englishkopie.png

Activatiefunctie¶

  • Stelt ons in staat niet-lineaire patronen te ontdekken in de data activations-1.png

Deep Learning¶

  • neuronen worden vaak gegroepeerd in lagen
  • begrip 'Deep Learning': toevoegen 'verborgen' lagen voegen abstractieniveaus toe

1_N8UXaiUKWurFLdmEhEHiWg.jpg

Situering ANN¶

  • Groot aantal toepassingsdomeinen

    • beeldherkenning
    • spraakherkennong
    • spelen van bord- en videospellen
    • …
  • Leren typisch …

    • … complexe modellen
    • … die vaak niet makkelijk te interpreteren zijn
    • … en vereisen vaak grondige tuning van parameters
  • Aparte wetenschappelijke discipline

    • groot aantal algoritmen en configuraties
    • systemen voor supervised, unsupervised en reinforcement learning
  • Deze presentatie: enkel supervised ANN

2. Perceptron¶

  • °1957, F. Rosenblatt, uitgevoerd a.d.h.v. potentiometers
  • systeem voor binaire classificatie

perceptron.png

Gebruik perceptron voor voorspellingen¶

percep_small.png

  • input vector $\mathbf{x}$: input data uitgebreid met $x_{0} = 1$
  • weight vector $\mathbf{w}$ ($w_0$ noemen we de bias)

  • Stap 1: bereken de som $z = \mathbf{w} \cdot \mathbf{x} = \sum_{i=0}^n w_i x_i $

  • Stap 2: pas op dit getal de stapfunctie van Heaviside toe: $f(z) = \begin{cases}1 & \text{if }\ z > 0,\\0 & \text{otherwise}\end{cases}$

Kortweg: $y = f(\mathbf{w} \cdot \mathbf{x})$

Leeralgoritme voor het trainingsproces¶

percep_small.png

  • de trainingset bestaat uit $s$ koppels $(\mathbf{x}_1,d_1),\dots,(\mathbf{x}_s,d_s)$ waarbij $d_i$ telkens de verwachte waarde aangeeft

Algoritme:

  • Stap 1: stel alle gewichten in $\mathbf{w}$ op 0: $w_i = 0$ (of random instellen mag ook)
  • Stap 2: voor elk koppel $(\mathbf{x}_j,d_j)$ uit de trainingset (= 1 epoch)
    • maak een voorspelling: $y_j = f(\mathbf{w} \cdot \mathbf{x}_j)$
    • update alle gewichten $w_i$ in $\mathbf{w}$ als volgt: $w_i = w_i + \alpha\cdot(d_j - y_j) x_{j,i} $
  • Stap 3: herhaal stap 2 tot de gemiddelde $(d_j - y_j)$ erg klein is geworden

Grafische voorstelling¶

leereffect.png

Belangrijke eigenschappen (1)¶

  • Model = lineaire classificatie

  • Daarnet algoritme voor offline learning (trainingsdata wordt in batch aangeboden), maar kan ook gebruikt worden voor online learning (aanbieden van 1 data-instantie leidt tot aanpassing model: geheugenvriendelijk; kan ook gebruikt worden in context waar er uit elke voorspelling opnieuw moet worden geleerd)

  • Men kan bewijzen: gewichten convergeren indien data lineair scheidbaar is

  • Hyperparameter: learning rate α met $0 < \alpha <= 1$.

    • Te klein kiezen: zeer trage convergentie.
    • Te hoog: oscillatie bij niet-lineair scheidbare data.

Belangrijke eigenschappen (2)¶

  • Er bestaan problemen waar het perceptron überhaupt geen antwoord op heeft bv. het XOR-problem

xor_cantchoo.png

  • Indien er meerdere oplossingen zijn, kiest het perceptron lukraak een oplossing

  • Bestaat perceptron voor regressie? Eigenlijk wel, wanneer de activatiefunctie wordt vervangen door $f(z) = z$

3. Multi-Layer Perceptron (MLP)¶

  • Een netwerk bestaande uit minstens 3 lagen van nodes (1 input, minstens 1 hidden en 1 output layer)
  • node = ± perceptron - typische activatiefunctie sigmoidaal ($f(z) = \tanh(z)$ of $f(z) = (1+e^{-z})^{-1}$)
  • Feedforward network: voorspelling maken van links naar rechts
  • Trainingsfase: updaten van gewichten van rechts naar links a.d.h.v. backpropagation

mlp.png

Backpropagation¶

  • The backward propagation of errors
  • Idee: ook hier gewichten aanpassen zodanig dat ze de fout op de verwachte output compenseren
  • Gradient descent methode: $\Delta w_{ji} = - \eta \frac{\partial E}{\partial w_{ji}}$

gradient-descent-2d-diagram-2.png

  • Kan een lokaal minimum zijn, maar geen globaal …

Decision boundary¶

opmerking: in deze figuur wordt de input layer niet meegeteld lippman.gif

MLPs in scikit (docs)¶

Klassen MLPClassifier en MLPRegressor

  • instelling solver: het algoritme dat gebruikt wordt tijdens de backpropagation (l-bfgs, adam, sgd)
  • instelling hidden_layer_sizes: het aantal hidden layers en nodes per hidden layer
  • de default activatiefunctie is $tanh$ bij binaire classificatie, $softmax$ bij multi-class classificatie, identieke functie bij regressie
  • instelling activation: de activatiefunctie (relu, tanh, ...)
  • ook de errorfunctie wordt aangepast naargelang de probleemstelling
  • instelling learning_rate en learning_rate_init (kan ook automatisch afnemen)
  • instelling max_iter

Demo parameter-tuning¶

In [2]:
from sklearn.neural_network import MLPClassifier
from sklearn.datasets import make_moons
from sklearn.model_selection import train_test_split
from matplotlib.colors import ListedColormap
import numpy as np
import matplotlib.pyplot as plt

X, y = make_moons(n_samples=100, noise=0.25, random_state=3)

X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, random_state=42)
In [3]:
# default = 100 hidden nodes and activation='relu'
mlp = MLPClassifier(solver='lbfgs', random_state=0).fit(X_train, y_train)

plot_2d_separator(mlp, X_train) # huplfunctie verborgen in deze notebook
plt.scatter(X_train[:, 0], X_train[:, 1], c=y_train, 
            cmap=ListedColormap(['#0000aa', '#ff2020']))
Out[3]:
<matplotlib.collections.PathCollection at 0x18cd658e430>
In [4]:
# 10 nodes in 1 hidden layer ...

mlp = MLPClassifier(solver='lbfgs', random_state=0, 
                    hidden_layer_sizes=[10]).fit(X_train, y_train)
C:\ProgramData\Anaconda3\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:541: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.

Increase the number of iterations (max_iter) or scale the data as shown in:
    https://scikit-learn.org/stable/modules/preprocessing.html
  self.n_iter_ = _check_optimize_result("lbfgs", opt_res, self.max_iter)
In [5]:
# 10 nodes in 1 hidden layer ...
# ... resulteren in een decision boundary van 10 lijnsegmenten

mlp = MLPClassifier(solver='lbfgs', random_state=0, hidden_layer_sizes=[10],
                    max_iter=300).fit(X_train, y_train)

plot_2d_separator(mlp, X_train) # huplfunctie verborgen in deze notebook
plt.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap=ListedColormap(['#0000aa', '#ff2020']))
Out[5]:
<matplotlib.collections.PathCollection at 0x18cd1e90940>
In [6]:
# laat ons een 2de laag toevoegen ...

mlp = MLPClassifier(solver='lbfgs', random_state=0, 
                    hidden_layer_sizes=[10,10]).fit(X_train, y_train)

plot_2d_separator(mlp, X_train) # huplfunctie verborgen in deze notebook
plt.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap=ListedColormap(['#0000aa', '#ff2020']))
Out[6]:
<matplotlib.collections.PathCollection at 0x18cd1ee8160>
In [7]:
# en laat ons de activatiefunctie veranderen naar tanh ...

mlp = MLPClassifier(solver='lbfgs', activation='tanh', random_state=0,
                    max_iter=300,
                    hidden_layer_sizes=[10,10]).fit(X_train, y_train)

plot_2d_separator(mlp, X_train) # huplfunctie verborgen in deze notebook
plt.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap=ListedColormap(['#0000aa', '#ff2020']))
Out[7]:
<matplotlib.collections.PathCollection at 0x18cd1f2bb50>

Regularisatie met de α-parameter

  • hoe hoger de alpha-parameter, des te meer hoge gewichten worden afgestraft om overfitting te voorkomen

gamma1.png

Gevoeligheid t.o.v. de keuze van de random startgewichten¶

  • parameter random_state

gamma2.png

Vergeet niet om je data te scalen¶

In [8]:
from sklearn.datasets import load_breast_cancer
cancer = load_breast_cancer()

X_train, X_test, y_train, y_test = train_test_split(
    cancer.data, cancer.target, random_state=0)

mlp = MLPClassifier(random_state=0)
mlp.fit(X_train, y_train)

print("Accuracy on training set: {:.2f}".format(mlp.score(X_train, y_train)))
print("Accuracy on test set: {:.2f}".format(mlp.score(X_test, y_test)))
Accuracy on training set: 0.93
Accuracy on test set: 0.93
In [9]:
print("Cancer data per-feature maxima:\n{}".format(cancer.data.max(axis=0)))
Cancer data per-feature maxima:
[2.811e+01 3.928e+01 1.885e+02 2.501e+03 1.634e-01 3.454e-01 4.268e-01
 2.012e-01 3.040e-01 9.744e-02 2.873e+00 4.885e+00 2.198e+01 5.422e+02
 3.113e-02 1.354e-01 3.960e-01 5.279e-02 7.895e-02 2.984e-02 3.604e+01
 4.954e+01 2.512e+02 4.254e+03 2.226e-01 1.058e+00 1.252e+00 2.910e-01
 6.638e-01 2.075e-01]

! Opgelet: schaal enkel de trainingsdata en gebruik dezelfde schaling op de testset

In [10]:
# compute the mean value per feature on the training set
mean_on_train = X_train.mean(axis=0)
# compute the standard deviation of each feature on the training set
std_on_train = X_train.std(axis=0)

# subtract the mean, and scale by inverse standard deviation
# afterward, mean=0 and std=1
X_train_scaled = (X_train - mean_on_train) / std_on_train
# use THE SAME transformation (using training mean and std) on the test set
X_test_scaled = (X_test - mean_on_train) / std_on_train

mlp = MLPClassifier(random_state=0)
mlp.fit(X_train_scaled, y_train)

print("Accuracy on training set: {:.3f}".format(
    mlp.score(X_train_scaled, y_train)))
print("Accuracy on test set: {:.3f}".format(mlp.score(X_test_scaled, y_test)))
Accuracy on training set: 0.991
Accuracy on test set: 0.965
C:\ProgramData\Anaconda3\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:686: ConvergenceWarning: Stochastic Optimizer: Maximum iterations (200) reached and the optimization hasn't converged yet.
  warnings.warn(
In [11]:
# laat ons het aantal iteraties dus verhogen ....

mlp = MLPClassifier(max_iter=1000, random_state=0)
mlp.fit(X_train_scaled, y_train)

print("Accuracy on training set: {:.3f}".format(
    mlp.score(X_train_scaled, y_train)))
print("Accuracy on test set: {:.3f}".format(mlp.score(X_test_scaled, y_test)))

# sterk resultaat !!
Accuracy on training set: 1.000
Accuracy on test set: 0.972

Visualisatie gewichten¶

In [12]:
plt.figure(figsize=(20, 5))
plt.imshow(mlp.coefs_[0], interpolation='none', cmap='viridis')
plt.yticks(range(30), cancer.feature_names)
plt.xlabel("Columns in weight matrix")
plt.ylabel("Input feature")
plt.colorbar()
Out[12]:
<matplotlib.colorbar.Colorbar at 0x18cd20178e0>

Besluit¶

Multi-Layer Perceptron

  • krachtige modellen - hoge performantie - complexe decision boundaries
  • vereisen scaling van de input data
  • vereisen uitgebreide parameter tuning
  • geleerde modellen moeilijk interpreteerbaar
  • werken best op homogene data (gelijkaardige soort features)
  • training: tijdsgebruik is een issue bij > 10.000 samples

Extra richtlijnen tuning MLPs:

  • l-bfgs is robuust maar enkel voor kleine datasets; adam gevoeliger aan schaling; sgd experimenteler
  • begin met 1 hidden layer en breid daarna uit
  • probeer ev. eerst te overfitten en dan te generaliseren

Bronnen en links¶

  • Sarah Guido, Andreas C. Mueller. Introduction to Machine Learning with Python.
  • Scikit User Guide, Neural Network Supervised
  • Wikipedia, ANN
  • Wikipedia, Perceptron
  • Scikit Docs, MLPClassifier
  • Sebastian Schuchmann, History of the first AI Winter, towardsdatascience, May 12, 2019
  • Youtube: Sebastian Schuchmann, The Man who forever changed Artificial Intelligence, youtube.com, Okt 22, 2019