Main Content

ベイズ最適化を使用した実験ハイパーパラメーターの調整

R2020b 以降

この例では、実験マネージャーでベイズ最適化を適用し、畳み込みニューラル ネットワークに最適なネットワーク ハイパーパラメーターと学習オプションを求める方法を説明します。ベイズ最適化により、実験においてハイパーパラメーターをスイープするための代替手法が得られます。各ハイパーパラメーターの値の範囲を指定し、最適化するメトリクスを選択します。すると、選択したメトリクスを最適化するハイパーパラメーターの組み合わせを実験マネージャーが検索します。ベイズ最適化には Statistics and Machine Learning Toolbox™ が必要です。

この例では、CIFAR-10 データ セットのイメージを分類するようネットワークに学習させます。この実験では、ベイズ最適化を使用し、カスタム メトリクス関数を最小化するハイパーパラメーターの組み合わせを見つけます。ハイパーパラメーターには、学習アルゴリズムのオプションに加え、ネットワーク アーキテクチャ自体のパラメーターも含まれます。カスタム メトリクス関数は、ランダムに選択されたテスト セットの分類誤差を求めます。実験マネージャーでのカスタム メトリクスの定義の詳細については、メトリクス関数を使用した深層学習実験の評価を参照してください。

あるいは、関数 bayesopt を呼び出すことで、最適なハイパーパラメーター値をプログラムによって見つけることもできます。詳細については、ベイズ最適化を使用した深層学習を参照してください。

実験を開く

まず、例を開きます。実験マネージャーによって、検証と実行が可能な事前構成済みの実験を含むプロジェクトが読み込まれます。実験を開くには、[実験ブラウザー] ペインで、BayesOptExperiment をダブルクリックします。

組み込みの学習実験は、説明、ハイパーパラメーターのテーブル、セットアップ関数、および実験の結果を評価するためのメトリクス関数の集合で構成されます。ベイズ最適化を使用する実験には、実験の期間を制限する追加のオプションが含まれます。詳細については、組み込みの学習実験の構成を参照してください。

[説明] フィールドには、実験を説明するテキストが表示されます。この例の説明は次のようになります。

Find optimal hyperparameters and training options for convolutional neural network.
Hyperparamters determine the network section depth, initial learning rate,
stochastic gradient descent momentum, and L2 regularization strength.

[ハイパーパラメーター] セクションでは、実験で使用する手法とハイパーパラメーターのオプションを指定します。各ハイパーパラメーターについて、次のオプションを指定できます。

  • 範囲 — 実数値または整数値のハイパーパラメーターの下限と上限を示す 2 要素のベクトル、または categorical ハイパーパラメーターが取り得る値をリストする string 配列または cell 配列を入力します。

  • — 実数値のハイパーパラメーターの場合は real、整数値のハイパーパラメーターの場合は integer、categorical ハイパーパラメーターの場合は categorical を選択します。

  • 変換 — 変換を使用しない場合は none、対数変換を使用する場合は log を選択します。log を選択する場合、ハイパーパラメーター値は正でなければなりません。この設定では、ベイズ最適化アルゴリズムはハイパーパラメーターを対数スケールでモデル化します。

実験を実行すると、実験マネージャーはハイパーパラメーターの最適な組み合わせを検索します。実験の各試行では、前の試行の結果に基づいてハイパーパラメーター値の新しい組み合わせが使用されます。この例では、次のハイパーパラメーターを使用します。

  • SectionDepth — このパラメーターはネットワークの深さを制御します。ネットワーク内の層の合計数は 9*SectionDepth+7 です。実験セットアップ関数において、各層の畳み込みフィルターの数は 1/sqrt(SectionDepth) に比例するため、パラメーター数と各反復に必要な計算量は、セクション深さが異なる場合でもほぼ同じになります。

  • InitialLearnRate — 学習率が小さすぎる場合、学習に時間がかかります。学習率が大きすぎる場合、学習結果が準最適になったり、発散したりすることがあります。最適な学習率は、学習させるネットワークにも依りますが、データにも左右されます。

  • Momentum — 確率的勾配降下モーメンタムは、前の反復での更新に比例する寄与を現在の更新に含めることによって、パラメーター更新に慣性を追加します。慣性効果により、パラメーター更新がより円滑に行われるようになり、確率的勾配降下に固有のノイズが低減されます。

  • L2Regularization — L2 正則化を使用して過適合を防止します。正則化強度の空間を検索して、適切な値を求めます。データ拡張やバッチ正規化も、ネットワークの正則化に役立ちます。

