自动编码器python_使用Keras完成自动编码器

学习使用Python中的Keras包,利用自动编码器Autoencoder,分析手写字体数据。

首先是准备工作,程序如下:

## 加载包

%matplotlib inline

%config InlineBackend.figure_format='jpeg'

from IPython.display import Image

import numpy as np

import pandas as pd

from keras.models import Model

from keras.layers import Dense, Dropout, Input

import keras as K

from sklearn.preprocessing import StandardScaler,OneHotEncoder

from sklearn import metrics

import matplotlib.pyplot as plt

import seaborn as sns

## 导入数据

(x_train, y_train), (x_test, y_test) = K.datasets.mnist.load_data()

print(x_train.shape)

print(y_train.shape)

print(x_test.shape)

print(y_test.shape)

(60000, 28, 28)

(60000,)

(10000, 28, 28)

(10000,)

数据中一共有60000张28x28的训练数据,10000张28x28的测试数据。因为下面将要使用的层都是全连接层,所以要将每张图像转化为1维向量。

# 图像数据进行预处理

x_train = x_train.astype('float32') / 255.

x_test = x_test.astype('float32') / 255.

## 更改数据尺寸

x_train = x_train.reshape((x_train.shape[0], -1))

x_test = x_test.reshape((x_test.shape[0], -1))

经过变化话,训练集为60000x784的矩阵,测试集为10000x784的矩阵。

搭建自动编码器网络框架

## 使用全连接层进行连接

input_img = Input(shape=(784,))

## encoded部分

encoded = Dense(128,activation="relu",name = "enco1")(input_img)

encoded = Dense(64,activation="relu",name = "enco2")(encoded)

encoded = Dense(32,activation="relu",name = "enco3")(encoded)

encoded = Dense(16,activation="relu",name = "enco4")(encoded)

encoded = Dense(8,activation="relu",name = "enco5")(encoded)

## decoded部分

decoded = Dense(16,activation="relu",name = "deco1")(encoded)

decoded = Dense(32,activation="relu",name = "deco2")(decoded)

decoded = Dense(64,activation="relu",name = "deco3")(decoded)

decoded = Dense(128,activation="relu",name = "deco4")(decoded)

decoded = Dense(784,activation="sigmoid",name = "deco5")(decoded)

## 连接为自编码模型

autoencoder = Model(input=input_img, output=decoded)

autoencoder.summary()

Layer (type) Output Shape Param #

=================================================================

input_1 (InputLayer) (None, 784) 0

_________________________________________________________________

enco1 (Dense) (None, 128) 100480

_________________________________________________________________

enco2 (Dense) (None, 64) 8256

_________________________________________________________________

enco3 (Dense) (None, 32) 2080

_________________________________________________________________

enco4 (Dense) (None, 16) 528

_________________________________________________________________

enco5 (Dense) (None, 8) 136

_________________________________________________________________

deco1 (Dense) (None, 16) 144

_________________________________________________________________

deco2 (Dense) (None, 32) 544

_________________________________________________________________

deco3 (Dense) (None, 64) 2112

_________________________________________________________________

deco4 (Dense) (None, 128) 8320

_________________________________________________________________

deco5 (Dense) (None, 784) 101136

=================================================================

Total params: 223,736

Trainable params: 223,736

Non-trainable params: 0

_________________________________________________________________

上面的自编码器框架中,会将784维的图像编码为8维,然后再解码到784维。在模型编译时,使用逐像素的交叉熵作为损失函数,优化器为adam。

## 使用逐像素的交叉熵作为损失函数,优化器为adam

autoencoder.compile(optimizer='adadelta', loss='binary_crossentropy')

针对0~1范围内的取值进行训练

## 模型训练

autoencoder_fit = autoencoder.fit(x_train, x_train,nb_epoch=100,batch_size=256,

shuffle=True,validation_data=(x_test,x_test),verbose=0)

## 绘制迭代次数和loss之间的关系

## 绘制图像

plt.figure(figsize=(10,6.5))

plt.plot(autoencoder_fit.epoch,autoencoder_fit.history["loss"],"ro-",lw = 2)

plt.plot(autoencoder_fit.epoch,autoencoder_fit.history["val_loss"],"bs-",lw = 2)

plt.grid()

plt.xlabel("Model epoch")

plt.ylabel("binary_crossentropy")

plt.title("Autoencoder")

plt.show()

上面是针对数据进行epoch=100的迭代训练。冰晶损失函数的取值进行可视化。

可以发现,经过100轮的训练后,模型几乎已经收敛。下面获取测试数据集经过编码后的8维特征,并对其进行可视化。

## 计算测试数据的Encoded,并可视化

## 先定义encoder模型作为输出

