遇见AE 自动编码器

自动编码器

 

 

自动编码器是一种数据的压缩算法,其中数据的压缩和解压缩函数是1)数据相关的,2)有损的,3)从样本中自动学习的。在大部分提到自动编码器的场合,压缩和解压缩的函数是通过神经网络实现的。

1)自动编码器是数据相关的(data-specific 或 data-dependent),这意味着自动编码器只能压缩那些与训练数据类似的数据。自编码器与一般的压缩算法,如MPEG-2,MP3等压缩算法不同,一般的通用算法只假设了数据是“图像”或“声音”,而没有指定是哪种图像或声音。比如,使用人脸训练出来的自动编码器在压缩别的图片,比如树木时性能很差,因为它学习到的特征是与人脸相关的。

2)自动编码器是有损的,意思是解压缩的输出与原来的输入相比是退化的,MP3,JPEG等压缩算法也是如此。这与无损压缩算法不同。

3)自动编码器是从数据样本中自动学习的,这意味着很容易对指定类的输入训练出一种特定的编码器,而不需要完成任何新工作。

搭建一个自动编码器需要完成下面三样工作:搭建编码器,搭建解码器,设定一个损失函数,用以衡量由于压缩而损失掉的信息。编码器和解码器一般都是参数化的方程,并关于损失函数可导,典型情况是使用神经网络。编码器和解码器的参数可以通过最小化损失函数而优化,例如SGD。

自编码器是一个好的数据压缩算法吗

通常情况下,使用自编码器做数据压缩,性能并不怎么样。以图片压缩为例,想要训练一个能和JPEG性能相提并论的自编码器非常困难,并且要达到这个性能,你还必须要把图片的类型限定在很小的一个范围内(例如JPEG不怎么行的某类图片)。自编码器依赖于数据的特性使得它在面对真实数据的压缩上并不可行,你只能在指定类型的数据上获得还可以的效果,但谁知道未来会有啥新需求?

那么,自编码器擅长做什么?

自编码器在实际应用中用的很少,2012年人们发现在卷积神经网络中使用自编码器做逐层预训练可以训练深度网络,但很快人们发现良好的初始化策略在训练深度网络上要比费劲的逐层预训练有效得多,2014年出现的Batch Normalization技术使得更深的网络也可以被有效训练,到了2015年底,通过使用残差学习(ResNet)我们基本上可以训练任意深度的神经网络。

目前自编码器的应用主要有两个方面,第一是数据去噪,第二是为进行可视化而降维。配合适当的维度和稀疏约束,自编码器可以学习到比PCA等技术更有意思的数据投影。

对于2D的数据可视化,t-SNE(读作tee-snee)或许是目前最好的算法,但通常还是需要原数据的维度相对低一些。所以,可视化高维数据的一个好办法是首先使用自编码器将维度降低到较低的水平(如32维),然后再使用t-SNE将其投影在2D平面上。Keras版本的t-SNE由Kyle McDonald实现了一下,放在了这里,另外scikit-learn也有一个简单实用的实现。

自编码器有什么用

自编码器的出名来自于网上很多机器学习课程的介绍,总而言之,一堆新手非常热爱自编码器而且怎么也玩不够,这就是这篇文章出现的意义【告诉你自编码器有什么卵用】。

自编码器吸引了一大批研究和关注的主要原因之一是很长时间一段以来它被认为是解决无监督学习的可能方案,即大家觉得自编码器可以在没有标签的时候学习到数据的有用表达。再说一次,自编码器并不是一个真正的无监督学习的算法,而是一个自监督的算法。自监督学习是监督学习的一个实例,其标签产生自输入数据。要获得一个自监督的模型,你需要想出一个靠谱的目标跟一个损失函数,问题来了,仅仅把目标设定为重构输入可能不是正确的选项。基本上,要求模型在像素级上精确重构输入不是机器学习的兴趣所在,学习到高级的抽象特征才是。事实上,当你的主要任务是分类、定位之类的任务时,那些对这类任务而言的最好的特征基本上都是重构输入时的最差的那种特征。

在应用自监督学习的视觉问题中,可能应用自编码器的领域有例如拼图,细节纹理匹配(从低分辨率的图像块中匹配其高分辨率的对应块)。下面这篇文章研究了拼图问题,其实很有意思,不妨一读。Unsupervised Learning of Visual Representations by Solving Jigsaw Puzzles.。此类问题的模型输入有些内置的假设,例如“视觉块比像素级的细节更重要”这样的,这种假设是普通的自编码器没有的。

使用Keras建立简单的自编码器

首先,先建立一个全连接的编码器和解码器:

from keras.layers import Input, Dense
from keras.models import Model
# this is the size of our encoded representations
encoding_dim = 32 
# 32 floats -> compression of factor 24.5, assuming the input is 784 floats
# this is our input placeholder
input_img = Input(shape=(784,))
# 'encoded' is the encoded representation of the input
encoded = Dense(encoding_dim, activation='relu')(input_img)
# 'decoded' is the lossy reconstruction of the input
decoded = Dense(784, activation='sigmoid')(encoded)
# this model maps an input to its reconstructionauto
encoder = Model(input=input_img, output=decoded)

然我们可以单独的使用编码器和解码器:

# this model maps an input to its encoded representation
encoder = Model(input=input_img, output=encoded)
# create a placeholder for an encoded (32-dimensional) input
encoded_input = Input(shape=(encoding_dim,))
# retrieve the last layer of the autoencoder model
decoder_layer = autoencoder.layers[-1]
# create the decoder model
decoder = Model(input=encoded_input, output=decoder_layer(encoded_input))

下面我们训练自编码器,来重构MNIST中的数字,这里使用逐像素的交叉熵作为损失函数,优化器为adam

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

然后准备MNIST数据,将其归一化和向量化,然后训练:

from keras.datasets import mnist
import numpy as np
(x_train, _), (x_test, _) = mnist.load_data()
x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.
x_train = x_train.reshape((len(x_train), np.prod(x_train.shape[1:])))
x_test = x_test.reshape((len(x_test), np.prod(x_test.shape[1:])))
print x_train.shape
print x_test.shape
autoencoder.fit(x_train, x_train, nb_epoch=50, batch_size=256, shuffle=True, validation_data=(x_test, x_test))

50个epoch后,看起来我们的自编码器优化的不错了,损失是0.10,我们可视化一下重构出来的输出:

 
# encode and decode some digits
# note that we take them from the *test* set
# use Matplotlib (don't ask)
import matplotlib.pyplot as plt
encoded_imgs = encoder.predict(x_test)
decoded_imgs = decoder.predict(encoded_imgs)
n = 10
# how many digits we will display
plt.figure(figsize=(20, 4))
for i in range(n): 
    # display original 
    ax = plt.subplot(2, n, i) 
    plt.imshow(x_test[i].reshape(28, 28)) 
    plt.gray() 
    ax.get_xaxis().set_visible(False) 
    ax.get_yaxis().set_visible(False) 
    # display reconstruction 
    ax = plt.subplot(2, n, i + n) 
   
 plt.imshow(decoded_imgs[i].reshape(28, 28)) 
    plt.gray() 
    ax.get_xaxis().set_visible(False) 
  
  ax.get_yaxis().set_visible(False)
    plt.show()

 

 

 

 

 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值