使用类优先级优化输入图像

时间:2016-10-25 09:03:04

标签: optimization tensorflow deep-learning

我正在尝试实施Google博客条目的第一部分 TensorFlow中的Inceptionism: Going Deeper into Neural Networks。到目前为止,我找到了几个资源,可以在natural language中解释它,也可以关注other parts or give code snippets for other frameworks。我理解优化关于类之前的随机输入图像的想法以及它在paper, section 2中给出的数学背后的数学,但是我无法使用TensorFlow自己实现它。

this SO question etarion 的有用评论,我现在知道您可以向优化器提供变量列表,而所有其他变量都不会受到影响。但是,在为优化程序提供随机图像作为变量时会导致

File "mnist_test.py", line 101, in main
    optimizer2 = tf.train.AdamOptimizer(learning_rate).minimize(-cost, var_list=[rnd_img])
File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/training/optimizer.py", line 198, in minimize
  name=name)
File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/training/optimizer.py", line 309, in apply_gradients
  (converted_grads_and_vars,))
ValueError: No gradients provided for any variable: ((None,<tensorflow.python.ops.variables.Variable object at 0x7feac1870410>),)

出于测试目的,我使用了一个简化的MNIST示例。我尽量保持它尽可能短,同时仍然可读和可执行:

def main():
    # parameters
    learning_rate = 0.001
    train_batches = 1000
    batch_size = 128
    display_step = 50

    # net parameters
    n_input = 784 #28x28
    n_classes = 10
    keep_prob = 0.75

    weights = {
        'wc1': tf.Variable(tf.truncated_normal([5, 5, 1, 32])),
        'wc2': tf.Variable(tf.truncated_normal([5, 5, 32, 64])),
        'wd1': tf.Variable(tf.truncated_normal([7*7*64, 1024])),
        'out': tf.Variable(tf.truncated_normal([1024, n_classes]))
    }

    biases = {
        'bc1': tf.Variable(tf.constant(0.1, shape=[32])),
        'bc2': tf.Variable(tf.constant(0.1, shape=[64])),
        'bd1': tf.Variable(tf.constant(0.1, shape=[1024])),
        'out': tf.Variable(tf.constant(0.1, shape=[n_classes]))
    }

    # tf inputs
    x = tf.placeholder(tf.float32, [None, n_input])
    y = tf.placeholder(tf.float32, [None, n_classes])
    dropout = tf.placeholder(tf.float32)

    # create net
    net = create_net(x, weights, biases, keep_prob)

    # define loss
    cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(net, y))

    # define optimizer
    optimizer = tf.train.AdamOptimizer(learning_rate).minimize(cost)

    # evaluation
    pred_correct = tf.equal(tf.argmax(net, 1), tf.argmax(y, 1))
    accuracy = tf.reduce_mean(tf.cast(pred_correct, tf.float32))

    print "loading mnist data"
    from tensorflow.examples.tutorials.mnist import input_data
    mnist = input_data.read_data_sets("/tmp/data/", one_hot=True)

    sess = tf.Session()
    sess.run(tf.initialize_all_variables())

    for i in xrange(train_batches):
        batch_x, batch_y = mnist.train.next_batch(batch_size)

        sess.run(optimizer, feed_dict={x: batch_x, y: batch_y, dropout: keep_prob})

        if i % display_step == 0:
            loss, acc = sess.run([cost, accuracy], feed_dict={x: batch_x, y: batch_y, dropout: 1.0})
            print "batch: %i, loss: %.5f, accuracy: %.5f" % (i, loss, acc)

    acc = sess.run(accuracy, feed_dict={x: mnist.test.images, y: mnist.test.labels, dropout: 1.0})
    print "test accuracy: %.5f" % (acc)

    # ====== this is where the reconstruction begins =====

    rnd_img = tf.Variable(tf.random_normal([1, n_input]))
    one_hot = np.zeros(10)
    one_hot[4] = 1;

    # the next line causes the error
    optimizer2 = tf.train.AdamOptimizer(learning_rate).minimize(-cost, var_list=[rnd_img])

    for i in xrange(1000):
        session.run(optimizer2, feed_dict={x: rnd_img, y: one_hot, dropout: 1.0})

    sess.close()

