このページの翻訳は最新ではありません。ここをクリックして,英語の最新版を参照してください。
この例では,あるイメージのスタイルを転送して第2のイメージにするネットワークの学習方法を示します。これは,[1]で定義されるアーキテクチャに基づいています。
この例は深層学習を使用したニューラルスタイル転送に似ていますが,スタイルイメージ年代でネットワークに学習させることで,より高速に動作します。入力イメージXをネットワークにフォワードパスしさえすれば,スタイル化されたイメージYを取得できるからです。
学習アルゴリズムの大まかなブロック線図は下のようになります。ここでは,入力イメージX,変換後のイメージY,スタイルイメージ年代という3つのイメージを使用して,損失を計算します。
損失関数は,事前学習済みのネットワークVGG-16を使用してイメージから特徴を抽出することに注意してください。その実装および数学的定義は,この例のスタイル転送損失の節で確認できます。
[2014火车图片]をクリックし,http://cocodataset.org/#download2014年から可可の学習イメージとキャプションをダウンロードして解凍します。imageFolder
で指定したフォルダーにデータを保存します。イメージをimageFolder
に解凍します。COCO 2014 は可可财团によって収集されたものです。
可可データセットを格納するディレクトリを作成します。
imageFolder = fullfile (tempdir,“可可”);如果~存在(imageFolder“dir”mkdir (imageFolder);结束
可可イメージを含むイメージデータストアを作成します。
imd = imageDatastore (imageFolder,“IncludeSubfolders”,真正的);
学習の実行には時間がかかることがあります。結果として得られるネットワークの精度を犠牲にして学習時間を短縮する場合は,分数
を小さな値に設定することにより,イメージデータストアのサブセットを選択します。
分数= 1;numObservations =元素个数(imds.Files);imd =子集(imd, 1:地板(numObservations *分数);
イメージのサイズを変更して,それらすべてをRGBに変換するには,拡張イメージデータストアを作成します。
augimds = augmentedImageDatastore([256 256],imds,“ColorPreprocessing”,“gray2rgb”);
スタイルイメージを読み取ります。
styleImage = imread (“starryNight.jpg”);style = imresize(styleImage,[256 256]);
選択したスタイルイメージを表示します。
图imshow (styleImage)标题(“风格形象”)
イメージ変換ネットワークを定義します。これはimage-to-imageネットワークです。このネットワークは,次の3つの部分で構成されます。
ネットワークの1番目の部分は,サイズ[256 x 256 x 3]のRGBイメージを入力として受け取り,それをサイズ(64 x 64 x 128)の特徴マップにダウンサンプリングします。
ネットワークの2番目の部分は,サポート関数residualBlock。
で定義された5つの同じ残差ブロックで構成されます。
ネットワークの3番目の部分は,特徴マップを元のサイズのイメージにアップサンプリングし,変換後のイメージを返します。この最後の部分ではupsampleLayer
を使用します。これは,この例にサポートファイルとして添付されているカスタム層です。
层= [%第一部分。imageInputLayer ([256 256 3),“名字”,“输入”,“归一化”,“没有”[9 9], 32,“填充”,“相同”,“名字”,“conv1”) groupNormalizationLayer (“channel-wise”,“名字”,“norm1”) reluLayer (“名字”,“relu1”卷积2dlayer ([3 3], 64,“步”2,“填充”,“相同”,“名字”,“conv2”) groupNormalizationLayer (“channel-wise”,“名字”,“norm2”) reluLayer (“名字”,“relu2”)卷积2dlayer ([3 3], 128,“步”2,“填充”,“相同”,“名字”,“conv3”) groupNormalizationLayer (“channel-wise”,“名字”,“norm3”) reluLayer (“名字”,“relu3”)%第二部分。residualBlock (“1”) residualBlock (“2”) residualBlock (“3”) residualBlock (“4”) residualBlock (“5”)%第三部分。upsampleLayer (“up1”卷积2dlayer ([3 3], 64,“步”, 1“填充”,“相同”,“名字”,“upconv1”) groupNormalizationLayer (“channel-wise”,“名字”,“norm6”) reluLayer (“名字”,“relu5”) upsampleLayer (“呼吁”)卷积2dlayer ([3 3], 32,“步”, 1“填充”,“相同”,“名字”,“upconv2”) groupNormalizationLayer (“channel-wise”,“名字”,“norm7”) reluLayer (“名字”,“relu6”3) convolution2dLayer(9日,“填充”,“相同”,“名字”,“conv_out”));lgraph = layerGraph(层);
残差ブロック内で欠損結合を追加します。
lgraph = connectLayers (lgraph,“relu3”,“add1 / in2”);lgraph = connectLayers (lgraph,“add1”,“add2 / in2”);lgraph = connectLayers (lgraph,“add2”,“add3 / in2”);lgraph = connectLayers (lgraph,“add3”,“add4 / in2”);lgraph = connectLayers (lgraph,“add4”,“折扣/ in2”);
イメージ変換ネットワークをプロットで可視化します。
图绘制(lgraph)标题(“变换网络”)
層グラフからdlnetwork
オブジェクトを作成します。
dlnetTransform = dlnetwork (lgraph);
この例では,事前学習済みのVGG-16深層ニューラルネットワークを使用して,コンテンツイメージとスタイルイメージの特徴をさまざまな層で抽出します。この多層にわたる特徴は,コンテンツとスタイルの損失を計算するのに使用されます。
事前学習済みのVGG-16ネットワークを取得するには,関数vgg16
を使用します。必要なサポートパッケージがインストールされていない場合,ダウンロード用リンクが表示されます。
netLoss = vgg16;
損失の計算に不可欠な特徴を抽出するために必要となるのは,最初の24個の層のみです。抽出し,層グラフに変換します。
lossLayers = netLoss.Layers(桥);lgraph = layerGraph (lossLayers);
dlnetwork
に変換します。
dlnetLoss = dlnetwork (lgraph);
この例のスタイル転送損失の節で定義する関数styleTransferLoss
を作成します。
関数styleTransferLoss
は,損失ネットワークdlnetLoss
,変換後の入力イメージdlX,
のミニバッチ,変換後のイメージ海底
のミニバッチ,スタイルイメージのグラム行列を含む配列dlSGram
,コンテンツ損失に関連する重みcontentWeight
,スタイル損失に関連する重みstyleWeight
を入力として受け取ります。この関数は,合計損失损失
と,個々のコンポーネントであるコンテンツ損失lossContent
およびスタイル損失lossStyle。
を返します。
関数styleTransferLoss
は,スタイル損失の計算において,サポート関数createGramMatrix
を使用します。
関数createGramMatrix
は,損失ネットワークによって抽出された特徴を入力として受け取り,ミニバッチ内の各イメージについてスタイル表現を返します。グラム行列の実装および数学的定義は,グラム行列の節で確認できます。
この例のモデル勾配関数の節にリストされている関数modelGradients
を作成します。この関数は,損失ネットワークdlnetLoss
,イメージ変換ネットワークdlnetTransform
,入力イメージdlX
のミニバッチ,スタイルイメージのグラム行列を含む配列dlSGram
,コンテンツ損失に関連する重みcontentWeight
,スタイル損失に関連する重みstyleWeight
を入力として受け取ります。この関数は,イメージ変換の学習可能なパラメーターについての損失の梯度
,イメージ変換ネットワークの状態,変換後のイメージ海底,
、合計損失损失
,コンテンツに関連する損失lossContent
,スタイルに関連する損失lossStyle。
を返します。
[1]と同様に,ミニバッチサイズを4として,学習を2エポック行います。
numEpochs = 2;miniBatchSize = 4;
拡張イメージデータストアの読み取りサイズをミニバッチのサイズに設定します。
augimds。MiniBatchSize = MiniBatchSize;
亚当最適化のオプションを指定します。学習率は0.001に勾配の減衰係数は0.01に2乗勾配の減衰係数は0.999に指定します。
learnRate = 0.001;gradientDecayFactor = 0.9;squaredGradientDecayFactor = 0.999;
GPUが利用できる場合,GPUで学習を行います。GPU を使用するには、Parallel Computing Toolbox™ とサポートされている GPU デバイスが必要です。サポートされているデバイスについては、リリース別のGPUサポート(并行计算工具箱)を参照してください。
executionEnvironment =“汽车”;
合計損失の計算において,スタイル損失に設定する重みとコンテンツ損失に設定する重みを指定します。
コンテンツ損失とスタイル損失のちょうど良いバランスを見つけるには,異なる重みの組み合わせを使った実験が必要になる場合もあることに注意してください。
weightContent = 1的军医;weightStyle = 3 e-8;
学習の進捗状況のプロット周波数を選択します。これにより,プロットの更新間隔における反復回数を指定します。
plotFrequency = 10;
学習中に損失を計算できるようにするには,スタールイメージのグラム行列を計算します。
スタイルイメージをdlarray
に変換します。
dlS = dlarray(单(styleImage),SSC的);
グラム行列を計算するには,スタイルイメージをVGG-16ネットワークに供給し,4つの異なる層で活性化を抽出します。
[dlSActivations1, dlSActivations2 dlSActivations3 dlSActivations4] =前进(dlnetLoss dlS,...“输出”,[“relu1_2”“relu2_2”“relu3_3”“relu4_3”]);
サポート関数createGramMatrix
を使用して,活性化の各セットについてグラム行列を計算します。
dlSGram {1} = createGramMatrix (dlSActivations1);dlSGram {2} = createGramMatrix (dlSActivations2);dlSGram {3} = createGramMatrix (dlSActivations3);dlSGram {4} = createGramMatrix (dlSActivations4);
学習プロットは次の2つの图で構成されます。
学習中の損失のプロットを示す图
イメージ変換ネットワークの入力イメージおよび出力イメージを含む图
学習プロットを初期化します。サポート関数initializeFigures。
における初期化の詳細をチェックできます。この関数が返すのは,損失をプロットしたときの軸ax₁
,検証イメージをプロットしたときの軸ax2
,コンテンツ損失を含むアニメーション化された線lineLossContent
,スタイル損失を含むアニメーション化された線lineLossStyle
,合計損失を含むアニメーション化された線lineLossTotal
です。
(ax₁,ax2 lineLossContent、lineLossStyle lineLossTotal] = initializeStyleTransferPlots ();
亚当オプティマイザーの平均勾配および平均2乗勾配のハイパーパラメーターを初期化します。
averageGrad = [];averageSqGrad = [];
学習の合計反復回数を計算します。
numIterations =地板(augimds.NumObservations * numEpochs / miniBatchSize);
学習前に反復回数およびタイマーを初期化します。
迭代= 0;开始=抽搐;
モデルに学習させます。実行には時間がかかることがあります。
%循环纪元。为我= 1:numEpochs重置和洗牌数据存储。重置(augimds);augimds = shuffle (augimds);%循环小批。而Hasdata (augimds) iteration = iteration + 1;%读取小批数据。data =阅读(augimds);%忽略epoch的最后一部分小批。如果(数据,1)< miniBatchSize大小继续结束%从数据存储中提取图像到单元格数组中。数据图像= {:1};沿着第四维度连接图像。X =猫(4、图像{:});X =单(X);%将小批数据转换为dlarray并指定尺寸标签% 'SSCB'(空间、空间、通道、批处理)。dlX = dlarray (X,“SSCB”);%如果在GPU上训练,则将数据转换为gpuArray。如果(executionEnvironment = =“汽车”&& canUseGPU) || executionEnvironment ==“图形”dlX = gpuArray (dlX);结束%评估模型梯度和网络状态使用的% dlfeval和模型梯度函数%的例子。(梯度、州、海底、失去、lossContent lossStyle] = dlfeval (@modelGradients,...dlnetLoss、dlnetTransform dlX、dlSGram weightContent, weightStyle);dlnetTransform。=状态;%更新网络参数。[dlnetTransform, averageGrad averageSqGrad] =...adamupdate (dlnetTransform、渐变averageGrad averageSqGrad,迭代,...learnRate、gradientDecayFactor squaredGradientDecayFactor);%每一次plotfrequency迭代,绘制训练进度。如果mod(iteration,plotFrequency) == 0 addpoints(lineLossTotal,iteration,double(gather(extractdata(loss)))) addpoints(lineLossContent,iteration,double(gather(extractdata(lossStyle))))))%使用迷你批处理的第一个映像作为验证映像。dlV = dlX (:,:,: 1);%使用先前计算的转换后的验证图像。dlVY =海底(:,:,:1);%使用函数imshow,转换为uint8。validationImage = uint8(收集(extractdata (dlV)));transformedValidationImage = uint8(收集(extractdata (dlVY)));%绘制输入图像和输出图像,并增加大小imshow (imtile ({validationImage, transformedValidationImage}),“父”, ax2);结束%显示训练开始后经过的时间和训练完成的百分比。D =持续时间(0,0,toc(开始),“格式”,“hh: mm: ss”);completionPercentage =圆(迭代/ numIterations * 100, 2);标题(ax₁,”时代:“+我+”,迭代:“+迭代+“的”+ numIterations +”(“+ completionPercentage +“%)”+”,过去:“+ drawnow字符串(D))结束结束
学習が終了すれば,選択したイメージに対してイメージ変換を使用できます。
変換するイメージを読み込みます。
imFilename =“peppers.png”;我= imread (imFilename);
入力イメージのサイズをイメージ変換の入力の次元に変更します。
[256256] im = imresize (im);
それをdlarray。
に変換します。
dlX = dlarray(单(im),“SSCB”);
利用可能な場合にGPUを使用するには,gpuArray
に変換します。
如果canUseGPU dlX = gpuArray(dlX);结束
スタイルをイメージに適用するには,関数预测。
を使用してイメージ変換にフォワードパスします。
海底=预测(dlnetTransform dlX);
イメージを範囲[0 255]に再スケーリングします。まず,関数双曲正切
を使用して,海底
を範囲[1]に再スケーリングします。次に,出力をシフトおよびスケーリングして,255年[0]の範囲に再スケーリングします。
Y = 255 *(双曲正切(海底)+ 1)/ 2;
プロット用にY
を準備します。関数extraxtdata
を使用してdlarray。
からデータを抽出します。関数gather を使用して、Y を GPU からローカル ワークスペースに転送します。
Y = uint8(收集(extractdata (Y)));
入力イメージ(左)をスタイル化されたイメージ(右)の隣に表示します。
图m = imtile({im,Y});imshow (m)
関数modelGradients
は,損失ネットワークdlnetLoss
,イメージ変換ネットワークdlnetTransform
,入力イメージdlX
のミニバッチ,スタイルイメージのグラム行列を含む配列dlSGram
,コンテンツ損失に関連する重みcontentWeight
,スタイル損失に関連する重みstyleWeight
を入力として受け取ります。また,イメージ変換の学習可能なパラメーターについての損失の梯度
,イメージ変換ネットワークの状態,変換後のイメージ海底
、合計損失损失
,コンテンツに関連する損失lossContent
,スタイルに関連する損失lossStyle。
を返します。
函数(梯度、州、海底、失去、lossContent lossStyle] =...modelGradients(dlnetLoss,dlnetTransform,dlX, dlgram,contentWeight,styleWeight) [dlY,state] = forward(dlnetTransform,dlX);海底= 255 *(双曲正切(海底)+ 1)/ 2;[损失,lossContent, lossStyle] = styleTransferLoss (dlnetLoss,海底,dlX dlSGram, contentWeight, styleWeight);梯度= dlgradient(损失、dlnetTransform.Learnables);结束
関数styleTransferLoss
は,損失ネットワークdlnetLoss
,入力イメージdlX,
のミニバッチ,変換後のイメージ海底
のミニバッチ,スタイルイメージのグラム行列を含む配列dlSGram
,コンテンツとスタイルに関連するそれぞれの重みcontentWeight
およびstyleWeight,
を入力として受け取ります。また,合計損失损失
と,個々のコンポーネントであるコンテンツ損失lossContent
およびスタイル損失lossStyle。
を返します。
コンテンツ損失は,入力イメージX
と出力イメージY
の間における空間構造体の差異がどの程度かを示す測定値です。
一方,スタイル損失は,スタイルイメージ年代
と出力イメージY
の間におけるスタイル外観の差異がどの程度かを示します。
以下のグラフは,styleTransferLoss
が合計損失を計算するために実装するアルゴリズムを説明しています。
まず,この関数は入力イメージX
,変換後のイメージY
,スタイルイメージ年代
を事前学習済みのネットワークVGG-16に渡します。この事前学習済みのネットワークは,これらのイメージからいくつかの特徴を抽出します。その後,アルゴリズムは,入力イメージXと出力イメージYの空間的な特徴を使用して,コンテンツ損失を計算します。さらに,出力イメージYとスタイルイメージ年代のスタイルの特徴を使用して,スタイル損失を計算します。最後に,コンテンツ損失とスタイル損失を加算して,合計損失を求めます。
ミニバッチ内の各イメージについて,コンテンツ損失関数は,元のイメージの特徴と,層relu_3_3
によって出力された変換後のイメージの特徴を比較します。具体的には,次のように,活性化間の平均二乗誤差を計算して,ミニバッチの平均損失を返します。
ここで,
は入力イメージを格納し,
は変換後のイメージを格納し,
はミニバッチサイズであり,
は層relu_3_3。
で抽出された活性化を表します。
スタイル損失を計算するには,ミニバッチに含まれる単一のイメージのそれぞれに対して,次を行います。
層relu1_2
、relu2_2
、relu3_3
、relu4_3
で活性化を抽出します。
4つの活性化 のそれぞれについて,グラム行列 を計算します。
対応するグラム行列間の二乗差を計算します。
前の手順で得られた各層 について4つの出力を合計します。
ミニバッチ全体のスタイル損失を求めるには,次のように,ミニバッチ内の各イメージ についてスタイル損失の平均を計算します。
ここで,
は層のインデックス,
はグラム行列です。
函数[损失,lossContent, lossStyle] = styleTransferLoss (dlX dlnetLoss,海底,...dlSGram、weightContent weightStyle)%提取激活。dlYActivations =细胞(1、4);dlYActivations [dlYActivations {1}, {2}, dlYActivations {3}, dlYActivations {4}] =...转发(dlnetLoss,海底,“输出”,[“relu1_2”“relu2_2”“relu3_3”“relu4_3”]);dlX dlXActivations =前进(dlnetLoss,“输出”,“relu3_3”);%计算激活之间的均方误差。lossContent = mean((dlYActivations{3} - dlXActivations).^2,“所有”);把所有四种激活的损失加起来。lossStyle = 0;为j = 1:4 G = createGramMatrix(dlYActivations{j});lossStyle = lossStyle + sum((G - dlSGram{j}).^2,“所有”);结束在小批量中平均损失。miniBatchSize =大小(dlX 4);lossStyle = lossStyle / miniBatchSize;%应用权重。lossContent = weightContent * lossContent;lossStyle = weightStyle * lossStyle;计算总损失。loss = lossContent + lossStyle;结束
関数residualBlock
は6つの層の配列を返します。これは畳み込み層,インスタンス正規化層,ReLu層,加算層で構成されます。groupNormalizationLayer(“channel-wise”)
は単純にインスタンス正規化層であることに注意してください。
函数layers =[卷积2dlayer ([3 3], 128,])“步”, 1“填充”,“相同”,“名字”,“convRes”+名称+“_1”) groupNormalizationLayer (“channel-wise”,“名字”,“normRes”+名称+“_1”) reluLayer (“名字”,“reluRes”+名称+“_1”)卷积2dlayer ([3 3], 128,“步”, 1“填充”,“相同”,“名字”,“convRes”+名称+“_2”) groupNormalizationLayer (“channel-wise”,“名字”,“normRes”+名称+“_2”) additionLayer (2“名字”,“添加”+名字)];结束
関数createGramMatrix
は,単一の層の活性化を入力として受け取り,ミニバッチ内の各イメージについてスタイル表現を返します。.
入力は,サイズ[W H, C, N]の特徴マップとなり,ここで,Hは高さ,Wは幅,Cはチャネルの数,Nはミニバッチサイズです。この関数は,サイズ[C, C, N]の配列G
を出力します。各部分配列G (:,:, k)
は,ミニバッチ内の
イメージに対応するグラム行列です。グラム行列の各エントリ
は,チャネル
と
の間の相関を表します。なぜなら,チャネル
内の各エントリは,次のように,チャネル
内の対応する位置にあるエントリを乗算するためです。
ここで, は,ミニバッチ内の イメージの活性化です。
グラム行列には,一緒に活性化する特徴についての情報が含まれますが,イメージのどこに特徴が表れるかについての情報は含まれません。これは,高さと幅の総和は,空間構造体についての情報を失うためです。損失関数は,この行列をイメージのスタイル表現として使用します。
函数G = createGramMatrix(activations) [h,w,numChannels] = size(activations,1:3);特点=重塑(激活,h * w, numChannels, []);featuresT = permute(features,[2 1 3]);G = dlmtimes(featuresT,features) / (h*w*numChannels);结束
约翰逊,贾斯汀,亚历山大·阿拉希和李飞飞。"实时风格转换和超分辨率的感知损失"计算机视觉欧洲会议.施普林格可汗,2016。
dlnetwork
|向前
|预测
|dlarray
|dlgradient
|dlfeval
|adamupdate