1. 关于tailored 特征描述子

自从深度学习的繁荣,利用自编码器、孪生网络、对抗网络采用数据驱动的形式设计tailored 特征描述子 成为了计算机视觉领域发展的重要推动力, 这不仅大大削弱了特征工程的压力,而且降低了相关领域学者对于数学基础的要求。 本博文重点在于介绍自编码器在tailored feature方面的潜力。

2. 什么是自编码器(Autoencoder)初步探索

自动编码器实质是Encode+Decode的过程,实际可以理解为是一种数据压缩+数据重建算法,其中数据的压缩和解压缩函数是数据相关的、有损的、从样本中自动学习的。在大部分提到自动编码器的场合,压缩和解压缩的函数是通过神经网络实现的。

  • 自动编码器是数据相关的(data-specific 或 data-dependent),这意味着自动编码器只能压缩那些与训练数据类似的数据,这维学习某一领域的tailored feature提供了可能。比如,使用人脸训练出来的自动编码器在压缩别的图片,比如树木时性能很差,因为它学习到的特征是与人脸相关的
  • 自动编码器是有损的,意思是解压缩的输出与原来的输入相比是退化的,这潜在有利于去除数据中不一致、非紧致的噪声
  • 自动编码器是从数据样本中自动学习的,这意味着很容易对指定类的输入训练出一种特定的编码器,而不需要完成任何新工作。

搭建一个自动编码器需要完成下面三样工作:搭建编码器,搭建解码器,设定一个损失函数,用以衡量由于压缩而损失掉的信息。编码器和解码器一般都是参数化的方程,并关于损失函数可导,典型情况是使用神经网络。编码器和解码器的参数可以通过最小化损失函数而优化,例如SGD。自编码器是一个自监督的算法,并不是一个无监督算法。自监督学习是监督学习的一个实例,其标签产生自输入数据。要获得一个自监督的模型,你需要一个靠谱的目标跟一个损失函数,仅仅把目标设定为重构输入可能不是正确的选项。基本上,要求模型在像素级上精确重构输入不是机器学习的兴趣所在,学习到高级的抽象特征才是。事实上,当主要任务是分类、定位之类的任务时,那些对这类任务而言的最好的特征基本上都是重构输入时的最差的那种特征。

目前自编码器的应用主要有两个方面,第一是数据去噪,第二是为进行可视化而降维。配合适当的维度和稀疏约束,自编码器可以学习到比PCA等技术更有意思的数据投影。对于2D的数据可视化,t-SNE(读作tee-snee)或许是目前最好的算法,但通常还是需要原数据的维度相对低一些。所以,可视化高维数据的一个好办法是首先使用自编码器将维度降低到较低的水平(如32维),然后再使用t-SNE将其投影在2D平面上。

3. 几种典型自编码器调研

自编码是神经网络的一种,经过训练后能尝试将输入复制到输出。自编码器内部有一个隐藏层 h,可以产生编码(code)表示输入。该网络可以看作由两部分组成:一个由函数 h = f(x) 表示的编码器和一个生成重构的解码器 r = g(h)。如果一个自编码器只是简单地学会将处处设置为 g(f(x)) = x,那么这个自编码器就没什么特别的用处。相反,我们不应该将自编码器设计成输入到输出完全相等。这通常需要向自编码器强加一些约束,使它只能近似地复制,并只能复制与训练数据相似的输入。这些约束强制模型考虑输入数据的哪些部分需要被优先复制,因此它往往能学习到数据的有用特性。

  • 欠完备自编码器

从自编码器获得有用特征的一种方法是限制 h的维度比 x 小,这种编码维度小于输入维度的自编码器称为欠完备undercomplete自编码器。学习欠完备的表示将强制自编码器捕捉训练数据中最显著的特征。学习过程可以简单地描述为最小化一个损失函数L(x,g(f(x))),其中 L 是一个损失函数,惩罚g(f(x)) 与 x 的差异,如均方误差。当解码器是线性的且 L 是均方误差,欠完备的自编码器会学习出与 PCA 相同的生成子空间。这种情况下,自编码器在训练来执行复制任务的同时学到了训据的主元子空间。如果编码器和解码器被赋予过大的容量,自编码器会执行复制任务而捕捉不到任何有关数据分布的有用信息。

  • 正则自编码器