if __name__ == "__main__":
    main()

我使用的辅助函数:

def create_net(x, weights, biases, dropout):
    x = tf.reshape(x, shape=[-1, 28, 28, 1])

    conv1 = conv2d_relu(x, weights['wc1'], biases['bc1'])
    conv1 = maxpool2d(conv1, 2)

    conv2 = conv2d_relu(conv1, weights['wc2'], biases['bc2'])
    conv2 = maxpool2d(conv2, 2)

    fc1 = fullyconnected_relu(conv2, weights['wd1'], biases['bd1'])
    fc1 = tf.nn.dropout(fc1, dropout)

    out = tf.add(tf.matmul(fc1, weights['out']), biases['out'])

    return out

def conv2d_relu(x, W, b, stride=1):
    conv = tf.nn.conv2d(x, W, strides=[1, stride, stride, 1], padding='SAME')
    conv = tf.nn.bias_add(conv, b)
    return tf.nn.relu(conv)

def maxpool2d(x, k=2, stride=2, padding='VALID'):
    return tf.nn.max_pool(x, ksize=[1, k, k, 1], strides=[1, stride, stride, 1], padding=padding)

def fullyconnected_relu(x, W, b):
    fc = tf.reshape(x, [-1, W.get_shape().as_list()[0]])
    fc = tf.add(tf.matmul(fc, W), b)
    fc = tf.nn.relu(fc)

我发现有些消息来源说当输出和要优化的变量之间的计算图中没有路径时会发生这种错误,但我不明白为什么会出现这种情况。