encoder = Model(input_img, encoded)

## 获取测试集的encoded

encoded_imgs = encoder.predict(x_test)

print(encoded_imgs.shape)

colna = ["feature"+str(ii+1) for ii in range(8)]

encoded_feture = pd.DataFrame(data = encoded_imgs,columns=colna)

encoded_feture["lab"] = ["cla_"+str(i) for i in y_test]

print(encoded_feture.head())

## 使用矩阵散点图可视化自编码的点分布

sns.pairplot(encoded_feture,hue="lab",size=3,diag_kind=None)

plt.title("Encoded feature")

plt.show()

feature1 feature2 feature3 feature4 feature5 feature6 feature7 \

0 12.116272 0.0 12.858566 15.669122 2.838675 10.398287 9.041433

1 1.157638 0.0 5.085598 7.185266 8.355832 4.039139 3.556945

2 4.089868 0.0 16.886538 20.305134 12.612089 17.451355 10.378060

3 12.908182 0.0 6.505641 5.012246 14.547909 6.277741 5.777000

4 18.666761 0.0 12.316364 8.246981 6.462950 10.300065 9.926409

feature8 lab

0 0.0 cla_7

1 0.0 cla_2

2 0.0 cla_1

3 0.0 cla_0

4 0.0 cla_4编码后特征矩阵散点图

下面对比编码前原始图像和解码后的图像,对比前几张图像。

## 可视化对比自编码前后的图像

decoded_imgs = autoencoder.predict(x_test)

n = 10

plt.figure(figsize=(20, 4))

for i in range(n):

# display original

plt.subplot(2, n, i+1)

plt.imshow(x_test[i].reshape(28, 28))

plt.gray()

plt.axis("off")

# display reconstruction

plt.subplot(2, n, i + n+1)

plt.imshow(decoded_imgs[i].reshape(28, 28))

plt.gray()

plt.axis("off")

plt.show()自编码图像前后对比

图像中第一行是原始的图像,第二行是对应的重新编码后的输出图像。上面的处理使用的数据没有经过标准化,下面对数据进行标准化处理,然后使用自编码器进行处理。

数据标准化的自动编码器

## 数据标准化

scale = StandardScaler()

x_train_s = scale.fit_transform(x_train)

x_test_s = scale.fit_transform(x_test)

## 使用逐像素的交叉熵作为损失函数,优化器为adam

autoencoder.compile(optimizer='adadelta', loss='binary_crossentropy')

## 模型训练,使用标准化后的数据

autoencoder_fit = autoencoder.fit(x_train_s, x_train_s,nb_epoch=100,batch_size=256,

shuffle=True,validation_data=(x_test_s,x_test_s),verbose=0)

## 绘制迭代次数和loss之间的关系

## 绘制图像

plt.figure(figsize=(10,6.5))

plt.plot(autoencoder_fit.epoch,autoencoder_fit.history["loss"],"ro-",lw = 2)

plt.plot(autoencoder_fit.epoch,autoencoder_fit.history["val_loss"],"bs-",lw = 2)

plt.grid()

plt.xlabel("Model epoch")

plt.ylabel("binary_crossentropy")

plt.title("Autoencoder")

plt.show()

不知为何损失函数的取值是负值。同样经过100轮的训练,模型收敛。

## 计算测试数据的Encoded,并可视化

## 先定义encoder模型作为输出

encoder = Model(input_img, encoded)

## 获取测试集的encoded

encoded_imgs = encoder.predict(x_test_s)

print(encoded_imgs.shape)

colna = ["feature"+str(ii+1) for ii in range(8)]

encoded_feture = pd.DataFrame(data = encoded_imgs,columns=colna)

encoded_feture["lab"] = ["cla_"+str(i) for i in y_test]

print(encoded_feture.head())

## 使用矩阵散点图可视化自编码的点分布

sns.pairplot(encoded_feture,hue="lab",size=3,diag_kind=None)

plt.title("Encoded feature")

plt.show()

直观上感受,编码得到的8维特征的矩阵散点图,并没有上面的矩阵散点图效果好。

## 可视化对比自编码前后的图像

decoded_imgs = autoencoder.predict(x_test_s)

n = 10

plt.figure(figsize=(20, 4))

for i in range(n):

# display original

plt.subplot(2, n, i+1)

plt.imshow(x_test_s[i].reshape(28, 28))

plt.gray()

plt.axis("off")

# display reconstruction

plt.subplot(2, n, i + n+1)

plt.imshow(decoded_imgs[i].reshape(28, 28))

plt.gray()

plt.axis("off")

plt.show()

第一行为标准化后的图像数据,第二行为自动编码器重建的图像。

你可能感兴趣的:(自动编码器python)