summaryrefslogtreecommitdiff
path: root/neuralnet.py
blob: 079e5878a5cf775cdd9a3b3402b4336841ad7156 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#!/usr/bin/python3
from sklearn import datasets
from sklearn import preprocessing
from sklearn.cross_validation import train_test_split
import tensorflow as tf
import numpy.random
import numpy as np

# Siehe Kommentar in dem Programm der linearen Regression
SEED = 42
numpy.random.seed(SEED)
tf.set_random_seed(SEED)

# Datenreihe laden
dataset = datasets.load_boston()
data, target = dataset.data, dataset.target

# Datenwerte für ein effektiveres Lernen zwischen 0 und 1 skalieren
data_scaler = preprocessing.MinMaxScaler()
data = data_scaler.fit_transform(data)
target_scaler = preprocessing.MinMaxScaler()
target = target_scaler.fit_transform(target)

# Datenwerte in Trainings- und Testreihe aufteilen
x_train, x_test, y_train, y_test = train_test_split(
    data, target, train_size=0.85
)

# Die Netzkonfiguration
BATCH = 50
STEPS = 300
HIDDEN = 11
IN = 13
OUT = 1
LEARNINGRATE = 0.01
DECAYRATE = 0.96
DECAYSTEPS = 50

# Der Lernverlauf wird in einem individuellem Dateinamen gespeichert,
# der je nach Konfiguration variiert.
RUNNAME = 'B'+str(BATCH)+'S'+str(STEPS)+'H'+str(HIDDEN)+'LR'+str(LEARNINGRATE)\
        + 'DR'+str(DECAYRATE)+'DS'+str(DECAYSTEPS)+'SD'+str(SEED)

# Es wird ausschließlich auf der CPU gerechnet,
# da die GPU zu lange zum Initialisieren braucht und mehr RAM.
with tf.device('/cpu:0'):
    sess = tf.InteractiveSession()
    # Ausführliche Kommentare und ein vereinfachter Ablauf
    # finden sich in Abschnitt 2.2.2 der Facharbeit.

    with tf.name_scope('input_layer'):
        matInput = tf.placeholder(tf.float32, [None, IN], name='input')
        vecTarget = tf.placeholder(tf.float32, [None], name='target')
        scalarNumelements = tf.shape(vecTarget, name='batch_length')
        vecBias = tf.Variable(tf.random_uniform([IN], -1.0, 1.0), name='bias')
        summaryBias = tf.histogram_summary("bias", vecBias)
        vecsBias = tf.tile(vecBias, scalarNumelements)
        vecsBias = tf.reshape(vecsBias, [-1, IN])
        matBiasedInput = tf.add(matInput, vecsBias, name='biased_input')

    with tf.name_scope('hidden_layer'):
        matWeights = tf.Variable(tf.random_uniform([IN, HIDDEN], -1.0, 1.0),
                                 name='weights')
        summaryWeights = tf.histogram_summary('weights', matWeights)
        matLayerin = tf.matmul(matBiasedInput, matWeights, name='layer_input')
        matLayerout = tf.sigmoid(matLayerin, name='layer_output')

    with tf.name_scope('output_layer'):
        vecTarget = vecTarget
        matWeightsHidden = tf.Variable(
                tf.random_uniform([HIDDEN, OUT], -1.0, 1.0),
                name='hidden-weights')
        summaryWeightsHidden = tf.histogram_summary('hiddenweights',
                                                    matWeightsHidden)
        matLayerinHidden = tf.matmul(matLayerout, matWeightsHidden,
                                     name='hidden_input')
        matLayeroutHidden = tf.sigmoid(matLayerinHidden, name='hidden_output')
        # nur vec, wenn OUT=1
        vecLayeroutHidden = tf.reshape(matLayeroutHidden, [-1])

    with tf.name_scope('cost'):
        vecDifference = tf.sub(vecTarget, vecLayeroutHidden, name='diff')
        scalarError = tf.reduce_sum(tf.abs(vecDifference), name='error')
        summaryError = tf.scalar_summary('error', scalarError)

    with tf.name_scope('train'):
        global_step = tf.Variable(0, trainable=False)
        learning_rate = tf.train.exponential_decay(LEARNINGRATE,
                                                   global_step, DECAYSTEPS,
                                                   DECAYRATE, staircase=True)
        train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(
                scalarError, global_step=global_step)

    summaries = tf.merge_all_summaries()
    writer = tf.train.SummaryWriter("/tmp/boston_logs/%s" % RUNNAME,
                                    sess.graph_def)
    # Alle Tensorflow-Variablen müssen bis hier spezifiziert sein!
    sess.run(tf.initialize_all_variables())

    # Training
    for count in range(0, int(len(x_train) / BATCH)):
        print("batch " + str(count))
        for i in range(0, STEPS):
            result = sess.run([summaries, train_step],
                              feed_dict={
                                matInput: x_train[count*BATCH:(count+1)*BATCH],
                                vecTarget: y_train[count*BATCH:(count+1)*BATCH]
                              })
            writer.add_summary(result[0], count * STEPS + i)

    print("Training beendet")

    print("Testergebnisse - Differenz zu echten Daten:")
    result = sess.run([vecLayeroutHidden],
                      feed_dict={
                          matInput: x_test,
                          vecTarget: y_test
                      })
    print("================================")
    print("erwartete Daten:")
    print("--------------------------------")
    # Ausgabedaten sind skaliert, zurückskalieren
    print(target_scaler.inverse_transform(y_test))
    print("--------------------------------")
    print("vorhergesagte Daten:")
    print(target_scaler.inverse_transform(result[0]))
    print("--------------------------------")
    print("")
    print("Differenz:")
    print("--------------------------------")
    # MSE aus der Differenz unskalierter Daten berechnen,
    # nicht MSE aus Differenz skalierter Daten unskalieren:
    # !!! (a - b) * f + o != (a * f + o) - (b * f + o)
    # <=> af - bf + o     != af - bf
    diff = target_scaler.inverse_transform(
            result[0]) - target_scaler.inverse_transform(y_test)
    print(diff)
    print("--------------------------------")
    print("")
    print("MSE")
    # Entsprechend (af - bf + o)^2 != (af - bf)^2…
    print(np.mean(diff ** 2))