Minimale Deep Netz

Das folgende minimale Deep Netz hat keinen anderen Zweck, als die Grundstruktur eines minimalen, neuronalen Netzwerkes zu zeigen. Es ist frei von jeder tieferen Bedeutung. Dadurch bleibt der Blick für die wesentlichen Komponenten im Netzwerk klar erkennbar.

Keine Aufgabe ist uns nicht zu schwer

Die einzige Aufgabe, die das Netz zu bewältigen hat ist einen Zusammenhang zwischen zufällig generierten Eingabedaten und ebenso zufällig generierten Labels herzustellen. Das ist natürlich totaler Quatsch, gerade weil es sich um zufällige Werte handelt. Was aber lernen wir aus dem Fortschritt, den wir beim Lernen beobachten können? Es kann sich nur um Overfitting handeln – also das adjustieren des Systems auf die Verteilung der Test-Daten. Die schlechteren Ergebnisse im Backtest bestärken diese These.

Künstliche One-Hot-Labels

Der interessanteste Teil ist der, wie im Code die Labels erzeugt werden. Denn wegen dem Typ der Loss-Funktion, müssen die Labels vom Typ One-Hot-encoded sein. Das ist ein Vektors der selben Dimension wie die Länge des Output-Layers. Im One-Hot-encoded-Vector steht nur in eine Spalte ein sehr hoher Wert, zumindest nahe bei 1 und alle anderen Spalten enthalten sehr niedrige Werte, nahe bei 0.

So werden zum Beispiel die Bilder des MNist-Datensatzes qualifiziert. Die y-Label sind 10-Dimensionale Vektoren, die eine 1 in der Spalte enthalten, die der dargestellten Zahl im Bild entspricht:

1 0 0 0 0 0 0 0 0 = 0
0 1 0 0 0 0 0 0 0 = 1
0 0 1 0 0 0 0 0 0 = 2
… u.s.w. …

Man kann aber auch andere Dinge als die Bilder der MNist-Datenbank kodieren. Übertrieben aber durchaus nahe an der Sache ist ein Beispiel aus dem Natural-Language-Processing:

1 0 0 0 0 0 …. Ich
0 1 0 0 0 0 …. Du
0 0 1 0 0 0 …. Er
… u.s.w. …

Die Vektoren mit denen hier gehandhabt wird haben längen um die Million!! Aber wie gesagt: Das hat alles nichts mit diesem Beispiel zu tun. Hier geht es nur um die Form…

from keras.models import Sequential
from keras.layers import Dense
import numpy as np
import keras
import random

# Hyper-Parameter
input_len = 100
output_len = 5
input_samples = 1000

# Model
model = Sequential()
model.add(Dense(units=64, activation='relu', 
model.add(Dense(units=128, activation='relu', input_dim=input_len))
model.add(Dense(units=output_len, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='sgd', metrics=['accuracy'])

# Erstellung der Trainingsdaten
x_train =  np.random.rand(int(input_samples), input_len)
# Erstellung der Labels für die Trainingsdaten
y_train_labels = np.array([random.randrange(0, output_len, 1) for _ in range(x_train.shape[0])])
y_train = np.zeros((y_train_labels.size, y_train_labels.max()+1))
y_train[np.arange(y_train_labels.size),y_train_labels] = 1

#--------------------------------
# Lernen
#--------------------------------
model.fit(x_train, y_train, epochs=50, batch_size=32, verbose=1)

# Erstellung der Testdaten
x_test = np.random.rand(int(input_samples*0.2), input_len)
# Erstellung der Labels für die Testdaten
y_test_labels = np.array([random.randrange(0, output_len, 1) for _ in range(x_test.shape[0])])
y_test = np.zeros((y_test_labels.size, y_test_labels.max()+1))
y_test[np.arange(y_test_labels.size),y_test_labels] = 1

#--------------------------------
# Backtest
#--------------------------------
loss_and_metrics = model.evaluate(x_test, y_test, batch_size=32)
print ("loss_and_metrics:", loss_and_metrics)