シャム ネットワークの学習とイメージの比較
この例では、シャム ネットワークに学習させて類似した手書き文字のイメージを特定する方法を説明します。
シャム ネットワークは深層学習ネットワークの一種で、同じアーキテクチャをもち、同じパラメーターと重みを共有する、2 つ以上の同一のサブネットワークを使用します。シャム ネットワークは通常、比較可能な 2 つの事例の関係性を見つけることに関わるタスクに使用されます。シャム ネットワークの一般的な使用例には、顔認識、シグネチャ検証 [1]、またはパラフレーズ識別 [2] などがあります。学習中に重みを共有することで学習させるパラメーターが少なくなり、比較的少量の学習データで良い結果が得られるため、シャム ネットワークはこれらのタスクにおいて良好に動作します。
シャム ネットワークは特に、クラスの数が多く、各クラスの観測値が少ない場合に役立ちます。このような場合、イメージをこれらのクラスに分類するよう深層畳み込みニューラル ネットワークに学習させるだけの十分なデータがありません。代わりに、シャム ネットワークによって 2 つのイメージが同じクラスに属するかどうかを判定することができます。
この例では、Omniglot データセット [3] を使用してシャム ネットワークに学習させ、手書き文字のイメージを比較します [4]。Omniglot データセットには 50 個のアルファベットの文字セットが含まれ、そのうち 30 個が学習用に、20 個がテスト用に分けられています。それぞれのアルファベットには、Ojibwe (カナダ先住民文字) の 14 個の文字から Tifinagh の 55 個の文字まで、数多くの文字が含まれています。そして、それぞれの文字には 20 個の手書きの観測値があります。この例では、2 つの手書きの観測値が同じ文字の異なるインスタンスであるかを特定するよう、ネットワークに学習させます。
シャム ネットワークを使用すると、次元削減によって類似のイメージを特定することもできます。例については、次元削減のためのシャム ネットワークの学習を参照してください。
学習データの読み込みと前処理
Omniglot 学習データセットをダウンロードして解凍します。
url = "https://github.com/brendenlake/omniglot/raw/master/python/images_background.zip"; downloadFolder = tempdir; filename = fullfile(downloadFolder,"images_background.zip"); dataFolderTrain = fullfile(downloadFolder,"images_background"); if ~exist(dataFolderTrain,"dir") disp("Downloading Omniglot training data (4.5 MB)...") websave(filename,url); unzip(filename,downloadFolder); end disp("Training data downloaded.")
Training data downloaded.
関数 imageDatastore
を使用して学習データをイメージ データストアとして読み込みます。ファイル名からラベルを抽出して Labels
プロパティを設定し、ラベルを手動で指定します。
imdsTrain = imageDatastore(dataFolderTrain, ... IncludeSubfolders=true, ... LabelSource="none"); files = imdsTrain.Files; parts = split(files,filesep); labels = join(parts(:,(end-2):(end-1)),"-"); imdsTrain.Labels = categorical(labels);
Omniglot 学習データセットは 30 個のアルファベットのモノクロの手書き文字で構成され、それぞれの文字について 20 個の観測値をもちます。イメージのサイズは 105 x 105 x 1 で、各ピクセルの値は 0
から 1
の範囲内です。
ランダムに選択したイメージを表示します。
idx = randperm(numel(imdsTrain.Files),8); for i = 1:numel(idx) subplot(4,2,i) imshow(readimage(imdsTrain,idx(i))) title(imdsTrain.Labels(idx(i)),Interpreter="none"); end
類似イメージと非類似イメージのペアの作成
ネットワークに学習させるには、データを類似イメージまたは非類似イメージのペアにグループ化しなければなりません。ここで、類似イメージは同じ文字の異なる手書きのインスタンスで、ラベルが同じであるのに対し、非類似イメージは異なる文字で、ラベルが異なります。関数 getSiameseBatch
(この例のサポート関数の節で定義) は、類似イメージまたは非類似イメージのランダム化されたペアである pairImage1
と pairImage2
を作成します。また、この関数は、イメージのペアが互いに類似か非類似かを識別するラベル pairLabel
を返します。イメージの類似ペアの場合は pairLabel = 1
、非類似ペアの場合は pairLabel = 0
になります。
一例として、5 つのイメージのペアをもつ、典型的な小さいセットを作成します。
batchSize = 10; [pairImage1,pairImage2,pairLabel] = getSiameseBatch(imdsTrain,batchSize);
生成されたイメージのペアを表示します。
for i = 1:batchSize if pairLabel(i) == 1 s = "similar"; else s = "dissimilar"; end subplot(2,5,i) imshow([pairImage1(:,:,:,i) pairImage2(:,:,:,i)]); title(s) end
この例では、学習ループの反復ごとに、イメージのペア 180 個から成る新しいバッチが作成されます。これにより、類似ペアと非類似ペアの比率がほぼ等しい大量のランダムなイメージのペアでネットワークに学習させることができます。
ネットワーク アーキテクチャの定義
シャム ネットワークのアーキテクチャを次の図に示します。
2 つのイメージを比較するために、各イメージが、重みを共有する 2 つの同一サブネットワークの一方を通過します。サブネットワークは、105 x 105 x 1 の各イメージを 4096 次元の特徴ベクトルに変換します。同じクラスのイメージの 4096 次元表現は類似しています。各サブネットワークの出力特徴ベクトルは、減算により組み合わされ、その結果が単一出力をもつ fullyconnect
演算に渡されます。sigmoid
演算は、この値を 0
から 1
の間の確率に変換します。この値は、イメージが類似か非類似かのネットワーク予測を示します。学習中のネットワークの更新には、ネットワーク予測と真のラベルの間におけるバイナリ交差エントロピー損失が使用されます。
この例では、2 つの同一サブネットワークが dlnetwork
オブジェクトとして定義されます。最終の fullyconnect
および sigmoid
演算は、サブネットワークの出力に対する関数演算として実行されます。
105 x 105 x 1 のイメージを受け取り、サイズが 4096 の特徴ベクトルを出力する一連の層としてサブネットワークを作成します。
convolution2dLayer
オブジェクトでは、狭い正規分布を使用して重みとバイアスを初期化します。
maxPooling2dLayer
オブジェクトでは、ストライドを 2
に設定します。
最終の fullyConnectedLayer
オブジェクトでは、出力サイズを 4096 に指定し、狭い正規分布を使用して重みとバイアスを初期化します。
layers = [ imageInputLayer([105 105 1],Normalization="none") convolution2dLayer(10,64,WeightsInitializer="narrow-normal",BiasInitializer="narrow-normal") reluLayer maxPooling2dLayer(2,Stride=2) convolution2dLayer(7,128,WeightsInitializer="narrow-normal",BiasInitializer="narrow-normal") reluLayer maxPooling2dLayer(2,Stride=2) convolution2dLayer(4,128,WeightsInitializer="narrow-normal",BiasInitializer="narrow-normal") reluLayer maxPooling2dLayer(2,Stride=2) convolution2dLayer(5,256,WeightsInitializer="narrow-normal",BiasInitializer="narrow-normal") reluLayer fullyConnectedLayer(4096,WeightsInitializer="narrow-normal",BiasInitializer="narrow-normal")]; lgraph = layerGraph(layers);
カスタム学習ループを使用してネットワークに学習させ、自動微分を有効にするには、層グラフを dlnetwork
オブジェクトに変換します。
net = dlnetwork(lgraph);
最終の fullyconnect
演算の重みを作成します。標準偏差 0.01 の狭い正規分布からランダムに選択してサンプリングし、重みを初期化します。
fcWeights = dlarray(0.01*randn(1,4096)); fcBias = dlarray(0.01*randn(1,1)); fcParams = struct(... "FcWeights",fcWeights,... "FcBias",fcBias);
ネットワークを使用するために、2 つのサブネットワークと減算、fullyconnect,
演算および sigmoid
演算をどのように組み合わせるかを定義する関数 forwardSiamese
(この例のサポート関数の節で定義) を作成します。関数 forwardSiamese
は、ネットワーク、fullyconnect
演算のパラメーターを含む構造体、および 2 つの学習イメージを受け取ります。関数 forwardSiamese
は 2 つのイメージの類似度についての予測を出力します。
モデル損失関数の定義
関数 modelLoss
(この例のサポート関数の節で定義) を作成します。関数 modelLoss
は、シャム サブネットワーク net
、fullyconnect
演算のためのパラメーター構造体、入力データのミニバッチ X1
および X2
とそのラベル pairLabels
を受け取ります。関数は損失値と、ネットワークの学習可能なパラメーターについての損失の勾配を返します。
シャム ネットワークの目的は、2 つの入力 X1
と X2
を区別することです。ネットワーク出力は 0
から 1
の間の確率です。値が 0
に近いほどイメージは非類似と予測され、1
に近いほどイメージは類似と予測されたことを示します。損失は、予測スコアと真のラベル値の間のバイナリ交差エントロピーで表されます。
ここで、真のラベル は 0 または 1 を取り、 は予測されたラベルです。
学習オプションの指定
学習中に使用するオプションを指定します。10000 回反復して学習させます。
numIterations = 10000; miniBatchSize = 180;
ADAM 最適化のオプションを指定します。
学習率を
0.00006
に設定します。勾配の減衰係数を
0.9
に、2 乗勾配の減衰係数を0.99
に設定。
learningRate = 6e-5; gradDecay = 0.9; gradDecaySq = 0.99;
GPU が利用できる場合、GPU で学習を行います。GPU を使用するには、Parallel Computing Toolbox™ とサポートされている GPU デバイスが必要です。サポートされているデバイスについては、GPU 計算の要件 (Parallel Computing Toolbox)を参照してください。GPU が使用可能で、関連するデータを GPU に配置できるかどうかを自動的に検出するには、executionEnvironment
の値を "auto"
に設定します。GPU がない場合、または学習で GPU を使用しない場合は、executionEnvironment
の値を "cpu"
に設定します。学習に必ず GPU を使用するには、executionEnvironment
の値を "gpu"
に設定します。
executionEnvironment = "auto";
モデルの学習
学習の進行状況プロットを初期化します。
figure C = colororder; lineLossTrain = animatedline(Color=C(2,:)); ylim([0 inf]) xlabel("Iteration") ylabel("Loss") grid on
ADAM ソルバーのパラメーターを初期化します。
trailingAvgSubnet = []; trailingAvgSqSubnet = []; trailingAvgParams = []; trailingAvgSqParams = [];
カスタム学習ループを使用してモデルに学習させます。学習データ全体をループ処理し、各反復でネットワーク パラメーターを更新します。
それぞれの反復で次を行います。
イメージ ペアのバッチの作成の節で定義されている関数
getSiameseBatch
を使用して、イメージ ペアとラベルのバッチを抽出。データを
dlarray
オブジェクトに変換し、次元ラベル"SSCB"
(spatial、spatial、channel、batch) にイメージ データを、"CB"
(channel、batch) にラベルを指定。GPU で学習する場合、データを
gpuArray
オブジェクトに変換。関数
dlfeval
およびmodelLoss
を使用してモデルの損失と勾配を評価。関数
adamupdate
を使用してネットワーク パラメーターを更新。
start = tic; % Loop over mini-batches. for iteration = 1:numIterations % Extract mini-batch of image pairs and pair labels [X1,X2,pairLabels] = getSiameseBatch(imdsTrain,miniBatchSize); % Convert mini-batch of data to dlarray. Specify the dimension labels % "SSCB" (spatial, spatial, channel, batch) for image data X1 = dlarray(X1,"SSCB"); X2 = dlarray(X2,"SSCB"); % If training on a GPU, then convert data to gpuArray. if (executionEnvironment == "auto" && canUseGPU) || executionEnvironment == "gpu" X1 = gpuArray(X1); X2 = gpuArray(X2); end % Evaluate the model loss and gradients using dlfeval and the modelLoss % function listed at the end of the example. [loss,gradientsSubnet,gradientsParams] = dlfeval(@modelLoss,net,fcParams,X1,X2,pairLabels); % Update the Siamese subnetwork parameters. [net,trailingAvgSubnet,trailingAvgSqSubnet] = adamupdate(net,gradientsSubnet, ... trailingAvgSubnet,trailingAvgSqSubnet,iteration,learningRate,gradDecay,gradDecaySq); % Update the fullyconnect parameters. [fcParams,trailingAvgParams,trailingAvgSqParams] = adamupdate(fcParams,gradientsParams, ... trailingAvgParams,trailingAvgSqParams,iteration,learningRate,gradDecay,gradDecaySq); % Update the training loss progress plot. D = duration(0,0,toc(start),Format="hh:mm:ss"); lossValue = double(loss); addpoints(lineLossTrain,iteration,lossValue); title("Elapsed: " + string(D)) drawnow end
ネットワークの精度の評価
Omniglot テスト データセットをダウンロードして解凍します。
url = "https://github.com/brendenlake/omniglot/raw/master/python/images_evaluation.zip"; downloadFolder = tempdir; filename = fullfile(downloadFolder,"images_evaluation.zip"); dataFolderTest = fullfile(downloadFolder,"images_evaluation"); if ~exist(dataFolderTest,"dir") disp("Downloading Omniglot test data (3.2 MB)...") websave(filename,url); unzip(filename,downloadFolder); end disp("Test data downloaded.")
Test data downloaded.
関数 imageDatastore
を使用してテスト データをイメージ データストアとして読み込みます。ファイル名からラベルを抽出して Labels
プロパティを設定し、ラベルを手動で指定します。
imdsTest = imageDatastore(dataFolderTest, ... IncludeSubfolders=true, ... LabelSource="none"); files = imdsTest.Files; parts = split(files,filesep); labels = join(parts(:,(end-2):(end-1)),"_"); imdsTest.Labels = categorical(labels);
テスト データセットには、ネットワークが学習済みのアルファベットとは異なる 20 個のアルファベットが含まれています。合計で、テスト データセットには 659 個の異なるクラスが存在します。
numClasses = numel(unique(imdsTest.Labels))
numClasses = 659
ネットワークの精度を計算するには、テスト ペアとして 5 つのランダムなミニバッチのセットを作成します。関数 predictSiamese
(この例のサポート関数の節で定義) を使用して、ネットワークの予測の評価とミニバッチにおける平均精度の計算を行います。
accuracy = zeros(1,5); accuracyBatchSize = 150; for i = 1:5 % Extract mini-batch of image pairs and pair labels [X1,X2,pairLabelsAcc] = getSiameseBatch(imdsTest,accuracyBatchSize); % Convert mini-batch of data to dlarray. Specify the dimension labels % "SSCB" (spatial, spatial, channel, batch) for image data. X1 = dlarray(X1,"SSCB"); X2 = dlarray(X2,"SSCB"); % If using a GPU, then convert data to gpuArray. if (executionEnvironment == "auto" && canUseGPU) || executionEnvironment == "gpu" X1 = gpuArray(X1); X2 = gpuArray(X2); end % Evaluate predictions using trained network Y = predictSiamese(net,fcParams,X1,X2); % Convert predictions to binary 0 or 1 Y = gather(extractdata(Y)); Y = round(Y); % Compute average accuracy for the minibatch accuracy(i) = sum(Y == pairLabelsAcc)/accuracyBatchSize; end
すべてのミニバッチで精度を計算します。
averageAccuracy = mean(accuracy)*100
averageAccuracy = 89.0667
イメージのテスト セットと予測の表示
ネットワークが類似ペアと非類似ペアを正しく識別しているかを視覚的にチェックするには、テスト用にイメージのペアの小さいバッチを作成します。関数 predictSiamese を使用して各テスト ペアの予測を取得します。イメージのペアを、予測、確率スコア、および予測の正誤を示すラベルと共に表示します。
testBatchSize = 10; [XTest1,XTest2,pairLabelsTest] = getSiameseBatch(imdsTest,testBatchSize);
データのテスト バッチを dlarray
に変換します。次元ラベル "SSCB"
(spatial、spatial、channel、batch) をイメージ データに指定します。
XTest1 = dlarray(XTest1,"SSCB"); XTest2 = dlarray(XTest2,"SSCB");
GPU を使用する場合は、データを gpuArray
に変換します。
if (executionEnvironment == "auto" && canUseGPU) || executionEnvironment == "gpu" XTest1 = gpuArray(XTest1); XTest2 = gpuArray(XTest2); end
予測確率を計算します。
YScore = predictSiamese(net,fcParams,XTest1,XTest2); YScore = gather(extractdata(YScore));
予測をバイナリの 0 または 1 に変換します。
YPred = round(YScore);
プロット用にデータを抽出します。
XTest1 = extractdata(XTest1); XTest2 = extractdata(XTest2);
予測ラベルと予測スコアでイメージをプロットします。
f = figure; tiledlayout(2,5); f.Position(3) = 2*f.Position(3); predLabels = categorical(YPred,[0 1],["dissimilar" "similar"]); targetLabels = categorical(pairLabelsTest,[0 1],["dissimilar","similar"]); for i = 1:numel(pairLabelsTest) nexttile imshow([XTest1(:,:,:,i) XTest2(:,:,:,i)]); title( ... "Target: " + string(targetLabels(i)) + newline + ... "Predicted: " + string(predLabels(i)) + newline + ... "Score: " + YScore(i)) end
ネットワークは、それらのイメージが学習データセットにまったく含まれていない場合でも、テスト イメージを比較して類似度を判定することができます。
サポート関数
学習と予測のためのモデル関数
ネットワークの学習中は関数 forwardSiamese
が使用されます。この関数は、サブネットワークや fullyconnect
演算および sigmoid
演算をどのように組み合わせて完全なシャム ネットワークを形成するかを定義します。forwardSiamese はネットワーク構造と 2 つの学習イメージを受け取り、2 つのイメージの類似度についての予測を出力します。この例では、関数 forwardSiamese
についてネットワーク アーキテクチャの定義の節で紹介されています。
function Y = forwardSiamese(net,fcParams,X1,X2) % forwardSiamese accepts the network and pair of training images, and % returns a prediction of the probability of the pair being similar (closer % to 1) or dissimilar (closer to 0). Use forwardSiamese during training. % Pass the first image through the twin subnetwork Y1 = forward(net,X1); Y1 = sigmoid(Y1); % Pass the second image through the twin subnetwork Y2 = forward(net,X2); Y2 = sigmoid(Y2); % Subtract the feature vectors Y = abs(Y1 - Y2); % Pass the result through a fullyconnect operation Y = fullyconnect(Y,fcParams.FcWeights,fcParams.FcBias); % Convert to probability between 0 and 1. Y = sigmoid(Y); end
関数 predictSiamese
は学習済みネットワークを使用して 2 つのイメージの類似度に関する予測を行います。この関数は、以前に定義した関数 forwardSiamese
に類似しています。ただし、predictSiamese
は関数 forward
ではなく関数 predict
をネットワークで使用します。これは、一部の深層学習層が学習中および予測中に異なる動作をするためです。この例では、関数 predictSiamese
についてネットワークの精度の評価の節で紹介されています。
function Y = predictSiamese(net,fcParams,X1,X2) % predictSiamese accepts the network and pair of images, and returns a % prediction of the probability of the pair being similar (closer to 1) or % dissimilar (closer to 0). Use predictSiamese during prediction. % Pass the first image through the twin subnetwork. Y1 = predict(net,X1); Y1 = sigmoid(Y1); % Pass the second image through the twin subnetwork. Y2 = predict(net,X2); Y2 = sigmoid(Y2); % Subtract the feature vectors. Y = abs(Y1 - Y2); % Pass result through a fullyconnect operation. Y = fullyconnect(Y,fcParams.FcWeights,fcParams.FcBias); % Convert to probability between 0 and 1. Y = sigmoid(Y); end
モデル損失関数
関数 modelLoss
は、シャム dlnetwork
オブジェクトの net
、ミニバッチ入力データ X1
と X2
のペア、およびそれらが類似か非類似かを示すラベルを受け取ります。この関数は、予測とグラウンド トゥルースの間のバイナリ交差エントロピー損失と、ネットワーク内の学習可能パラメーターについての損失の勾配を返します。この例では、関数 modelLoss
についてモデル損失関数の定義の節で紹介されています。
function [loss,gradientsSubnet,gradientsParams] = modelLoss(net,fcParams,X1,X2,pairLabels) % Pass the image pair through the network. Y = forwardSiamese(net,fcParams,X1,X2); % Calculate binary cross-entropy loss. loss = binarycrossentropy(Y,pairLabels); % Calculate gradients of the loss with respect to the network learnable % parameters. [gradientsSubnet,gradientsParams] = dlgradient(loss,net.Learnables,fcParams); end
バイナリ交差エントロピー損失関数
関数 binarycrossentropy
は、ネットワーク予測とペア ラベルを受け入れ、バイナリ交差エントロピー損失値を返します。
function loss = binarycrossentropy(Y,pairLabels) % Get precision of prediction to prevent errors due to floating point % precision. precision = underlyingType(Y); % Convert values less than floating point precision to eps. Y(Y < eps(precision)) = eps(precision); % Convert values between 1-eps and 1 to 1-eps. Y(Y > 1 - eps(precision)) = 1 - eps(precision); % Calculate binary cross-entropy loss for each pair loss = -pairLabels.*log(Y) - (1 - pairLabels).*log(1 - Y); % Sum over all pairs in minibatch and normalize. loss = sum(loss)/numel(pairLabels); end
イメージ ペアのバッチの作成
次の関数は、ラベルに基づいて類似または非類似のイメージのランダム化されたペアを作成します。この例では、関数 getSiameseBatch
について類似イメージと非類似イメージのペアの作成の節で紹介されています。
シャム バッチ取得関数
getSiameseBatch
は、ランダムに選択されたバッチまたはペアになっているイメージを返します。平均して、この関数は類似ペアと非類似ペアのバランスの取れたセットを生成します。
function [X1,X2,pairLabels] = getSiameseBatch(imds,miniBatchSize) pairLabels = zeros(1,miniBatchSize); imgSize = size(readimage(imds,1)); X1 = zeros([imgSize 1 miniBatchSize],"single"); X2 = zeros([imgSize 1 miniBatchSize],"single"); for i = 1:miniBatchSize choice = rand(1); if choice < 0.5 [pairIdx1,pairIdx2,pairLabels(i)] = getSimilarPair(imds.Labels); else [pairIdx1,pairIdx2,pairLabels(i)] = getDissimilarPair(imds.Labels); end X1(:,:,:,i) = imds.readimage(pairIdx1); X2(:,:,:,i) = imds.readimage(pairIdx2); end end
類似ペア取得関数
関数 getSimilarPair
は、同じクラスに属し、かつ類似ペアのラベルが 1 に等しいイメージについて、インデックスのランダムなペアを返します。
function [pairIdx1,pairIdx2,pairLabel] = getSimilarPair(classLabel) % Find all unique classes. classes = unique(classLabel); % Choose a class randomly which will be used to get a similar pair. classChoice = randi(numel(classes)); % Find the indices of all the observations from the chosen class. idxs = find(classLabel==classes(classChoice)); % Randomly choose two different images from the chosen class. pairIdxChoice = randperm(numel(idxs),2); pairIdx1 = idxs(pairIdxChoice(1)); pairIdx2 = idxs(pairIdxChoice(2)); pairLabel = 1; end
非類似ペア取得関数
関数 getDissimilarPair
は、異なるクラスに属し、かつ非類似ペアのラベルが 0 に等しいイメージについて、インデックスのランダムなペアを返します。
function [pairIdx1,pairIdx2,label] = getDissimilarPair(classLabel) % Find all unique classes. classes = unique(classLabel); % Choose two different classes randomly which will be used to get a % dissimilar pair. classesChoice = randperm(numel(classes),2); % Find the indices of all the observations from the first and second % classes. idxs1 = find(classLabel==classes(classesChoice(1))); idxs2 = find(classLabel==classes(classesChoice(2))); % Randomly choose one image from each class. pairIdx1Choice = randi(numel(idxs1)); pairIdx2Choice = randi(numel(idxs2)); pairIdx1 = idxs1(pairIdx1Choice); pairIdx2 = idxs2(pairIdx2Choice); label = 0; end
参考文献
[1] Bromley, J., I. Guyon, Y. LeCun, E. Säckinger, and R. Shah. "Signature Verification using a "Siamese" Time Delay Neural Network." In Proceedings of the 6th International Conference on Neural Information Processing Systems (NIPS 1993), 1994, pp737-744. Available at Signature Verification using a "Siamese" Time Delay Neural Network on the NIPS Proceedings website.
[2] Wenpeg, Y., and H Schütze. "Convolutional Neural Network for Paraphrase Identification." In Proceedings of 2015 Conference of the North American Chapter of the ACL, 2015, pp901-911. Available at Convolutional Neural Network for Paraphrase Identification on the ACL Anthology website
[3] Lake, B. M., Salakhutdinov, R., and Tenenbaum, J. B. "Human-level concept learning through probabilistic program induction." Science, 350(6266), (2015) pp1332-1338.
[4] Koch, G., Zemel, R., and Salakhutdinov, R. (2015). "Siamese neural networks for one-shot image recognition". In Proceedings of the 32nd International Conference on Machine Learning, 37 (2015). Available at Siamese Neural Networks for One-shot Image Recognition on the ICML'15 website.
参考
dlarray
| dlgradient
| dlfeval
| dlnetwork
| adamupdate