我的问题是:

  1. 为什么优化器不能应用任何渐变?
  2. 这是实现类的可视化的正确方法吗?
  3. 提前致谢。

    修改

    这是完整的代码,在纳入已接受的答案后(对任何感兴趣的人)。无论如何,结果仍然不如预期,因为脚本基本上在100000轮重建后产生随机图像。欢迎提出意见。

    import tensorflow as tf
    import numpy as np
    import skimage.io
    
    def conv2d_relu(x, W, b, stride=1):
        conv = tf.nn.conv2d(x, W, strides=[1, stride, stride, 1], padding='SAME')
        conv = tf.nn.bias_add(conv, b)
        return tf.nn.relu(conv)
    
    def maxpool2d(x, k=2, stride=2, padding='VALID'):
        return tf.nn.max_pool(x, ksize=[1, k, k, 1], strides=[1, stride, stride, 1], padding=padding)
    
    def fullyconnected_relu(x, W, b):
        fc = tf.reshape(x, [-1, W.get_shape().as_list()[0]])
        fc = tf.add(tf.matmul(fc, W), b)
        fc = tf.nn.relu(fc)
    
        return fc;
    
    def create_net(x, weights, biases, dropout):
        x = tf.reshape(x, shape=[-1, 28, 28, 1])
    
        conv1 = conv2d_relu(x, weights['wc1'], biases['bc1'])
        conv1 = maxpool2d(conv1, 2)
    
        conv2 = conv2d_relu(conv1, weights['wc2'], biases['bc2'])
        conv2 = maxpool2d(conv2, 2)
    
        fc1 = fullyconnected_relu(conv2, weights['wd1'], biases['bd1'])
        fc1 = tf.nn.dropout(fc1, dropout)
    
        out = tf.add(tf.matmul(fc1, weights['out']), biases['out'])
    
        return out
    
    def save_image(img_data, name):
        img = img_data.reshape(28,28)
    
        mi = np.min(img)
        ma = np.max(img)
    
        img = (img-mi)/(ma-mi)
        skimage.io.imsave(name, img)
    
    def main():
        # parameters
        learning_rate = 0.001
        train_batches = 1000
        batch_size = 100
        display_step = 50
    
        # net parameters
        n_input = 784 #28x28
        n_classes = 10
        keep_prob = 0.75
    
        weights = {
            'wc1': tf.Variable(tf.truncated_normal([5, 5, 1, 32])),
            'wc2': tf.Variable(tf.truncated_normal([5, 5, 32, 64])),
            'wd1': tf.Variable(tf.truncated_normal([7*7*64, 1024])),
            'out': tf.Variable(tf.truncated_normal([1024, n_classes]))
        }
    
        biases = {
            'bc1': tf.Variable(tf.constant(0.1, shape=[32])),
            'bc2': tf.Variable(tf.constant(0.1, shape=[64])),
            'bd1': tf.Variable(tf.constant(0.1, shape=[1024])),
            'out': tf.Variable(tf.constant(0.1, shape=[n_classes]))
        }
    
        # tf inputs
        x = tf.placeholder(tf.float32, [None, n_input])
        y = tf.placeholder(tf.float32, [None, n_classes])
        dropout = tf.placeholder(tf.float32)
    
        # create net
        net = create_net(x, weights, biases, dropout)
    
        # define loss
        cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(net, y))
    
        # define optimizer
        optimizer = tf.train.AdamOptimizer(learning_rate).minimize(cost)
    
        # evaluation
        pred_correct = tf.equal(tf.argmax(net, 1), tf.argmax(y, 1))
        accuracy = tf.reduce_mean(tf.cast(pred_correct, tf.float32))
    
        print "loading mnist data"
        from tensorflow.examples.tutorials.mnist import input_data
        mnist = input_data.read_data_sets("/tmp/data/", one_hot=True)
    
        sess = tf.Session()
    
        sess.run(tf.initialize_all_variables())
    
        for i in xrange(train_batches):
            batch_x, batch_y = mnist.train.next_batch(batch_size)
    
            sess.run(optimizer, feed_dict={x: batch_x, y: batch_y, dropout: keep_prob})
    
            if i % display_step == 0:
                loss, acc = sess.run([cost, accuracy], feed_dict={x: batch_x, y: batch_y, dropout: 1.0})
                print "batch: %i, loss: %.5f, accuracy: %.5f" % (i, loss, acc)
    
        acc = sess.run(accuracy, feed_dict={x: mnist.test.images, y: mnist.test.labels, dropout: 1.0})
        print "test accuracy: %.5f" % (acc)
    
        # reconstruction part
        rnd_img = tf.Variable(tf.random_normal([1, n_input]))
    
        one_hot = np.zeros((1, 10))
        one_hot[0,1] = 1;
    
        net2 = create_net(rnd_img, weights, biases, dropout)
        cost2 = -tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(net2, y))
        optimizer2 = tf.train.AdamOptimizer(learning_rate).minimize(cost2, var_list=[rnd_img])
    
        init_var_list = []
    
        for var in tf.all_variables():
            if(not tf.is_variable_initialized(var).eval(session=sess)):
                init_var_list.append(var)
    
        sess.run(tf.initialize_variables(init_var_list))
    
        save_image(rnd_img.eval(sess), "bevor.tiff")
    
        for i in xrange(100000):
            _, loss = sess.run([optimizer2, cost2], feed_dict={y: one_hot, dropout: 1.0})
            if(i%10000 == 0):
                cur_img = rnd_img.eval(session=sess)
                print "loss:", loss, "mi:", np.min(cur_img), "ma:", np.max(cur_img)
    
        save_image(rnd_img.eval(sess), "after.tiff")
    
        sess.close()
    
    if __name__ == "__main__":
        main()
    

    一些解释:在使用新的输入变量和优化器重建图形之后,我不得不初始化新变量,即rnd_img和Adam优化器使用的一些辅助变量,因此循环遍及all_variables()并检查初始化状态。如果有人知道更优雅的方式,请告诉我。或者也许这就是我没有得到任何结果的原因?

1 个答案:

答案 0 :(得分:2)

rnd_img需要您优化的图形的一部分。在您的情况下,您只需创建一个变量并告诉优化器对其进行优化,但该变量未与图中的损失相关联。例如,您可以使用rnd_image而不是x(但使用相同的权重!)再次调用create_net,为此创建成本,然后为该成本创建最小化操作。然后,为了优化,您只能输入y。