autoencoder自编码器原理以及在mnist数据集上的实现

在这里插入图片描述
Autoencoder是常见的一种非监督学习的神经网络。它实际由一组相对应的神经网络组成(可以是普通的全连接层,或者是卷积层,亦或者是LSTMRNN等等,取决于项目目的),其目的是将输入数据降维成一个低维度的潜在编码,再通过解码器将数据还原出来。因此autoencoder总是包含了两个部分,编码部分以及解码部分。编码部分负责将输入降维编码,解码部分负责让输出层通过潜在编码还原出输入层。我们的训练目标就是使得输出层与输入层之间的差距最小化。

我们会发现,有一定的风险使得训练出的AE模型是一个恒等函数,这是一个需要尽量避免的问题。

Autoencoder CNN 卷积自编码器

下面我们就用一个简单的基于mnist数据集的实现,来更好地理解autoencoder的原理。
首先是import相关的模块,定义一个用于对比显示输入图像与输出图像的可视化函数。

# Le dataset MNIST
from tensorflow.keras.datasets import mnist
import tensorflow as tf
from tensorflow.keras.layers import Input,Dense, Conv2D, Conv2DTranspose, MaxPooling2D, Flatten, UpSampling2D, Reshape
from tensorflow.keras.models import Model,Sequential
import numpy as np
import matplotlib.pyplot as pltdef MNIST_AE_disp(img_in, img_out, img_idx):num_img = len(img_idx)plt.figure(figsize=(18, 4))for i, image_idx in enumerate(img_idx):# 显示输入图像ax = plt.subplot(2, num_img, i + 1)plt.imshow(img_in[image_idx].reshape(28, 28))plt.gray()ax.get_xaxis().set_visible(False)ax.get_yaxis().set_visible(False)# 显示输出图像ax = plt.subplot(2, num_img, num_img + i + 1)plt.imshow(img_out[image_idx].reshape(28, 28))plt.gray()ax.get_xaxis().set_visible(False)ax.get_yaxis().set_visible(False)plt.show()

加载数据并对mnist图像数据进行预处理,包括正则化以及将图片扩充成28,28,1的三维。

(x_train, y_train), (x_test, y_test) = mnist.load_data()
# 正则化 [0, 255] à [0, 1]
x_train=x_train.astype('float32')/float(x_train.max())
x_test=x_test.astype('float32')/float(x_test.max())x_train=x_train.reshape(len(x_train),x_train.shape[1], x_train.shape[2], 1)
x_test=x_test.reshape(len(x_test),x_test.shape[1], x_test.shape[2], 1)

接下来就是自编码器神经网络的构建了。这里编码器与解码器都由两个卷积层构成,编码部分的池化层,对应了解码部分的upsampling层,以此来保证输入输出层的维度是一致的。

