Main Content

カスタム重み初期化関数の指定

この例では、leaky ReLU 層が続く畳み込み層のカスタム He 重み初期化関数を作成する方法を示します。

leaky ReLU 層が続く畳み込み層の He 初期化子は、ゼロ平均と分散 σ2=2(1+a2)n をもつ正規分布からサンプリングを行います。ここで、a は畳み込み層に続く leaky ReLU 層のスケールで、n = FilterSize(1) * FilterSize(2) * NumChannels です。

学習可能な層については、オプション WeightsInititializerInputWeightsInitializer、または RecurrentWeightsInitializer"he" に設定する場合、ソフトウェアは a=0 を使用します。a を異なる値に設定するには、重み初期化子として使用するカスタム関数を作成します。

データの読み込み

数字のサンプル データをイメージ データストアとして読み込みます。関数 imageDatastore は、フォルダー名に基づいてイメージに自動的にラベルを付けます。

unzip("DigitsData.zip");
imds = imageDatastore("DigitsData", ...
    IncludeSubfolders=true, ...
    LabelSource="foldernames");

データを学習データ セットと検証データ セットに分割し、学習セットの各カテゴリに 750 個のイメージが含まれ、検証セットに各ラベルの残りのイメージが含まれるようにします。splitEachLabel は、データストアを学習用と検証用の 2 つの新しいデータストアに分割します。

numTrainFiles = 750;
[imdsTrain,imdsValidation] = splitEachLabel(imds,numTrainFiles,"randomize");

カスタム重み初期化関数の作成

関数 leakyHe は、sz (層の重みのサイズ) を入力に取り、leaky ReLU 層が続く畳み込み層の He 初期化子によって与えられる重みの配列を返します。また、この関数は、leaky ReLU 層のスケール乗算器を指定する、オプションの入力引数 scale を受け入れます。

function weights = leakyHe(sz,scale)

% If not specified, then use default scale = 0.1
if nargin < 2
    scale = 0.1;
end

filterSize = [sz(1) sz(2)];
numChannels = sz(3);
numIn = filterSize(1) * filterSize(2) * numChannels;

varWeights = 2 / ((1 + scale^2) * numIn);
weights = randn(sz) * sqrt(varWeights);

end

ネットワーク アーキテクチャの定義

畳み込みニューラル ネットワーク アーキテクチャを定義します。

  • イメージ入力層のサイズは [28 28 1] (入力イメージのサイズ)

  • フィルター サイズが 3、フィルター数がそれぞれ 8、16 および 32 である、3 つの 2 次元畳み込み層

  • 各畳み込み層に続く leaky ReLU 層

  • サイズが 10 (クラス数) の全結合層

  • ソフトマックス層

各畳み込み層について、重み初期化子を関数 leakyHe に設定します。

inputSize = [28 28 1];
numClasses = 10;

layers = [
    imageInputLayer(inputSize)
    convolution2dLayer(3,8,WeightsInitializer=@leakyHe)
    leakyReluLayer
    convolution2dLayer(3,16,WeightsInitializer=@leakyHe)
    leakyReluLayer
    convolution2dLayer(3,32,WeightsInitializer=@leakyHe)
    leakyReluLayer
    fullyConnectedLayer(numClasses)
    softmaxLayer];

ネットワークの学習

学習オプションを指定し、ネットワークに学習させます。学習を 4 エポック行います。勾配の発散を防ぐために、勾配しきい値を 2 に設定します。エポックごとに 1 回ネットワークを検証します。学習の進行状況をプロットで表示し、精度を監視します。

関数trainnetを使用してニューラル ネットワークに学習させます。分類には、クロスエントロピー損失を使用します。既定では、関数 trainnet は利用可能な GPU がある場合にそれを使用します。GPU での学習には、Parallel Computing Toolbox™ ライセンスとサポートされている GPU デバイスが必要です。サポートされているデバイスの詳細については、GPU 計算の要件 (Parallel Computing Toolbox)を参照してください。そうでない場合、関数 trainnet は CPU を使用します。実行環境を指定するには、ExecutionEnvironment 学習オプションを使用します。

maxEpochs = 4;
miniBatchSize = 128;
numObservations = numel(imdsTrain.Files);
numIterationsPerEpoch = floor(numObservations / miniBatchSize);

options = trainingOptions("sgdm", ...
    MaxEpochs=maxEpochs, ...
    MiniBatchSize=miniBatchSize, ...
    GradientThreshold=2, ...
    ValidationData=imdsValidation, ...
    ValidationFrequency=numIterationsPerEpoch, ...
    Verbose=false, ...
    Metrics="accuracy", ...
    Plots="training-progress");

[netDefault,infoDefault] = trainnet(imdsTrain,layers,"crossentropy",options);

ネットワークのテスト

testnet関数を使用してニューラル ネットワークをテストします。単一ラベルの分類では、精度を評価します。精度は、正しい予測の割合です。既定では、testnet 関数は利用可能な GPU がある場合にそれを使用します。実行環境を手動で選択するには、testnet 関数の ExecutionEnvironment 引数を使用します。

accuracy = testnet(netDefault,imdsValidation,"accuracy");

追加オプションの指定

関数 leakyHe は、オプションの入力引数 scale を受け入れます。追加の変数をカスタム重み初期化関数に入力するには、この関数を単一の入力 sz を受け入れる無名関数として指定します。これを行うには、@leakyHe のインスタンスを @(sz)leakyHe(sz,scale) に置き換えます。ここで、無名関数は単一の入力引数 sz のみを受け入れ、指定された scale 入力引数で関数 leakyHe を呼び出します。

次の変更を加えて前と同じネットワークを作成し、学習させます。

  • leaky ReLU 層で、スケール乗算器を 0.01 に設定します。

  • 関数 leakyHe で畳み込み層の重みを初期化し、スケール乗算器も指定します。

scale = 0.01;

layers = [
    imageInputLayer(inputSize)
    convolution2dLayer(3,8,WeightsInitializer=@(sz)leakyHe(sz,scale))
    leakyReluLayer(scale)
    convolution2dLayer(3,16,WeightsInitializer=@(sz)leakyHe(sz,scale))
    leakyReluLayer(scale)
    convolution2dLayer(3,32,WeightsInitializer=@(sz)leakyHe(sz,scale))
    leakyReluLayer(scale)
    fullyConnectedLayer(numClasses)
    softmaxLayer];

[netCustom,infoCustom] = trainnet(imdsTrain,layers,"crossentropy",options);

testnet 関数を使用してネットワークをテストします。

accuracy = testnet(netCustom,imdsValidation,"accuracy");

結果の比較

関数 trainnet で返される情報出力から検証精度を抽出します。

validationAccuracy = [
    infoDefault.ValidationHistory.Accuracy, ...
    infoCustom.ValidationHistory.Accuracy];

各ネットワークについて、検証精度に対するエポック数をプロットします。

figure
epochs = 0:maxEpochs;
plot(epochs,validationAccuracy)
title("Validation Accuracy")
xlabel("Epoch")
ylabel("Validation Accuracy")
legend(["Leaky He (Default)" "Leaky He (Custom)"],'Location','southeast')

参考文献

  1. He, Kaiming, Xiangyu Zhang, Shaoqing Ren, and Jian Sun. "Delving deep into rectifiers: Surpassing human-level performance on imagenet classification." In Proceedings of the IEEE international conference on computer vision, pp. 1026-1034. 2015.

参考

| |

関連するトピック