实例80:实现去噪自编码

首先建立一个去噪声自编码,然后对第一层的输出做一次简单的自编码压缩,然后再将第二层的输出做一个softmax的分类,最后,把这3个网络的中间层拿出来,组成一个新的网络进行微调。

1. 引入头文件,创建网络模型及定义学习参数变量

实例描述

对MNIST集中的原始输入图片加入噪声,在自编码网络中进行训练,得到抗干扰更强的特征提取模型。

import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
from tensorflow.examples.tutorials.mnist import input_data

#导入MNIST数据
mnist = input_data.read_data_sets("/data/", one_hot=True)

#建立训练和测试数据
train_X   = mnist.train.images
train_Y = mnist.train.labels
test_X    = mnist.test.images
test_Y  = mnist.test.labels
print ("MNIST ready")

2. 定义占位符

最终训练的网络为一个输入,一个输入出和中间两个隐藏层。
输入层维度为784,中间两个隐藏层的维度为256、128,最后输出层的维度为10

n_input    = 784 
n_hidden_1 = 256    #第一层自编码
n_hidden_2 = 128    #第二层自编码
n_classes = 10

#定义占位符
#第一层输入
x = tf.placeholder("float", [None, n_input])
y = tf.placeholder("float", [None, n_input])
dropout_keep_prob = tf.placeholder("float")     #dropout参数
#第二层输入
l2x = tf.placeholder("float", [None, n_hidden_1])
l2y = tf.placeholder("float", [None, n_hidden_1]) 
#第三层输入
l3x = tf.placeholder("float", [None, n_hidden_2])
l3y = tf.placeholder("float", [None, n_classes])

本例中需要建立4个网络:每一层都用一个网络来训练,需要训练3个网络,最后再把训练好的各层组合在一起,形成第4个网络。

3. 定义学习参数

除了输入层,后面的其他三层(256、128、10)每一层都需要单独使用一个自编码网络来训练,所以需要创建3套学习参数。

weights = {
    #网络1  784-256-784
    'h1': tf.Variable(tf.random_normal([n_input, n_hidden_1])),
    'l1_h2': tf.Variable(tf.random_normal([n_hidden_1, n_hidden_1])),
    'l1_out': tf.Variable(tf.random_normal([n_hidden_1, n_input])),
    #网络2  256-128-256
    'l2_h1': tf.Variable(tf.random_normal([n_hidden_1, n_hidden_2])),
    'l2_h2': tf.Variable(tf.random_normal([n_hidden_2, n_hidden_2])),
    'l2_out': tf.Variable(tf.random_normal([n_hidden_2, n_hidden_1])),
    #网络3  128-10
    'out': tf.Variable(tf.random_normal([n_hidden_2, n_classes]))
}

biases = {
    'b1': tf.Variable(tf.zeros([n_hidden_1])),
    'l1_b2': tf.Variable(tf.zeros([n_hidden_1])),
    'l1_out': tf.Variable(tf.zeros([n_input])),
    
    'l2_b1': tf.Variable(tf.zeros([n_hidden_2])),
    'l2_b2': tf.Variable(tf.zeros([n_hidden_2])),
    'l2_out': tf.Variable(tf.zeros([n_hidden_1])),
    
    'out': tf.Variable(tf.zeros([n_classes]))
}

4. 第1层网络结构

为第1层建立一个自编码网络,并定义其网络结构。这里加入噪声,需要用dropout层

#第一层的输出
l1_out = tf.nn.sigmoid(tf.add(tf.matmul(x, weights['h1']), biases['b1'])) 

#第一层的解码器
def noise_l1_autodecoder(layer_1, _keep_prob):
    #对输入层进行dropout
     layer_1out = tf.nn.dropout(layer_1, _keep_prob) 
    #编码
    layer_2 = tf.nn.sigmoid(tf.add(tf.matmul(layer_1out, _weights['l1_h2']), _biases['l1_b2'])) 
    #dropout
    layer_2out = tf.nn.dropout(layer_2, _keep_prob) 
    #解码
    return tf.nn.sigmoid(tf.matmul(layer_2out, _weights['l1_out']) + _biases['l1_out'])
    
#第一层解码输出
l1_reconstruction = noise_l1_autodecoder(l1_out, weights, biases, dropout_keep_prob)

