TensorFlow实现AutoEncoder自编码器


Posted in Python onMarch 09, 2018

一、概述

AutoEncoder大致是一个将数据的高维特征进行压缩降维编码,再经过相反的解码过程的一种学习方法。学习过程中通过解码得到的最终结果与原数据进行比较,通过修正权重偏置参数降低损失函数,不断提高对原数据的复原能力。学习完成后,前半段的编码过程得到结果即可代表原数据的低维“特征值”。通过学习得到的自编码器模型可以实现将高维数据压缩至所期望的维度,原理与PCA相似。

TensorFlow实现AutoEncoder自编码器

二、模型实现

1. AutoEncoder

首先在MNIST数据集上,实现特征压缩和特征解压并可视化比较解压后的数据与原数据的对照。

先看代码:

import tensorflow as tf 
import numpy as np 
import matplotlib.pyplot as plt 
 
# 导入MNIST数据 
from tensorflow.examples.tutorials.mnist import input_data 
mnist = input_data.read_data_sets("MNIST_data/", one_hot=False) 
 
learning_rate = 0.01 
training_epochs = 10 
batch_size = 256 
display_step = 1 
examples_to_show = 10 
n_input = 784 
 
# tf Graph input (only pictures) 
X = tf.placeholder("float", [None, n_input]) 
 
# 用字典的方式存储各隐藏层的参数 
n_hidden_1 = 256 # 第一编码层神经元个数 
n_hidden_2 = 128 # 第二编码层神经元个数 
# 权重和偏置的变化在编码层和解码层顺序是相逆的 
# 权重参数矩阵维度是每层的 输入*输出,偏置参数维度取决于输出层的单元数 
weights = { 
 'encoder_h1': tf.Variable(tf.random_normal([n_input, n_hidden_1])), 
 'encoder_h2': tf.Variable(tf.random_normal([n_hidden_1, n_hidden_2])), 
 'decoder_h1': tf.Variable(tf.random_normal([n_hidden_2, n_hidden_1])), 
 'decoder_h2': tf.Variable(tf.random_normal([n_hidden_1, n_input])), 
} 
biases = { 
 'encoder_b1': tf.Variable(tf.random_normal([n_hidden_1])), 
 'encoder_b2': tf.Variable(tf.random_normal([n_hidden_2])), 
 'decoder_b1': tf.Variable(tf.random_normal([n_hidden_1])), 
 'decoder_b2': tf.Variable(tf.random_normal([n_input])), 
} 
 
# 每一层结构都是 xW + b 
# 构建编码器 
def encoder(x): 
 layer_1 = tf.nn.sigmoid(tf.add(tf.matmul(x, weights['encoder_h1']), 
         biases['encoder_b1'])) 
 layer_2 = tf.nn.sigmoid(tf.add(tf.matmul(layer_1, weights['encoder_h2']), 
         biases['encoder_b2'])) 
 return layer_2 
 
 
# 构建解码器 
def decoder(x): 
 layer_1 = tf.nn.sigmoid(tf.add(tf.matmul(x, weights['decoder_h1']), 
         biases['decoder_b1'])) 
 layer_2 = tf.nn.sigmoid(tf.add(tf.matmul(layer_1, weights['decoder_h2']), 
         biases['decoder_b2'])) 
 return layer_2 
 
# 构建模型 
encoder_op = encoder(X) 
decoder_op = decoder(encoder_op) 
 
# 预测 
y_pred = decoder_op 
y_true = X 
 
# 定义代价函数和优化器 
cost = tf.reduce_mean(tf.pow(y_true - y_pred, 2)) #最小二乘法 
optimizer = tf.train.AdamOptimizer(learning_rate).minimize(cost) 
 