[ベイズ最適化オプション] では、実行する試行の最大時間 (秒単位) と最大回数を入力することで、実験の期間を指定できます。ベイズ最適化の能力を最大限に活用するには、目的関数の評価を少なくとも 30 回行います。

[セットアップ関数] セクションでは、実験用の学習データ、ネットワーク アーキテクチャ、および学習オプションを構成する関数を指定します。この関数を MATLAB® エディターで開くには、[編集] をクリックします。この関数のコードは、セットアップ関数にも示されています。セットアップ関数への入力は、ハイパーパラメーター テーブルのフィールドをもつ構造体です。この関数は、イメージ分類問題用のネットワークに学習させるために使用する 3 つの出力を返します。この例のセットアップ関数には、以下のセクションが含まれています。

  • 学習データの読み込みでは、CIFAR-10 データ セットからイメージとラベルをダウンロードして抽出します。このデータセットは約 175 MB です。インターネット接続の速度によっては、ダウンロード プロセスに時間がかかることがあります。学習データについて、この例では、ランダムな平行移動と水平方向の反転を適用することにより、augmentedImageDatastoreを作成します。データ拡張は、ネットワークで過適合が発生したり、学習イメージの正確な詳細が記憶されたりすることを防止するのに役立ちます。ネットワーク検証を有効にするために、この例では 5000 個のイメージを拡張なしで使用します。このデータセットの詳細については、イメージ データセットを参照してください。

datadir = tempdir;
downloadCIFARData(datadir);

[XTrain,YTrain,XTest,YTest] = loadCIFARData(datadir);
idx = randperm(numel(YTest),5000);
XValidation = XTest(:,:,:,idx);
YValidation = YTest(idx);

imageSize = [32 32 3];
pixelRange = [-4 4];
imageAugmenter = imageDataAugmenter( ...
    RandXReflection=true, ...
    RandXTranslation=pixelRange, ...
    RandYTranslation=pixelRange);
augimdsTrain = augmentedImageDatastore(imageSize,XTrain,YTrain, ...
    DataAugmentation=imageAugmenter);

  • ネットワーク アーキテクチャの定義では、深層学習による分類用の畳み込みニューラル ネットワークのアーキテクチャを定義します。この例では、学習させるネットワークに、補助関数 convBlock によって生成された 3 つのブロックがあります。この関数のコードを見るには、畳み込み層のブロックの作成を参照してください。各ブロックには、SectionDepth 個の同一の畳み込み層が含まれます。各畳み込み層の後に、バッチ正規化層と ReLU 層が続きます。空間の出力サイズが入力サイズと常に同じになるように、畳み込み層はパディングを追加しています。ブロック間では、最大プーリング層は係数 2 で空間次元をダウンサンプリングします。各畳み込み層で必要な計算量が確実にほぼ同じとなるように、フィルターの数は 1 つのセクションから次のセクションに進むたびに 2 倍ずつ増加します。各畳み込み層のフィルターの数は 1/sqrt(SectionDepth) に比例します。それにより、深さの異なるネットワークでパラメーターの数がほぼ同じになり、反復ごとに必要となる計算量もほぼ同じになります。

