看了Deep Auto-encoder,然后实现了一下,但是发现要初始化好参数,不然可能效果不佳。Deep Auto-encoder的实现
SDAE的思想是每次训练一层网络,训练好了之后将此网络的输入当做下一层网络的输入,用于训练下一层网络。这样当前k层训练好之后,再训练第k+1层,而不是像我上面那个文章一样,一次性将k层一起训练了。将每层都训练好之后,再结合起来进行训练(fine-tune),这样能够达到比较好的效果。
SDAE的思想可以再搜一下,可以了解更清楚。
实现效果:
单独训练好每一层的网络,然后测试一下效果(上面是原图,下面是编码再解码的图片):
然后将网络结合起来进行训练,下面是迭代6000次的效果,测试的时候发现有的图片效果很棒,有的效果不太好(上面是原图,下面是编码再解码的图片):
上面的效果encoder的最后一层神经元有30个,即将28 x 28的图片降到30维,然后再从30维转回图片的效果。
但是30维不好显示在二维图形上面,所以下面将30换成2,然后用散点图进行显示。
重新训练,将图片降到2维之后,再从2维解码生成图片,效果如下:
从测试集中选取了3000个图片,然后通过encoder进行编码,降到2维,绘制效果如下:
可以看出0,1,2,6的被分隔得很开,其他的会重叠在一起。
上面的实验结果都是没有加入噪声数据的,加入20%的噪声数据,即随机将图片上面的像素值设置为0,效果如下(上面的是噪声图片,下面是编码再解码生成的图片):
可以看出,SDAE可以从噪声数据进行降维,然后生成去噪的图片,效果还是不错的。上面的效果是降到10维的效果。
降到2维的效果:
不知道为什么加了噪声之后,生成的图片反而没有黑点了,有点神奇。
代码:
# coding=utf-8
from keras.datasets import mnist
from keras.layers import Input, Dense, Reshape,Flatten
from keras.models import Sequential, Model
from keras.optimizers import Adam, SGD
from keras.layers.convolutional import UpSampling2D, Conv2D,MaxPooling2D,Conv2DTranspose
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import sys
import os
import numpy as np
from tensorflow.examples.tutorials.mnist import input_data
img_height = 28
img_width = 28
batch_size = 64
mnist = input_data.read_data_sets('../data/MNIST_data', one_hot=True)
def img_to_code(img_input):
if trained_encoder is not None:
return trained_encoder.predict(img_input)
else:
return img_input
def noise(code):
idx = np.around(np.random.uniform(0.,code.shape[1]-1,size=int(code.shape[1]/5))).astype(np.int)
noise_code = np.copy(code)
noise_code[:,idx] = 0
return noise_code
def train_one_by_one():
epochs = 3000
delta = 0
trained_encoder = None
layers = [28 * 28, 700, 400, 200, 50,10,2]
decoders = []
for i in range(len(layers) - 1):
encoder = Sequential()
if i == len(layers) -2:
encoder.add(Dense(units=layers[i + 1]))
else:
encoder.add(Dense(units=layers[i + 1],activation='sigmoid'))
decoder = Sequential()
decoder.add(Dense(units=layers[i], activation='sigmoid'))
encoder_input = Input(shape=(layers[i],))
code = encoder(encoder_input)
reconstruct_code = decoder(code)
combined = Model(encoder_input, reconstruct_code)
optimizer = Adam(0.001)
combined.compile(loss='mse', optimizer=optimizer)
for j in range(epochs):
imgs, _ = mnist.train.next_batch(batch_size)
# 由之前训练好的encoder 将image转成code 如果没有训练过的encoder 那code就是image
code = imgs if (trained_encoder is None) else trained_encoder.predict(imgs)
noise_code = noise(code)
loss = combined.train_on_batch(noise_code, code)
if j % 50 == 0:
print("%d layer,loss:%f"%(i,loss))
# 经过上面的for循环 已经又训练好了一层encoder 将encoder与之前的合并
if trained_encoder is None:
trained_encoder = encoder
else:
img_input = Input(shape=[img_width * img_height])
input_code = trained_encoder(img_input)
code = encoder(input_code)
trained_encoder = Model(img_input,code)
# 保存当前encoder 对应的decoder
decoders.append(decoder)
epochs += delta #每层增加1000次迭代次数
img_input = Input(shape=[img_width * img_height])
decoders.reverse()
last_decode = trained_encoder(img_input)
for decoder in decoders:
last_decode = decoder(last_decode)
combined = Model(img_input, last_decode)
combined.compile(loss='mse', optimizer=optimizer)
return trained_encoder,combined
def train(combined,epochs):
losses = []
for i in range(epochs):
imgs, labels = mnist.train.next_batch(batch_size)
noise_imgs = noise(imgs)
loss = combined.train_on_batch(noise_imgs, imgs)
if i >= 20 and i % 5 == 0:
print("epoch:%d,loss:%f" % (i, loss))
losses.append(loss)
plt.plot(np.arange(20, epochs, 5), losses)
plt.show()
picture_num = 4
def test(combined):
figure_num = 1
for _ in range(picture_num):
imgs, labels = mnist.test.next_batch(3)
noise_imgs = noise(imgs)
score = combined.evaluate(noise_imgs, imgs, verbose=0)
print("Test loss:", score)
output_imgs = combined.predict(noise_imgs)
for i in range(3):
plt.figure(figure_num)
plt.subplot(2, 3, i + 1) # 两行一列的第一个子图
plt.imshow(noise_imgs[i].reshape((28, 28)), cmap='gray')
plt.subplot(2, 3, i + 1 + 3) # 两行一列的第二个子图
plt.imshow(output_imgs[i].reshape((28, 28)), cmap='gray')
figure_num += 1
def plot_low_dimension():
imgs, labels = mnist.test.next_batch(3000)
labels = np.transpose(np.nonzero(labels))[:,1]
codes = encoder.predict(imgs)
plt.figure(10)
i = 0
for color in ['red','blue','green','black','chocolate','silver','lawngreen','darkcyan','lawngreen','c']:
y = (labels.T == i)
x = codes[y]
plt.scatter(x[:,0],x[:,1],c=color,label=str(i),alpha=0.6,edgecolors='white')
i+=1
plt.title('Scatter')
plt.xlabel('x')
plt.ylabel('y')
plt.legend(loc='best')
plt.show()
def plot_3d():
imgs, labels = mnist.test.next_batch(3000)
labels = np.transpose(np.nonzero(labels))[:,1]
codes = encoder.predict(imgs)
plt.figure(4)
ax = Axes3D(fig)
i = 0
for color in ['red','blue','green','black','chocolate','silver','lawngreen','darkcyan','lawngreen','c']:
y = (labels.T == i)
x = codes[y]
plt.scatter(x[:,0],x[:,1],x[:,2],c=color,label=str(i),alpha=0.6,edgecolors='white')
i+=1
# 绘制图例
ax.legend(loc='best')
# 添加坐标轴(顺序是Z, Y, X)
ax.set_zlabel('Z', fontdict={'size': 15, 'color': 'red'})
ax.set_ylabel('Y', fontdict={'size': 15, 'color': 'red'})
ax.set_xlabel('X', fontdict={'size': 15, 'color': 'red'})
# 展示
plt.show()
if __name__ == '__main__':
encoder, combined = train_one_by_one()
train(combined, 6000)
test(combined)
# plot_low_dimension()