Main Content

Deep Learning Toolbox での自動微分の使用

自動微分を使用したカスタム学習と計算

自動微分は、カスタム学習ループ、カスタム層、および深層学習のその他のカスタマイズの作成を容易にします。

一般的に、深層学習における学習をカスタマイズする最も簡単な方法は、dlnetwork を作成することです。必要な層をネットワークに含めます。次に、ある種の勾配降下を使用して、カスタム ループの学習を実行します。ここで、勾配は目的関数の勾配です。目的関数には、分類誤差、クロスエントロピー、またはネットワークの重みのその他の関連スカラー関数を使用できます。dlarray をサポートする関数の一覧を参照してください。

次の例は、高度なカスタム学習ループを示します。ここで、f は損失などの目的関数、g はネットワーク net の重みについての目的関数の勾配です。関数 update は、ある種の勾配降下を表します。

% High-level training loop
n = 1;
while (n < nmax)
    [f,g] = dlfeval(@model,net,X,T);
    net = update(net,g);
    n = n + 1;
end

dlfeval を呼び出して目的関数と勾配の数値を計算します。勾配の自動計算を有効にするには、データ Xdlarray でなければなりません。

X = dlarray(X);

目的関数には dlgradient の呼び出しによる勾配の計算が含まれます。dlgradient の呼び出しは、dlfeval で評価を行う関数に含まれていなければなりません。

function [f,g] = model(net,X,T)
% Calculate objective using supported functions for dlarray
    Y = forward(net,X);
    f = fcnvalue(Y,T); % crossentropy or similar
    g = dlgradient(f,net.Learnables); % Automatic gradient
end

dlfeval-dlgradient-dlarray 構文とカスタム学習ループを使った dlnetwork の使用例については、カスタム学習ループを使用したネットワークの学習を参照してください。自動微分を使用するカスタム学習の詳細は、カスタム学習ループ、損失関数、およびネットワークの定義を参照してください。

自動微分への dlgradientdlfeval の併用

自動微分を使用するには、関数に含まれる dlgradient を呼び出し、dlfeval を使用して関数を評価しなければなりません。微分を取得する点を dlarray オブジェクトとして表します。これにより、データ構造が管理され、評価のトレースが有効になります。たとえば、Rosenbrock 関数は最適化の一般的なテスト関数です。

function [f,grad] = rosenbrock(x)

f = 100*(x(2) - x(1).^2).^2 + (1 - x(1)).^2;
grad = dlgradient(f,x);

end

x0 = [–1,2] で Rosenbrock 関数の値と勾配を計算します。Rosenbrock 関数で自動微分を有効にするには、x0dlarray として渡します。

x0 = dlarray([-1,2]);
[fval,gradval] = dlfeval(@rosenbrock,x0)
fval =

  1x1 dlarray

   104


gradval =

  1x2 dlarray

   396   200

自動微分の使用例については、カスタム学習ループを使用したネットワークの学習を参照してください。

微分のトレース

勾配を数値的に評価するために、dlarray は、自動微分の背景で説明するように、リバース モードの微分用のデータ構造を構築します。このデータ構造は、微分計算の "トレース" です。自動微分と微分のトレースを使用する際には、次のガイドラインに留意してください。

  • 新しい dlarray を目的関数の計算に含めたり、そのオブジェクトについて微分を試みないでください。次に例を示します。

    function [dy,dy1] = fun(x1)
    x2 = dlarray(0);
    y = x1 + x2;
    dy = dlgradient(y,x2); % Error: x2 is untraced
    dy1 = dlgradient(y,x1); % No error even though y has an untraced portion
    end
  • extractdata をトレースされた引数と使用しないでください。これを行うと、トレースが破損します。次に例を示します。

    fun = @(x)dlgradient(x + atan(extractdata(x)),x);
    % Gradient for any point is 1 due to the leading 'x' term in fun.
    dlfeval(fun,dlarray(2.5))
    ans =
    
      1x1 dlarray
    
         1

    ただし、extractdata を使用すると、従属変数から新しい独立変数を導入できます。

  • 並列処理中にトレース対象の dlarray オブジェクトをクライアントとワーカーの間で移動すると、トレースが中断します。トレース対象の dlarray オブジェクトは、ワーカーに保存され、未トレースの dlarray オブジェクトとしてクライアントに読み込まれます。並列処理中にトレースが中断されないようにするには、必要な勾配をワーカー上ですべて計算してから、それらの勾配をクライアント上で結合します。例については、カスタム学習ループを使用したネットワークの並列学習を参照してください。

  • サポートされている関数のみを使用してください。サポートされている関数のリストについては、dlarray をサポートする関数の一覧を参照してください。サポートされていない関数 f を使用するには、サポートされている関数を使用して f の実装を試みます。

自動微分の特性

  • 自動微分を使用した勾配の評価は、スカラー値関数に対してのみ行えます。中間の計算には任意の数の変数を使用できますが、最終関数値はスカラーでなければなりません。ベクトル値関数の微分を取得する必要がある場合、一度に 1 つの成分の微分を取得します。この場合、 dlgradient の名前と値のペアの引数 'RetainData'true に設定することを検討してください。

  • dlgradient を呼び出すと、特定の点での微分が評価されます。理論値がない場合、一般的に、微分の値について任意の選択が行われます。たとえば、関数 relurelu(x) = max(x,0)x = 0 では微分不可能です。一方、dlgradient は微分の値を返します。

    x = dlarray(0);
    y = dlfeval(@(t)dlgradient(relu(t),t),x)
    y =
    
      1x1 dlarray
    
         0

    近傍点 eps での値は異なります。

    x = dlarray(eps);
    y = dlfeval(@(t)dlgradient(relu(t),t),x)
    y =
    
      1x1 dlarray
    
         1

参考

| | |

関連するトピック