with tf.Session() as sess: 
 # tf.initialize_all_variables() no long valid from 
 # 2017-03-02 if using tensorflow >= 0.12 
 if int((tf.__version__).split('.')[1]) < 12 and int((tf.__version__).split('.')[0]) < 1: 
  init = tf.initialize_all_variables() 
 else: 
  init = tf.global_variables_initializer() 
 sess.run(init) 
 # 首先计算总批数,保证每次循环训练集中的每个样本都参与训练,不同于批量训练 
 total_batch = int(mnist.train.num_examples/batch_size) #总批数 
 for epoch in range(training_epochs): 
  for i in range(total_batch): 
   batch_xs, batch_ys = mnist.train.next_batch(batch_size) # max(x) = 1, min(x) = 0 
   # Run optimization op (backprop) and cost op (to get loss value) 
   _, c = sess.run([optimizer, cost], feed_dict={X: batch_xs}) 
  if epoch % display_step == 0: 
   print("Epoch:", '%04d' % (epoch+1), "cost=", "{:.9f}".format(c)) 
 print("Optimization Finished!") 
 
 encode_decode = sess.run( 
  y_pred, feed_dict={X: mnist.test.images[:examples_to_show]}) 
 f, a = plt.subplots(2, 10, figsize=(10, 2)) 
 for i in range(examples_to_show): 
  a[0][i].imshow(np.reshape(mnist.test.images[i], (28, 28))) 
  a[1][i].imshow(np.reshape(encode_decode[i], (28, 28))) 
 plt.show()

代码解读:

首先,导入将要使用到的各种库和数据集,定义各个参数如学习率、训练迭代次数等,清晰明了便于后期修改。由于自编码器的神经网络结构非常有规律性,都是xW + b的结构,故将每一层的权重W和偏置b的变量tf.Variable统一置于一个字典中,通过字典的key值更加清晰明了的描述。模型构建思路上,将编码器部分和解码器部分分开构建,每一层的激活函数使用Sigmoid函数,编码器通常与编码器使用同样的激活函数。通常编码器部分和解码器部分是一个互逆的过程,例如我们设计将784维降至256维再降至128维的编码器,解码器对应的就是从128维解码至256维再解码至784维。定义代价函数,代价函数表示为解码器的输出与原始输入的最小二乘法表达,优化器采用AdamOptimizer训练阶段每次循环将所有的训练数据都参与训练。经过训练,最终将训练结果与原数据可视化进行对照,如下图,还原度较高。如果增大训练循环次数或者增加自编码器的层数,可以得到更好的还原效果。

运行结果:

TensorFlow实现AutoEncoder自编码器

2. Encoder

Encoder编码器工作原理与AutoEncoder相同,我们将编码得到的低维“特征值”在低维空间中可视化出来,直观显示数据的聚类效果。具体地说,将784维的MNIST数据一步步的从784到128到64到10最后降至2维,在2维坐标系中展示遇上一个例子不同的是,在编码器的最后一层中我们不采用Sigmoid激活函数,而是将采用默认的线性激活函数,使输出为(-∞,+∞)。

完整代码:

import tensorflow as tf 
import matplotlib.pyplot as plt 
 
from tensorflow.examples.tutorials.mnist import input_data 
mnist = input_data.read_data_sets("MNIST_data/", one_hot=False) 
 
learning_rate = 0.01 
training_epochs = 10 
batch_size = 256 
display_step = 1 
n_input = 784 
X = tf.placeholder("float", [None, n_input]) 
 
