Main Content

最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

カスタム学習ループを使用したネットワークの学習

この例では、カスタム学習率スケジュールで手書きの数字を分類するネットワークに学習させる方法を示します。

必要なオプション (たとえば、カスタム学習率スケジュール) が関数 trainingOptions に用意されていない場合、自動微分を使用して独自のカスタム学習ループを定義できます。

この例では、"時間ベースの減衰" 学習率スケジュールで手書きの数字を分類するようにネットワークに学習させます。各反復で、ソルバーは ρt=ρ01+kt によって与えられる学習率を使用します。ここで、t は反復回数、ρ0 は初期学習率、k は減衰です。

学習データの読み込み

数字データを読み込みます。

[XTrain,YTrain] = digitTrain4DArrayData;
classes = categories(YTrain);
numClasses = numel(classes);

ネットワークの定義

ネットワークを定義し、イメージ入力層で 'Mean' オプションを使用して平均イメージを指定します。

layers = [
    imageInputLayer([28 28 1], 'Name', 'input', 'Mean', mean(XTrain,4))
    convolution2dLayer(5, 20, 'Name', 'conv1')
    batchNormalizationLayer('Name','bn1')
    reluLayer('Name', 'relu1')
    convolution2dLayer(3, 20, 'Padding', 1, 'Name', 'conv2')
    batchNormalizationLayer('Name','bn2')
    reluLayer('Name', 'relu2')
    convolution2dLayer(3, 20, 'Padding', 1, 'Name', 'conv3')
    batchNormalizationLayer('Name','bn3')
    reluLayer('Name', 'relu3')
    fullyConnectedLayer(numClasses, 'Name', 'fc')
    softmaxLayer('Name','softmax')];
lgraph = layerGraph(layers);

層グラフから dlnetwork オブジェクトを作成します。

dlnet = dlnetwork(lgraph)
dlnet = 
  dlnetwork with properties:

         Layers: [12×1 nnet.cnn.layer.Layer]
    Connections: [11×2 table]
     Learnables: [14×3 table]
          State: [6×3 table]
     InputNames: {'input'}
    OutputNames: {'softmax'}

モデル勾配関数の定義

この例の最後にリストされている関数 modelGradients を作成します。この関数は dlnetwork オブジェクト dlnet、入力データ dlX のミニバッチとそれに対応するラベル Y を受け取り、dlnet における学習可能なパラメーターについての損失の勾配、および対応する損失を返します。

学習オプションの指定

ミニバッチ サイズを 128 として、学習を 5 エポック行います。

numEpochs = 5;
miniBatchSize = 128;

SGDM 最適化のオプションを指定します。減衰 0.01 の初期学習率 0.01、およびモーメンタム 0.9 を指定します。

initialLearnRate = 0.01;
decay = 0.01;
momentum = 0.9;

学習の進行状況をプロットに可視化します。

plots = "training-progress";

GPU が利用できる場合、GPU で学習を行います。GPU を使用するには、Parallel Computing Toolbox™、および Compute Capability 3.0 以上の CUDA® 対応 NVIDIA® GPU が必要です。

executionEnvironment = "auto";

モデルの学習

カスタム学習ループを使用してモデルに学習させます。

各エポックについて、データをシャッフルしてデータのミニバッチをループで回します。各エポックの最後に、学習の進行状況を表示します。

各ミニバッチで次を行います。

  • ラベルをダミー変数に変換。

  • 基となる型が single の dlarray オブジェクトにデータを変換し、次元ラベル 'SSCB' (spatial、spatial、channel、batch) を指定。

  • GPU で学習する場合、gpuArray オブジェクトに変換。

  • dlfeval と関数 modelGradients を使用してモデルの勾配、状態、および損失を評価し、ネットワークの状態を更新。

  • 時間ベースの減衰学習率スケジュールの学習率を決定。

  • 関数 sgdmupdate を使用してネットワーク パラメーターを更新。

学習の進行状況プロットを初期化します。

if plots == "training-progress"
    figure
    lineLossTrain = animatedline('Color',[0.85 0.325 0.098]);
    ylim([0 inf])
    xlabel("Iteration")
    ylabel("Loss")
    grid on
end

SGDM ソルバーの速度パラメーターを初期化します。

velocity = [];

ネットワークに学習をさせます。

