这个例子展示了如何训练一个生成对抗网络(GAN)来生成图像。
生成对抗网络(GAN)是一种能够生成与输入真实数据具有相似特征的数据的深度学习网络。
GAN由两个相互联系的网络组成:
生成器——给定一个随机值(潜在输入)向量作为输入,这个网络生成的数据与训练数据具有相同的结构。
鉴别器 - 包含来自两个训练数据的观察,并且产生的数据从数据发生器的给定批次中,该网络试图观测为“真实的”或“产生”进行分类。
要训练甘,同时培养两个网络以最大限度地提高性能:
培养生成器生成的数据说,“傻瓜”鉴别。
训练识别器区分真实和生成的数据。
为了优化发电机的性能,给定的所生成的数据时最大限度地鉴别器的损失。也就是说,发电机的目的是生成数据鉴别归类为“真正的”。
为了优化鉴别器的性能,当给定批次的真实数据和生成数据时,将鉴别器的损失降到最低。也就是说,鉴别器的目标是不被生成器“愚弄”。
理想情况下,这些策略会产生一个生成令人信服的真实数据的生成器和一个识别器,它已经学习了训练数据所特有的强特征表示。
下载并解压缩花卉数据集[1]。
url =“http://download.tensorflow.org/example_images/flower_photos.tgz”;downloadFolder = tempdir;文件名= fullfile (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数组生成图像:
这个网络:
使用a将噪声的1×1×100数组转换为7×7×128数组项目和重塑层。
使用一系列具有批处理规范化和ReLU层的置换卷积层,将生成的阵列升级为64×64×3阵列。
将此网络体系结构定义为一个层图,并指定以下网络属性。
用于转置卷积层,指定与每个层数目减少的滤波器,2的步幅和在每个边缘上的输出的裁剪5乘5的过滤器。
对于最后的转置卷积层,指定生成图像的三个RGB通道对应的3个5×5滤波器,以及前一层的输出大小。
在网络的末端,包括一个tanh层。
要投影和重塑噪声输入,请使用自定义层projectAndReshapeLayer
,作为支持文件附加到此示例。万博1manbetx的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;
指定Adam优化的选项。对于这两个网络,请指定
的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.447 - 0.741 [0]);lineScoreDiscriminator = animatedline (scoreAxes,“颜色”,[0.85 0.325 0.098]);传说('发电机',鉴频器的);ylim([0 1])包含(“迭代”)ylabel (“分数”网格)在
训练甘。对于每个epoch,重新洗牌数据存储并循环小批数据。
对于每个小批量:
在[-1 -1]范围内重新缩放图像。
将数据转换为dlarray
具有底层类型的对象单
并指定维度标签“SSCB”
(空间,空间,渠道,批)。
生成一个dlarray
对象,该对象包含用于生成器网络的随机值数组。
对于GPU训练,将数据转换为gpuArray
对象。
使用评估模型梯度dlfeval
和modelGradients
函数。
使用。更新网络参数adamupdate
函数。
绘制两个网络的得分。
在每一个validationFrequency
迭代,显示一批生成的图像为固定的发电机输入。
跑步训练需要一些时间。
迭代= 0;开始=抽搐;循环超过epoch。对于时代= 1:numEpochs%重置和转移数据存储。重置(augimds);augimds = shuffle (augimds);对小批进行循环。而hasdata(augimds) iteration = iteration + 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。状态= stateGenerator;更新鉴别器网络参数。[dlnetDiscriminator, trailingAvgDiscriminator trailingAvgSqDiscriminator] =…adamupdate(dlnetDiscriminator,gradientsDiscriminator,…trailingAvgDiscriminator,trailingAvgSqDiscriminator,迭代,…learnRate、gradientDecayFactor squaredGradientDecayFactor);%更新生成的网络参数。[dlnetGenerator, trailingAvgGenerator trailingAvgSqGenerator] =…adamupdate (dlnetGenerator gradientsGenerator,…trailingAvgGenerator,trailingAvgSqGenerator,迭代,…learnRate、gradientDecayFactor squaredGradientDecayFactor);每个验证频率迭代,显示批量生成的图像使用%剩余发电机输入如果mod(iteration,validationFrequency) == 0 || iteration == 1%生成图像使用海出发电机输入。dlXGeneratedValidation =预测(dlnetGenerator dlZValidation);在[0 1]范围内平铺和缩放图像。我= 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”);标题(…”时代:“+划时代+", "+…“迭代:“+迭代+", "+…”经过:“+ drawnow字符串(D))结束结束
在这里,鉴别器学习了一个强大的特征表示来识别生成图像中的真实图像。反过来,生成器也学习了类似的强大特性表示,这使它能够生成逼真的数据。
训练图显示发电机和鉴别网络的分数。要了解更多关于如何解释网络的分数,看监控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
应用sigmoid函数将其转换为概率。
函数[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);对于每个网络,计算与损耗相关的梯度。gradient生成器= dlgradient(lossGenerator, dlnetGenerator.Learnables)“RetainData”,真正的);gradientsDiscriminator = dlgradient(lossDiscriminator,dlnetDiscriminator.Learnables);结束
生成器的目标是生成鉴别器分类为“真实”的数据。为了最大限度地提高鉴别器对生成的图像进行真实分类的概率,最小化负对数似然函数。
考虑到输出 鉴频器:
为输入图像属于“real”类的概率。
为输入图像属于“生成”类的概率。
注意sigmoid操作
发生在modelGradients
函数。给出了发电机的损耗函数
在哪里 包含生成图像的鉴别器输出概率。
鉴别的目的是通过发电机不被“愚弄”。为了最大限度地提高的概率鉴别的实部和生成的图像之间成功地鉴别,最小化的相应的负对数似然函数的总和。
鉴别器的损耗函数为
在哪里 包含真实图像的鉴别器输出概率。
要在0到1的范围内度量生成器和鉴别器实现各自目标的情况,可以使用分数的概念。
生成器得分是对生成的图像的鉴别器输出对应的概率的平均值:
识别器得分是真实图像和生成图像的识别器输出所对应的概率的平均值:
分数与损失成反比,但有效地包含相同的信息。
函数[lossGenerator, lossDiscriminator] = ganLoss(probReal,probGenerated)%计算鉴别器网络的损耗。-均值(log(probReal)) -均值(log(1-probGenerated);%计算损失的发电网络。lossGenerator =意味着(日志(probGenerated));结束
TensorFlow团队。花卉http://download.tensorflow.org/example_images/flower_photos.tgz
Radford, Alec, Luke Metz和Soumith Chintala。"具有深度卷积生成对抗网络的无监督表示法学习"arXiv预印本arXiv: 1511.06434(2015)。
adamupdate
|dlarray
|dlfeval
|dlgradient
|dlnetwork
|向前
|预测