自动编码器

news2024/11/23 0:40:30

ea0f5969c51110ac712cde82116d0087.png

Autoencoder is designed in a way to perform task of data encoding plus data decoding to reconstruct input.  -- Anushka Jain

前言

两兄弟 N.Coder 和 D.Coder 经营着一家艺术画廊。一周末,他们举办了一场特别奇怪的展览,因为它只有一面墙,没有实体艺术品。当他们收到一幅新画时,N.Coder 在墙上选择一个点作为标记来代表这幅画,然后扔掉原来的艺术品。当顾客要求观看这幅画时,D.Coder 尝试仅使用墙上相关标记的坐标来重新创作这件艺术品。

展墙如下图所示,每个黑点是 N.Coder 放置的一个标记,代表一幅画。在墙上坐标 [–3.5, 1] 处的那幅原图 (original) 数字 6 的画 N.Coder 对其进行了重建 (reconstruction)。

e6953f5f165f589cfff941fe9bd6f30e.png

下图展示了更多例子,顶行的数字是原图,中行的坐标是 N.Coder 将图挂在墙上的坐标,底行是 D.Coder 根据坐标重建的作品。

d7e4614a804f8e9862b9c6f248cd555a.png

问题来了,N.Coder 如何决定每幅画在展墙上对应的坐标,而使得 D.Coder 仅用它就能重建原图的?原来是两兄弟在放置标记和重建作品的过程中,仔细监控售票处因顾客因重建质量不佳而要求退款而造成的收入损失,他们经过多年的“训练”逐渐“精通”标记放置和作品重建,而最大限度地减少这种收入损失。从上图对比原图和重建可以看出,两兄弟之间的磨合效果还不错。来参观艺术品的顾客很少抱怨 D.Coder 重新创作的画作与他们来参观的原始作品有很大的不同。

有一天,N.Coder 望着展墙,有了一个大胆的想法,对于那些墙上当前没有标记的部分,如果让 D.Coder 来重建能创作出什么样的作品?如果成功的话,那么他们就可以举办自己 100% 原创的画展了。想想就兴奋,于是 D.Coder 随机选取了之前没有标记的坐标 (红点) 来重建,结果如下图所示。

dcf2c96b931956738484fca2b8f0b015.png

正如你所看到的,重建效果较差,有些图甚至都分辨不出是什么数字。那么到底出了什么问题,Coder 两兄弟该如何改进他们的方案呢?


1. 自动编码器

前言的故事其实就是类比自动编码器 (autoencoder),D.Coder 音译为 encoder,即编码器,做的事情就是将图片转成坐标,而 N.Coder 音译为 decoder,即解码器,做的事情就是将坐标还原成图片。上节的两兄弟监控的收入损失其实就是模型训练时用的损失函数。

故事归故事,让我们看看自动编码器的严谨描述,它本质上就是一个神经网络,包含:

  • 一个编码器 (encoder):用来把高维数据压缩成低维表征向量。

  • 一个解码器 (decoder):用来将低维表征向量还原成高维数据。

该流程如下图所示,original input data 是高维图片数据,图片包含很多像素因此是高维的,而 representation vector 是低维表征向量,本例用的二维向量 [-2.0, -0.5] 是低维的。

2bc9b8313a81fe73551a4c1b2cfd9617.jpeg

该网络经过训练,可以找到编码器和解码器的权重,最小化原始输入与输入通过编码器和解码器后的重建之间的损失。表征向量是将原始图像压缩到较低维的潜空间。通过选择潜空间 (latent space) 中的任何点,我们应该能够通过将该点传递给解码器来生成新的图像,因为解码器已经学会了如何将潜空间中的点转换为可看的图像。

在前言描述中,N.Coder 和 D.Coder 使用表示二维潜空间 (墙壁) 内的向量对每个图像进行编码。之所以用二维是为了可视化潜空间,在实践中,潜空间通常高过两维,以便更自由地捕获图像中更大的细微差别。


2. 模型解析

2.1 初次见面

一般来说,最好用单独的文件来创建模型的类,比如下面的 Autoencoder class。这样其他项目可以灵活调用此类。下面代码首先展示了 Autoencoder 的框架,__init__() 是构造函数,通过调用 _build() 来创建模型,compile() 函数用于设定优化器,save() 函数用于保存模型,load_weights() 函数用于下次使用模型时加载权重,train() 函数用于训练模型。

614371eae65e433bac45da5f33462ce4.png

构建函数包含 8 个必需参数和 2 个默认参数,input_dim 是图片的维度,z_dim 是潜空间的维度,剩下的 6 个必需参数分别是编码器和解码器的滤波器个数 (filters)、滤波器大小 (kernel_size)、步长大小 (strides)。

f491ea7f86c2f3e97deaa5798a16f563.png

