本文内容参考了Conditional VAE (Variational Auto Encoder) 条件付きVAE

是对官方网页Train Variational Autoencoder (VAE) to Generate Images的改进,该网页的翻译可见MATLAB实现自编码器(四)——变分自编码器实现图像生成Train Variational Autoencoder (VAE) to Generate Images。

1.Load Data

下载数据并解压,然后加载,没有变化

2.Construct Network

与官方网页相比,改进了代码,更加细致,同时增加了解析

2.1.Overview

自动编码器包含两个部分:编码器和解码器。 编码器接受图像输入并输出压缩表示(编码),压缩表示是大小为latent_dim的矢量,在此示例中为20。 解码器获取压缩表示,对其进行解码,然后重新创建原始图像。
变分自编码器的结构如下图所示,后面带有具体部分的意义

2.1.1编码器

  • 面板[a]显示尺寸为28 x 28的图像输入。
  • 面板[b]是独热向量形式的标签输入。下一部分将对此进行说明。
  • 在面板[c]中,标签输入被嵌入到向量中,并被整形为28 x 28。
  • 输入的图像和重塑的标签覆盖在面板[d]中。
  • 在面板[e]中,分层图像被卷积并向下采样。
  • 在面板[f]中,神经网络返回潜在空间的均值和方差。请注意,本演示假定图像可以被压缩为矢量。我们还假设向量(潜空间)具有正态分布。如果采用其他类型的分布,则可以自定义分布的类型,这可能会产生更好的结果。
  • 从面板的正态分布中抽样随机值[g]。

2.1.2解码器

  • 如面板[h]所示,标签信息输入到解码器。
  • 如面板[i]中所示,使用编码器估算的均值和方差对随机值进行采样。
  • 在面板[j]中,将随机值和标签信息连接在一起。
  • 在面板[k]中,连接的向量按比例放大为28×28。
  • 在面板[l]中,将输入图像重构为最终输出图像。

2.2.Define an encoder ([a], [d], [e], and [f])

编码器使用卷积层,relu层和完全连接层将图像和标签信息压缩到潜在空间上。

latentDim = 20; % 压缩表示的大小
imageSize = [28 28 1]; % 输入图像的大小
numClasses = size(countcats(YTrain),1); % 定义输入图像的种类数(在此演示中:10)
encoderLG = layerGraph([imageInputLayer(imageSize,'Name','input_encoder','Normalization','none')  % 图像输入层concatenationLayer(3,2,'Name','cat') % a layer to gather the two-input    % 收集两个输入的层convolution2dLayer(3, 32, 'Padding','same', 'Stride', 2, 'Name', 'conv1') % 卷积层1323*3的卷积核,全0填充,步长为2reluLayer('Name','relu1')  % 激活函数层1convolution2dLayer(3, 64, 'Padding','same', 'Stride', 2, 'Name', 'conv2') % 卷积层2323*3的卷积核,全0填充,步长为2reluLayer('Name','relu2')  % 激活函数层2fullyConnectedLayer(2 * latentDim, 'Name', 'fc_encoder') % 编码器输出潜在空间上值的均值和方差]);

2.3.Define an encoder ([b] and [c])

类别(class)信息被转换为独热向量,其中与目标图像相对应的索引为1(其余为0),具体见下图。
标签输入被转换为嵌入向量,并被整形为28×28。 下面的示例为4 x 4。
要嵌入和调整标签输入的形状,请使用附加到此示例作为支持文件的自定义层embedAndReshapeLayer。

embeddingDimension = 50;  % 标签调整后的大小
encoderLabel = [          % 对标签进行编码imageInputLayer([1 1],'Name','labels','Normalization','none')embedAndReshapeLayer(imageSize,embeddingDimension,numClasses,'emb')];lgraphDiscriminator = addLayers(encoderLG,encoderLabel); % 标签编码层添加到编码器中
lgraphDiscriminator = connectLayers(lgraphDiscriminator,'emb','cat/in2'); % 标签编码的输出是cat层的两个输入之一
analyzeNetwork(lgraphDiscriminator)  % 分析整个编码器网络

2.4.Construct decoder ([i], [j], [k] and [l])