n_hidden_1 = 128 
n_hidden_2 = 64 
n_hidden_3 = 10 
n_hidden_4 = 2 
weights = { 
 'encoder_h1': tf.Variable(tf.truncated_normal([n_input, n_hidden_1],)), 
 'encoder_h2': tf.Variable(tf.truncated_normal([n_hidden_1, n_hidden_2],)), 
 'encoder_h3': tf.Variable(tf.truncated_normal([n_hidden_2, n_hidden_3],)), 
 'encoder_h4': tf.Variable(tf.truncated_normal([n_hidden_3, n_hidden_4],)), 
 'decoder_h1': tf.Variable(tf.truncated_normal([n_hidden_4, n_hidden_3],)), 
 'decoder_h2': tf.Variable(tf.truncated_normal([n_hidden_3, n_hidden_2],)), 
 'decoder_h3': tf.Variable(tf.truncated_normal([n_hidden_2, n_hidden_1],)), 
 'decoder_h4': tf.Variable(tf.truncated_normal([n_hidden_1, n_input],)), 
} 
biases = { 
 'encoder_b1': tf.Variable(tf.random_normal([n_hidden_1])), 
 'encoder_b2': tf.Variable(tf.random_normal([n_hidden_2])), 
 'encoder_b3': tf.Variable(tf.random_normal([n_hidden_3])), 
 'encoder_b4': tf.Variable(tf.random_normal([n_hidden_4])), 
 'decoder_b1': tf.Variable(tf.random_normal([n_hidden_3])), 
 'decoder_b2': tf.Variable(tf.random_normal([n_hidden_2])), 
 'decoder_b3': tf.Variable(tf.random_normal([n_hidden_1])), 
 'decoder_b4': tf.Variable(tf.random_normal([n_input])), 
} 
def encoder(x): 
 layer_1 = tf.nn.sigmoid(tf.add(tf.matmul(x, weights['encoder_h1']), 
         biases['encoder_b1'])) 
 layer_2 = tf.nn.sigmoid(tf.add(tf.matmul(layer_1, weights['encoder_h2']), 
         biases['encoder_b2'])) 
 layer_3 = tf.nn.sigmoid(tf.add(tf.matmul(layer_2, weights['encoder_h3']), 
         biases['encoder_b3'])) 
 # 为了便于编码层的输出,编码层随后一层不使用激活函数 
 layer_4 = tf.add(tf.matmul(layer_3, weights['encoder_h4']), 
         biases['encoder_b4']) 
 return layer_4 
 
def decoder(x): 
 layer_1 = tf.nn.sigmoid(tf.add(tf.matmul(x, weights['decoder_h1']), 
         biases['decoder_b1'])) 
 layer_2 = tf.nn.sigmoid(tf.add(tf.matmul(layer_1, weights['decoder_h2']), 
         biases['decoder_b2'])) 
 layer_3 = tf.nn.sigmoid(tf.add(tf.matmul(layer_2, weights['decoder_h3']), 
        biases['decoder_b3'])) 
 layer_4 = tf.nn.sigmoid(tf.add(tf.matmul(layer_3, weights['decoder_h4']), 
        biases['decoder_b4'])) 
 return layer_4 
 
encoder_op = encoder(X) 
decoder_op = decoder(encoder_op) 
 
y_pred = decoder_op 
y_true = X 
 
cost = tf.reduce_mean(tf.pow(y_true - y_pred, 2)) 
optimizer = tf.train.AdamOptimizer(learning_rate).minimize(cost) 
 
with tf.Session() as sess: 
 # tf.initialize_all_variables() no long valid from 
 # 2017-03-02 if using tensorflow >= 0.12 
 if int((tf.__version__).split('.')[1]) < 12 and int((tf.__version__).split('.')[0]) < 1: 
  init = tf.initialize_all_variables() 
 else: 
  init = tf.global_variables_initializer() 
 sess.run(init) 
 total_batch = int(mnist.train.num_examples/batch_size) 
 for epoch in range(training_epochs): 
  for i in range(total_batch): 
   batch_xs, batch_ys = mnist.train.next_batch(batch_size) # max(x) = 1, min(x) = 0 
   _, c = sess.run([optimizer, cost], feed_dict={X: batch_xs}) 
  if epoch % display_step == 0: 
   print("Epoch:", '%04d' % (epoch+1), "cost=", "{:.9f}".format(c)) 
 print("Optimization Finished!") 
 
 encoder_result = sess.run(encoder_op, feed_dict={X: mnist.test.images}) 
 plt.scatter(encoder_result[:, 0], encoder_result[:, 1], c=mnist.test.labels) 
 plt.colorbar() 
 plt.show()

实验结果:

TensorFlow实现AutoEncoder自编码器

由结果可知,2维编码特征有较好的聚类效果,图中每个颜色代表了一个数字,聚集性很好。

