import tensorflow as tf
import tensorlayer as tl
import gzip
import os
import numpy as np
import logging
import matplotlib.pyplot as plt
########################
#改写原函数,地址:https://github.com/tensorlayer/tensorlayer/blob/master/tensorlayer/files.py
## Load dataset functions
def load_mnist_dataset_by_q(shape=(-1, 784), path="data"):
"""Load MNIST dataset.
Automatically download MNIST dataset and return the training, validation and test set with 50000, 10000 and 10000 digit images respectively.
Parameters
----------
shape : tuple
The shape of digit images e.g. (-1,784) or (-1, 28, 28, 1).
path : str
The path that the data is downloaded to, defaults is ``data/mnist/``.
Examples
--------
>>> X_train, y_train, X_val, y_val, X_test, y_test = tl.files.load_mnist_dataset(shape=(-1,784))
>>> X_train, y_train, X_val, y_val, X_test, y_test = tl.files.load_mnist_dataset(shape=(-1, 28, 28, 1))
"""
path = os.path.join(path, 'MNIST_data/')
# We first define functions for loading MNIST images and labels.
# For convenience, they also download the requested files if needed.
def load_mnist_images(path, filename):
# filepath = maybe_download_and_extract(filename, path, 'http://yann.lecun.com/exdb/mnist/')
filepath = path + filename
logging.info(filepath)
# Read the inputs in Yann LeCun's binary format.
with gzip.open(filepath, 'rb') as f:
data = np.frombuffer(f.read(), np.uint8, offset=16)
# The inputs are vectors now, we reshape them to monochrome 2D images,
# following the shape convention: (examples, channels, rows, columns)
data = data.reshape(shape)
# The inputs come as bytes, we convert them to float32 in range [0,1].
# (Actually to range [0, 255/256], for compatibility to the version
# provided at http://deeplearning.net/data/mnist/mnist.pkl.gz.)
return data / np.float32(256)
def load_mnist_labels(path, filename):
# filepath = maybe_download_and_extract(filename, path, 'http://yann.lecun.com/exdb/mnist/')
filepath = path + filename
# Read the labels in Yann LeCun's binary format.
with gzip.open(filepath, 'rb') as f:
data = np.frombuffer(f.read(), np.uint8, offset=8)
# The labels are vectors of integers now, that's exactly what we want.
return data
# Download and read the training and test set images and labels.
logging.info("Load or Download MNIST > {}".format(path))
X_train = load_mnist_images(path, 'train-images-idx3-ubyte.gz')
y_train = load_mnist_labels(path, 'train-labels-idx1-ubyte.gz')
X_test = load_mnist_images(path, 't10k-images-idx3-ubyte.gz')
y_test = load_mnist_labels(path, 't10k-labels-idx1-ubyte.gz')
# We reserve the last 10000 training examples for validation.
X_train, X_val = X_train[:-10000], X_train[-10000:]
y_train, y_val = y_train[:-10000], y_train[-10000:]
# We just return all the arrays in order, as expected in main().
# (It doesn't matter how we do this as long as we can read them again.)
X_train = np.asarray(X_train, dtype=np.float32)
y_train = np.asarray(y_train, dtype=np.int32)
X_val = np.asarray(X_val, dtype=np.float32)
y_val = np.asarray(y_val, dtype=np.int32)
X_test = np.asarray(X_test, dtype=np.float32)
y_test = np.asarray(y_test, dtype=np.int32)
return X_train, y_train, X_val, y_val, X_test, y_test
########################
X_train, y_train, X_val, y_val, X_test, y_test = load_mnist_dataset_by_q(shape=(-1,784),path='/Users/qyk/Desktop/py/tensorflow/MNIST')
#超参数
learning_rate = 0.0001
lambda_12_w = 0.01
n_epochs = 200
batch_size = 128
print_interval = 200
#模型结构参数
hidden_size = 196
input_size = 784
image_width = 28
#模型类别:可选Sigmoid和ReLU
model = 'sigmoid'
# model = 'relu'
########################
##定义模型
x = tf.placeholder(dtype=tf.float32,shape=[None,784],name='x')
print('Build Network')
if model == 'relu':
#输入层f(x)
network = tl.layers.InputLayer(inputs=x,name='input')
network = tl.layers.DenseLayer(layer=network,n_units=hidden_size,act=tf.nn.relu,name='relu1')
#隐层输出
encoded_img = network.outputs
#重构层输出
recon_layer1 = tl.layers.DenseLayer(layer=network,n_units=input_size,act=tf.nn.softplus,name='recon_layer1')
elif model == 'sigmoid':
# 输入层f(x)
network = tl.layers.InputLayer(inputs=x, name='input')
network = tl.layers.DenseLayer(layer=network, n_units=hidden_size, act=tf.nn.sigmoid, name='sigmoid1')
# 隐层输出
encoded_img = network.outputs
# 重构层输出
recon_layer1 = tl.layers.DenseLayer(layer=network, n_units=input_size, act=tf.nn.sigmoid, name='recon_layer1')
########################
#定义损失函数
y = recon_layer1.outputs
train_params = recon_layer1.all_params[-4:]
#均方误差
mse = tf.reduce_sum(tf.squared_difference(y,x),1)
mse = tf.reduce_mean(mse)
#权值衰减
L2_w = tf.contrib.layers.l2_regularizer(lambda_12_w)(train_params[0]) + tf.contrib.layers.l2_regularizer(lambda_12_w)(train_params[2])
#稀疏性约束
activation_out = recon_layer1.all_layers[-2]
L1_a = 0.001 * tf.reduce_mean(activation_out)
#相对熵KLD
beta = 5
rho = 0.15
p_hat = tf.reduce_mean(activation_out,0)
KLD = beta * tf.reduce_sum(rho * tf.log(tf.divide(rho,p_hat)) + (1 - rho) * tf.log((1 - rho)/ (tf.subtract(float(1), p_hat))))
#联合损失函数
if model == 'sigmoid':
cost = mse + L2_w + KLD
if model == 'relu':
cost = mse + L2_w + L1_a
#定义优化器
train_op = tf.train.AdamOptimizer(learning_rate).minimize(cost)
saver = tf.train.Saver()
########################
##模型训练
#一个Epoch的batch数量
total_batch = X_train.shape[0] // batch_size
sess = tf.InteractiveSession()
tl.layers.initialize_global_variables(sess)
# 开始训练
for epoch in range(n_epochs):
avg_cost = 0
#这里可以用tl.iterate.minibatches 代替
for i in range(total_batch):
batch_x = X_train[i * batch_size:(i + 1) * batch_size]
batch_y = y_train[i * batch_size:(i + 1) * batch_size]
batch_x = np.array(batch_x).astype(np.float32)
batch_cost,_ = sess.run([cost,train_op],feed_dict={x: batch_x})
avg_cost += batch_cost
if not i % print_interval:
print('Minibatch: %03d | Cost: %.3f' % (i + 1, batch_cost))
#打印一个Epoch的信息
print('Epoch: %03d | AvgCost: %.3f' % (epoch + 1, avg_cost / (i + 1)))
#保存模型为tensorflow的ckpt格式
saver.save(sess,save_path='/Users/qyk/Desktop/py/tensorlayer/autoencoder/autoencoder.ckpt')
########################
#plot it
n_images = 15
fig, axes = plt.subplots(nrows=2, ncols=n_images, sharex=True, sharey=True, figsize= (20, 2.5))
#准备输入数据
test_images = X_test[:n_images]
with tf.Session() as sess:
#加载训练好的模型
saver.restore(sess, save_path='/Users/qyk/Desktop/py/tensorlayer/autoencoder/autoencoder.ckpt')
#获取重构数据
decoded = sess.run(recon_layer1.outputs, feed_dict={x: test_images})
#获取f(x)的W参数
if model == 'relu':
weights = sess.run(tl.layers.get_variables_with_name('relu1/W:0',False,True))
elif model == 'sigmoid':
weights = sess.run(tl.layers.get_variables_with_name('sigmoid1/W:0',False,True))
#获取g(h)的参数
recon_weights = sess.run(tl.layers.get_variables_with_name('recon_layer1/W:0',False,True))
recon_bias = sess.run(tl.layers.get_variables_with_name('recon_layer1/b:0', False, True))
#保存图片
for i in range(n_images):
for ax, img in zip(axes, [test_images, decoded]):
ax[i].imshow(img[i].reshape((image_width,image_width)),cmap='binary')
plt.show()