正则自编码器使用的损失函数可以鼓励模型学习其他特性(除了将输入复制到输出),而不必限制使用浅层的编码器和解码器以及小的编码维数来限制模型的容量。这些特性包括稀疏表示、表示的小导数、以及对噪声或输入缺失的鲁棒性。即使模型容量大到足以学习一个无意义的恒等函数,非线性且过完备的正则自编码器仍然能够从数据中学到一些关于数据分布的有用信息。

  • 稀疏自编码器

稀疏自编码器简单地在训练时结合编码层的稀疏惩罚 Ω(h) 和重构误差:L(x,g(f(x))) + Ω(h),其中 g(h) 是解码器的输出,通常 h 是编码器的输出,即 h = f(x)。稀疏自编码器一般用来学习特征,以便用于像分类这样的任务。稀疏正则化的自编码器必须反映训练数据集的独特统计特征,而不是简单地充当恒等函数。以这种方式训练,执行附带稀疏惩罚的复制任务可以得到能学习有用特征的模型。

  • 去噪自编码器

去噪自编码器(denoisingautoencoder, DAE)最小化L(x,g(f(˜ x))),其中 ˜ x 是被某种噪声损坏的 x 的副本。因此去噪自编码器必须撤消这些损坏,而不是简单地复制输入。它是一类接受损坏数据作为输入,并训练来预测原始未被损坏数据作为输出的自编码器。DAE 的训练准则(条件高斯p(x | h))能让自编码器学到能估计数据分布得分的向量场 (g(f(x)) − x) ,这是 DAE 的一个重要特性。

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

利用全连接层构建简单的自编码器如下:

代码和效果和下图所示:

