列车条件剖成对抗性网络(CGAN)

此示例示出了如何培养条件生成对抗网络(CGAN),以生成图像。

甲生成对抗网络(GAN)是一种类型的深度学习网络,可以产生具有类似特性作为输入训练数据的数据。

阿甘由两个网络,在一起训练的:

  1. Generator -给定一个随机值向量作为输入,该网络生成的数据与训练数据具有相同的结构。

  2. Discriminator——给定一批包含来自训练数据和来自生成器生成数据的数据,这个网络尝试将观察分类为“真实的”或“生成的”。

一个有条件的生成对抗网络是一种甘也需要在训练过程中优势的标签。

  1. 发电机 - 给定一个标签和随机数组作为输入,该网络具有相同的结构,对应于同一标签的训练数据生成的观测数据。

  2. 鉴别器 - 包含来自两个训练数据的观察和生成的数据从生成器标签数据的给定批次中,该网络试图观测为“真实的”或“产生”进行分类。

要培养条件GAN,同时培养两个网络以最大限度地提高性能:

  • 训练发生器产生“愚弄”鉴别器的数据。

  • 训练鉴别真实和产生的数据之间进行区分。

使发电机的性能,给定生成的标记的数据时,最大限度地鉴相器的损耗。也就是说,发电机的目的是生成标记数据鉴别归类为“真正的”。

为了最大限度地提高鉴别的性能,因为这两个真正的批次和生成标记数据时,最小化鉴别的损失。也就是说,鉴别的目的是为了不“上当”由发电机。

理想情况下,这些策略导致生成令人身临其境的逼真数据生成对应于输入标签和了解,是每个标签的训练数据的特征强大的功能表示鉴别。

负荷训练数据

下载并解压数据集[1]。

URL ='http://download.tensorflow.org/example_images/flower_photos.tgz';downloadFolder = TEMPDIR;文件名=完整文件(downloadFolder,'flower_dataset.tgz');imageFolder =完整文件(downloadFolder,'flower_photos');如果〜存在(imageFolder,“目录”)DISP(“花下载数据集(218 MB)......”)websave(文件名,url);解压(文件名,downloadFolder)结束

创建一个包含照片的图像数据存储。

datasetFolder =完整文件(imageFolder);IMDS = imageDatastore(datasetFolder,...'IncludeSubfolders',真正,...'LABELSOURCE','foldernames');

查看类的数量。

类=类别(imds.Labels);numClasses = numel(类)
numClasses = 5

增加的数据包括随机水平翻转和调整图像具有尺寸64通过-64。

增强因子= imageDataAugmenter('RandXReflection',真正的);augimds = augmentedImageDatastore([64 64],IMDS,“DataAugmentation”,增强因子);

定义发电机网络

定义以下两输入网络,其产生图像给出1 * 1 * 100阵列的随机值和相应的标签的:

该网络:

  • 1-通过-1-通过-100阵列噪声与4×4×1024阵列转换。

  • 将分类标签转换为嵌入向量,并将其重塑为4×4数组。

  • 串接从沿着通道维度中的两个输入端所得到的图像。输出是一个4×1025阵列。

  • Upscales所得阵列64由64×3使用一系列与批标准化和RELU层转置卷积层的阵列。

定义该网络体系结构作为层图形和指定以下网络属性。

  • 对于分类输入,使用50的嵌入维。

  • 用于转置卷积层,指定与每个层数目减少的滤波器,2的跨度和“相同”裁剪输出的5乘5的过滤器。

  • 对于最终的转置卷积层,指定对应于所生成的图像的三个RGB通道中的三个5×5滤波器。

  • 在网络的端部,包括一个双曲正切层。

项目和重塑噪声输入,使用自定义层projectAndReshapeLayer,附连到本实施例中作为支撑文件。万博1manbetx该projectAndReshapeLayer对象upscales使用完全连接操作的输入和重塑输出到指定的大小。

要输入标签到网络中,使用imageInputLayer对象,并指定图像大小为1×1。要嵌入和重塑标签输入,使用自定义层embedAndReshapeLayer,附连到本实施例中作为支撑文件。万博1manbetx该embedAndReshapeLayer对象转换使用嵌入和完全连接的操作的分类标签到指定的尺寸的一个通道的图像。