numClasses = numel(unique(YTrain));
numF = round(16/sqrt(params.SectionDepth));
layers = [
    imageInputLayer(imageSize)

    convBlock(3,numF,params.SectionDepth)
    maxPooling2dLayer(3,Stride=2,Padding="same")

    convBlock(3,2*numF,params.SectionDepth)
    maxPooling2dLayer(3,Stride=2,Padding="same")

    convBlock(3,4*numF,params.SectionDepth)
    averagePooling2dLayer(8)

    fullyConnectedLayer(numClasses)
    softmaxLayer
    classificationLayer];

  • "学習オプションの指定" では、ベイズ最適化アルゴリズムによって生成された学習オプション InitialLearnRateMomentum、および L2Regularization の値を使用し、実験用のtrainingOptionsオブジェクトを定義します。この例では、ネットワークの学習を一定のエポック数行い、最後の方のエポックでは、エポックごとに検証を行い、学習率を 10 分の 1 に下げます。これにより、パラメーター更新のノイズが減少し、ネットワーク パラメーターが安定して損失関数が最小値に近づくようになります。

miniBatchSize = 256;
validationFrequency = floor(numel(YTrain)/miniBatchSize);
options = trainingOptions("sgdm", ...
    InitialLearnRate=params.InitialLearnRate, ...
    Momentum=params.Momentum, ...
    MaxEpochs=60, ...
    LearnRateSchedule="piecewise", ...
    LearnRateDropPeriod=40, ...
    LearnRateDropFactor=0.1, ...
    MiniBatchSize=miniBatchSize, ...
    L2Regularization=params.L2Regularization, ...
    Shuffle="every-epoch", ...
    Verbose=false, ...
    ValidationData={XValidation,YValidation}, ...
    ValidationFrequency=validationFrequency);

[メトリクス] セクションは、実験結果を評価するオプションの関数を指定します。ネットワークの学習が完了するたびに、実験マネージャーによってこれらの関数が評価されます。この例には、カスタム メトリクス関数 ErrorRate が含まれています。この関数は、5000 個のテスト イメージとラベルをランダムに選択し、学習したネットワークをそれらのイメージで評価し、ネットワークが誤分類するイメージの比率を計算します。この関数を MATLAB エディターで開くには、メトリクス関数の名前を選択して [編集] をクリックします。この関数のコードは、誤り率の計算にも示されています。

[最適化] フィールドと [方向] フィールドは、ベイズ最適化アルゴリズムが目的関数として使用するメトリクスを示します。この実験の場合、実験マネージャーは、ErrorRate メトリクスの値を最小化しようとします。

実験の実行

実験を実行すると、実験マネージャーは、選択されたメトリクスについて、ハイパーパラメーターの最適な組み合わせを検索します。実験の各試行では、前の試行の結果に基づいてハイパーパラメーター値の新しい組み合わせが使用されます。

学習に時間がかかる場合があります。実験の期間を制限するには、[ベイズ最適化オプション] で試行の最大時間または最大回数を減らします。ただし、試行回数が 30 回未満の場合、ベイズ最適化アルゴリズムが最適なハイパーパラメーターのセットに収束しない可能性があることに注意してください。

既定では、実験マネージャーは一度に 1 つの試行を実行します。Parallel Computing Toolbox™ を使用している場合は、複数の試行を同時に実行したり、クラスター内のバッチ ジョブとして実験をオフロードしたりできます。

  • 一度に 1 つの実験を実行するには、"実験マネージャー" ツールストリップの [モード][Sequential] を選択し、[実行] をクリックします。

  • 複数の試行を同時に実行するには、[モード][Simultaneous] を選択し、[実行] をクリックします。現在の並列プールがない場合、実験マネージャーは既定のクラスター プロファイルを使用して並列プールを起動します。その後、実験マネージャーは、並列プールにあるワーカーと同じ数の同時試行を実行します。最良の結果を得るには、実験を実行する前に、GPU と同じ数のワーカーで並列プールを起動します。詳細については、実験マネージャーを使用したネットワークの並列学習GPU 計算の要件 (Parallel Computing Toolbox)を参照してください。

  • 実験をバッチ ジョブとしてオフロードするには、[モード][Batch Sequential] または [Batch Simultaneous] を選択し、[クラスター][Pool Size] を指定して、[実行] をクリックします。詳細については、Offload Experiments as Batch Jobs to Clusterを参照してください。

結果テーブルに、各試行のメトリクス関数の値が表示されます。実験マネージャーは、選択されたメトリクスが最適値である試行を強調表示します。たとえば、この実験では、5 番目の試行で誤差率が最小になっています。

