这个例子展示了如何训练生成式对抗网络来生成图像。
生成的对抗性网络(GaN)是一种深度学习网络,可以生成具有与输入实际数据相似特征的数据。
GAN由两个一起训练的网络组成:
发电机 - 给定随机值的向量(潜在输入)作为输入,该网络生成具有与训练数据相同结构的数据。
鉴别者 - 给定批次包含训练数据的观察的数据,并从发电机生成数据,这个网络试图将观察分类为“真实的”
或“生成”
。
要训练甘甘,可以同时列出两个网络,以最大限度地提高两者的性能:
火车生成器生成“愚弄”鉴别者的数据。
培训鉴别器以区分实际和生成的数据。
为了优化发电机的性能,在给定的数据时最大化鉴别器的丢失。也就是说,发电机的目的是生成鉴别器分类为的数据“真实的”
。
为了优化鉴别器的性能,在给定批次的真实和生成数据时,最小化判别符的丢失。也就是说,鉴别者的目标是由发电机“被愚弄”。
理想情况下,这些策略会产生一个生成令人信服的真实数据的生成器,以及一个学习了训练数据特征的强特征表示的鉴别器。
下载并提取花朵数据集[1]。
URL =.'http://download.tensorflow.org/example_images/flower_photos.tgz';downloadfolder = tempdir;filename = fullfile(downloadFolder,'flower_dataset.tgz');imagefolder = fullfile(downloadFolder,'flower_photos');如果~存在(imageFolder'dir')disp('下载鲜花数据集(218 MB)......')Websave(Filename,URL);Untar(文件名,DownloadFolder)结尾
创建一个包含鲜花照片的图像数据存储。
datasetFolder = fullfile (imageFolder);imd = imageDatastore (datasetFolder,...'insertumbfolders',真的);
增强数据以包括随机水平翻转,并调整图像大小以具有64乘值64。
增量= imageDataAugmenter ('randxreflection',真的);Augimds = AugmentedimageDataStore([64 64],IMDS,'dataaugmentation',增强者);
定义以下网络架构,从大小100的随机向量生成图像。
这个网络:
使用a将大小100到7-ob-7-by-128阵列的随机向量转换为项目和重塑层。
使用具有批量归一化和Relu层的一系列转换卷积层将产生的数组升高到64×64×3阵列。
将此网络架构定义为一个层图,并指定以下网络属性。
对于转置的卷积层,指定5×5滤波器,每个层的过滤器数量减小,2的步幅和每个边缘上的输出裁剪。
对于最终转置卷积层,指定与生成图像的三个RGB通道对应的三个5-5-5滤波器,以及前一层的输出大小。
在网络的末端,包括一个tanh层。
要投影并重塑噪声输入,请使用自定义层ProjectAndreshapelayer.
,附加到该示例作为支持文件。万博1manbetx这ProjectAndreshapelayer.
Object使用完全连接的操作Upscales输入,并将输出重新插入指定大小。
filtersize = 5;numfilters = 64;numlattentinputs = 100;ProjectionSize = [4 4 512];tallersgenerator = [featureinputlayer(numlatentinputs,'名称'那“在”)ProjectAndreshapelayer(Projectionsize,NumlattentInputs,'名称'那'proj');transposedConv2dLayer (filterSize 4 * numFilters,'名称'那'tconv1'batchnormalizationlayer('名称'那'bnorm1')剥离('名称'那'relu1')TransposedConv2dlayer(过滤,2 * NumFilters,'走吧'2,'裁剪'那“相同”那'名称'那'tconv2'batchnormalizationlayer('名称'那'bnorm2')剥离('名称'那“relu2”) transposedConv2dLayer (filterSize numFilters,'走吧'2,'裁剪'那“相同”那'名称'那'tconv3'batchnormalizationlayer('名称'那'bnorm3')剥离('名称'那“relu3”) transposedConv2dLayer (filterSize 3'走吧'2,'裁剪'那“相同”那'名称'那'tconv4')Tanhlayer('名称'那'tanh')];Lgroggenerator = LayerGraph(层Generator);
要使用自定义训练循环训练网络并启用自动分化,将图层图转换为adlnetwork.
对象。
dlnetgenerator = dlnetwork(lgropgenerator);
定义以下网络,该网络分类真实和生成的64×64图像。
创建一个网络,它接收64 × 64 × 3的图像,并使用一系列带有批处理归一化和泄漏ReLU层的卷积层返回标量预测评分。使用dropout为输入图像添加噪声。
对于丢弃层,请指定丢弃概率为0.5。
对于卷积层,指定5 × 5滤波器,并为每个层增加滤波器的数量。还要指定步幅为2和输出的填充。
对于泄漏的Relu层,指定0.2的等级。
对于最终图层,用一个4×4滤波器指定卷积层。
要输出范围[0,1]的概率,使用sigmoid.
功能MapicalGRADENTERS.
功能,列出模型梯度函数该示例的部分。
dropoutprob = 0.5;numfilters = 64;Scale = 0.2;InputSize = [64 64 3];filtersize = 5;LayersDiscriminator = [ImageInputLayer(输入,'正常化'那'没有任何'那'名称'那“在”)DropoutLayer(DropoutProb,'名称'那'退出')卷积2dlayer(过滤,numfilters,'走吧'2,'填充'那“相同”那'名称'那'conv1')漏髓范围(秤,'名称'那'lrelu1')卷积2dlayer(过滤,2 * numfilters,'走吧'2,'填充'那“相同”那'名称'那'conv2'batchnormalizationlayer('名称'那“bn2”)漏髓范围(秤,'名称'那'lrelu2')卷积2dlayer(过滤,4 * numfilters,'走吧'2,'填充'那“相同”那'名称'那'conv3'batchnormalizationlayer('名称'那“bn3”)漏髓范围(秤,'名称'那'lrelu3')卷积2dlayer(过滤,8 * numfilters,'走吧'2,'填充'那“相同”那'名称'那“conv4”batchnormalizationlayer('名称'那“bn4”)漏髓范围(秤,'名称'那'lrelu4'1) convolution2dLayer(4日,'名称'那“conv5”)];Lgraphdiscriminator = DaterGraph(LayersDiscriminator);
要使用自定义训练循环训练网络并启用自动分化,将图层图转换为adlnetwork.
对象。
dlnetdiscriminator = dlnetwork(lgraphdiscriminator);
创建函数MapicalGRADENTERS.
,列于模型梯度函数示例的一部分,它以发电机和鉴别器网络为输入,一个迷你输入数据,随机值阵列和翻转因子,并返回到网络中的学习参数的损失梯度和两个网络的分数。
迷你批量大小为128的火车,500时代。对于较大的数据集,您可能不需要为尽可能多的时期训练。
numepochs = 500;minibatchsize = 128;
指定ADAM优化选项。对于两个网络,请指定:
学习率为0.0002
梯度衰减因子0.5
平方梯度衰减因子为0.999
学习= 0.0002;梯度Dayfactor = 0.5;squaredgradientdecayfactor = 0.999;
如果鉴别者学会过快地区分真实和生成的图像,则发电机可以无法训练。为了更好地平衡鉴别器和发电机的学习,通过随机翻转标签将噪声添加到真实数据。
指定A.Flipfactor.
值为0.3,以翻转30%的真实标签(占总标签的15%)。请注意,由于所有生成的图像仍然正确标记,这不会损害发电机。
flipfactor = 0.3;
每100次迭代显示生成的验证映像。
验证频率= 100;
采用minibatchqueue
处理和管理迷你批次的图像。对于每个迷你批处理:
使用自定义迷你批处理预处理功能Preprocessminibatch.
(在此示例结束时定义)以重新缩放范围内的图像[1]
。
丢弃任何具有少于128个观察的部分迷你批次。
使用尺寸标签格式化图像数据'SSCB'
(spatial, spatial, channel, batch)。默认情况下,minibatchqueue
对象将数据转换为dlarray.
底层类型的对象单
。
在GPU上培训如果有一个可用的。当。。。的时候'outputenvironment'
选择minibatchqueue
是“汽车”
那minibatchqueue
将每个输出转换为GPUArray.
如果有可用的GPU。使用GPU需要并行计算工具箱™和支持CUDA®的NVIDIA®GPU,其计算能力为3.0或更高。
Augimds.minibatchsize =小匹匹匹匹配;executionenvironment =“汽车”;兆贝可= minibatchqueue (augimds,...'minibatchsize',小匹马,...'partialminibatch'那'丢弃'那...“MiniBatchFcn”,@preprocessminibatch,...“MiniBatchFormat”那'SSCB'那...'outputenvironment',刽子毒环境;
使用自定义训练循环训练模型。在训练数据上循环并在每次迭代时更新网络参数。要监视培训进度,请使用已停用的随机值阵列显示一批生成的图像,以输入到发电机以及分数的曲线图。
初始化Adam的参数。
trailingAvgGenerator = [];trailingAvgSqGenerator = [];trailingAvgDiscriminator = [];trailingAvgSqDiscriminator = [];
为了监视培训进度,使用进入发电机的固定随机向量显示一批生成的图像并绘制网络分数。
创建一个保留的随机值数组。
numvalidationimages = 25;zvalidation = Randn(NumlatentInputs,NumValidationImages,'单身的');
将数据转换为dlarray.
对象并指定维标签“CB”
(频道,批量)。
dlzvalidation = dlarray(zvalidation,“CB”);
对于GPU培训,将数据转换为GPUArray.
对象。
如果(execultenvironment ==.“汽车”&& canusegpu)||executionenvironment ==.“图形”dlzvalidation = gpuarray(dlzvalidation);结尾
初始化培训进度图。创建一个数字并调整它宽度的大小。
f =图;F.Position(3)= 2 * F.Position(3);
为生成的图像和网络分数创建一个子图。
imageaxes =子图(1,2,1);scoreaxes =子图(1,2,2);
初始化Scores Plot的动画行。
lineScoreGenerator = animatedline (scoreAxes,'颜色',[0 0.447 0.741]);LineScoredIscriminator = AnimatedLine(Scoreaxes,'颜色',[0.85 0.325 0.098]);传奇('发电机'那'鉴别者');ylim([01])xlabel(“迭代”) ylabel (“分数”) 网格在
训练甘。对于每个时代,将数据存储和循环播放和循环在迷你批量数据上。
对于每个迷你批处理:
使用模型梯度评估使用dlfeval
和MapicalGRADENTERS.
函数。
使用使用的网络参数更新网络参数adamupdate.
函数。
绘制两个网络的分数。
毕竟验证频繁
迭代,显示一批生成的图像,用于固定的保持发生器输入。
培训可能需要一些时间来运行。
迭代= 0;start = tic;%循环epochs。为了时代= 1:numEpochs重置和洗牌数据存储。洗牌(MBQ);%循环在迷你批次。尽管Hasdata(MBQ)迭代=迭代+ 1;%读取迷你批次数据。DLX =下一个(MBQ);%为发电机网络生成潜在输入。转换成%dlarray并指定维标签'cb'(通道,批次)。%如果在GPU上训练,则将潜在输入转换为gpuArray。Z = randn (numLatentInputs miniBatchSize,'单身的');dlz = dlarray(z,“CB”);如果(execultenvironment ==.“汽车”&& canusegpu)||executionenvironment ==.“图形”DLZ = GPUARRAY(DLZ);结尾%使用Model梯度和发电机状态进行评估%dlfeval和easturedients函数在结束时列出% 例子。[梯度总是,梯度分子剂,术语或级别,刻痕试验器,划分脉状物] =...dlfeval(@modelgradients,dlnetgenerator,dlnetdiscriminator,dlx,dlz,flipfactor);dlnetgenerator.state = stategenerator;%更新鉴别器网络参数。[DlnetDiscriminator,trailingavgdiscriminator,trailingavgsqdiscriminator] =...Adamupdate(DLNETDISCRIMINATOR,梯度DISCRIMINATOR,...TrailIghaVGDIscriminator,Trailingavgsqdiscriminator,迭代,...学习,梯度dayfactor,squaredgradientdecayfactor);%更新生成网络参数。[DlnetGenerator,TrailingAvggenerator,TrailingAvgsqgenerator] =...adamupdate (dlnetGenerator gradientsGenerator,...Trailighavggenerator,trailighavgsqgenerator,迭代,...学习,梯度dayfactor,squaredgradientdecayfactor);%每次validationFrequency迭代,使用%保持发电机输入。如果mod(迭代,验证频率)== 0 ||迭代== 1%使用保持的发电机输入生成图像。dlxgeneratedValidation =预测(DlnetGenerator,DLZValidation);%瓷砖并重新归类范围的图像[0 1]。i = Imtile(提取数据(DLXGeneratedValidation));我= Rescale(i);%显示图像。次要情节(1、2、1);图像(imageAxes,我)xticklabels ([]);yticklabels ([]);标题(“生成的图像”);结尾%更新分数绘图。次要情节(1、2、2)addpoints (lineScoreGenerator,迭代,...双(收集(摘录(刻度))))));addpoints(LineScoredIscriminator,迭代,...双(收集(提取物)));%用培训进度信息更新标题。d =持续时间(0,0,toc(start),'格式'那'hh:mm:ss');标题(...”时代:“+ epoch +”、“+...“迭代:”+迭代+”、“+...”经过:“+字符串(d))绘制结尾结尾
这里,鉴别器已经学习了强大的特征表示,其识别生成图像之间的真实图像。反过来,发电机已经学习了类似强的特征表示,其允许它生成类似于训练数据的图像。
训练图显示了发电机和鉴别器网络的分数。了解有关如何解释网络分数的更多信息,请参阅监控GAN培训进度,识别常见故障模式。
要生成新的图像,请使用预测
函数在生成器上使用dlarray.
包含一批随机载体的对象。要将图像显示在一起,请使用inmtile.
使用函数并使用图像重新扫描图像rescale.
函数。
创建一个dlarray.
包含一批25个随机向量的对象,以输入发电机网络。
numobservations = 25;znew = randn(numlatentinputs,numobservations,'单身的');dlZNew = dlarray (ZNew,“CB”);
要使用GPU生成图像,还将数据转换为GPUArray.
对象。
如果(execultenvironment ==.“汽车”&& canusegpu)||executionenvironment ==.“图形”dlZNew = gpuArray (dlZNew);结尾
使用的新图像预测
使用发电机和输入数据。
dlxgeneratednew =预测(Dlnetgenerator,dlznew);
显示图像。
i = Imtile(提取数据(DLXGeneratedNew));我= Rescale(i);图图像(i)轴离开标题(“生成的图像”)
这个函数MapicalGRADENTERS.
作为输入发电机和鉴别器dlnetwork.
对象dlnetGenerator
和dlnetdiscriminator
,迷你批次输入数据DLX.
,一个随机值数组DLZ.
,以及翻转的真实标签的百分比Flipfactor.
,并返回关于网络中的学习参数,发电机状态和两个网络的分数的丢失渐变。因为鉴别器输出不在范围内[0,1],所以MapicalGRADENTERS.
函数应用Sigmoid函数将其转换为概率。
功能[梯度总是,梯度分子剂,术语或级别,刻痕试验器,划分脉状物] =...ModelGRADENTERS(DLNETGENERATOR,DLNETDISCRIMINATOR,DLX,DLZ,FLIPFORTOR)%计算使用鉴别器网络的实际数据的预测。dlypry =前进(DlnetDiscriminator,DLX);%计算具有鉴别器网络的生成数据的预测。[dlxgenerated,stategenerator] =向前(DlnetGenerator,DLZ);dlypredgenerated =前进(dlnetdiscriminator,dlxgenerated);%将鉴别器输出转换为概率。probgenerated = sigmoid(dlypredgenerated);probreal = sigmoid(dlypred);%计算鉴别器的得分。scoreDiscriminator = (mean(probReal) + mean(1-probGenerated)) / 2;%计算生成器的得分。刻录物=平均值(probgenerated);%随机翻转真实图像的标签的一部分。numObservations =大小(probReal 4);idx = randperm(numObservations,floor(flipFactor * numObservations));%翻转标签。probreal(::::,idx)= 1 - probreal(::::,IDX);%计算GaN丢失。[损失Generator] = Ganloss(Probreal,Probgenerated);%对于每个网络,计算相对于损失的梯度。gradientsGenerator = dlgradient(lossGenerator, dlnetGenerator。可学的,'etaindata',真的);梯度Discriminator = Dlgradient(LockDiscriminator,DLNetDiscriminator.Learnables);结尾
发电机的目的是生成鉴别器分类为的数据“真实的”
。为了最大化发电机的图像被鉴别器分类的概率,最小化负对数似函数。
鉴于输出 判别者:
输入图像属于类的概率是概率“真实的”
。
输入图像属于类的概率是概率“生成”
。
请注意,SIGMOID操作
发生在MapicalGRADENTERS.
函数。发电机的损耗函数为
在哪里 包含生成的图像的鉴别器输出概率。
判别者的目标是由发电机“被愚弄”。为了最大化鉴别器在真实和生成的图像之间成功区分的概率,最小化相应的负对数似章的总和。
给出了该鉴别器的损失函数
在哪里 包含真实图像的鉴别器输出概率。
从0到1尺度测量发电机和鉴别者如何实现各自的目标,您可以使用分数的概念。
发电机分数是与生成的图像的鉴别器输出对应的概率的平均值:
鉴别器分数是与真实和生成的图像的鉴别器输出对应的概率的平均值:
分数与损失成反比,但有效地包含相同的信息。
功能[损失Generator,损失Discriminator] = Ganloss(Probreal,Probenerated)%计算鉴别器网络的损耗。lossDiscriminator = -mean(log(probReal)) -mean(log(1-probGenerated));%计算发电机网络的损耗。损失generator = -mean(log(probgenerated));结尾
这Preprocessminibatch.
函数使用以下步骤预处理数据:
从传入单元格数组中提取图像数据并将其连接到数字阵列中。
重新归类图像在范围内[1]
。
功能x = preprocessminibatch(数据)%contenate mini-batchX =猫(4、数据{:});%重新归类范围[-1 1]中的图像。x = Rescale(x,-1,1,'Inputmin',0,'inputmax',255);结尾
TensorFlow团队。花朵http://download.tensorflow.org/example_images/flower_photos.tgz
Radford,Alec,Luke Metz和Soumith Chintala。“用深卷积生成的对抗网络进行无监督的代表学习。”预印刷品,2015年11月19日提交。http://arxiv.org/abs/1511.06434。
adamupdate.
|dlarray.
|dlfeval
|Dlgradient.
|dlnetwork.
|向前
|minibatchqueue
|预测