numLatentInputs = 100;embeddingDimension = 50;numFilters = 64;filterSize = 5;projectionSize = [4 4 1024];layersGenerator = [imageInputLayer([1个1 numLatentInputs]'正常化','没有',“名字”,'噪声')projectAndReshapeLayer (projectionSize numLatentInputs,“项目”);concatenationLayer(3,2,“名字”,'猫');transposedConv2dLayer(filterSize,4个* numFilters,“名字”,'tconv1')batchNormalizationLayer(“名字”,'BN1')reluLayer (“名字”,'relu1')transposedConv2dLayer(filterSize,2个* numFilters,“步”,2,“裁剪”,'相同',“名字”,'tconv2')batchNormalizationLayer(“名字”,'BN2')reluLayer (“名字”,'relu2')transposedConv2dLayer(filterSize,numFilters,“步”,2,“裁剪”,'相同',“名字”,'tconv3')batchNormalizationLayer(“名字”,'BN3')reluLayer (“名字”,'relu3')transposedConv2dLayer(filterSize,3,“步”,2,“裁剪”,'相同',“名字”,'tconv4')tanhLayer(“名字”,“正切”));lgraphGenerator = layerGraph (layersGenerator);[imageInputLayer([1 1]),“名字”,'标签','正常化','没有')embedAndReshapeLayer (projectionSize (1:2), embeddingDimension numClasses,'EMB'));lgraphGenerator = addLayers(lgraphGenerator,层);lgraphGenerator = connectLayers(lgraphGenerator,'EMB',“猫/平方英寸”);

若要使用自定义训练循环训练网络并使其自动区分,请将层图转换为dlnetwork目的。

dlnetGenerator = dlnetwork(lgraphGenerator)
dlnetGenerator = dlnetwork与属性:层:[16×1 nnet.cnn.layer.Layer]连接:[15×2表] Learnables:[19×3表]状态:[6×3表] InputNames:{ '噪音''标签'} OutputNames:{ '正切'}

定义鉴别网络

定义以下两输入网络,这真实分类和给定的生成的64通过-64的图像的一组图像和相应的标签。

创建一个网络,作为输入64通过-64×1的图像和相应的标签,并使用与批标准化和漏RELU层的一系列卷积层的输出标量预测得分。噪声添加到使用辍学输入图像。

  • 对于漏失层,指定的0.25的差的概率。

  • 对于卷积层,指定与每个层越来越多的过滤器5乘5的过滤器。也指定为2,并在每个边缘上的输出的填充步幅。

  • 对于泄漏RELU层,指定0.2的比例。

  • 对于最后的层,与一个4乘4滤波器指定一个卷积层。

dropoutProb = 0.25;numFilters = 64;标度= 0.2;inputSize = [64 64 3];filterSize = 5;layersDiscriminator = [imageInputLayer(inputSize,'正常化','没有',“名字”,'图片')dropoutLayer(dropoutProb,“名字”,'退出')concatenationLayer(3,2,“名字”,'猫')convolution2dLayer(filterSize,numFilters,“步”,2,'填充','相同',“名字”,'CONV1')leakyReluLayer(规模、“名字”,'lrelu1')convolution2dLayer(filterSize,2个* numFilters,“步”,2,'填充','相同',“名字”,'CONV2')batchNormalizationLayer(“名字”,'BN2')leakyReluLayer(规模、“名字”,'lrelu2')convolution2dLayer(filterSize,4个* numFilters,“步”,2,'填充','相同',“名字”,'conv3')batchNormalizationLayer(“名字”,'BN3')leakyReluLayer(规模、“名字”,'lrelu3')convolution2dLayer(filterSize,8个* numFilters,“步”,2,'填充','相同',“名字”,'CONV4')batchNormalizationLayer(“名字”,'BN4')leakyReluLayer(规模、“名字”,'lrelu4')convolution2dLayer(4,1,“名字”,'conv5'));lgraphDiscriminator = layerGraph(layersDiscriminator);[imageInputLayer([1 1]),“名字”,'标签','正常化','没有')embedAndReshapeLayer(inputSize,embeddingDimension,numClasses,'EMB'));lgraphDiscriminator = addLayers (lgraphDiscriminator层);lgraphDiscriminator = connectLayers (lgraphDiscriminator,'EMB',“猫/平方英寸”);

若要使用自定义训练循环训练网络并使其自动区分,请将层图转换为dlnetwork目的。

