Frage

Ich versuche, Faltungsautoencoder in Tensorflow im MNIST -Datensatz zu implementieren.

Das Problem besteht sollte lernen.

Ich verwende 2x2 -Kerne mit Stride 2 für die Eingangs- und Ausgangswändungen, aber die Filter scheinen ordnungsgemäß zu gelernt zu werden. Wenn ich die Daten visualisiere, wird das Eingabebild durch 16 (1st conv) und 32 Filter (2. CONV) übergeben und scheint durch Bildinspektion in Ordnung zu sein (dh anscheinend Merkmale wie Kurven, Kreuze usw. werden erkannt).

Das Problem scheint sich im vollständig verbundenen Teil des Netzwerks zu ergeben: Unabhängig davon, was das Eingabebild ist, wird seine Codierung sein stets das Gleiche.

Mein erster Gedanke ist "Ich füttere es wahrscheinlich nur mit Nullen beim Training", aber ich glaube nicht, dass ich diesen Fehler gemacht habe (siehe Code unten).

Bearbeiten Ich erkannte, dass der Datensatz nicht gemischt war, was eine Tendenz einführte und die Ursache des Problems sein konnte. Nach der Einführung ist der durchschnittliche Verlust niedriger (0,06 anstelle von 0,09), und in der Tat sieht das Ausgangsbild wie ein verschwommenes 8 aus, aber die Schlussfolgerungen sind dieselben: Die codierte Eingabe ist gleich, wie es das Eingabebild ist.

Hier ein Beispieleingang mit dem relativen Ausgang

A sample input with the relative output

Hier sind die Aktivierung für das Bild oben, wobei die beiden vollständig verbundenen Schichten unten (Codierung ist der Bottommost).

activations

Schließlich gibt es hier die Aktivierung für die vollständig verbundenen Schichten für verschiedene Eingänge. Jedes Eingangsbild entspricht einer Zeile in den Aktivierungsbildern.

Wie Sie sehen können, ergeben sie immer die gleiche Ausgabe. Wenn ich transponierte Gewichte verwende, anstatt verschiedene initialisieren, sieht die erste FC -Schicht (Bild in der Mitte) etwas randomisierter aus, aber das zugrunde liegende Muster ist immer noch offensichtlich. In der Codierungsschicht (Bild unten) ist die Ausgabe immer gleich, unabhängig von der Eingabe (natürlich variiert das Muster von einem Training und dem nächsten).

FC layers activation

Hier ist der entsprechende Code

# A placeholder for the input data
x = tf.placeholder('float', shape=(None, mnist.data.shape[1]))

# conv2d_transpose cannot use -1 in output size so we read the value
# directly in the graph
batch_size = tf.shape(x)[0]

# Variables for weights and biases
with tf.variable_scope('encoding'):
    # After converting the input to a square image, we apply the first convolution, using 2x2 kernels
    with tf.variable_scope('conv1'):
        wec1 = tf.get_variable('w', shape=(2, 2, 1, m_c1), initializer=tf.truncated_normal_initializer())
        bec1 = tf.get_variable('b', shape=(m_c1,), initializer=tf.constant_initializer(0))
    # Second convolution
    with tf.variable_scope('conv2'):
        wec2 = tf.get_variable('w', shape=(2, 2, m_c1, m_c2), initializer=tf.truncated_normal_initializer())
        bec2 = tf.get_variable('b', shape=(m_c2,), initializer=tf.constant_initializer(0))
    # First fully connected layer
    with tf.variable_scope('fc1'):
        wef1 = tf.get_variable('w', shape=(7*7*m_c2, n_h1), initializer=tf.contrib.layers.xavier_initializer())
        bef1 = tf.get_variable('b', shape=(n_h1,), initializer=tf.constant_initializer(0))
    # Second fully connected layer
    with tf.variable_scope('fc2'):
        wef2 = tf.get_variable('w', shape=(n_h1, n_h2), initializer=tf.contrib.layers.xavier_initializer())
        bef2 = tf.get_variable('b', shape=(n_h2,), initializer=tf.constant_initializer(0))