在此演示中,我使用ReLu层进行激活,但Leaky ReLu倾向于在GAN(生成对抗网络)中使用。
解码器将21 x 1的输入比例放大为28 x 28。 上采样如下图所示。

其中转置卷积层的介绍见transposedConv2dLayer

decoderLG = layerGraph([imageInputLayer([1 1 latentDim],'Name','i','Normalization','none') % 潜在维度在最后一部分中定义concatenationLayer(3,2,'Name','cat')   % 收集两个输入的层transposedConv2dLayer(7, 64, 'Cropping', 'same', 'Stride', 7, 'Name', 'transpose1') %转置卷积层进行上采样,647*7的卷积核,步长为7reluLayer('Name','relu1')  % 激活层transposedConv2dLayer(3, 64, 'Cropping', 'same', 'Stride', 2, 'Name', 'transpose2')reluLayer('Name','relu2')transposedConv2dLayer(3, 32, 'Cropping', 'same', 'Stride', 2, 'Name', 'transpose3')reluLayer('Name','relu3')transposedConv2dLayer(3, 1, 'Cropping', 'same', 'Name', 'transpose4')]);

2.5.Construct decoder ([g] and [h])

如编码器中所述,标签输入被嵌入到向量中并被整形以用作解码器的输入。

embeddingDimension = 20; % 标签调整后的大小
projectionSize = [1 1];
layers = [               % 对标签进行编码和整形   imageInputLayer([1 1],'Name','labels','Normalization','none')embedAndReshapeLayer(projectionSize(1:2),embeddingDimension,numClasses,'emb')];
lgraphGenerator = addLayers(decoderLG,layers);
lgraphGenerator = connectLayers(lgraphGenerator,'emb','cat/in2'); % 标签编码的输出是cat层的两个输入之一
analyzeNetwork(lgraphGenerator)   % 分析整个解码器生成网络

2.6.图层转换

要使用自定义训练循环训练两个网络并启用自动微分,将层图转换为dlnetwork对象。

encoderNet = dlnetwork(lgraphDiscriminator);
decoderNet = dlnetwork(lgraphGenerator);

3.Define Model Gradients Function定义模型梯度函数

梯度函数的介绍与原网页一致,但是将原来解码编码过程图替换为新的图片,可以结合二者进行理解。

4.Specify Training Options指定训练选项

这一部分没有变化,见原网页代码。

5.Train Model模型训练

增加了不进行训练的选项,可以直接调用保存好的网络(有点迁移学习的味道),没有进行具体的翻译,暂且搁置。
cpu版的电脑不建议进行训练,耗时太长!!

doTraining=1; % 设置为1进行PC训练
if doTraining==1
for epoch = 1:numEpochs % the tranining data is learned in total of "numEpochs" timestic;for i = 1:numIterations iteration = iteration + 1;idx = (i-1)*miniBatchSize+1:i*miniBatchSize; % the mini-batch is not shuffledXBatch = XTrain(:,:,:,idx); %Obtain the next mini-batch from the training set.XBatch = dlarray(single(XBatch), 'SSCB'); % conver the mini-batch data to use VAEYBatch = permute(YTrain(idx),[2 3 4 1]);%exchange the dimension in the TValidation% For example, the 2nd dimension goes to 4th dimensionYBatch = dlarray(single(YBatch), 'SSCB'); % Convert the mini-batch to a dlarray object, % making sure to specify the dimension labels 'SSCB' (spatial, spatial, channel, batch).% if your GPU is available for the training,convert the dlarray to a gpuArray object.if (executionEnvironment == "auto" && canUseGPU) || executionEnvironment == "gpu"XBatch = gpuArray(XBatch);           end % Evaluate the model gradients using the dlfeval and modelGradients functions.    [infGrad, genGrad] = dlfeval(...@modelGradients, encoderNet, decoderNet, XBatch,YBatch);% Update the network learnables and the average gradients for both networks, using the adamupdate function.[decoderNet.Learnables, avgGradientsDecoder, avgGradientsSquaredDecoder] = ...adamupdate(decoderNet.Learnables, ...genGrad, avgGradientsDecoder, avgGradientsSquaredDecoder, iteration, lr);[encoderNet.Learnables, avgGradientsEncoder, avgGradientsSquaredEncoder] = ...adamupdate(encoderNet.Learnables, ...infGrad, avgGradientsEncoder, avgGradientsSquaredEncoder, iteration, lr);endelapsedTime = toc;% estimate the mean and variace with log scale on the latent space% assuming it has a normal distribution[z, zMean, zLogvar] = sampling(encoderNet, XTraindl,YTraindl);% decode the compressed value to the image-shape value xPred = sigmoid(forward(decoderNet,z,YTraindl));% calculate the ELBO loss. the loss decreases when the  elbo = ELBOloss(XTraindl, xPred, zMean, zLogvar);addpoints(lineLossTrain,iteration,double(gather(extractdata(elbo))))title("Loss During Training: Epoch - " + epoch + "; Iteration - " + iteration)drawnow
end
elseload encoderNet; load encoderNet
end