実験マネージャーは、選択されたメトリクスが最適となる試行を決定するために、最良点の基準 "min-observed" を使用します。詳細については、ベイズ最適化のアルゴリズム (Statistics and Machine Learning Toolbox)bestPoint (Statistics and Machine Learning Toolbox)を参照してください。

結果の評価

実験内で最適な試行の混同行列を表示するには、結果テーブル内で誤差率が最も低い行を選択します。次に、[結果の確認][検証データ] をクリックします。

追加の計算を実行するには、学習済みのネットワークをワークスペースにエクスポートします。

  1. [実験マネージャー] ツールストリップで、[エクスポート][学習済みネットワーク] をクリックします。

  2. ダイアログ ウィンドウで、エクスポートしたネットワークのワークスペース変数の名前を入力します。既定の名前は trainedNetwork です。

  3. エクスポートしたネットワークを補助関数 testSummary への入力として使用します。たとえば、MATLAB コマンド ウィンドウで次のように入力します。

testSummary(trainedNetwork)

この関数のコードを見るには、テスト統計量の要約を参照してください。この関数は、いくつかの方法でネットワークを評価します。

  • テスト セット全体のラベルを予測し、テスト誤差を計算します。実験マネージャーはネットワークにテスト セット全体を当てることなく最適なネットワークを判断するため、テスト誤差はカスタム メトリクス ErrorRate の値よりも高くなる可能性があります。

  • 標準誤差 (testErrorSE) と、汎化誤差率の近似した 95% 信頼区間 (testError95CI) を計算します。この計算では、テスト セットの各イメージの分類を特定の成功確率をもつ独立事象として扱います。この仮定を使用することで、誤って分類されるイメージの数が二項分布に従います。この方法は通常、"Wald 法" と呼ばれます。

  • この方法では、いくつかのテスト イメージを、予測されたクラスおよびそのクラスである確率と共に表示します。

この関数は、MATLAB コマンド ウィンドウに、これらの統計量の概要を表示します。

******************************************
Test error rate: 0.1829
Standard error: 0.0039
95% confidence interval: [0.1753, 0.1905]
******************************************

実験結果に関する観測結果を記録するには、注釈を追加します。

  1. 結果テーブルで、最適な結果が得られた試行の [ErrorRate] セルを右クリックします。

  2. [注釈の追加] を選択します。

  3. [注釈] ペインで、テキスト ボックスに観測結果を入力します。

詳細については、実験結果の並べ替え、フィルター処理、および注釈追加を参照してください。

実験を閉じる

[実験ブラウザー] ペインでプロジェクトの名前を右クリックし、[プロジェクトを閉じる] を選択します。実験マネージャーによって、プロジェクトに含まれるすべての実験と結果が閉じられます。

セットアップ関数

この関数は、実験用の学習データ、ネットワーク アーキテクチャ、および学習オプションを構成します。この関数への入力は、ハイパーパラメーター テーブルのフィールドをもつ構造体です。この関数は、イメージ分類問題用のネットワークに学習させるために使用する 3 つの出力を返します。

function [augimdsTrain,layers,options] = BayesOptExperiment_setup(params)

学習データの読み込み

datadir = tempdir;
downloadCIFARData(datadir);

[XTrain,YTrain,XTest,YTest] = loadCIFARData(datadir);
idx = randperm(numel(YTest),5000);
XValidation = XTest(:,:,:,idx);
YValidation = YTest(idx);

imageSize = [32 32 3];
pixelRange = [-4 4];
imageAugmenter = imageDataAugmenter( ...
    RandXReflection=true, ...
    RandXTranslation=pixelRange, ...
    RandYTranslation=pixelRange);
augimdsTrain = augmentedImageDatastore(imageSize,XTrain,YTrain, ...
    DataAugmentation=imageAugmenter);

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