#cost和优化器
l1_cost = tf.reduce_mean(tf.pow(l1_reconstruction-y, 2)) 
l1_optm = tf.train.AdamOptimizer(0.01).minimize(l1_cost) 

5. 第2层网络结构

为第2层建立一个自编码网络,并定义其网络结构


#第二层的输出
l2_out = tf.nn.sigmoid(tf.add(tf.matmul(l2x, weights['l2_h1']), biases['l2_b1'])) 
#自编码器
def l2_autodecoder(layer1_2, _weights, _biases):
    layer1_2out = tf.nn.sigmoid(tf.add(tf.matmul(layer1_2, _weights['l2_h2']), _biases['l2_b2'])) 
    return tf.nn.sigmoid(tf.matmul(layer1_2out, _weights['l2_out']) + _biases['l2_out'])

# 第二层的解码输出
l2_reconstruction = l2_autodecoder(l2_out, weights, biases)

# COST
l2_cost = tf.reduce_mean(tf.pow(l2_reconstruction-l2y, 2))
# OPTIMIZER
optm2 = tf.train.AdamOptimizer(0.01).minimize(l2_cost)

6. 第3层网络结构

对第三层网络进行softmax分类


#第三层的输出
l3_out = tf.matmul(l3x, weights['out']) + biases['out']
l3_cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=l3_out, labels=l3y))
l3_optm = tf.train.AdamOptimizer(0.01).minimize(l3_cost)

7. 定义级联网络结构

上面三层网络都是定义的单独的网络,将3层网络级联在一起,建立第4个网络,并定义其网络结构。这里服用了l1_out的节点,因为第1层的输入也是原始样本,与级联网络中的第一层一样。


#将三层网络级联
# 1联2
l1_l2out = tf.nn.sigmoid(tf.add(tf.matmul(l1_out, weights['l2_h1']), biases['l2_b1'])) 
# 2联3
pred = tf.matmul(l1_l2out, weights['out']) + biases['out']
#定义cost和优化器
cost3 = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=pred, labels=l3y))
optm3 = tf.train.AdamOptimizer(0.001).minimize(cost3)
print ("l3 级联 ")

8. 第1层网络训练

epochs     = 50
batch_size = 100
disp_step  = 10
load_epoch =49
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    
    print ("开始训练")
    for epoch in range(epochs):
        num_batch  = int(mnist.train.num_examples/batch_size)
        total_cost = 0.
        for i in range(num_batch):
            batch_xs, batch_ys = mnist.train.next_batch(batch_size)
            batch_xs_noisy = batch_xs + 0.3*np.random.randn(batch_size, 784)
            feeds = {x: batch_xs_noisy, y: batch_xs, dropout_keep_prob: 0.5}
            sess.run(l1_optm, feed_dict=feeds)
            total_cost += sess.run(l1_cost, feed_dict=feeds)
        # DISPLAY
        if epoch % disp_step == 0:
            print ("Epoch %02d/%02d average cost: %.6f" 
                   % (epoch, epochs, total_cost/num_batch))
        
    
    print(sess.run(weights['h1'])) 
    print (weights['h1'].name) 
           
    print ("完成")    
    show_num = 10
    test_noisy = mnist.test.images[:show_num] + 0.3*np.random.randn(show_num, 784)
    encode_decode = sess.run(
        l1_reconstruction, feed_dict={x: test_noisy, dropout_keep_prob: 1.})
    f, a = plt.subplots(3, 10, figsize=(10, 3))
    for i in range(show_num):
        a[0][i].imshow(np.reshape(test_noisy[i], (28, 28)))
        a[1][i].imshow(np.reshape(mnist.test.images[i], (28, 28)))
        a[2][i].matshow(np.reshape(encode_decode[i], (28, 28)), cmap=plt.get_cmap('gray'))
    plt.show()

在这里插入图片描述
只通过一个自编码层进行训练得到的结果如上,可以将图片中的噪声去掉,这是采用了dropout的效果,dropout值设为0.5,有一半的节点会丢掉。

9. 第2层网络训练