from keras.layers import Input, Dense, Conv2D, MaxPooling2D, UpSampling2D
from keras.models import Model# 编码
input_img = Input(shape=(28,28,1))
x = Conv2D(filters=16, kernel_size=(3,3), activation='relu', padding='same')(input_img)
x = MaxPooling2D(pool_size=(2,2))(x)
encoded = Conv2D(filters=8, kernel_size=(3,3), activation='relu', padding='same')(x)# 解码
x = Conv2D(filters=16, kernel_size=(3,3), activation='relu', padding='same')(encoded)
x = UpSampling2D(size=(2,2))(x)
decoded = Conv2D(filters=1,kernel_size=(3,3), activation='sigmoid', padding='same')(x)autoencodeur = Model(input_img, decoded)
autoencodeur.summary()
Model: "model_8"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_10 (InputLayer)        [(None, 28, 28, 1)]       0         
_________________________________________________________________
conv2d_36 (Conv2D)           (None, 28, 28, 16)        160       
_________________________________________________________________
max_pooling2d_17 (MaxPooling (None, 14, 14, 16)        0         
_________________________________________________________________
conv2d_37 (Conv2D)           (None, 14, 14, 8)         1160      
_________________________________________________________________
conv2d_38 (Conv2D)           (None, 14, 14, 16)        1168      
_________________________________________________________________
up_sampling2d_9 (UpSampling2 (None, 28, 28, 16)        0         
_________________________________________________________________
conv2d_39 (Conv2D)           (None, 28, 28, 1)         145       
=================================================================
Total params: 2,633
Trainable params: 2,633
Non-trainable params: 0
_________________________________________________________________

接下来就是AE神经网络的训练,与一般的神经网络不同的地方在于,在上述问题中训练自编码器时,输入输出都是同样的mnist图像,以保证在最后输出层能够无限接近输入层,损失降低到最小。

autoencodeur.compile(optimizer='Adam',loss='binary_crossentropy')
autoencodeur.fit(x_train, x_train, batch_size=256, epochs=5)

由于mnist数据集较为简单,在经过五个epoch之后AE模型基本收敛。

Epoch 1/5
235/235 [==============================] - 59s 250ms/step - loss: 0.3742
Epoch 2/5
235/235 [==============================] - 59s 250ms/step - loss: 0.0706
Epoch 3/5
235/235 [==============================] - 59s 250ms/step - loss: 0.0676
Epoch 4/5
235/235 [==============================] - 59s 251ms/step - loss: 0.0666
Epoch 5/5
235/235 [==============================] - 59s 249ms/step - loss: 0.0658

我们从数据集中随机选取10张图片,来对比一下通过自编码器后输入输出的图片的区别。

# 挑选十个随机的图片
num_images=10
np.random.seed(42)
random_test_images=np.random.randint(x_test.shape[0], size=num_images)
# 预测输出图片
decoded_img=autoencodeur.predict(x_test)
# 显示并对比输入与输出图片
MNIST_AE_disp(x_test, decoded_img, random_test_images)

在这里插入图片描述
我们从上述例子中可以看到,输出层与输入层相差无几,但是也并不是完全一致的,这说明了我们的自编码器运作正常且并没有生成一个恒等模型。接下来我们通过AE来构建一个去噪模型。

Autoencoder denoising 降噪自编码器

在这个部分中,我们将利用自编码器来实现对图片的降噪功能。首先我们生成一些带噪点的图片。

noise_factor = 0.4
x_train_noisy = x_train + noise_factor * np.random.normal(loc=0.0, scale=1.0, size=x_train.shape) 
x_test_noisy = x_test + noise_factor * np.random.normal(loc=0.0, scale=1.0, size=x_test.shape) # clip 用于规定最小值和最大值,array中的值如果小于0则变为0 如果大于1则变为1
x_train_noisy = np.clip(x_train_noisy, 0., 1.)
x_test_noisy = np.clip(x_test_noisy, 0., 1.)

直接使用上述已经训练好的模型,来看看当输入是带噪点的图像时,我们的卷积自编码器的输出是什么样的。

num_images=10
np.random.seed(42)
random_test_images_noisy=np.random.randint(x_test_noisy.shape[0], size=num_images) # list that contains the index of images chosen
print(random_test_images)
# On détermine l'image encodée et l'image décodée
decoded_img_noisy=autoencodeur.predict(x_test_noisy) 
# visialisation
MNIST_AE_disp(x_test_noisy, decoded_img_noisy, random_test_images_noisy)

在这里插入图片描述
第一行对应的图片是我们手动生成的有噪点的图像,第二行对应的图片则是我们通过卷积自编码器后的输出图像。可以发现,输出的图像并没有完全一致,而是一定程度上已经去噪了,其实这可以进一步地佐证卷积神经网络处理带噪数据体现出的鲁棒性,即相较全连接层而言,对噪声的敏感程度更低。当然,这个降噪效果还不是很理想,因此我们创建一个新的autoencoder用于处理这一类降噪问题。

DAE = Model(input_img, decoded)
DAE.summary()
DAE.compile(optimizer='Adam', loss='binary_crossentropy')
DAE.fit(x_train_noisy, x_train, batch_size=256, epochs=5)

这个降噪用的自编码器,其架构与上述卷积自编码器相同,唯一有区别的地方在于训练时,我们的输入层变成了带噪图片,而输出层是没有噪声的图片,以此来达到降噪的训练目的。

同样的随机在数据集中选取图片进行对比,我们发现通过这个降噪自编码器后,图像的噪点明显减少了,而且与使用单纯的卷积自编码器不同的是,图像没有明显的钝化,清晰度很高。
在这里插入图片描述
在mnist数据集上的实现,同样可以给我们在其他的图片降噪问题上以启发,可以推测的是,更复杂的有噪图片通过类似的处理,也可以达到类似优秀的降噪效果。

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

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

相关文章

vscode编写插件详细过程

vscode编写插件详细过程 前言 之前编写了一个vscode插件用vscode写博客和发布,然后有园友要求写一篇来介绍如何开发一个vscode扩展插件,或者说介绍开发这个插件的过程。然而文章还没有写,园子里面已经有人发布一个文章,是园友上…

cannot find output in imported module librosa报错解决

librosa一直都是用处很广泛的python声音信号处理模块,但在最近的版本更新中,将原本的librosa.output给删去了。 为了代替之前的librosa.output.write_wav函数将音频写入wav文件中,现可以用模块soundfile代替。 soundfile.write(file, data, …

2018-2019-2 20175328 《Java程序设计》第十一周学习总结

十三章主要内容——Java网络编程 一、URL类 URL类是java.net包中的一个重要的类,URL的实例封装着一个统一资源定位符(Uniform Resource Locator),使用URL创建对象的应用程序称作客户端程序。 一个URL对象通常包含最基本的三部分信息:协议、地…

修改Header方法

/*** 修改header信息&#xff0c;key-value键值对儿加入到header中,如果存在&#xff0c;替换* param request* param key* param value*/ public static void reflectRequestParam(HttpServletRequest request, String key, String value){Class<? extends HttpServletReq…

pytorch学习笔记 1. pytorch基础 tensor运算

pytorch与tensorflow是两个近些年来使用最为广泛的机器学习模块。开个新坑记录博主学习pytorch模块的过程&#xff0c;不定期更新学习进程。 文章较为适合初学者&#xff0c;欢迎对代码和理解指点讨论&#xff0c;下面进入正题。 import torch import numpy as npt1 torch.te…

2019年区块链的主旋律是中间层协议

2019年区块链的主旋律是中间层协议 过去一年加密资产市场从其峰值下跌超过85%的市值。但对我&#xff0c;一个坚定的区块链企业家&#xff0c;这实际上是一件好事&#xff0c;区块链的未来看起来比以往任何时候都更有希望。2017年ICO热潮开始的疯狂至少产生了一个强烈的积极影响…

Java枚举的内容可以使用map的方式

枚举的内容可以使用map的方式 package com.chinamobile.framework.common.enums;import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils;import java.util.ArrayList; import java.util.HashMap; import java.util.List; import jav…

tensorflow gpu windows配置步骤教学

本文主要针对在windows10环境下的tensorflow配置问题&#xff0c;在linux和mac等其他环境中的配置就不过多赘述(windows总是那个问题最多的环境&#xff0c;建议使用linux &#x1f603;)。 本文中配置的环境为 python 3.8.5 tensorflow-gpu 2.4.1 1. 更新nvidia显卡驱动至最…

numpy一维数组永远为列向量

import numpy as np a np.array([1,3,4,5]) print(a.shape) a np.transpose(a) print(a.shape) print(a)a np.ravel(a) print(a.shape) print(a)a a.reshape((1,4)) print(a.shape)输出如下 (4,) (4,) [1 3 4 5] (4,) [1 3 4 5] (1, 4)我们会发现&#xff0c;对于一维的数…

【BJOI 2019】奥术神杖

题意 你有一个长度为 $n$ 的模板串&#xff08;由 $0-9$ 这 $10$ 个数字和通配符 $.$ 组成&#xff09;&#xff0c;还有 $m$ 个匹配串&#xff08;只由 $0-9$ 这 $10$ 个数字组成&#xff09;&#xff0c;每个匹配串有一个魔力值 $v_i$。你要把模板串的每个 $.$ 都换成一个数字…

keras模型中的默认初始化权重

权重的初始化&#xff0c;决定了模型训练的起点。一个良好的初始化可以加快训练过程&#xff0c;同时避免模型收敛至局部最小值。为了在训练过程中避免使得权重的变化总沿着同一个方向&#xff0c;我们尽量避免将所有权重都初始化为同一个值&#xff0c;如全0矩阵或全1矩阵。 …

java oracle的枚举错误

public enum OracleErrorTypeEnum implements BaseEnum {ORA00001("ORA-00001","不允许有重复的数据"),ORA00017("ORA-00017","请求会话以设置跟踪事件"),ORA00018("ORA-00018","超出最大会话数"),ORA00019(&quo…

C# 篇基础知识10——多线程

1.线程的概念 单核CPU的计算机中&#xff0c;一个时刻只能执行一条指令&#xff0c;操作系统以“时间片轮转”的方式实现多个程序“同时”运行。操作系统以进程&#xff08;Process&#xff09;的方式运行应用程序&#xff0c;进程不但包括应用程序的指令流&#xff0c;也包括运…

keras中mean square error均方误差理解

机器学习中&#xff0c;针对不同的问题选用不同的损失函数非常重要&#xff0c;而均方误差就是最基本&#xff0c;也是在解决回归问题时最常用的损失函数。本文就keras模块均方误差的计算梳理了一些细节。 首先看一下均方误差的数学定义 : 均方误差是预测向量与真实向量差值的…

Java并发Semaphore信号量的学习

public class MyThreadTest {private final static Semaphore semaphore new Semaphore(2);// 设置2个车位public static void main(String[] args) {System.out.println("start");p(semaphore, true, 1);p(semaphore, false, 2);p(semaphore, false, 3);p(semaphor…

快速理解binary cross entropy 二元交叉熵

Binary cross entropy 二元交叉熵是二分类问题中常用的一个Loss损失函数&#xff0c;在常见的机器学习模块中都有实现。本文就二元交叉熵这个损失函数的原理&#xff0c;简单地进行解释。 首先是二元交叉熵的公式 : Loss−1N∑i1Nyi⋅log⁡(p(yi))(1−yi)⋅log(1−p(yi))Loss …

Docker搭建自己的GitLab

Docker搭建自己的GitLab docker 介绍 **GitLab: ** GitLab 是一个用于仓库管理系统的开源项目&#xff0c;使用Git作为代码管理工具&#xff0c;并在此基础上搭建起来的web服务 **Docker: ** Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖…

kolla-ansible-----常用命令

常用命令 kolla-ansible prechecks -i multinode #部署前环境检测 kolla-genpwd #生成/etc/kolla/password.yml密码配置文件 kolla-ansible post-deploy -i multinode #生成认证文件 kolla-ansible mariadb_recovery -i /opt/mutinode #恢复数据库 kolla-ansible -i multi…

python numpy 分离与合并复数矩阵实部虚部的方法

在进行数字信号处理的过程中&#xff0c;我们往往有对短时傅里叶变换频谱(spectrogram)进行分析的需求。常见的分析手段对应欧拉公式分为两种&#xff0c;要么使用模与相位的形式&#xff0c;要么使用实部虚部。本文分享一个简单的将复数光谱图分解为实部与虚部以及将两个部分重…