numClasses = numel(unique(YTrain));
numF = round(16/sqrt(params.SectionDepth));
layers = [
    imageInputLayer(imageSize)

    convBlock(3,numF,params.SectionDepth)
    maxPooling2dLayer(3,Stride=2,Padding="same")

    convBlock(3,2*numF,params.SectionDepth)
    maxPooling2dLayer(3,Stride=2,Padding="same")

    convBlock(3,4*numF,params.SectionDepth)
    averagePooling2dLayer(8)

    fullyConnectedLayer(numClasses)
    softmaxLayer
    classificationLayer];

学習オプションの指定

miniBatchSize = 256;
validationFrequency = floor(numel(YTrain)/miniBatchSize);
options = trainingOptions("sgdm", ...
    InitialLearnRate=params.InitialLearnRate, ...
    Momentum=params.Momentum, ...
    MaxEpochs=60, ...
    LearnRateSchedule="piecewise", ...
    LearnRateDropPeriod=40, ...
    LearnRateDropFactor=0.1, ...
    MiniBatchSize=miniBatchSize, ...
    L2Regularization=params.L2Regularization, ...
    Shuffle="every-epoch", ...
    Verbose=false, ...
    ValidationData={XValidation,YValidation}, ...
    ValidationFrequency=validationFrequency);

end

畳み込み層のブロックの作成

この関数は、numConvLayers 個の畳み込み層のブロックを作成します。各層には filterSizenumFilters 個のフィルターを指定し、それぞれの後にバッチ正規化層と ReLU 層を配置します。

function layers = convBlock(filterSize,numFilters,numConvLayers)
layers = [
    convolution2dLayer(filterSize,numFilters,Padding="same")
    batchNormalizationLayer
    reluLayer];
layers = repmat(layers,numConvLayers,1);
end

誤り率の計算

このメトリクス関数は、trainedNetworktrainingInfo、および parameters のフィールドを含む構造体を入力として受け取ります。

  • trainedNetwork は、関数 trainNetwork によって返される SeriesNetwork オブジェクトまたは DAGNetwork オブジェクトです。

  • trainingInfo は、関数 trainNetwork によって返される学習情報を含む構造体です。

  • parameters は、ハイパーパラメーター テーブルのフィールドをもつ構造体です。

この関数は、5,000 個のテスト イメージとラベルを選択し、テスト セットで学習させたネットワークを評価し、予測イメージ ラベルを計算し、テスト データの誤差率を計算します。

function metricOutput = ErrorRate(trialInfo)

datadir = tempdir;
[~,~,XTest,YTest] = loadCIFARData(datadir);

idx = randperm(numel(YTest),5000);
XTest = XTest(:,:,:,idx);
YTest = YTest(idx);
YPredicted = classify(trialInfo.trainedNetwork,XTest);

metricOutput = 1 - mean(YPredicted == YTest);
end

テスト統計量の要約

この関数は、テストの誤差率、標準誤差、および近似した 95% 信頼区間を計算し、MATLAB コマンド ウィンドウに、これらの統計量の概要を表示します。この関数は、予測されたクラスおよびそのクラスである確率と共に、いくつかのテスト イメージも表示します。

function testSummary(net)

datadir = tempdir; 
[~,~,XTest,YTest] = loadCIFARData(datadir);

[YPredicted,probs] = classify(net,XTest);
testError = 1 - mean(YPredicted == YTest);
NTest = numel(YTest);
testErrorSE = sqrt(testError*(1-testError)/NTest);
testError95CI = [testError - 1.96*testErrorSE, testError + 1.96*testErrorSE];

fprintf("\n******************************************\n\n");
fprintf("Test error rate: %.4f\n",testError);
fprintf("Standard error: %.4f\n",testErrorSE);
fprintf("95%% confidence interval: [%.4f, %.4f]\n",testError95CI(1),testError95CI(2));
fprintf("\n******************************************\n\n");

figure
idx = randperm(numel(YTest),9);
for i = 1:numel(idx)
    subplot(3,3,i)
    imshow(XTest(:,:,:,idx(i)));
    prob = num2str(100*max(probs(idx(i),:)),3);
    predClass = string(YPredicted(idx(i)));
    label = predClass+": "+prob+"%";
    title(label)
end
end

参考

アプリ

関数

関連するトピック