6.Visualize Results可视化结果

更加细致,三部分作了具体介绍

6.1.Encode-Decode

要可视化和解释结果,请使用帮助程序可视化功能。 这些帮助器功能在本示例的最后定义。
VisualizeReconstruction函数显示从每个类中随机选择的一位,并在通过自动编码器后对其进行重构。

visualizeReconstruction(XTest, YTest, encoderNet, decoderNet)

6.2.Display the distribution of the latent space after dimension reduction with t-SNE

VisualizeLatentSpace函数采用将测试图像通过编码器网络后生成的均值和方差编码(每个维度为20),并对包含每个图像编码的矩阵执行t-SNE。 然后,您可以可视化由均值定义的潜在空间以及以t-SNE为特征的二维方差。
有关t-SNE的详细信息,请参阅下面的补充文件或Federico Errica博士撰写的页面。Step-By-Step Derivation of SNE and t-SNE gradients

visualizeLatentSpace(XTest, YTest, encoderNet)

6.3.Synthesizing digits using the conditional VAE constructed in this script

该功能是新增加的,首先检查训练数据中每个数字被压缩到的潜在空间。 然后使用每个数字的潜在空间来合成每个数字。
将合成数字保存到GIF文件中。

numRepeat=30;% 重复合成过程的次数。 每一次操作合成一百个数字。
TileForGif=generateDigits(decoderNet,encoderNet,XTrain,YTrain,numRepeat);% this fumction was made in the end of this script
fig=figure;set(gcf,'visible','on') % impose the figure outside the script
filename = 'conditional_VAE.gif'; % Specify the output file name
for i=1:numRepeatimshow(TileForGif(:,:,:,i))title(sprintf('pattern: %d',i))pause(.1)drawnowframe = getframe(fig);[A,map] = rgb2ind(frame.cdata,256);if i == 1imwrite(A,map,filename,'gif','LoopCount',Inf,'DelayTime',.1);elseimwrite(A,map,filename,'gif','WriteMode','append','DelayTime',.1);end
end

7.下一步

可变自动编码器只是用于执行生成任务的众多可用模型之一。 它们适用于图像较小且具有明确定义的特征的数据集(例如MNIST)。 对于具有较大图像的更复杂的数据集,生成对抗网络(GAN)往往会表现更好,并生成噪声较小的图像。 有关显示如何实施GAN生成64×64RGB图像的示例,请参阅训练生成对抗网络Train Generative Adversarial Network (GAN)。

8.Helper Functions帮助函数

相关函数请看文章MATLAB实现自编码器(五)——变分自编码器(VAE)实现图像生成的帮助函数
有些改进,更加具体