注意网络模型的输入不是MNIST图片,而是上一层的输出,所以在准备输入数据时,要让图片数据在上一层的模型中计算一次再进行输入。

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    
    print ("开始训练")
    for epoch in range(epochs):
        num_batch  = int(mnist.train.num_examples/batch_size)
        total_cost = 0.
        for i in range(num_batch):
            batch_xs, batch_ys = mnist.train.next_batch(batch_size)

            l1_h = sess.run(l1_out, feed_dict={x: batch_xs, y: batch_xs, dropout_keep_prob: 1.})
            _,l2cost = sess.run([optm2,l2_cost], feed_dict={l2x: l1_h, l2y: l1_h })
            total_cost += l2cost
       
       # log
        if epoch % disp_step == 0:
            print ("Epoch %02d/%02d average cost: %.6f" 
                   % (epoch, epochs, total_cost/num_batch))
        
    print(sess.run(weights['h1'])) 
    print (weights['h1'].name)  
    print ("完成  layer_2 训练")
    
    show_num = 10
    testvec = mnist.test.images[:show_num]
    out1vec = sess.run(l1_out, feed_dict={x: testvec,y: testvec, dropout_keep_prob: 1.})
    out2vec = sess.run(l2_reconstruction, feed_dict={l2x: out1vec})

    f, a = plt.subplots(3, 10, figsize=(10, 3))
    for i in range(show_num):
        a[0][i].imshow(np.reshape(testvec[i], (28, 28)))
        a[1][i].matshow(np.reshape(out1vec[i], (16, 16)), cmap=plt.get_cmap('gray'))
        a[2][i].matshow(np.reshape(out2vec[i], (16, 16)), cmap=plt.get_cmap('gray'))
    plt.show()

在这里插入图片描述
第2层的输入图片经过一个全连接层后的输出维度为256,不是原来的图片了

10. 第3层网络训练

同理,这次的输入也需要经过上面两次的运算才行。

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    
    print ("开始训练")
    for epoch in range(epochs):
        num_batch  = int(mnist.train.num_examples/batch_size)
        total_cost = 0.
        for i in range(num_batch):
            batch_xs, batch_ys = mnist.train.next_batch(batch_size)               
            l1_h = sess.run(l1_out, feed_dict={x: batch_xs, y: batch_xs, dropout_keep_prob: 1.})               
            l2_h = sess.run(l2_out, feed_dict={l2x: l1_h, l2y: l1_h })
            _,l3cost = sess.run([l3_optm,l3_cost], feed_dict={l3x: l2_h, l3y: batch_ys})

            total_cost += l3cost
        # DISPLAY
        if epoch % disp_step == 0:
            print ("Epoch %02d/%02d average cost: %.6f" 
                   % (epoch, epochs, total_cost/num_batch))
           
       
    print ("完成  layer_3 训练")
    # 测试 model
    correct_prediction = tf.equal(tf.argmax(pred, 1), tf.argmax(l3y, 1))
    # 计算准确率
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
    print ("Accuracy:", accuracy.eval({x: mnist.test.images, l3y: mnist.test.labels}))

第3层则为再加一层的输出为128维度。

11. 栈式自编码网络验证。

直接验证真个分类模型,将MNIST数据输入进去,看分类的结果如何。

# 测试 model
    correct_prediction = tf.equal(tf.argmax(pred, 1), tf.argmax(l3y, 1))
    # 计算准确率
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
    print ("Accuracy:", accuracy.eval({x: mnist.test.images, l3y: mnist.test.labels}))

12. 级联微调

下面进入微调阶段,将网络模型联起来进行分类训练。

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    
    print ("开始训练")
    for epoch in range(epochs):
        num_batch  = int(mnist.train.num_examples/batch_size)
        total_cost = 0.
        for i in range(num_batch):
            batch_xs, batch_ys = mnist.train.next_batch(batch_size)
            
            feeds = {x: batch_xs, l3y: batch_ys}
            sess.run(optm3, feed_dict=feeds)
            total_cost += sess.run(cost3, feed_dict=feeds)
        # DISPLAY
        if epoch % disp_step == 0:
            print ("Epoch %02d/%02d average cost: %.6f" 
                   % (epoch, epochs, total_cost/num_batch))
           
    print ("完成  级联 训练")

相当于直接调用已经训练好的参数再进行训练,由于网络模型中层的初始值已经训练好了,所以开始就有很低的错误率,接着训练时,错误率进一步下降。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值