dlnetDiscriminator = dlnetwork(lgraphDiscriminator)
可学习表:[19×3表]状态:[6×3表]InputNames: {'images' 'label '} OutputNames: {'conv5'}

定义模式渐变和损失函数

创建功能modelGradients,列于型号渐变功能的示例的部分,该部分作为输入发电机和鉴别网络中,小批量的输入数据,以及随机值的阵列,并返回损失的梯度相对于在网络中可以学习的参数和的阵列生成的图像。

指定培训选项

列车与128 500个历元迷你批量大小。

numEpochs = 500;miniBatchSize = 128;augimds。MiniBatchSize = MiniBatchSize;

为Adam优化指定选项。对于两个网络,使用:

  • 的0.0002学习率

  • 的0.5 A梯度衰减因子

  • 的0.999甲平方梯度衰减因子

learnRate = 0.0002;gradientDecayFactor = 0.5;squaredGradientDecayFactor = 0.999;

在GPU上火车(如果可用)。使用GPU需要并行计算工具箱™和启用CUDA®GPUNVIDIA®计算能力3.0或更高版本。

executionEnvironment =“汽车”;

每100次迭代更新训练进度图。

validationFrequency = 100;

如果鉴别器过快地学会区分真实图像和生成图像,那么产生器可能无法训练。为了更好地平衡鉴别器和生成器的学习,随机翻转真实图像的一个比例的标签。指定0.5的翻转因子。

flipFactor = 0.5;

火车模型

使用自定义训练循环训练模型。循环训练数据并在每次迭代时更新网络参数。为了监控训练进度,可以使用一个拖出的随机值数组显示一批生成的图像,然后输入到生成器和网络分数中。

初始化为亚当优化的参数。

velocityDiscriminator = [];trailingAvgGenerator = [];trailingAvgSqGenerator = [];trailingAvgDiscriminator = [];trailingAvgSqDiscriminator = [];

初始化的训练进度的情节。创建人物并调整它有宽度的两倍。

f =图;f.Position (3) = 2 * f.Position (3);

创建生成的图像和得分图的次要情节。

imageAxes =副区(1,2,1);scoreAxes =副区(1,2,2);

初始化分数图的动画线。

lineScoreGenerator = animatedline(scoreAxes,'颜色',[0 0.447 0.741]);lineScoreDiscriminator = animatedline(scoreAxes,'颜色',[0.85 0.325 0.098]);

自定义图表的外观。

传说('发电机',“鉴别”);ylim([0 1])xlabel(“迭代”)ylabel(“得分”)网格

要监控训练进度,创建一个持有了一批25 1 * 1逐的numLatentInputs随机值的阵列,并通过5对应的标签集1(对应于类)重复5次,其中,所述标签是在所述阵列的第四维。

numValidationImagesPerClass = 5;ZValidation = randn(1,1,numLatentInputs,numValidationImagesPerClass * numClasses,'单');TValidation =单(repmat(1:numClasses,[1个numValidationImagesPerClass]));TValidation =置换(TValidation,[1 3 4 2]);

转换的数据dlarray对象,并指定维度标签'SSCB'(空间,空间信道,批次)。

dlZValidation = dlarray (ZValidation,'SSCB');dlTValidation = dlarray(TValidation,'SSCB');

对于GPU训练,将数据转换成gpuArray对象。

如果(执行环境==“汽车”&& canUseGPU) b| executionEnvironment ==“GPU”dlZValidation = gpuArray (dlZValidation);dlTValidation = gpuArray (dlTValidation);结束

训练甘。对于每个纪元,洗牌数据和循环数据的小批。

为每个mini-batch:

  • 为了确保鉴别器的输入与生成器的输出相匹配,对真实图像进行缩放,使像素的取值范围为[- 1,1]。

  • 转换的图像数据和标签dlarray有基础对象类型并指定尺寸的标签'SSCB'(空间,空间信道,批次)。

  • 生成dlarray对象包含随机值的阵列用于发电机网络。

  • 对于GPU训练,将数据转换成gpuArray对象。

  • 评估使用模型梯度dlfevalmodelGradients函数。

  • 更新使用的网络参数adamupdate函数。

  • 画出两个网络的分数。

  • 之后每validationFrequency迭代中,显示一个批次的固定保持出发电机输入生成的图像。

培训可能需要一些时间来运行。