用构建函数创建自动编码器,命名为 AE。输入数据是黑白图片,其维度是 (28, 28, 1),潜空间用的 2D 平面,因此 z_dim = 2。此外六个参数的值都是一个大小为 4 的列表,那么编码模型和解码模型都含有 层。

41996eca81986cbc66210449c00cc21e.png

在 AutoEncoder 类里面定义 _build() 函数,构建编码器和解码器并将两者相连,代码框架如下 (后三小节会逐个分析):

b7e26d790a854c907ec7b96e2c747385.png

接下两小节我们来一一剖析自动编码器中的编码模型和解码模型。

2.2 编码模型

编码器的任务是将输入图片转换成潜空间的一个点,编码模型在 _build() 函数里面的具体实现如下:

48424cefb480392ad40528316bccf3c3.png

代码解释如下:

  • 第 2-3 行将图片定义为 encoder 的输入。

  • 第 5-17 行按顺序将卷积层堆起来。

  • 第 19 行记录 x 的形状,K.int_shape 的返回是一个元组 (None, 7, 7, 64),第 0 个元素是样本大小,用 [1:] 返回除样本大小的数据形状 (7, 7, 64)。

  • 第 20 行将最后的卷积层打平成为一个 1D 向量。

  • 第 21 行的稠密层将该向量转成另一个大小为 z_dim 的 1D 向量。

  • 第 22 行构建 encoder 模型,分别在 Model() 函数确定入参 encoder_input 和 encoder_output。

