使用自动微分的自定义训练和计算

自动区分功能使创建自定义训练循环,自定义层和其他深度学习自定义更加容易。
通常,自定义深度学习培训的最简单方法是创建dlnetwork。在网络中包括所需的层。然后,通过使用某种梯度下降来在自定义循环中执行训练,其中梯度是目标函数的梯度。目标函数可以是分类误差,交叉熵或网络权重的任何其他相关标量函数。请参见具有dlarray支持的功能列表
此示例是自定义训练循环的高级版本。在此,f 是目标函数,例如损失,g是目标函数相对于网络中权重的梯度net。该 update函数表示某种类型的梯度下降。

  1. % High-level training loop
  2. n = 1;
  3. while (n < nmax)
  4. [f,g] = dlfeval(@model,net,dlX,t);
  5. net = update(net,g);
  6. n = n + 1;
  7. end

可以使用 dlfeval计算对象和梯度的数值,如果想要自动计算微分,dlX必须是一个dlarray类型。

  1. dlX = dlarray(X);

目标函数dlgradient调用计算梯度。该dlgradient调用必须在要dlfeval评估的函数内部 。

  1. function [f,g] = model(net,dlX,T)
  2. % Calculate objective using supported functions for dlarray
  3. y = forward(net,dlX);
  4. f = fcnvalue(y,T); % crossentropy or similar
  5. g = dlgradient(f,net.Learnables); % Automatic gradient
  6. end

对于使用一个例子dlnetwork用一个简单的 dlfeval- dlgradient-dlarray 语法,请参阅梯度-CAM揭示了为什么深度学习决策背后。有关使用自定义训练循环的更复杂示例,请参阅训练生成对抗网络(GAN)。有关使用自动微分的自定义训练的更多详细信息,请参阅定义自定义训练循环,损失函数和网络

使用 dlgradientdlfeval来求解自动微分

要使用自动微分,必须dlgradient在函数内部调用并使用评估函数dlfeval。表示将导数作为dlarray对象的点,该对象管理数据结构并启用评估跟踪。例如,Rosenbrock函数是用于优化的常见测试函数。

  1. function [f,grad] = rosenbrock(x)
  2. f = 100*(x(2) - x(1).^2).^2 + (1 - x(1)).^2;
  3. grad = dlgradient(f,x);
  4. end

计算在x0 = [–1,2]处的Rosenbrock函数的值和梯度。启用自动分化在Rosenbrock函数,通过 x0作为dlarray

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

fval =

1x1 dlarray

104

gradval =

1x2 dlarray

396 200

有关使用自动微分的示例,请参阅Grad-CAM揭示了深度学习决策背后的原因

导数轨迹

为了从数值上评估梯度dlarray,如自动微分背景中所述,构造一个用于反向模式微分的数据结构。此数据结构是微分计算的 轨迹。使用自动微分和派生跟踪时,请记住以下准则:

  • 不要dlarray在目标函数计算中引入新的内容,并尝试针对该对象进行区分。例如:

    1. function [dy,dy1] = fun(x1)
    2. x2 = dlarray(0);
    3. y = x1 + x2;
    4. dy = dlgradient(y,x2); % Error: x2 is untraced
    5. dy1 = dlgradient(y,x1); % No error even though y has an untraced portion
    6. end
  • 不要extractdata 与跟踪参数一起使用。这样做会破坏跟踪。例如:

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

    ans =

1x1 dlarray

  1. 1
  • 但是,您可以用来extractdata从一个依赖变量中引入一个新的独立变量。
  • 仅使用支持的功能。请参见具有dlarray支持的功能列表。要使用不受支持的函数f,请尝试使用受支持的函数实现f

    自动微分的特征

  • 您只能对标量值函数使用自动微分来评估梯度。中间计算可以具有任意数量的变量,但是最终函数值必须为标量。如果需要取向量值函数的导数,则一次取一个分量的导数。在这种情况下,请考虑将“ dlgradient 'RetainData'名称/值”对参数设置为 true

  • 调用以dlgradient 评估特定点的导数。当没有理论值时,软件通常会对导数的值进行任意选择。例如, relu函数relu(x) = max(x,0)不可在上微分x = 0。但是,dlgradient 返回导数的值。
    1. x = dlarray(0);
    2. y = dlfeval(@(t)dlgradient(relu(t),t),x)

    y =

1x1 dlarray

  1. 0

在附近点eps处的值是不同的

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

y =

1x1 dlarray

  1. 1

当前,dlarray不允许高阶导数。换句话说,您不能通过调用dlgradient 两次来计算二阶导数。