迭代= 0;开始=抽动;%遍历时期。历元= 1:numEpochs%重置和洗牌的数据存储。复位(augimds);augimds =洗牌(augimds);%遍历迷你批次。hasdata(augimds)迭代=迭代+ 1;读取小批数据,并为%发电机网络。data =阅读(augimds);%忽略最后的部分小批量划时代的。如果大小(数据,1)继续结束X =猫(4,数据{:,1} {:});X =单(X);T =单(data.response);T =置换(T,[2 3 4 1]);Z = randn(1,1,numLatentInputs,miniBatchSize,'单');%重缩放在范围[-1 1]的影像。X =重新调整(X,-1,1,'InputMin',0,'InputMax',255);%转换小批量数据的dlarray并指定尺寸的标签% 'SSCB'(空间的,空间的,信道,批次)。DLX = dlarray(X,'SSCB');DLZ = dlarray(Z,'SSCB');DLT = dlarray(T,'SSCB');%如果在GPU训练,然后数据转换为gpuArray。如果(执行环境==“汽车”&& canUseGPU) b| executionEnvironment ==“GPU”DLX = gpuArray(DLX);DLZ = gpuArray(DLZ);DLT = gpuArray(DLT);结束%评估模型梯度和生成器状态使用%dlfeval和modelGradients功能在的末尾列出%的例子。[gradientsGenerator,gradientsDiscriminator,stateGenerator,scoreGenerator,scoreDiscriminator] =...dlfeval(@modelGradients,dlnetGenerator,dlnetDiscriminator,DLX,DLT,DLZ,flipFactor);dlnetGenerator.State = stateGenerator;%更新鉴别网络参数。[dlnetDiscriminator,trailingAvgDiscriminator,trailingAvgSqDiscriminator] =...adamupdate (dlnetDiscriminator gradientsDiscriminator,...trailingAvgDiscriminator trailingAvgSqDiscriminator,迭代,...learnRate,gradientDecayFactor,squaredGradientDecayFactor);更新生成器网络参数。[dlnetGenerator,trailingAvgGenerator,trailingAvgSqGenerator] =...adamupdate(dlnetGenerator,gradientsGenerator,...trailingAvgGenerator trailingAvgSqGenerator,迭代,...learnRate,gradientDecayFactor,squaredGradientDecayFactor);%每validationFrequency迭代,显示批次使用所生成的图像的%持有了发电机输入。如果MOD(迭代,validationFrequency)== 0 ||迭代== 1%生成使用持有了发电机输入图像。dlXGeneratedValidation =预测(dlnetGenerator,dlZValidation,dlTValidation);%瓷砖和重新缩放图像在范围[0 1]。我= imtile (extractdata (dlXGeneratedValidation),...'GridSize',(numValidationImagesPerClass numClasses]);I =重新调节(我);%显示图像。副区(1,2,1);图像(imageAxes,I)xticklabels([]);yticklabels([]);标题(“生成的图像”);结束更新分数图副区(1,2,2)addpoints(lineScoreGenerator,迭代,...双(聚(ExtractData由(scoreGenerator))));addpoints(lineScoreDiscriminator,迭代,...双(聚(ExtractData由(scoreDiscriminator))));%更新标题与训练进度信息。d =持续时间(0,0,TOC(开始),'格式','HH:MM:SS');标题(...“时代”+时代+“”+...“迭代”+迭代+“”+...“经历:”+串(d))的DrawNow结束结束

在这里,鉴别了解到,标识生成的图像中实时图像的强大的功能表现。反过来,发电机学到了同样强大的功能表现,它允许它来生成逼真的数据。每列对应于一个类。

训练图显示了生成器和鉴别器网络的得分。要了解更多关于如何解释网络分数的信息,请参见监视器甘训练进程,并确定共同的故障模式

生成新形象

要生成特定类的新图像,使用预测在具有发电机功能dlarray含有一批加工对象物1乘1逐numLatentInputs随机值的阵列和对应于所需的类标记的阵列。转换的数据dlarray对象,并指定维度标签'SSCB'(空间,空间信道,批次)。对于GPU预测,将数据转换成gpuArray。要显示的图像一起,使用imtile使用功能和重新调整图像重新调整函数。

创建的对应于所述第一类的随机值的36个矢量阵列。

numObservationsNew = 36;idxClass = 1;Z = randn(1,1,numLatentInputs,numObservationsNew,'单');T = repmat(single(idxClass),[1 1 1 numObservationsNew]);