from keras.layers import Input, Dense
from keras.models import Model
from keras.datasets import mnist
import numpy as np
import matplotlib.pyplot as plt(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)encoding_dim = 32
input_img = Input(shape=(784,))encoded = Dense(encoding_dim, activation='relu')(input_img)
decoded = Dense(784, activation='sigmoid')(encoded)autoencoder = Model(inputs=input_img, outputs=decoded)
encoder = Model(inputs=input_img, outputs=encoded)encoded_input = Input(shape=(encoding_dim,))
decoder_layer = autoencoder.layers[-1]decoder = Model(inputs=encoded_input, outputs=decoder_layer(encoded_input))autoencoder.compile(optimizer='adadelta', loss='binary_crossentropy')autoencoder.fit(x_train, x_train, epochs=50, batch_size=256, shuffle=True, validation_data=(x_test, x_test))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):ax = plt.subplot(2, n, i + 1)plt.imshow(x_test[i].reshape(28, 28))plt.gray()ax.get_xaxis().set_visible(False)ax.get_yaxis().set_visible(False)ax = plt.subplot(2, n, i + 1 + 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()

Dense784-Dense32-Dense784结果如下,其损失loss=0.1044:

Dense784-Dense256-Dense64-Dense256-Dense784结果如下,其损失loss=0.0879:

  • 稀疏自编码器、深层自编码器

如果我们对隐层单元施加稀疏性约束的话,会得到更为紧凑的表达,只有一小部分神经元会被激活。在Keras中,可以通过添加一个activity_regularizer达到对某层激活值进行约束的目的。encoded = Dense( encoding_dim, activation='relu', activity_regularizer = regularizers.activity_l1(10e-5) )(input_img)。深度-稀疏自编码器如下:

Note:在keras中存在3个正则化技巧,分别是权重正则化。偏置正则化、激活正则化

from keras.layers import Input, Dense
from keras import regularizers
from keras.models import Model
from keras.datasets import mnist
import numpy as np
import matplotlib.pyplot as plt# only need images, this is self-supervised process
(x_train, _), (x_test, _) = mnist.load_data()x_train = x_train.astype('float32') / 255. # normalization
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)input_img = Input(shape=(784,))
encoded = Dense(128, activation='relu',#activity_regularizer = regularizers.l1(0.000001))(input_img)
encoded = Dense(64, activation='relu',#activity_regularizer = regularizers.l1(0.00001))(encoded)
decoded_input = Dense(32, activation='relu', #activity_regularizer = regularizers.l1(0.00001))(encoded)
decoded = Dense(64, activation='relu')(decoded_input)
decoded = Dense(128, activation='relu')(decoded)
decoded = Dense(784, activation='sigmoid')(decoded)autoencoder = Model(inputs=input_img, outputs=decoded)
encoder = Model(inputs=input_img, outputs=decoded_input)autoencoder.compile(optimizer='adadelta', loss='binary_crossentropy')
autoencoder.fit(x_train, x_train, epochs=50, batch_size=256, shuffle=True, validation_data=(x_test, x_test))encoded_imgs = encoder.predict(x_test)
decoded_imgs = autoencoder.predict(x_test)n = 10  # how many digits we will display
plt.figure(figsize=(20, 6))
for i in range(n):# original imagesax = plt.subplot(3, n, i + 1)plt.imshow(x_test[i].reshape(28, 28))plt.gray()ax.get_xaxis().set_visible(False)ax.get_yaxis().set_visible(False)ax = plt.subplot(3, n, i + 1 + n)plt.imshow(encoded_imgs[i].reshape(8, 4))#plt.gray()plt.set_cmap('jet')ax.get_xaxis().set_visible(False)ax.get_yaxis().set_visible(False)ax = plt.subplot(3, n, i + 1 + n + 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()

Dense784-Dense128-Dense64-Dense32-Dense64-Dense128-Dense784 (无正则化)结果显示,loss=0.1144:

Dense784-Dense128-Dense64-Dense32-Dense64-Dense128-Dense784 (激活正则化1e-6)结果显示,loss=0.1396:

  • 卷积自编码器:用卷积层构建自编码器

当输入是图像时,使用卷积神经网络是更好的。卷积自编码器的编码器部分由卷积层和MaxPooling层构成,MaxPooling负责空域下采样。而解码器由卷积层和上采样层构成。

from keras.layers import Input, Convolution2D, MaxPooling2D, UpSampling2D
from keras.models import Model
from keras.datasets import mnist
from keras.callbacks import TensorBoard
import matplotlib.pyplot as plt# only need images, this is self-supervised process
(x_train, _), (x_test, _) = mnist.load_data()x_train = x_train.astype('float32') / 255. # normalization
x_test = x_test.astype('float32') / 255.
x_train = x_train.reshape((len(x_train), 28, 28, 1))
x_test = x_test.reshape((len(x_test), 28, 28, 1))
print(x_train.shape)
print(x_test.shape)input_img = Input(shape=(28, 28, 1))x = Convolution2D(16, (3, 3), activation='relu', padding='same')(input_img)
x = MaxPooling2D((2, 2), padding='same')(x)
x = Convolution2D(8, (3, 3), activation='relu', padding='same')(x)
x = MaxPooling2D((2, 2), padding='same')(x)
x = Convolution2D(8, (3, 3), activation='relu', padding='same')(x)
encoded = MaxPooling2D((2, 2), padding='same')(x)x = Convolution2D(8, (3, 3), activation='relu', padding='same')(encoded)
x = UpSampling2D((2, 2))(x)
x = Convolution2D(8, (3, 3), activation='relu', padding='same')(x)
x = UpSampling2D((2, 2))(x)
x = Convolution2D(16, (3, 3), activation='relu')(x)
x = UpSampling2D((2, 2))(x)
decoded = Convolution2D(1, (3, 3), activation='sigmoid', padding='same')(x)encoder = Model(inputs=input_img, outputs=encoded)
autoencoder = Model(inputs=input_img, outputs=decoded)
autoencoder.compile(optimizer='adadelta', loss='binary_crossentropy')autoencoder.fit(x_train, x_train, epochs=50, batch_size=256,shuffle=True, validation_data=(x_test, x_test),callbacks=[TensorBoard(log_dir='autoencoder')])encoded_imgs = encoder.predict(x_test)
decoded_imgs = autoencoder.predict(x_test)n = 10  # how many digits we will display
plt.figure(figsize=(20, 6))
for i in range(n):# original imagesax = plt.subplot(3, n, i + 1)plt.imshow(x_test[i].reshape(28, 28))plt.gray()ax.get_xaxis().set_visible(False)ax.get_yaxis().set_visible(False)ax = plt.subplot(3, n, i + 1 + n)plt.imshow(encoded_imgs[i].reshape(16, 8))#plt.gray()plt.set_cmap('jet')ax.get_xaxis().set_visible(False)ax.get_yaxis().set_visible(False)ax = plt.subplot(3, n, i + 1 + n + 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()

结果显示:

  • 使用自动编码器进行图像去噪

我们把训练样本用噪声污染,然后使解码器解码出干净的照片,以获得去噪自动编码器。首先我们把原图片加入高斯噪声,然后把像素值clip到0~1。

from keras.layers import Input, Convolution2D, MaxPooling2D, UpSampling2D
from keras.models import Model
from keras.datasets import mnist
from keras.callbacks import TensorBoard
import matplotlib.pyplot as plt# only need images, this is self-supervised process
(x_train, _), (x_test, _) = mnist.load_data()x_train = x_train.astype('float32') / 255. # normalization
x_test = x_test.astype('float32') / 255.
x_train = x_train.reshape((len(x_train), 28, 28, 1))
x_test = x_test.reshape((len(x_test), 28, 28, 1))
print(x_train.shape)
print(x_test.shape)input_img = Input(shape=(28, 28, 1))x = Convolution2D(16, (3, 3), activation='relu', padding='same')(input_img)
x = MaxPooling2D((2, 2), padding='same')(x)
x = Convolution2D(8, (3, 3), activation='relu', padding='same')(x)
x = MaxPooling2D((2, 2), padding='same')(x)
x = Convolution2D(8, (3, 3), activation='relu', padding='same')(x)
encoded = MaxPooling2D((2, 2), padding='same')(x)x = Convolution2D(8, (3, 3), activation='relu', padding='same')(encoded)
x = UpSampling2D((2, 2))(x)
x = Convolution2D(8, (3, 3), activation='relu', padding='same')(x)
x = UpSampling2D((2, 2))(x)
x = Convolution2D(16, (3, 3), activation='relu')(x)
x = UpSampling2D((2, 2))(x)
decoded = Convolution2D(1, (3, 3), activation='sigmoid', padding='same')(x)encoder = Model(inputs=input_img, outputs=encoded)
autoencoder = Model(inputs=input_img, outputs=decoded)
autoencoder.compile(optimizer='adadelta', loss='binary_crossentropy')autoencoder.fit(x_train, x_train, epochs=50, batch_size=256,shuffle=True, validation_data=(x_test, x_test),callbacks=[TensorBoard(log_dir='autoencoder')])encoded_imgs = encoder.predict(x_test)
decoded_imgs = autoencoder.predict(x_test)n = 10  # how many digits we will display
plt.figure(figsize=(20, 6))
for i in range(n):# original imagesax = plt.subplot(3, n, i + 1)plt.imshow(x_test[i].reshape(28, 28))plt.gray()ax.get_xaxis().set_visible(False)ax.get_yaxis().set_visible(False)ax = plt.subplot(3, n, i + 1 + n)plt.imshow(encoded_imgs[i].reshape(16, 8))#plt.gray()plt.set_cmap('jet')ax.get_xaxis().set_visible(False)ax.get_yaxis().set_visible(False)ax = plt.subplot(3, n, i + 1 + n + 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()

去噪效果显示,loss=0.1028:

博文参考:

https://www.cnblogs.com/happylion/p/4209570.html

https://blog.csdn.net/marsjhao/article/details/73480859

自编码器深度分析+定制特征描述子构建初探相关推荐

  1. SIFT算法特征描述子构建---关键点定位原理及代码

    0.引言 sift针对局部特征进行特征提取,在尺度空间寻找极值点,提取位置,尺度,旋转不变量,生成特征描述子. 总共分四个步骤: 尺度金字塔生成 关键点/极值点提取 生成梯度直方图 特征描述子构建 s ...

  2. PCL:点云特征描述子3D_object_recognition_(descriptors)

    PCL官网:https://pointclouds.org/ 翻译自该网站:http://robotica.unileon.es/index.php/PCL/OpenNI_tutorial_4:_3D ...

  3. 【特征匹配】BRIEF特征描述子原理及源码解析

    相关:Fast原理及源码解析 Harris原理及源码解析 SIFT原理及源码解析 SURF原理及源码解析 转载请注明出处: http://blog.csdn.net/luoshixian099/art ...

  4. 图像特征描述子(一)——HOG

    本文主要参考博客:1.https://www.cnblogs.com/panchuangai/p/12567973.html 2.https://blog.csdn.net/weixin_383678 ...

  5. 图像特征点及特征描述子总结

    参考博客 https://blog.csdn.net/qq_28193895/article/details/80845803 https://blog.csdn.net/u013989576/art ...

  6. BRIEF 特征描述子

    FROM:http://www.cnblogs.com/ronny/p/4081362.html Binary Robust Independent Elementary Features www.c ...

  7. 特征描述子提取公用接口

    OpenCV封装了一些特征描述子提取算法,使得用户能够解决该问题时候方便使用各种算法.这章用来计算的描述子提取被表达成一个高维空间的向量 vector.所有实现 vector 特征描述子子提取的部分继 ...

  8. sift计算描述子代码详解_浅谈SIFT特征描述子

    SIFT是我接触最早的图像局部特征描述子之一,其实最初,始终觉得局部特征描述子是些非常玄虚的东西.对于SIFT,这种感觉更是尤为强烈,"尺度空间""拉普拉斯高斯算子(Lo ...

  9. image.merge图像有什么变化_图像特征工程:HOG特征描述子介绍

    介绍 在机器学习算法的世界里,特征工程是非常重要的.实际上,作为一名数据科学家,这是我最喜欢的方面之一!从现有特征中设计新特征并改进模型的性能,这就是我们进行最多实验的地方. 世界上一些顶级数据科学家 ...

最新文章

  1. codeforces educational round110 e
  2. 本周最热 AI 论文大集合,还不快一键收藏?
  3. getopt()和getopt_long()用法
  4. 你需要熟练运用的12个命令行工具
  5. python足球投注_/usr/lib目录属性更改引发的蝴蝶效应
  6. 子类怎么继承父类方法中的变量_关于继承的那些事!
  7. php引入odbc模块,php如何用odbc调用存储过程?
  8. c# union结构体_P/Invoke各种总结(八、在C#中使用Union联合体)
  9. 波卡DOT国库报告:130.89万个DOT被销毁 9.2%DOT 用来资助国库支出议案
  10. Linux 命令(115)—— rev 命令
  11. 超详细的Java面试题总结(二)之Java基础知识篇
  12. windows.location属性(常用知识点)
  13. EasyRecovery深度扫描以恢复桌面遗失数据的方法
  14. MaxtoCode 2.0 7月1日发布 测试版
  15. java boxlayout 换行,继承FlexboxLayout自定义可自动换行的tag标签
  16. 关于Redis缓存和数据库一致性问题
  17. 云表中表单使用导入excel到明细
  18. 2021年全球及中国企业级路由器市场竞争格局分析,呈现出寡头竞争的市场格局「图」
  19. 广东IPTV机顶盒安装第三方应用
  20. 将数据库中的表结构导出到excel中(写数据库设计说明书)

热门文章

  1. HP LoadRunner 12.02 Tutorial T7177-88037教程独家中文版
  2. JavaScipt中的Math.ceil() 、Math.floor() 、Math.round()
  3. 6月第一周国内域名解析商:万网继续抢占DNSPod份额
  4. NYOJ 16(矩形嵌套)
  5. 易宝典文章——用ISA 2006标准版发布Exchange 2010的OWA系列之申请Excha
  6. 大家说火箭进决赛的机会有多大?
  7. 灵感编程:最大公约数算法解析
  8. hdu 2215(最小圆覆盖)
  9. 两款简易计算器纯js版附源码下载
  10. 微软大法好不好,终于要对比了