自动编码(AE)器的简单实现python
二.自动编码器的发展简述git
三. 实验github
传统的自动编码器是一种数据的压缩算法,其算法包括编码阶段和解码阶段,且拥有对称的结构。
目前自编码器的应用主要有两个方面,第一是数据去噪,第二是为进行可视化而降维。配合适当的维度和稀疏约束,自编码器能够学习到比PCA等技术更有意思的数据投影。优化
传统编码器的编解码过程描述如图:ui
其中过程可使用以下公式描述:编码
其中,
为编码的权重和偏置,
,
为解码的权重和偏置。
损失函数描述为以下形式:
自动编码器的训练过程使用传统的基于梯度的方式进行训练。
评价:
学界评价:传统自编码器的目的是使输出与输入尽可能相同,这彻底能够经过学习两个恒等函数来完成,可是这样的变换没有任何意义,由于咱们真正关心的是隐层表达,而不是实际输出。所以,针对自编码器的不少改进方法都是对隐层表达增长必定的约束,迫使隐层表达与输入不一样。
自编码器真正关心的是隐藏层的特征表达,一个好的表达可以捕获输入信号的稳定结构,以该目的为出发出现了降噪自动编码器。降噪自动编码器,首先对干净的输入信号加入噪声产生一个受损的信号。而后将受损信号送入传统的自动编码器中,使其重建回原来的无损信号。
降噪自编码器的编解码过程描述如图:
其中过程可使用以下公式描述:
其中为噪声的分布,
为加入噪声后的输入,
,
为编码的权重和偏置,
,
为解码的权重和偏置。
降噪自编码器的目标是最小化损失函数。
降噪自编码器与传统的自动编码器的主要区别在于:
评价:
学界评价:降噪自编码器经过对输入信号人为地进行损坏,主要是为了达到两个目的,首先是为了不使隐层单元学习一个传统自编码器中没有实际意义的恒等函数,其次就是为了使隐层单元能够学习到一个更加具备鲁棒性的特征表达。
降噪自编码器最大的优势在于,重建信号对输入中的噪声具备必定的鲁棒性,而最大的缺陷在于每次进行网络训练以前,都须要对干净输入信号人为地添加噪声,以得到它的损坏信号,这无形中就增长了该模型的处理时间。
参考深度置信网络的方法,将降噪自编码器进行堆叠能够构形成堆叠降噪自编码器。与自编码器和降噪自编码器不一样,堆叠降噪自编码器的提出是为了解决。
降噪自编码器的编解码过程描述如图:
其中,编码器 分别对应的是预先训练好的降噪自编码器
到
的编码函数.
每一个子问题的训练过程与降噪自编码器自编码器相同.
整个堆叠降噪自编码器的训练过程以下:
其中为噪声的分布,
为加入噪声后的输入,
,
为编码的权重和偏置,
,
为解码的权重和偏置。
堆叠降噪自编码器与降噪自编码器的区别在于:
评价:
学界评价:堆叠降噪自编码器是降噪自编码器的一个应用方法.
全卷积网络是一种面向特定应用(图像语义分割)的卷积神经网络,其结构图以下图所示:
与经典的CNN在卷积层以后使用全链接层获得固定长度的特征向量进行分类(全联接层+softmax输出)不一样,FCN能够接受任意尺寸的输入图像,采用反卷积层对最后一个卷积层的feature map进行上采样, 使它恢复到输入图像相同的尺寸,从而能够对每一个像素都产生了一个预测, 同时保留了原始输入图像中的空间信息, 最后在上采样的特征图上进行逐像素分类。
与全卷积网络相似的一种无监督方法称为卷机自动编码器.
因为卷积神经网络所取得的各类优异表现,直接推进了卷积自编码器的产生.卷积自编码器属于传统自编码器的一个特例.它使用卷积层和池化层替代了原来的全链接层.卷积
自编码器能很好的保留二维信号的空间信息.
学界评价:其主要差异在于卷积自编码器采用卷积方式对输入信号进行线性变换,而且其权重是共享的,这点与卷积神经网络同样。所以,重建过程就是基于隐藏编码的基本图像块的线性组合。
我实现后的感觉:
变分自编码器是一种主要用于数据生成的自编码器的变体.看成为生成模型时,首先利用数据训练变分自编码器,而后只使用变分自编码器的解码部分,自动生成与训练数据相似的输出.
其结构图如图所示:
整个结构能够分红三个部分,分别是编码部分,解码部分和生成部分.编码部分和解码部分同时进行训练,目标函数是从KL散度的概念中推倒获得的.
其中表明了输入数据,
表明了隐变量(latent varibles)(一个相似隐层输出的几率描述),
变分编码器的目标能够描述为最大化生成的几率
其中 为模型的参数,也是优化的对象.通常选取
loss函数的推导过程:
首先咱们但愿编码器部分生成的随机变量与理想的
尽可能接近,所以使用KL散度的概念对两个随机变量的类似性进行描述.
其中,为散度符号.利用贝叶斯公式将上述公式展开获得:
通过变换能够获得:
该公式正好是变分自编码器的目标函数.目标函数能够分红两个部分,分别约束了中间的隐变量受到一个标准分布的约束和输出图像尽可能与原图相同.
编码器名称 | 提出时间 | 改进点 | 目的 |
---|---|---|---|
传统自编码器 | 1986 | 无 | 无 |
降噪自编码器 | 2008 | 将带有噪声的损坏信息做为输入信号 | 使重建信号鲁棒性更强 |
堆叠自编码器 | 2008 | 将多层结构和栈式训练引入自编码器 | 使自编码器能够训练更高层数 |
卷积自编码器 | 2011 | 将卷积层引入自编码器 | 更好的处理图片数据,获得更好的效果 |
变分自编码器 | 2014 | 至关于在传统自编码器的隐层表达上增长一个对隐变量的约束,提出了一种将几率模型和神经网络结构的方法 | 使编码器产生的隐层表达知足正态分布,可以更好的生成图像模型 |
传统的自动编码器分为编码器部分和解码器部分,总体模型结构如图所示:
模型分为三个子模块,由上至下分别为输入层,编码器层和解码器层,编码器将输入维度为784(28 28)的mnint灰度值转化为一个维度为2的值.编码器将维度为2的值解码回维度为784(28 28)的mnint灰度值.
使用python-keras代码实现关键代码以下.
def __init__(self, ENCODING_DIM_INPUT=784, ENCODING_DIM_OUTPUT=2, Name = "ae"): input_image = Input(shape=(ENCODING_DIM_INPUT, )) # encoding layer hidden_layer = Dense(ENCODING_DIM_OUTPUT, activation='relu')(input_image) # decoding layer decode_output = Dense(ENCODING_DIM_INPUT, activation='relu')(hidden_layer) # build autoencoder, encoder, decoder autoencoder = Model(inputs=input_image, outputs=decode_output) encoder = Model(inputs=input_image, outputs=hidden_layer) # compile autoencoder autoencoder.compile(optimizer='adam', loss='mse', metrics=['accuracy']) self.autoencoder = autoencoder self.encoder = encoder
本实验讨论使用relu和tanh两种激活函数的自监督训练的状况.训练的loss函数选择为方均根偏差.
训练过程的loss变化图像以下.
使用tanh做为激活函数时,loss变化状况以下.
能够观察到,loss收敛到0.0685,效果较好.使用relu做为激活函数一样可以有效收敛,不过偏差数值相对较大.因为篇幅缘由不将图片在此进行展现.偏差数值相对较大的缘由将在下一节进行讨论.
本节将从重建图像和编码器输出层的二维可视化图像两部分进行展现,分别展现使用tanh和relu两种损失函数的训练结果.
训练好的自动编码器重建图像(使用relu激活函数)以下图:
训练好的自动编码器重建图像(使用tanh激活函数)以下图:
二者对比能够发现relu函数训练出的模型存在一些像素颗粒,这也验证了上一节loss函数较大的实验结果.为了解释该问题,展现编码器输出层的二维可视化图片.
训练好的编码器输出图像(使用relu激活函数)以下图:
训练好的编码器输出图像(使用tanh激活函数)以下图:
以上两张图片是 编码器-解码器 结构中编码器部分的输出绘制成的二维可视化图片,不一样的颜色表明了不一样的数字,对应的数字在右边的图例中进行了显示.从以上两张图片中能够获得:
传统自编码器有很大的改进空间,改进空间的能够从几个方面阐述:
传统的自动编码器分为编码器部分和解码器部分,总体模型结构如图所示:
模型分为三个子模块,由上至下分别为输入层,多层编码器层和多层解码器层,编码器将输入维度为784(28 28)的mnint灰度值转化为一个维度为2的值.编码器将维度为2的值解码回维度为784(28 28)的mnint灰度值
使用python-keras代码实现关键代码以下.
class DAE(ae.AE): def __init__( self, ENCODING_DIM_INPUT=784, ENCODING_DIM_LAYER1=128, ENCODING_DIM_LAYER2=64, ENCODING_DIM_LAYER3=10, ENCODING_DIM_OUTPUT=2,Name="dae" ): # input placeholder input_image = Input(shape=(ENCODING_DIM_INPUT, )) # encoding layer encode_layer1 = Dense(ENCODING_DIM_LAYER1, activation='relu')(input_image) encode_layer2 = Dense(ENCODING_DIM_LAYER2, activation='relu')(encode_layer1) encode_layer3 = Dense(ENCODING_DIM_LAYER3, activation='relu')(encode_layer2) encode_output = Dense(ENCODING_DIM_OUTPUT)(encode_layer3) # decoding layer decode_layer1 = Dense(ENCODING_DIM_LAYER3, activation='relu')(encode_output) decode_layer2 = Dense(ENCODING_DIM_LAYER2, activation='relu')(decode_layer1) decode_layer3 = Dense(ENCODING_DIM_LAYER1, activation='relu')(decode_layer2) decode_output = Dense(ENCODING_DIM_INPUT, activation='tanh')(decode_layer3) # build surprised learning model SL_output = Dense(10, activation='softmax')(encode_output) # build autoencoder, encoder autoencoder = Model(inputs=input_image, outputs=decode_output) encoder = Model(inputs=input_image, outputs=encode_output) SL_model = Model(inputs=input_image, outputs=SL_output) # compile autoencoder autoencoder.compile(optimizer='adam', loss='mse', metrics=['accuracy']) SL_model.compile(optimizer='adam', loss='mse', metrics=['accuracy'])
代码定义了三个模型,分别是用于自监督训练的 autoencoder, 用于二维化的编码器 encoder 和用于进行有监督训练的 SL_model.
堆叠降噪自动编码器分为无监督的预训练过程和有监督的训练过程两部分.
本部分分别进行说明.
自监督的预训练过程loss变化状况以下.
无监督的训练过程正确率acc变化状况以下.
能够看到,在两个训练阶段,方法能够有效的达到收敛.
如下几点须要指出:
本节将从重建图像和编码器输出层的二维可视化图像两部分进行展现
预训练部分
重建图像
下图展现了添加噪声的效果(第一行原图,第二行增长噪声的图).
下图展现了,对添加噪声的图片进行重构的结果(第一行增长噪声的图,第二行重构图)
编码器输出层的二维可视化图像
下图展现了添加噪声的效果(第一行原图,第二行增长噪声的图).
如下几点须要指出:
有监督训练部分
通过有监督的训练
重建图像(由于不是目标,因此必然走样)
下图展现了,对添加噪声的图片进行重构的结果(第一行增长噪声的图,第二行重构图)
编码器输出层的二维可视化图像
通过有监督学习,二维可视化图中各个组的界限更加清晰.
堆叠降噪自编码器的改进有如下启发:
卷积自编码器自动编码器分为编码器部分和解码器部分,总体模型结构如图所示:
使用python-keras代码实现关键代码以下.
def __init__(self,CHANNEL_1 = 16,CHANNEL_2 = 8,CHANNEL_OUTPUT = 1, Name="cae"): # input placeholder input_image = Input(shape=(28, 28, 1)) # encoding layer x = Conv2D(CHANNEL_1, (3, 3), activation='relu', padding="same")(input_image) x = MaxPool2D((2, 2), padding='same')(x) x = Conv2D(CHANNEL_2, (3, 3), activation='relu', padding='same')(x) encode_output = MaxPool2D((2, 2), padding='same')(x) # decoding layer x = Conv2D(CHANNEL_2, (3, 3), activation='relu', padding='same')(encode_output) x = UpSampling2D((2, 2))(x) x = Conv2D(CHANNEL_1, (3, 3),activation='relu', padding='same')(x) x = UpSampling2D((2, 2))(x) decode_output = Conv2D(CHANNEL_OUTPUT, (3, 3), activation='sigmoid', padding='same')(x) # build surprised learning model encode_output_flatten = Flatten()(decode_output) SL_output = Dense(10, activation='softmax')(encode_output_flatten) # build autoencoder, encoder autoencoder = Model(inputs=input_image, outputs=decode_output) encoder = Model(inputs=input_image, outputs=encode_output) SL_model = Model(inputs=input_image, outputs=SL_output) # compile autoencoder autoencoder.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) SL_model.compile(optimizer='adam', loss='mse', metrics=['accuracy'])
堆叠降噪自动编码器分为无监督的预训练过程和有监督的训练过程两部分.
本部分分别进行说明.
在自监督的预训练过程loss变化状况以下.
图像显示,自监督的训练loss收敛于0.07左右,该偏差比降噪自编码器的0.09要小.与传统自编码器的训练偏差相差很少.可是从下文可知其训练效果明显优于传统自动编码器.
在有监督的训练过程正确率acc变化状况以下.
图像显示,有监督训练过程的正确率上升到0.99,比降噪自动编码器的正确(0.95)率更高.
所以在mnist数据集中的重建任务和分类任务中,卷积自动编码器有必定优点.
不过如下几点须要指出:
能够看到和stacked AE的主要区别在于局部卷积链接,而不全部层都是全链接。对图像和某些其余数据影响在空间局部的问题,比全链接更合适.所以效果更加优秀.
于降噪自动编码器相同,首先对图片增长噪声:
而后对增长噪声的图片进行去噪:
去噪结果比较优秀,与上文中全部的结果相比是最优秀的.
变分自动编码器的结构最为复杂,而且在模型中引入了隐变量,和KL散度等几率论概念.对模型的实现形成了必定的影响.
自动编码器分为编码器部分和解码器部分,总体模型结构如图所示:
上图中并无展开编码器和解码器的结构,编码器(encoder) 与 解码器(decoder)的形式分别以下:
encoder:
decoder:
使用python-keras代码实现关键代码以下.
class VAE(ae.AE): def __init__( self, ENCODING_DIM_INPUT = 784, intermediate_dim = 512, batch_size = 128, latent_dim = 2, mse_loss = True, Name="vae" ): self.name = Name # input placeholder input_image = Input(shape=(ENCODING_DIM_INPUT,), name='encoder_input') # VAE model = encoder + decoder # encoding layer x = Dense(intermediate_dim, activation='relu')(input_image) z_mean = Dense(latent_dim, name='z_mean')(x) z_log_var = Dense(latent_dim, name='z_log_var')(x) z = Lambda(sampling, output_shape=(latent_dim,), name='z')([z_mean, z_log_var]) # build decoder model latent_inputs = Input(shape=(latent_dim,), name='z_sampling') x = Dense(intermediate_dim, activation='relu')(latent_inputs) outputs = Dense(ENCODING_DIM_INPUT, activation='sigmoid')(x) # # build surprised learning model # SL_output = Dense(10, activation='softmax')() # build autoencoder, encoder encoder = Model(input_image, [z_mean, z_log_var, z], name='encoder') decoder = Model(latent_inputs, outputs, name='decoder') # SL_model = Model(inputs=input_image, outputs=SL_output) outputs = decoder(encoder(input_image)[2]) autoencoder = Model(input_image, outputs, name='vae_mlp') # compile autoencoder # VAE loss = mse_loss or xent_loss + kl_loss if mse_loss: reconstruction_loss = mse(input_image, outputs) else: reconstruction_loss = binary_crossentropy(input_image,outputs) reconstruction_loss *= ENCODING_DIM_INPUT kl_loss = 1 + z_log_var - K.square(z_mean) - K.exp(z_log_var) kl_loss = K.sum(kl_loss, axis=-1) kl_loss *= -0.5 vae_loss = K.mean(reconstruction_loss + kl_loss) autoencoder.add_loss(vae_loss) autoencoder.compile(optimizer='adam') autoencoder.summary() # SL_model.compile(optimizer='adam', loss='mse', metrics=['accuracy']) self.autoencoder = autoencoder self.encoder = encoder self.decoder = decoder
因为,变分自动编码器主要应用于图像生成,而并不是是提取与分类,所以变分降噪自动编码器只有自监督的训练过程..
在自监督的训练过程,使用 KL散度+交叉熵 做为loss函数,loss变化状况以下.
能够看散度能够收敛到145的状况,可以有效进行收敛.
在自监督的训练过程,使用 KL散度+方均根 做为loss函数,loss变化状况以下.
对于两种损失函数效果的讨论在下文中进行.
使用 KL散度+交叉熵 做为损失函数
基于kl散度的loss训练结果二维可视化以下
使用生成器对图像进行生成能够获得以下结果.
使用 KL散度+方均根 做为损失函数
基于kl散度的loss训练结果二维可视化以下
使用生成器对图像进行生成能够获得以下结果.
因为方均根与交叉熵的区别在于 解码器重现偏差上面的区别,在编码器部分一样使用kl散度做为loss,所以二者的可视化结果相似.
如下几点须要指出:
相关代码请见:
https://github.com/zangzelin/Auto-encoder-AE-SAE-DAE-CAE-DAE-with-keras-in-Mnist-and-report
本文做者:邻泽居士