MATLAB实现自编码器(六)——变分自编码器(VAE)官网代码的改进相关推荐

  1. 【阿里云课程】深度生成模型基础,自编码器与变分自编码器

    大家好,继续更新有三AI与阿里天池联合推出的深度学习系列课程,本次更新内容为第11课中两节,介绍如下: 第1节:生成模型基础 本次课程是阿里天池联合有三AI推出的深度学习系列课程第11期,深度生成模型 ...

  2. 【TensorFlow-windows】学习笔记六——变分自编码器

    #前言 对理论没兴趣的直接看代码吧,理论一堆,而且还有点复杂,我自己的描述也不一定准确,但是代码就两三句话搞定了. 国际惯例,参考博文 论文:Tutorial on Variational Autoe ...

  3. 机器学习-自编码器,变分自编码器及其变种的基本原理(一)

    本篇从自编码器(Auto-Encoder)入手,进行扩展,论述了监督学习和无监督学习的相关知识.接着讲解了自编码器的各种变种,以及比较难以理解的变分自编码器(Variational Auto-Enco ...

  4. 自编码器,变分自编码器和生成对抗网络异同

    一. AE(AutoEncoder) 参考AutoEncoder 1.1 自编码器简单模型介绍 自编码器可以理解为一个试图去 还原其原始输入的系统. 自动编码模型主要由编码器和解码器组成,其主要目的是 ...

  5. torch实现自编码器_Pytorch-自编码器与变分自编码器

    提前导包: 1 importtorch2 from torch importnn, optim3 from torch.utils.data importDataLoader4 from torchv ...

  6. 【自然语言处理系列】自编码器AE、变分自编码器VAE和条件变分自编码器CVAE

    作者:CHEONG 公众号:AI机器学习与知识图谱 研究方向:自然语言处理与知识图谱 本文主要分享自编码器.变分自编码器和条件变分自编码器的相关知识以及在实际实践中的应用技巧,原创不易转载请注明出处, ...

  7. 【生成模型】变分自编码器(VAE)及图变分自编码器(VGAE)

    这段时间在学习机器学习中有关不确定性和概率分布的知识,发现了VAE这样一个有趣的方向,想抓紧时间整理一下VAE的主要思想和方法,然后思考如何迁移应用到自己的研究方向上. 从直观上理解VAE 变分自编码 ...

  8. 46.变分自编码器 VAE

    变分自编码器(Variational Auto-Encoders,VAE) VAE是生成数据用的,GAN(对抗神经网络)也是生成数据用的 在上一节的自编码器也可以生成数据,但是它对中间encode的变 ...

  9. (脑肿瘤分割笔记:四七)--自编码器和变分自编码介绍具有变分自编码器正则化的U型分割结构

    本文只是记录个人阅读论文的感想与思考!难免存在错误!如若理解有误还请各位大佬指出!感谢! 目录 相关概念 自编码器(AE) 自编码器存在的问题 变分自编码器(VAE) 关于正则化的直观解释 论文一:3 ...

最新文章

  1. 如何在本地站点打开html,如何在本地运行的网页上创建指向本地文件的链接?...
  2. Spring Boot 拦截器
  3. 8086汇编贪吃蛇(随机食物+速度递增)
  4. springboot多环境加载yml和logback配置
  5. javascript的prototype继承问题
  6. 大家为什么去国企后都不想跳槽了?
  7. 对java:comp/env的研究(转)
  8. 使用AD14创建异形PCB板
  9. Julia安装与配置Jupyter Notebook
  10. 爬取B站弹幕并生成HTML格式的词云图
  11. voip和rtc_VoIP语音通话研究【进阶篇(四):freeswitch+webrtc+sip.js的通话】
  12. 【读书笔记】你离考研成功就差这本书
  13. 密钥mysql_MySQL加密和密钥管理
  14. 离散数学-数理逻辑知识整理(修改版)
  15. 腾讯云服务器安装java服务部署环境
  16. Deep Face Recognition读书笔记
  17. 免费WAP改变自我现状 谈四个赢利途
  18. Lesson 49 At the butcher's
  19. 迪杰斯特拉算法---求解最短路径
  20. oracle常用函数之trim( )、ltrim( )、rtrim( )

热门文章

  1. UVA12412 A Typical Homework (a.k.a 师兄帮帮忙)
  2. 花几千块钱买了电脑,别老只上QQ啊,校内啊,这些手机就能干的事 来源: 长华不挂科的日志
  3. Android11 解锁屏幕无反应,Android11 setting中增加永不息屏
  4. android 眨眼效果
  5. 主机IP是什么?IP与服务器的联系与类型什么?
  6. bkt项目 (四)搭建环境并测试之3添加日志和 Thymeleaf 模板
  7. 如何免费下载word文档
  8. 兼职APP开发的市场分析情况
  9. RK3399应用开发 | 基于u8g2驱动oled显示系统基本信息(时间、IP、CPU负载、CPU温度)
  10. GLES3使用GPGPU记录