此示例显示如何在MATLAB中创建变形AUTOENCODER(VAE)以生成位数图像。VAE以Mnist数据集的样式生成手绘数字。
VAES与常规AutoEncoders不同,因为它们不使用编码解码过程来重建输入。相反,它们对潜在空间施加概率分布,并学习分布,使得来自解码器的输出分布与观察到的数据的分布匹配。然后,它们从此分发中采样以生成新数据。
在此示例中,您构建VAE网络,将其培训在Mnist数据集上,并生成与数据集中的新图像非常相似。
从中下载mnist文件http://yann.lecun.com/exdb/mnist/并将Mnist数据加载到工作空间[1]中。打电话给processImagesMNIST
和processLabelsMNIST
附加到本示例中的辅助函数将文件中的数据加载到MATLAB数组中。
因为VAE将重建的数字与输入进行比较而不是对禁止分类标签,所以您无需在Mnist数据集中使用训练标签。
TrainimagesFile =.“train-images-idx3-ubyte.gz”;testImagesFile =“t10k-images-idx3-ubyte.gz”;testlabelsfile =.'t10k-labels-idx1-ubyte.gz';XTrain = processImagesMNIST (trainImagesFile);
阅读Mnist图像数据...数据集中的图像数量:60000 ...
numTrainImages =大小(XTrain 4);XTest = processImagesMNIST (testImagesFile);
阅读Mnist图像数据...数据集中的图像数量:10000 ...
ytest = processlabelsmnist(testlabelsfile);
阅读Mnist标签数据...数据集中的标签数:10000 ...
AutoEncoders有两部分:编码器和解码器。编码器拍摄图像输入并输出压缩表示(编码),这是大小的矢量Latentdim
在此示例中等于20。解码器采用压缩表示,解码,并重新创建原始图像。
为了使计算在数值上更加稳定,通过使网络从方差的对数中学习,将可能值的范围从[0,1]增加到[-inf, 0]。定义两个大小的向量latent_dim.
:一个手段
一个用于差异的对数
.然后使用这两个向量来创建分布到样本。
使用2-D卷积后跟一个完全连接的图层从28×28×1个MNIST图像到潜在空间中的编码。然后,使用转换的2-D卷曲将1-1×20展示回到28×28×1×1的图像中。
Latentdim = 20;图像= [28 28 1];Encoderlg = layerGraph([imageInputlayer(图像化,'名称'那“input_encoder”那'正常化'那“没有”32岁的)convolution2dLayer (3'填充'那'相同的'那'走吧'2,'名称'那'conv1')剥离('名称'那“relu1”)卷积2dlayer(3,64,'填充'那'相同的'那'走吧'2,'名称'那“conv2”)剥离('名称'那'relu2')全康连接层(2 * Latentdim,'名称'那“fc_encoder”)]);Decoderlg = layerGraph([ImageInputLayer([1 1 Latentdim],'名称'那'一世'那'正常化'那“没有”64年)transposedConv2dLayer(7日,“种植”那'相同的'那'走吧'7'名称'那'transposs1')剥离('名称'那“relu1”)TransposedConv2dlayer(3,64,“种植”那'相同的'那'走吧'2,'名称'那'transposs2')剥离('名称'那'relu2')TransposedConv2dlayer(3,32,“种植”那'相同的'那'走吧'2,'名称'那'transposs3')剥离('名称'那'relu3') transposedConv2dLayer(3、1“种植”那'相同的'那'名称'那“transpose4”)]);
要使用自定义训练循环培训两个网络并启用自动分化,将图层图转换为dlnetwork.
对象。
Encodernet = DLnetwork(Encoderlg);decodernet = dlnetwork(decoderlg);
辅助功能modelGradients采用编码器和解码器dlnetwork.
对象和迷你输入数据X
,并返回损失相对于网络中可学习参数的梯度。这个helper函数在本例的最后定义。
该函数分两步执行此过程:抽样和损失.采样步骤对均值和方差向量进行采样以将最终编码传递到解码器网络。但是,由于无法通过随机采样操作的BackProjagation无法使用,因此必须使用Reparameterization技巧.此技巧将随机采样操作移动到辅助变量 ,这是由平均值转移的 并按标准偏差缩放 .这个想法是从 与抽样相同 , 在哪里 .下图以图形方式描绘了这个想法。
丢失步骤通过采样步骤通过解码器网络传递编码,并确定丢失,然后用于计算梯度。VAE中的损失,也称为证据下限(ELBO)损失,定义为两个单独损失条款的总和:
.
这重建损失测量通过使用平均平均错误(MSE)解码器输出是如何关闭原始输入:
.
这KL损失或者kullback-leibler发散,测量两个概率分布之间的差异。在这种情况下最小化KL损耗意味着确保学习方法和差异尽可能接近目标(正常)分布。对于大小的潜在尺寸 ,获得KL损失为
.
包括KL损耗项的实际效果是将由于重建损失紧紧地围绕潜在空间的中心而收拾群集,形成连续的空间。
在可用的GPU上进行训练(需要并行计算工具箱™)。
executionenvironment =“汽车”;
设置网络的培训选项。使用ADAM Optimizer时,需要为每个网络初始化尾随平均梯度以及带空数组的尾随平均梯度方形衰减率.
numepochs = 50;minibatchsize = 512;LR = 1E-3;numiterations =楼层(numtrainimages / minibatchsize);迭代= 0;avggradientsencoder = [];avggradientssquaredencoder = [];avggradientsdecoder = [];avggradientssquareddecoder = [];
使用自定义训练循环训练模型。
对于时代中的每次迭代:
从训练集中获取下一个小批量。
将mini-batch转换为adlarray
对象,确保指定维度标签'SSCB'
(空间,空间,频道,批量)。
对于GPU培训,转换dlarray
到一个GPUArray.
目的。
使用该评估模型梯度dlfeval.
和modelGradients
功能。
使用该网络更新网络学习信息和两个网络的平均渐变adamupdate
功能。
在每个时代结束时,通过AutoEncoder通过测试集图像,并显示该时期的损耗和培训时间。
为了epoch = 1:numepochs tic;为了i = 1:numiterations迭代=迭代+ 1;IDX =(I-1)*小匹匹配+ 1:i *小匹匹配;Xbatch = XTrain(::::,IDX);xbatch = dlarray(单(xbatch),'SSCB');如果(execultenvironment ==.“汽车”&& canusegpu)||executionenvironment ==.“GPU”xbatch = gpuarray(xbatch);结束[infGrad, genGrad] = dlfeval(......@modelgradients,encodernet,decodernet,xbatch);[decodernet.learnables,avggradientsdecoder,avggradientssquareddecoder] =......adamupdate(decodernet.learnables,......Gengrad,AvggradientsDecoder,AvggradientsSquaredDecoder,迭代,LR);[Encodernet.Learnables,AvggradientsEncoder,avggradientssquaredencoder] =......adamupdate(Encodernet.learnables,......Infgrad,AvggradientsEncoder,AvggradientsSquaredencoder,迭代,LR);结束Elapsedtime = TOC;[z,zmean,zlogvar] =采样(Encodernet,xtest);xPred = sigmoid(forward(decoderNet, z));elbo = elboloss(xtest,xpred,zmean,zlogvar);DISP(“时代:”+ epoch +“测试eLbo lock =”+聚集(提取数据(elbo))+......".纪元所花费的时间= "+ Elapsedtime +“S”)结束
纪元:1测试ELBO损失= 28.0145。epoch: 2 Test ELBO loss = 24.8995epoch: 3测试ELBO损失= 23.2756。epoch: 4测试ELBO损失= 21.151。epoch: 5测试ELBO损失= 20.5335。epoch: 6 Test ELBO loss = 20.232。epoch: 7测试ELBO损失= 19.9988epoch: 8测试ELBO损失= 19.8955。epoch: 9测试ELBO损失= 19.7991。epoch: 10测试ELBO损失= 19.6773。 Time taken for epoch = 8.4269s Epoch : 11 Test ELBO loss = 19.5181. Time taken for epoch = 8.5771s Epoch : 12 Test ELBO loss = 19.4532. Time taken for epoch = 8.4227s Epoch : 13 Test ELBO loss = 19.3771. Time taken for epoch = 8.5807s Epoch : 14 Test ELBO loss = 19.2893. Time taken for epoch = 8.574s Epoch : 15 Test ELBO loss = 19.1641. Time taken for epoch = 8.6434s Epoch : 16 Test ELBO loss = 19.2175. Time taken for epoch = 8.8641s Epoch : 17 Test ELBO loss = 19.158. Time taken for epoch = 9.1083s Epoch : 18 Test ELBO loss = 19.085. Time taken for epoch = 8.6674s Epoch : 19 Test ELBO loss = 19.1169. Time taken for epoch = 8.6357s Epoch : 20 Test ELBO loss = 19.0791. Time taken for epoch = 8.5512s Epoch : 21 Test ELBO loss = 19.0395. Time taken for epoch = 8.4674s Epoch : 22 Test ELBO loss = 18.9556. Time taken for epoch = 8.3943s Epoch : 23 Test ELBO loss = 18.9469. Time taken for epoch = 10.2924s Epoch : 24 Test ELBO loss = 18.924. Time taken for epoch = 9.8302s Epoch : 25 Test ELBO loss = 18.9124. Time taken for epoch = 9.9603s Epoch : 26 Test ELBO loss = 18.9595. Time taken for epoch = 10.9887s Epoch : 27 Test ELBO loss = 18.9256. Time taken for epoch = 10.1402s Epoch : 28 Test ELBO loss = 18.8708. Time taken for epoch = 9.9109s Epoch : 29 Test ELBO loss = 18.8602. Time taken for epoch = 10.3075s Epoch : 30 Test ELBO loss = 18.8563. Time taken for epoch = 10.474s Epoch : 31 Test ELBO loss = 18.8127. Time taken for epoch = 9.8779s Epoch : 32 Test ELBO loss = 18.7989. Time taken for epoch = 9.6963s Epoch : 33 Test ELBO loss = 18.8. Time taken for epoch = 9.8848s Epoch : 34 Test ELBO loss = 18.8095. Time taken for epoch = 10.3168s Epoch : 35 Test ELBO loss = 18.7601. Time taken for epoch = 10.8058s Epoch : 36 Test ELBO loss = 18.7469. Time taken for epoch = 9.9365s Epoch : 37 Test ELBO loss = 18.7049. Time taken for epoch = 10.0343s Epoch : 38 Test ELBO loss = 18.7084. Time taken for epoch = 10.3214s Epoch : 39 Test ELBO loss = 18.6858. Time taken for epoch = 10.3985s Epoch : 40 Test ELBO loss = 18.7284. Time taken for epoch = 10.9685s Epoch : 41 Test ELBO loss = 18.6574. Time taken for epoch = 10.5241s Epoch : 42 Test ELBO loss = 18.6388. Time taken for epoch = 10.2392s Epoch : 43 Test ELBO loss = 18.7133. Time taken for epoch = 9.8177s Epoch : 44 Test ELBO loss = 18.6846. Time taken for epoch = 9.6858s Epoch : 45 Test ELBO loss = 18.6001. Time taken for epoch = 9.5588s Epoch : 46 Test ELBO loss = 18.5897. Time taken for epoch = 10.4554s Epoch : 47 Test ELBO loss = 18.6184. Time taken for epoch = 10.0317s Epoch : 48 Test ELBO loss = 18.6389. Time taken for epoch = 10.311s Epoch : 49 Test ELBO loss = 18.5918. Time taken for epoch = 10.4506s Epoch : 50 Test ELBO loss = 18.5081. Time taken for epoch = 9.9671s
要显示和解释结果,请使用助手可视化功能.这些辅助功能在该示例的末尾定义。
这VisualizeReconstruction
函数显示每类的随机选择的数字伴随着通过AutoEncoder后的重建。
这visualizelatentspace.
函数采用在通过编码器网络传递测试图像之后生成的平均值和方差编码(尺寸20中的每一个),并在包含每个图像的编码的矩阵上执行主成分分析(PCA)。然后,您可以可视化由两个尺寸的手段和差异定义的潜在空间,其两个维度由两个第一主组件为特征。
这产生
功能初始化从正常分布采样的新编码,并输出当这些编码通过解码器网络时生成的图像。
VisualErizerConstruction(XTEST,YTEST,EndoDernet,Decodernet)
VisualizElatentsPace(XTEST,YTEST,ENCODERNET)
生成(Decodernet,Latentdim)
变形AutoEncoders只是用于执行生成任务的许多可用模型之一。它们在图像较小的数据集上运行良好,并且具有明确定义的功能(例如Mnist)。对于具有较大图像的更复杂的数据集,生成的对抗网络(GAN)倾向于执行更好并产生具有较少噪声的图像。有关展示如何实施GAN生成64乘64 RGB图像的示例,请参阅火车生成对抗网络(GaN).
LeCun, Y. C. Cortes和C. J. C. Burges。“MNIST手写数字数据库”。http://yann.lecun.com/exdb/mnist/.
这modelGradients
函数接受编码器和解码器dlnetwork.
对象和迷你输入数据X
,并返回损失相对于网络中可学习参数的梯度。该函数执行三个操作:
通过调用来获取编码采样
在通过编码器网络的迷你批次图像上的功能。
通过解码器网络通过编码并调用丢失来获得损失elboloss.
功能。
通过调用来计算两个网络的学习参数的损失渐变Dlgradient.
功能。
功能[infGrad, genGrad] = modelGradients(encoderNet, decoderNet, x) [z, zMean, zLogvar] = sampling(encoderNet, x);xPred = sigmoid(forward(decoderNet, z));损失= ELBOloss(x, xPred, zMean, zLogvar);[genGrad, infGrad] = dlgradient(loss, decoderNet。可学的,......encoderNet.Learnables);结束
这采样
功能从输入图像获取编码。最初,它通过编码器网络传递了迷你批次图像并分割大小的输出(2 * Latentdim)*小匹匹匹匹配
进入矩阵和差异矩阵,每个尺寸Latentdim * Batchsize.
.然后,它使用这些矩阵来实现Reparameterization技巧并计算编码。最后,它将此编码转换为adlarray
对象的SSCB格式。
功能[zsampled,zmean,zlogvar] =采样(eNODernet,x)压缩=向前(Encodernet,x);d =尺寸(压缩,1)/ 2;zmean =压缩(1:d,:);zlogvar =压缩(1 + D:结束,:);sz = size(zmean);epsilon = randn(sz);sigma = exp(.5 * zlogvar);z = epsilon。* sigma + zmean;z =重塑(z,[1,1,sz]);zsampled = dlarray(z,'SSCB');结束
这elboloss.
函数接受平均值和方差的编码采样
函数,并利用它们计算ELBO损失。
功能elbo = elboloss(x,xpred,zmean,zlogvar)方块= 0.5 *(Xpred-x)。^ 2;重建=总和(正方形,[1,2,3]);kl = -.5 * sum(1 + zlogvar - zmean。^ 2 - exp(zlogvar),1);elbo =卑鄙(重建+ kl);结束
这VisualizeReconstruction
功能随机选择Mnist数据集的每个数字的两个图像,通过VAE传递它们,并用原始输入并排重建。请注意,绘制内部包含的信息dlarray
对象,您需要首先使用它来提取它提取数据
和收集
功能。
功能VisualErizerConstruction(XTEST,YTEST,EndoDernet,Decodernet)f =图;图(f)标题(“示例地面真相图像与重建图像”)为了我= 1:2为了c = 0:9 idx = irandomidxofclass(ytest,c);x = xtest(::,:,idx);[z,〜,〜] =采样(Encodernet,x);Xpred = sigmoid(前进(Decodernet,z));x =收集(提取数据(x));Xpred =收集(提取数据(Xpred));比较= [x,x,(size(x,1),1),xpred];子图(4,5,(I-1)* 10 + C + 1),imshow(比较,[]),结束结束结束功能Idx = iRandomidXofclass(t,c)idx = t ==分类(c);idx = find(idx);idx = idx(randi(numel(idx),1));结束
这visualizelatentspace.
函数可视化由构成编码器网络输出的平均值和方差矩阵定义的潜在空间,并定位由每个数字的潜在空间表示构成的簇。
该函数通过从中提取均值和方差矩阵来开始dlarray
对象。因为无法使用通道/批处理尺寸(C和B)的转发矩阵,所以函数调用stripdims
在转发矩阵之前。然后,它在两个矩阵上执行主成分分析(PCA)。为了在两个维度中可视化潜在空间,该功能保持前两个主组件并互相互相绘制。最后,函数颜色为数字类,以便您可以观察群集。
功能VisualizElatentsPace(xtest,ytest,endodernet)[〜,zmean,zlogvar] =采样(Encodernet,xtest);zmean = stribdims(zmean)';zmean =收集(提取数据(zmean));zlogvar = stribdims(zlogvar)';zlogvar =收集(提取数据(zlogvar));[〜,Scoremean] = PCA(Zmean);[〜,scoreLogvar] = PCA(Zlogvar);c = parula(10);F1 =数字;图(F1)标题(“潜在的空间”)ah =子图(1,2,1);分散(批量(:,2),商学院(:,1),[],C(双(ytest),:));ah.ydir ='撤销';轴平等的Xlabel(“Z_m_u(2)”)ylabel(“Z_m_u(1)”) cb = colorbar;CB.Ticks = 0:(1/9):1;cb.ticklabels = string(0:9);啊=情节(1、2、2);散射(scoreLogvar (:, 2), scoreLogvar (: 1), [], c(双重(欧美):));ah.ydir ='撤销';Xlabel(“z_v_a_r(2)”)ylabel(“z_v_a_r(1)”) cb = colorbar;CB.Ticks = 0:(1/9):1;cb.ticklabels = string(0:9);轴平等的结束
这产生
功能测试VAE的生成能力。它初始化一个dlarray
对象,包含25个随机生成的编码,将它们通过解码器网络,并绘制输出。
功能生成(Decodernet,Latentdim)randomNoise = Dlarray(Randn(1,1,Latentdim,25),'SSCB');ConsigationImage = Sigmoid(预测(Decodernet,RandomNoise));babledimage =提取数据(bafectwardimage);F3 =数字;图(f3)imshow(imtile(contabtionimage,“ThumbnailSize”,[100100]))标题(“生成的位数”)绘制结束
adamupdate
|dlarray
|dlfeval.
|Dlgradient.
|dlnetwork.
|分层图
|sigmoid.