用 summary() 函数打印出编码模型的信息,用来描述每层的名称类型 (layer (type))、输出形状 (Output Shape) 和参数个数 (Param #)。

AE.encoder.summary()

c4f20413ce5fcbe898fc06bd998db6ff.jpeg

2.3 解码模型

解码器是编码器的镜像,只不过不是使用卷积层,而是使用卷积转置层 (convolutional transpose layers) 来构建。当步长设为 2,卷积层每次将图片的高和宽减半,而卷积转置层将图片的高和宽翻倍。具体操作见下图。

92b5f97634553cad248216075d1f6aad.jpeg

解码器在 _build() 函数里面的具体实现如下:

355fdc539193fcf4d3d7382a4a0949cf.png

代码解释如下:

  • 第 1 行将 encoder 的输出定义为 decoder 的输入。

  • 第 2-3 行将 1D 向量重塑成形状为 (7, 7, 64) 的张量。

  • 第 6-15 行按顺序将卷积转置层堆起来。

  • 第 7-22 行:

    • 如果是最后一层,用 sigmoid 函数转换,得到的结果在 0-1 之间当成像素

    • 如果不是最后一层,用 leaky relu 函数转换,并加上批归一化 (batch normalization) 和随机失活 (dropout) 的处理。

  • 第 24-25 行构建 decoder 模型,分别在 Model() 函数确定入参 decoder_input 和 decoder_output,前者是 encoder 的输出,即潜空间的点,而后者是重建的图片。

用 summary() 函数打印出解码模型的信息。

AE.decoder.summary()

072320cbe3fc877be3ad28f7c0e8b5ee.jpeg

2.4 串联起来

为了能同时训练编码器和解码器,我们需要将两者连在一起,

5d3c19c6ca90c7e76e8dd1eda454a3b9.png

代码解释如下:

  • 第 1 行将 encoder_input 作为整体模型的输入 model_input (中间产物 encoder_output 是编码器的输出)。

  • 第 2 行将解码器的输出作为整体模型的输出 model_output (解码器的输入就是编码器的输出)。

  • 第 3 行构建 autoencoder 模型,分别在 Model() 函数确定入参 model_input 和 model_output。

一图胜千言。

b0d7720df6b60f82f881475e10e9a2d9.png

2.5 训练模型

构建好模型之后,只需要定义损失函数和编译优化器。损失函数通常选择均方误差 (RMSE)。编译 complie() 函数的实现如下,用的是 Adam 优化器,学习率设为 0.0005:

33b744cb01c9ab46cbb815746c5b2716.png

训练模型用 fit() 函数,批大小设为 32,epoch 设为 200,代码如下:

66c4eb564fc19ead4d407dd93ddf050d.png

在测试集上随机选 10 个看看效果:

bbca1fbcc40082907a820e88418dbe71.png

8aa2a9de7fdf2c468d84f8728d1a22c7.png

10 张图中只有 4 张重建效果还行。


3. 三大缺陷

模型训练之后,我们可以可视化图片在潜空间的情况。通过模型中的 encoder 在测试集生成坐标在 2D 散点图中显示。

6bcdac9c73ef12eb299149ae44122128.png

c0a8bfc0a941d8b62f6802ed7f432b4f.png

图中有三个现象值得注意:

  1. 有些数字的占地区域很小,比如红色的 9,有些数字的占地区域很大,比如紫色的 0。

  2. 图中的点对于 (0, 0) 不对称,比如 x 轴上负值的点比正值的点会多很多,有些点甚至到了 x =-15 处。

  3. 颜色之间有很大的间隙,其中包含很少的点,如上图左上角。

上述三大缺陷使我们从潜空间中采样非常困难:

  • 对于缺陷 1, 由于数字 9 比 0 的占地区域大,那么我们更容易采样到 9。

  • 对于缺陷 2,从技术上讲,我们可以采样平面上任何点。但每个数字的分布是不确定的,如果分布不是对称的话,那么随机采样的会很难操作。

  • 对于缺陷 3,从下图可看出从潜空间中的空白处有的根本重构不出像样的数字。

07443e4e7b7d3c6924e78ac3dcf742b9.png

缺陷 3 空白出重构不出数字还好理解,但下图两条红线表示的重构就让人担忧了。这两个点都不在空白处,但是还是无法解码成像样的数字。根本原因就是自动编码器并没有强制确保生成的潜空间是连续的,例如,即便 (2,-2) 能够生成令人满意的数字 4,但该模型没有一个机制来确保点 (2.1, –2.1) 也能产生令人满意的数字 4。

7284fa4ffd9d667988a3d426ae46696f.png


总结

自动编码器只需要特征不需要标签,是一种无监督学习的模型,用于重建数据。该模型是一个生成模型,但从上节提到的三大缺陷,该生成模型对于低维黑白数字的效果都不好,那么对于高维彩色人脸的效果会更差。

这个自编码器框架是好的,那么我们应该如何解决这三个缺陷能生成一个强大的自动编码器。这个就是下篇的内容,变分自动编码器 (Variational AutoEncoder, VAE)。


https://www.signalplus.com/

ea3c34c4c4cb55e6915d077657ca7e65.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1015838.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

nginx中sent_timeout属性使用注意事项

send_timeout使用注意事项 send_timeout:指客户端向服务器发送请求并且等待服务器返回数据的时间,超过这个时间链接就断开。如果咱们返回的数据复杂,很耗时,就将该值设置大些。注意该时间指准备过程,不是传输过程(下载…

在线海报图片设计器、图片编辑器源码/仿照稿定设计源码

在线海报设计系统素材设计源码是一个漂亮且功能强大的在线海报图片设计器,仿照稿定设计而成。该系统适用于多种场景,包括海报图片生成、电商分享图、文章长图、视频/公众号封面等。用户无需下载软件,即可轻松实现创意,迅速完成排版…

7-38 掉入陷阱的数字

输入样例: 5 输出样例: 1:16 2:22 3:13 4:13 ACcode: #include <bits/stdc.h>using namespace std;int main(){int n;cin >> n;vector<int> ans;int limit 1;ans.push_back(n);for(int i0; i<limit; i){//各位数字的和int sum 0;int num ans[i];w…

独立开发了一款Material3风格的RSS阅读器 - Agr Reader

截图 背景&#x1f4d6; 在之前接触到RSS后&#xff0c;发现RSS真是一个十分不错的信息聚合的方式&#xff0c;虽然现在看来RSS的时代已经开始落幕&#xff0c;但是至少目前还是处于能用的阶段。 在我用了Android上好几个RSS阅读App后&#xff0c;发现很多在全文解析方面不是…

栈与队列经典题目——用栈实现队列

上篇文章对栈和队列的一个经典题目——Leetcode.225-用队列实现栈进行讲解。本篇文章将对另一个题目Leetcode.232-用栈实现队列进行讲解 1. Leetcode.232——用栈实现队列&#xff1a; 题目如下&#xff1a; 1.1 大体思路分析&#xff1a; 题目要求需要实现下列函数所表示的…

JAVA注解总结

总结一下java注解。 元注解 元注解也是一种注解。元注解的作用就是来限制和定义一个普通的注解。 注解的语法 public(可选) interface 注解名称{ 具体的参数 } 注解里面的参数 第一个表示参数的类型是什么&#xff0c;类型后面可以跟[],表示数组&#xff0c;在后面就是参数…

详解机器视觉性能指标相关概念——混淆矩阵、IoU、ROC曲线、mAP等

目录 0. 前言 1. 图像分类性能指标 1.1 混淆矩阵(Confusion Matrix) 1.2 准确率(Precision) 1.3 召回率(Recall) 1.4 F1值(F1 score) 1.5 ROC曲线(接收者工作特征曲线&#xff0c;Receiver Operating Characteristic curve) 1.6 mAP(mean Average Precision) 2. 图像分…

Apereo CAS反序列化漏洞中数据加解密研究

Apereo CAS反序列化漏洞中数据加解密研究 0x01、简介0x02、网上获取资料0x03、初步运行失败1、分析&#xff1a;2、Tips&#xff1a; 0x04、分析原因1、自己写解密算法 / 直接使用cas工程的相关jar包、java文件&#xff0c;调用解密函数2、为什么会解密失败&#xff1f; 0x05、…

企业级数据仓库-数仓实战

数仓实战 安装包大小 安装清单 环境搭建 一、环境搭建01&#xff08;机器准备&#xff09; 准备好三台虚拟机&#xff0c;并进行修改hostname、在hosts文件增加ip地址和主机名映射 。 1、设置每个虚拟机的hostname vi /etc/sysconfig/network 修改HOSTNAMEnode02修改hostna…

PY32F003F18之输入捕获

输入捕获是定时器的功能之一&#xff0c;配合外部引脚&#xff0c;捕获脉宽时间或采集周期。 CPU中的定时器最基本的功能就是计数功能&#xff0c;其次是输入捕获(IC)&#xff0c;再次就是比较输出(OC)&#xff0c;还有就是使用引脚对外部时钟进行计数&#xff0c;触发信号捕捉…

6- 华为云查看容器日志

1 查看位置 二 进入容器查看 ls cat main.py # 退出命令是 exit() 或者 quit() cat main.py 在docker使用该命令进入文件后的退出命令

Mapbox gl HTML经纬度点渲染,动态轨迹播放,自定义图形以及轨迹上显示箭头方向

Mapbox gl HTML经纬度点渲染&#xff0c;动态轨迹播放&#xff0c;自定义图形以及轨迹上显示箭头方向 1. 效果图2. 源码2.1 line.html2.2line_arrow.html 参考 今天要排查个问题&#xff0c;需要显示多个经纬度点连接成线段的方向&#xff0c;于是尝试下展示。 1. mapbox渲染经…

element plus封装el-select添加后缀图标并添加远程搜索和对话框功能

当提交的表单Form需要填某个实体的外键ID时&#xff0c;当然不可能使用el-input组件&#xff0c;这个适合提交字符串&#xff0c;然后用户又不可能记住某个引用的外键ID&#xff0c;这时候使用el-select还是必要的。 el-select组件一般都作为下拉选择框使用&#xff0c;但仅在…

Java实现通过文字生成图片

一、前言 在实际应用中&#xff0c;我们可能需要将用户姓名作为头像显示&#xff0c;那么我们可以通过Java来实现。 二、如何实现 1.定义一个工具类&#xff0c;代码如下&#xff1a; import org.slf4j.Logger; import org.slf4j.LoggerFactory;import javax.imageio.ImageIO…

三分钟使用ngrok实现内网穿透

1.官网注册 官网地址&#xff1a;https://ngrok.com/ tips:若使用邮箱注册自行认证 2.下载对应部署电脑 压缩包&#xff08;此处笔者使用自己电脑因此以Windows11作为案例&#xff09; 解压下载的ngrok压缩包&#xff0c;在对应目录进入命令提示符装口&#xff08;也可直接…

竞赛 基于机器视觉的银行卡识别系统 - opencv python

1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于深度学习的银行卡识别算法设计 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f9ff; 更多资料, 项目分享&#xff1a; https://gitee.com/dancheng…

基于 I2C 协议的 AD实验(附代码)

目录 1. 理论学习 1.1 AD介绍 1.2 I2C 简介 1.2.1 I2C物理层 1.2.2 I2C协议层 1.3 PCF8591芯片简介 1.3.1 引脚信息 1.3.2 功能描述 2. 实验 2.1 硬件资源 2.2 模块框图 2.3 程序设计 2.3.1 工程整体框图 2.3.2 I2C驱动模块 1. 模块框图 2. 波形图分析&#xf…

来看看Python MetaClass元类详解

MetaClass元类&#xff0c;本质也是一个类&#xff0c;但和普通类的用法不同&#xff0c;它可以对类内部的定义&#xff08;包括类属性和类方法&#xff09;进行动态的修改。可以这么说&#xff0c;使用元类的主要目的就是为了实现在创建类时&#xff0c;能够动态地改变类中定义…

Docker网络学习

文章目录 Docker容器网络1.Docker为什么需要网络管理2. Docker网络简介3. 常见的网络类型4. docker 网络管理命令5.两种网络加入差异6.网络讲解docker Bridge 网络docker Host 网络docker Container 网络docker none 网络 Docker容器网络 1.Docker为什么需要网络管理 容器的网…

Linux启动速度优化方法总结

文章目录 一、启动耗时统计printk timeinitcall_debugbootgraphbootchartgpio示波器 二、内核优化方法kernel压缩方式加载位置内核裁剪预设置lpj数值initcall优化内核initcall_module并行减少pty/tty个数内核module 三、其他优化ubootXIP 四、总结 要对Linux系统启动速度进行优…