这个例子展示了如何训练一个生成式对抗网络(GAN)来生成图像。
甲生成对抗网络(GAN)是一种类型的深度学习网络,可以产生具有类似特性的作为输入的实际数据的数据。
GAN由两个相互联系的网络组成:
发电机 - 给定的随机值(潜输入)作为输入的一矢量,该网络具有相同的结构作为训练数据来生成数据。
鉴别器 - 包含来自两个训练数据的观察,并且产生的数据从数据发生器的给定批次中,该网络试图观测为“真实的”或“产生”进行分类。
要训练甘,同时培养两个网络以最大限度地提高性能:
培养生成器生成的数据说,“傻瓜”鉴别。
训练鉴别真实和产生的数据之间进行区分。
为了优化发电机的性能,给定的所生成的数据时最大限度地鉴别器的损失。也就是说,发电机的目的是生成数据鉴别归类为“真正的”。
为了优化鉴别器的性能,给定的实际和产生的数据的批次时,最小化所述鉴相器的损耗。也就是说,鉴别的目的是为了不“上当”由发电机。
理想情况下,这些策略会产生一个生成令人信服的真实数据的生成器和一个已经学习了训练数据特征的强特征表示的鉴别器。
下载及解压花卉数据集[1]。
url ='http://download.tensorflow.org/example_images/flower_photos.tgz';downloadFolder = TEMPDIR;文件名=完整文件(downloadFolder,'flower_dataset.tgz');imageFolder = fullfile (downloadFolder,“flower_photos”);如果~存在(imageFolder“dir”)DISP(下载花卉数据集(218mb)…)websave(文件名,URL);解压缩(文件名,downloadFolder)结束
创建一个包含花的照片的图像数据存储。
datasetFolder = fullfile (imageFolder);imd = imageDatastore (datasetFolder,…'IncludeSubfolders',真正的);
增加数据以包含随机的水平翻转,并将图像大小调整为64 * 64。
增量= imageDataAugmenter ('RandXReflection',真正的);的翻译是:augimds = augmentedImageDatastore([64 64],imds,'DataAugmentation'、增压器);
定义以下网络架构,它从随机值的1×1×100数组生成图像:
这个网络:
噪声的1 * 1 * 100阵列转换为使用7×7×128阵列项目和重塑层。
使用具有批处理标准化和ReLU层的一系列置换卷积层,将得到的阵列升级为64×64×3的阵列。
将此网络体系结构定义为一个层图,并指定以下网络属性。
用于转置卷积层,指定与每个层数目减少的滤波器,2的步幅和在每个边缘上的输出的裁剪5乘5的过滤器。
对于最后的转置卷积层,指定三个5×5的滤波器分别对应生成图像的三个RGB通道,以及前一层的输出大小。
在网络的末端,包括一个tanh层。
项目和重塑噪声输入,使用自定义层projectAndReshapeLayer
,作为支持文件附加到此示例。金宝app的projectAndReshapeLayer
层upscales使用完全连接操作的输入和重塑输出到指定的大小。
filterSize = 5;numFilters = 64;numLatentInputs = 100;projectionSize = [4 4 512];layersGenerator = [imageInputLayer([1 1 numlatentinput]),“归一化”,'没有','名称',“在”)projectAndReshapeLayer(projectionSize,numLatentInputs,'PROJ');transposedConv2dLayer (filterSize 4 * numFilters,'名称','tconv1')batchNormalizationLayer ('名称',“bnorm1”)reluLayer('名称',“relu1”)transposedConv2dLayer (2 * numFilters filterSize,“跨越论”2,“种植”,'相同','名称','tconv2')batchNormalizationLayer ('名称',“bnorm2”)reluLayer('名称',“relu2”)transposedConv2dLayer (filterSize numFilters,“跨越论”2,“种植”,'相同','名称','tconv3')batchNormalizationLayer ('名称',“bnorm3”)reluLayer('名称',“relu3”)transposedConv2dLayer(filterSize,3,“跨越论”2,“种植”,'相同','名称',“tconv4”)tanhLayer ('名称',“正切”));lgraphGenerator = layerGraph (layersGenerator);
用一个定制的训练循环训练网络并启用自动分化,该层图形转换成dlnetwork
宾语。
dlnetGenerator = dlnetwork (lgraphGenerator);
定义以下网络,它对真实的和生成的64×64图像进行分类。
创建一个获取64×64×3图像的网络,并使用具有批处理标准化和泄漏ReLU层的一系列卷积层返回标量预测分数。使用dropout向输入图像添加噪声。
对于漏失层,指定0.5的差的概率。
对于卷积层,指定5×5的过滤器,并为每个层指定越来越多的过滤器。还可以指定步长为2和输出的填充。
对于漏气的ReLU层,指定0.2的刻度。
对于最后的层,与一个4乘4滤波器指定的卷积层。
若要输出[0,1]范围内的概率,请使用乙状结肠
功能型号渐变功能。
dropoutProb = 0.5;numFilters = 64;标度= 0.2;inputSize = [64 64 3];filterSize = 5;layersDiscriminator = [imageInputLayer(inputSize,“归一化”,'没有','名称',“在”)dropoutLayer (0.5,'名称',“辍学”)convolution2dLayer (filterSize numFilters,“跨越论”2,“填充”,'相同','名称','CONV1')leakyReluLayer(规模,'名称',“lrelu1”)convolution2dLayer (2 * numFilters filterSize,“跨越论”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”1)convolution2dLayer(4日,'名称',“conv5”));lgraphDiscriminator = layerGraph (layersDiscriminator);
用一个定制的训练循环训练网络并启用自动分化,该层图形转换成dlnetwork
宾语。
dlnetDiscriminator = dlnetwork(lgraphDiscriminator);
创建函数modelGradients
,在上市型号渐变功能该部分以一个小批量的输入数据、一个随机值数组和一个翻转因子作为输入生成器和鉴别器网络,并返回网络中可学习参数的损失梯度和两个网络的得分。
列车与128 500个历元迷你批量大小。还设置了增强的图像数据存储到小批量的读取大小。对于更大的数据集,您可能不需要为培养尽可能多的时期。
numEpochs = 500;miniBatchSize = 128;augimds.MiniBatchSize = miniBatchSize;
指定亚当优化的选项。对于这两种网络,指定
的0.0002学习率
梯度衰减系数为0.5
的0.999甲平方梯度衰减因子
learnRate = 0.0002;gradientDecayFactor = 0.5;squaredGradientDecayFactor = 0.999;
在GPU上训练(如果有的话)。使用GPU需要并行计算工具箱™和CUDA®启用NVIDIA®GPU计算能力3.0或更高。
执行环境=“汽车”;
如果鉴别器学习区分真实图像和生成图像的速度过快,那么生成器可能无法训练。为了更好地平衡鉴别器和生成器的学习,通过随机翻转标签来给真实数据添加噪声。
指定翻转30%的真实标签。这意味着总标签数量的15%将被翻转。注意,这并不损害生成器,因为所有生成的图像仍然被正确地标记。
flipFactor = 0.3;
显示所生成的验证图像每100次迭代。
validationFrequency = 100;
培养使用自定义的训练循环模型。遍历所有的训练数据,并更新在每次迭代的网络参数。为了监测训练进度,显示使用随机值,以输入的持有出阵列的批量生成的图像到发电机以及分数的曲线图。
为Adam初始化参数。
trailingAvgGenerator = [];trailingAvgSqGenerator = [];trailingAvgDiscriminator = [];trailingAvgSqDiscriminator = [];
为了监控训练进度,使用持有出分批送入发生器随机值的固定阵列的显示批量生成的图像并绘制网络分数。
创建一个保留的随机值数组。
numValidationImages = 25;ZValidation = randn (1, 1, numLatentInputs numValidationImages,“单一”);
将数据转换为dlarray
对象,并指定尺寸的标签“SSCB”
(空间,空间,渠道,批)。
dlZValidation = dlarray(ZValidation,“SSCB”);
对于GPU训练,将数据转换成gpuArray
对象。
如果(executionEnvironment = =“汽车”&& canUseGPU)||执行环境==“图形”dlZValidation = gpuArray(dlZValidation);结束
初始化训练进度图。创建一个图形,并将其大小调整为宽度的两倍。
F =图。f.Position(3)= 2 * f.Position(3);
为生成的图像和newtork分数创建子图。
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(“分数”网格)上
训练GAN。对于每一个时代,洗牌对数据的小批量数据存储和循环。
对于每个小批量:
在[-1]范围内重新缩放图像。
将数据转换为dlarray
有基础对象类型单
并指定尺寸的标签“SSCB”
(空间,空间,渠道,批)。
生成dlarray
对象,该对象包含生成器网络的随机值数组。
对于GPU训练,将数据转换成gpuArray
对象。
评估使用模型梯度dlfeval
和modelGradients
函数。
更新使用的网络参数adamupdate
函数。
画出两个网络的分数。
在每一个validationFrequency
迭代,显示一批生成的图像为固定的发电机输入。
跑步训练需要一些时间。
迭代= 0;开始=抽搐;循环超过epoch。对于时代= 1:numEpochs%重置和转移数据存储。重置(augimds);augimds = shuffle (augimds);对小批量进行循环。而hasdata(augimds)迭代=迭代+ 1;读取小批数据。数据=读(augimds);忽略历元的上一个部分小批。如果(数据,1)< miniBatchSize大小继续结束数据的%串连小批量和产生对于潜在输入%发电机网络。X =猫(4、数据{:1}{:});X =单(X);Z = randn (1, - 1, numLatentInputs大小(X, 4),“单一”);在[-1]范围内重新缩放图像。X =重新调整(X,-1,1,“InputMin”0,'InputMax',255);将小批量数据转换为dlarray并指定尺寸标签% 'SSCB'(空间,空间,渠道,批)。DLX = dlarray(X,“SSCB”);DLZ = dlarray(Z,“SSCB”);%如果在GPU上训练,则将数据转换为gpuArray。如果(executionEnvironment = =“汽车”&& canUseGPU)||执行环境==“图形”dlX = gpuArray (dlX);dlZ = gpuArray (dlZ);结束%评估模型梯度和发电机状态使用%dlfeval和modelGradients功能在的末尾列出%的例子。[gradientsGenerator,gradientsDiscriminator,stateGenerator,scoreGenerator,scoreDiscriminator] =…dlfeval(@modelGradients,dlnetGenerator,dlnetDiscriminator,DLX,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%生成图像使用helout发电机输入。dlXGeneratedValidation =预测(dlnetGenerator dlZValidation);%瓷砖和重新缩放图像在范围[0 1]。I = imtile(ExtractData由(dlXGeneratedValidation));I =重新调节(我);%显示图像。次要情节(1、2、1);图像(imageAxes,我)xticklabels ([]);yticklabels ([]);标题(“生成的图像”);结束%更新的得分图次要情节(1、2、2)addpoints (lineScoreGenerator,迭代,…双(收集(extractdata (scoreGenerator))));addpoints (lineScoreDiscriminator迭代,…双(收集(extractdata (scoreDiscriminator))));用培训进度信息更新标题。d =持续时间(0,0,TOC(开始),“格式”,“hh: mm: ss”);标题(…”时代:“+划时代+“”+…“迭代:“+迭代+“”+…”经过:“+串(d))的DrawNow结束结束
在这里,鉴别了解到,标识生成的图像中实时图像的强大的功能表现。反过来,发电机学到了同样强大的功能表现,它允许它来生成逼真的数据。
训练图显示发电机和鉴别网络的分数。要了解更多关于如何解释网络的分数,看监控GAN的培训进度,识别常见的故障模式。
若要生成新图像,请使用预测
在具有发电机功能dlarray
对象包含一批1 * 1 * 100阵列的随机值。要显示的图像一起,使用imtile
使用功能和重新调整图像重新调节
函数。
创建一个dlarray
含有一批25 1 * 1 * 100阵列的随机值的输入到发电机网络对象。
ZNew = randn (1, 1, numLatentInputs, 25岁,“单一”);dlZNew = dlarray (ZNew,“SSCB”);
要生成使用GPU的图像,也转换数据gpuArray
对象。
如果(executionEnvironment = =“汽车”&& canUseGPU)||执行环境==“图形”dlZNew = gpuArray (dlZNew);结束
生成使用新的图像预测
函数与发电机和输入数据。
dlXGeneratedNew =预测(dlnetGenerator,dlZNew);
显示图像。
我= imtile (extractdata (dlXGeneratedNew));I =重新调节(我);数字图像(I)轴离标题(“生成的图像”)
功能modelGradients
作为输入的发电机和鉴别dlnetwork
对象dlnetGenerator
和dlnetDiscriminator
,一个小批输入数据DLX
,随机值的阵列DLZ
以及要翻转的实际标签的百分比flipFactor,
并返回损失的梯度相对于在网络中可学习参数,发电机状态,以及两个网络的分数。因为鉴别器输出不是在范围[0,1],modelGradients
应用双曲线函数将其转换成概率。
功能[gradientsGenerator,gradientsDiscriminator,stateGenerator,scoreGenerator,scoreDiscriminator] =…模型梯度(dlnetGenerator, dlnetDiscriminator, dlX, dlZ, flipFactor)%计算的预测与鉴别网络真实数据。dlYPred =正向(dlnetDiscriminator,DLX);%使用鉴别器网络计算生成数据的预测。[dlXGenerated,stateGenerator] =向前(dlnetGenerator,DLZ);dlYPredGenerated =正向(dlnetDiscriminator,dlXGenerated);将鉴别器输出转换为概率。probGenerated =乙状结肠(dlYPredGenerated);probReal =乙状结肠(dlYPred);计算鉴别器的分数。scoreDiscriminator =((平均(probReal)+平均(1-probGenerated))/ 2);计算生成器的分数。scoreGenerator =意味着(probGenerated);随机%翻转真实图像的标签的一小部分。numObservations =大小(probReal 4);idx = randperm(numObservations,floor(flipFactor * numObservations));%翻页标签probReal (:,:,:, idx) = 1-probReal (:,:,:, idx);%计算氮化镓损耗。[lossGenerator,lossDiscriminator] = ganLoss(probReal,probGenerated);对于每个网络,计算相对于损耗的梯度。= dlgradient(lossGenerator, dlnetGenerator.Learnables)“RetainData”,真正的);gradientsDiscriminator = dlgradient(lossDiscriminator,dlnetDiscriminator.Learnables);结束
发电机的目的是生成数据鉴别归类为“真正的”。为了最大限度地从发电机图像被鉴别归类为真正的概率,尽量减少负面数似然函数。
鉴于输出 鉴频器:
为输入图像属于“实数”类的概率。
是输入图像属于“而生成”之类的概率。
需要注意的是乙状结肠操作
发生在modelGradients
函数。给出了发电机的损耗函数
在哪里 包含生成图像的鉴别器输出概率。
鉴别的目的是通过发电机不被“愚弄”。为了最大限度地提高的概率鉴别的实部和生成的图像之间成功地鉴别,最小化的相应的负对数似然函数的总和。
用于鉴别的损失函数为
在哪里 包含真实图像的鉴别器输出概率。
要在0到1的范围内度量生成器和鉴别器实现各自目标的情况,可以使用分数的概念。
生成器得分是所生成图像的鉴别器输出对应的概率的平均值:
识别器得分是真实图像和生成图像的识别器输出对应的概率的平均值:
比分是成反比的损失,但有效地包含了相同的信息。
功能[lossGenerator,lossDiscriminator] = ganLoss(probReal,probGenerated)%计算的亏损为鉴别网络。-均值(log(probReal)) -均值(log(1-probGenerated);%计算损失的发电网络。lossGenerator = -mean(日志(probGenerated));结束
该TensorFlow团队。花卉http://download.tensorflow.org/example_images/flower_photos.tgz
雷德福,亚历克,卢克梅斯和Soumith Chintala。“无监督表示深切卷积生成对抗性的网络学习。”arXiv预印本arXiv: 1511.06434(2015)。
adamupdate
|dlarray
|dlfeval
|dlgradient
|dlnetwork
|向前
|预测