转换的数据dlarray具有维度标签的对象'SSCB'(空间,空间,通道,批次)。

DLZ = dlarray(Z,'SSCB');DLT = dlarray(T,'SSCB');

使用GPU生成图像,也将数据转换为gpuArray对象。

如果(执行环境==“汽车”&& canUseGPU) b| executionEnvironment ==“GPU”DLZ = gpuArray(DLZ);DLT = gpuArray(DLT);结束

生成使用图像预测函数与生成器网络。

dlXGenerated =预测(dlnetGenerator, dlZ dlT);

显示在图中的生成的图像。

图I = imtile(ExtractData由(dlXGenerated));I =重新调节(我);imshow(I)称号(“类:”+类(idxClass))

在这里,生成器网络根据指定的类生成映像。

型号渐变功能

功能modelGradients以发生器和鉴别器为输入dlnetwork对象dlnetGeneratordlnetDiscrimintor中,小批量的输入数据的dlX,相应的标签dlT和随机值的阵列dlZ,并返回损失的梯度相对于在网络中可学习参数,发电机状态,以及网络分数。

如果鉴别器过快地学会区分真实图像和生成图像,那么产生器可能无法训练。为了更好地平衡鉴别器和生成器的学习,随机翻转真实图像的一个比例的标签。

功能[gradientsGenerator,gradientsDiscriminator,stateGenerator,scoreGenerator,scoreDiscriminator] =...modelGradients(dlnetGenerator,dlnetDiscriminator,DLX,DLT,DLZ,flipFactor)%计算的预测与鉴别网络真实数据。dlYPred =正向(dlnetDiscriminator,DLX,DLT);%计算的预测以与鉴别器网络产生的数据。[dlXGenerated,stateGenerator] =向前(dlnetGenerator,DLZ,DLT);dlYPredGenerated =正向(dlnetDiscriminator,dlXGenerated,DLT);%计算概率。probGenerated =乙状结肠(dlYPredGenerated);probReal =乙状结肠(dlYPred);%计算发电机和鉴别器的分数scoreGenerator =平均值(probGenerated);scoreDiscriminator =(均值(probReal)+平均(1-probGenerated))/ 2;%翻转标签。numObservations =尺寸(dlYPred,4);IDX = randperm(numObservations,地板(flipFactor * numObservations));probReal(:,:,:,IDX)= 1  -  probReal(:,:,:,IDX);%计算的GAN损失。[lossGenerator,lossDiscriminator] = ganLoss(probReal,probGenerated);%对于每个网络,计算梯度相对于损失。gradientsGenerator = dlgradient(lossGenerator,dlnetGenerator.Learnables,'RetainData',真正的);gradient = dgradient (lossDiscriminator, dlnetDiscriminator.Learnables);结束

甘损失函数

发电机的目的是生成数据鉴别归类为“真正的”。为了最大限度地从发电机图像被鉴别归类为真正的概率,尽量减少负面数似然函数。

鉴于输出 Y 鉴别的:

  • Y = σ ( Y ) 是输入图像属于类“真实”的概率。

  • 1 - Y 是输入图像属于“而生成”之类的概率。

需要注意的是乙状结肠操作 σ 在里面modelGradients函数。为发电机的损失函数为

lossGenerator = - 意思 ( 日志 ( Y 产生 ) ) ,

哪里 Y G e n e r 一个 t e d 包含所生成的图像的鉴相器输出的概率。

鉴别的目的是通过发电机不被“愚弄”。为了最大限度地提高的概率鉴别的实部和生成的图像之间成功地鉴别,最小化的相应的负对数似然函数的总和。用于鉴别的损失函数为

lossDiscriminator = - 意思 ( 日志 ( Y 真实 ) ) - 意思 ( 日志 ( 1 - Y 产生 ) ) ,

哪里 Y R e 一个 l 包含了真实图像鉴别器输出概率。

功能[lossGenerator,lossDiscriminator] = ganLoss(scoresReal,scoresGenerated)%计算损失鉴别网络。lossGenerated = -mean(日志(1  -  scoresGenerated));lossReal = -mean(日志(scoresReal));%合并损失鉴别网络。lossDiscriminator = lossReal + lossGenerated;%计算发电机网络的损耗。lossGenerator = -mean(日志(scoresGenerated));结束

参考

另请参阅

||||||

相关话题