numObservations = numel(YTrain);
numIterationsPerEpoch = floor(numObservations./miniBatchSize);

iteration = 0;
start = tic;

% Loop over epochs.
for epoch = 1:numEpochs
    % Shuffle data.
    idx = randperm(numel(YTrain));
    XTrain = XTrain(:,:,:,idx);
    YTrain = YTrain(idx);
    
    % Loop over mini-batches.
    for i = 1:numIterationsPerEpoch
        iteration = iteration + 1;
        
        % Read mini-batch of data and convert the labels to dummy
        % variables.
        idx = (i-1)*miniBatchSize+1:i*miniBatchSize;
        X = XTrain(:,:,:,idx);
        
        Y = zeros(numClasses, miniBatchSize, 'single');
        for c = 1:numClasses
            Y(c,YTrain(idx)==classes(c)) = 1;
        end
        
        % Convert mini-batch of data to dlarray.
        dlX = dlarray(single(X),'SSCB');
        
        % If training on a GPU, then convert data to gpuArray.
        if (executionEnvironment == "auto" && canUseGPU) || executionEnvironment == "gpu"
            dlX = gpuArray(dlX);
        end
        
        % Evaluate the model gradients, state, and loss using dlfeval and the
        % modelGradients function and update the network state.
        [gradients,state,loss] = dlfeval(@modelGradients,dlnet,dlX,Y);
        dlnet.State = state;
        
        % Determine learning rate for time-based decay learning rate schedule.
        learnRate = initialLearnRate/(1 + decay*iteration);
        
        % Update the network parameters using the SGDM optimizer.
        [dlnet, velocity] = sgdmupdate(dlnet, gradients, velocity, learnRate, momentum);
        
        % Display the training progress.
        if plots == "training-progress"
            D = duration(0,0,toc(start),'Format','hh:mm:ss');
            addpoints(lineLossTrain,iteration,double(gather(extractdata(loss))))
            title("Epoch: " + epoch + ", Elapsed: " + string(D))
            drawnow
        end
    end
end

モデルのテスト

真のラベルをもつテスト セットで予測を比較して、モデルの分類精度をテストします。

[XTest, YTest] = digitTest4DArrayData;

次元フォーマットが 'SSCB' である dlarray オブジェクトにデータを変換します。GPU で予測する場合、データを gpuArray にも変換します。

dlXTest = dlarray(XTest,'SSCB');
if (executionEnvironment == "auto" && canUseGPU) || executionEnvironment == "gpu"
    dlXTest = gpuArray(dlXTest);
end

例の最後にリストされている関数 modelPredictions を使用してイメージを分類し、スコアが最も高いクラスを見つけます。

dlYPred = modelPredictions(dlnet,dlXTest,miniBatchSize);
[~,idx] = max(extractdata(dlYPred),[],1);
YPred = classes(idx);

分類精度を評価します。

accuracy = mean(YPred == YTest)
accuracy = 0.9910

モデル勾配関数

関数 modelGradients は、dlnetwork オブジェクト dlnet、入力データ dlX のミニバッチとそれに対応するラベル Y を受け取り、dlnet における学習可能なパラメーターについての損失の勾配、ネットワークの状態、および損失を返します。勾配を自動的に計算するには、関数 dlgradient を使用します。

function [gradients,state,loss] = modelGradients(dlnet,dlX,Y)

[dlYPred,state] = forward(dlnet,dlX);

loss = crossentropy(dlYPred,Y);
gradients = dlgradient(loss,dlnet.Learnables);

end

モデル予測関数

関数 modelPredictions は、dlnetwork オブジェクト dlnet、入力データの配列 dlX、およびミニバッチ サイズを受け取り、指定サイズのミニバッチを反復することによりモデル予測を出力します。

function dlYPred = modelPredictions(dlnet,dlX,miniBatchSize)

numObservations = size(dlX,4);
numIterations = ceil(numObservations / miniBatchSize);

numClasses = dlnet.Layers(11).OutputSize;
dlYPred = zeros(numClasses,numObservations,'like',dlX);

for i = 1:numIterations
    idx = (i-1)*miniBatchSize+1:min(i*miniBatchSize,numObservations);
    
    dlYPred(:,idx) = predict(dlnet,dlX(:,:,:,idx));
end

end

参考

| | | | | |

関連するトピック