reshaped_x = tf.reshape(x, (-1, 28, 28, 1))
y1 = tf.nn.conv2d(reshaped_x, wec1, strides=(1, 2, 2, 1), padding='VALID')
y2 = tf.nn.sigmoid(y1 + bec1)
y3 = tf.nn.conv2d(y2, wec2, strides=(1, 2, 2, 1), padding='VALID')
y4 = tf.nn.sigmoid(y3 + bec2)
y5 = tf.reshape(y4, (-1, 7*7*m_c2))
y6 = tf.nn.sigmoid(tf.matmul(y5, wef1) + bef1)
encode = tf.nn.sigmoid(tf.matmul(y6, wef2) + bef2)

with tf.variable_scope('decoding'):
    # for the transposed convolutions, we use the same weights defined above
    with tf.variable_scope('fc1'):
        #wdf1 = tf.transpose(wef2)
        wdf1 = tf.get_variable('w', shape=(n_h2, n_h1), initializer=tf.contrib.layers.xavier_initializer())
        bdf1 = tf.get_variable('b', shape=(n_h1,), initializer=tf.constant_initializer(0))
    with tf.variable_scope('fc2'):
        #wdf2 = tf.transpose(wef1)
        wdf2 = tf.get_variable('w', shape=(n_h1, 7*7*m_c2), initializer=tf.contrib.layers.xavier_initializer())
        bdf2 = tf.get_variable('b', shape=(7*7*m_c2,), initializer=tf.constant_initializer(0))
    with tf.variable_scope('deconv1'):
        wdd1 = tf.get_variable('w', shape=(2, 2, m_c1, m_c2), initializer=tf.contrib.layers.xavier_initializer())
        bdd1 = tf.get_variable('b', shape=(m_c1,), initializer=tf.constant_initializer(0))
    with tf.variable_scope('deconv2'):
        wdd2 = tf.get_variable('w', shape=(2, 2, 1, m_c1), initializer=tf.contrib.layers.xavier_initializer())
        bdd2 = tf.get_variable('b', shape=(1,), initializer=tf.constant_initializer(0))

u1 = tf.nn.sigmoid(tf.matmul(encode, wdf1) + bdf1)
u2 = tf.nn.sigmoid(tf.matmul(u1, wdf2) + bdf2)
u3 = tf.reshape(u2, (-1, 7, 7, m_c2))
u4 = tf.nn.conv2d_transpose(u3, wdd1, output_shape=(batch_size, 14, 14, m_c1), strides=(1, 2, 2, 1), padding='VALID')
u5 = tf.nn.sigmoid(u4 + bdd1)
u6 = tf.nn.conv2d_transpose(u5, wdd2, output_shape=(batch_size, 28, 28, 1), strides=(1, 2, 2, 1), padding='VALID')
u7 = tf.nn.sigmoid(u6 + bdd2)
decode = tf.reshape(u7, (-1, 784))

loss = tf.reduce_mean(tf.square(x - decode))
opt = tf.train.AdamOptimizer(0.0001).minimize(loss)

try:
    tf.global_variables_initializer().run()
except AttributeError:
    tf.initialize_all_variables().run() # Deprecated after r0.11

print('Starting training...')
bs = 1000 # Batch size
for i in range(501): # Reasonable results around this epoch 
    # Apply permutation of data at each epoch, should improve convergence time
    train_data = np.random.permutation(mnist.data)
    if i % 100 == 0:
        print('Iteration:', i, 'Loss:', loss.eval(feed_dict={x: train_data}))
    for j in range(0, train_data.shape[0], bs):
        batch = train_data[j*bs:(j+1)*bs]
        sess.run(opt, feed_dict={x: batch})
        # TODO introduce noise
print('Training done')
War es hilfreich?

Lösung

Nun, das Problem hing hauptsächlich mit der Kernelgröße zusammen. Die Verwendung von 2x2 Faltung mit dem Schritt von (2,2) wurde eine schlechte Idee. Die Verwendung von 5x5- und 3x3 -Größen ergab anständige Ergebnisse.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit datascience.stackexchange
scroll top