当然,本次实验所得到的结果只是对AutoEncoder做一个简单的介绍,要想得到期望的效果,还应该设计更加复杂的自编码器结构,得到区分性更好的特征。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python学习笔记之常用函数及说明
May 23 Python
简单上手Python中装饰器的使用
Jul 12 Python
Python编程判断这天是这一年第几天的方法示例
Apr 18 Python
使用Python制作微信跳一跳辅助
Jan 31 Python
python判断设备是否联网的方法
Jun 29 Python
Python坐标线性插值应用实现
Nov 13 Python
Python关于__name__属性的含义和作用详解
Feb 19 Python
在PyCharm中遇到pip安装 失败问题及解决方案(pip失效时的解决方案)
Mar 10 Python
Python 使用双重循环打印图形菱形操作
Aug 09 Python
python 调用API接口 获取和解析 Json数据
Sep 28 Python
python 通过使用Yolact训练数据集
Apr 06 Python
深入理解pytorch库的dockerfile
Jun 10 Python
TensorFlow实现MLP多层感知机模型
Mar 09 #Python
TensorFlow实现Softmax回归模型
Mar 09 #Python
用python实现百度翻译的示例代码
Mar 09 #Python
TensorFlow深度学习之卷积神经网络CNN
Mar 09 #Python
TensorFlow实现卷积神经网络CNN
Mar 09 #Python
新手常见6种的python报错及解决方法
Mar 09 #Python
Python 函数基础知识汇总
Mar 09 #Python
You might like
php生成文件
2007/01/15 PHP
frename PHP 灵活文件命名函数 frename
2009/09/09 PHP
php强制运行广告的方法
2014/12/01 PHP
thinkphp实现上一篇与下一篇的方法
2014/12/08 PHP
PHP_SELF,SCRIPT_NAME,REQUEST_URI区别
2014/12/24 PHP
PHP面向对象程序设计类的定义与用法简单示例
2016/12/27 PHP
自写的利用PDO对mysql数据库增删改查操作类
2018/02/19 PHP
PHP 对象继承原理与简单用法示例
2020/04/21 PHP
javascript实现yield的方法
2013/11/06 Javascript
js获取客户端外网ip的简单实例
2013/11/21 Javascript
JavaScript使用setTimeout实现延迟弹出警告框的方法
2015/04/07 Javascript
JavaScript使用encodeURI()和decodeURI()获取字符串值的方法
2015/08/04 Javascript
Javascript的表单验证-提交表单
2016/03/18 Javascript
javascript数组去重方法总结(推荐)
2019/03/20 Javascript
微信小程序个人中心的列表控件实现代码
2020/04/26 Javascript
vue 监听窗口变化对页面部分元素重新渲染操作
2020/07/28 Javascript
jquery+ajax实现异步上传文件显示进度条
2020/08/17 jQuery
[05:45]Ti4观战指南(下)
2014/07/07 DOTA
[01:07:20]DOTA2-DPC中国联赛 正赛 Dynasty vs XG BO3 第二场 2月2日
2021/03/11 DOTA
python中使用mysql数据库详细介绍
2015/03/27 Python
Python字典操作详细介绍及字典内建方法分享
2018/01/04 Python
Python控制键盘鼠标pynput的详细用法
2019/01/28 Python
对Pycharm创建py文件时自定义头部模板的方法详解
2019/02/12 Python
django-初始配置(纯手写)详解
2019/07/30 Python
python可迭代对象去重实例
2020/05/15 Python
python两种注释用法的示例
2020/10/09 Python
Python使用paramiko连接远程服务器执行Shell命令的实现
2021/03/04 Python
办理暂住证介绍信
2014/01/11 职场文书
应届生简历中的自我评价
2014/01/13 职场文书
《夏夜多美》教学反思
2014/02/17 职场文书
主管竞聘书范文
2014/03/31 职场文书
广告艺术设计专业自荐书
2014/07/08 职场文书
六查六看自查报告
2014/10/14 职场文书
神龙架导游词
2015/02/11 职场文书
实习生辞职信范文
2015/03/02 职场文书
导游词之藏龙百瀑景区
2019/12/30 职场文书