使用自动微分的自定义训练和计算
自动区分功能使创建自定义训练循环,自定义层和其他深度学习自定义更加容易。
通常,自定义深度学习培训的最简单方法是创建dlnetwork
。在网络中包括所需的层。然后,通过使用某种梯度下降来在自定义循环中执行训练,其中梯度是目标函数的梯度。目标函数可以是分类误差,交叉熵或网络权重的任何其他相关标量函数。请参见具有dlarray支持的功能列表。
此示例是自定义训练循环的高级版本。在此,f
是目标函数,例如损失,g
是目标函数相对于网络中权重的梯度net
。该 update
函数表示某种类型的梯度下降。
% High-level training loop
n = 1;
while (n < nmax)
[f,g] = dlfeval(@model,net,dlX,t);
net = update(net,g);
n = n + 1;
end
可以使用 dlfeval
计算对象和梯度的数值,如果想要自动计算微分,dlX
必须是一个dlarray类型。
dlX = dlarray(X);
目标函数dlgradient
调用计算梯度。该dlgradient
调用必须在要dlfeval
评估的函数内部 。
function [f,g] = model(net,dlX,T)
% Calculate objective using supported functions for dlarray
y = forward(net,dlX);
f = fcnvalue(y,T); % crossentropy or similar
g = dlgradient(f,net.Learnables); % Automatic gradient
end
对于使用一个例子dlnetwork
用一个简单的 dlfeval
- dlgradient
-dlarray
语法,请参阅梯度-CAM揭示了为什么深度学习决策背后。有关使用自定义训练循环的更复杂示例,请参阅训练生成对抗网络(GAN)。有关使用自动微分的自定义训练的更多详细信息,请参阅定义自定义训练循环,损失函数和网络。
使用 dlgradient
和dlfeval
来求解自动微分
要使用自动微分,必须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函数,通过 x0
作为dlarray
。
x0 = dlarray([-1,2]);
[fval,gradval] = dlfeval(@rosenbrock,x0)
fval =
1x1 dlarray
104
gradval =
1x2 dlarray
396 200
有关使用自动微分的示例,请参阅Grad-CAM揭示了深度学习决策背后的原因。
导数轨迹
为了从数值上评估梯度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支持的功能列表。要使用不受支持的函数f,请尝试使用受支持的函数实现f。
自动微分的特征
您只能对标量值函数使用自动微分来评估梯度。中间计算可以具有任意数量的变量,但是最终函数值必须为标量。如果需要取向量值函数的导数,则一次取一个分量的导数。在这种情况下,请考虑将“
dlgradient
'RetainData'
名称/值”对参数设置为true
。- 调用以
dlgradient
评估特定点的导数。当没有理论值时,软件通常会对导数的值进行任意选择。例如,relu
函数relu(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
当前,dlarray
不允许高阶导数。换句话说,您不能通过调用dlgradient
两次来计算二阶导数。