Matlab 计算两层神经网络的梯度

Matlab 计算两层神经网络的梯度,matlab,neural-network,vectorization,octave,gradient-descent,Matlab,Neural Network,Vectorization,Octave,Gradient Descent,我想知道下面的MATLAB/倍频程代码是否可以矢量化 function grads = compute_grads(data, ann, lambda) [~, N] = size(data.X); % First propagate the data S = evaluate(data.X, ann); G = -(data.Y - S{2}); % Second layer gradient is easy. l2g.W = G*S{1}';

我想知道下面的MATLAB/倍频程代码是否可以矢量化

function grads = compute_grads(data, ann, lambda)
    [~, N] = size(data.X);
    % First propagate the data
    S = evaluate(data.X, ann);
    G = -(data.Y - S{2});

    % Second layer gradient is easy.
    l2g.W = G*S{1}';
    l2g.b = mean(G)';
    G = G' * ann{2}.W;

    [m, d] = size(ann{1}.W);
    [K, ~] = size(ann{2}.W);

    % I would like to vectorize this calculation.
    l1g.W = zeros(m, d);
    l1g.b = mean(G)';
    for i = 1:N
        x = data.X(:, i);
        g = G(i, :);
        l1 = S{1}(:, i);
        g = g * diag(l1 > 0);
        l1g.W = l1g.W + g'*x';
    end
    grads = {l1g, l2g};
    for k=1:length(grads)
        grads{k}.W = grads{k}.W/N + 2*lambda*ann{k}.W;
    end
end
该代码计算两层神经网络的梯度。第二层有一个softmax激活函数,如第4行
G=-(data.Y-S{2})所示。第一层由
for
循环中的gunk执行ReLU激活,该循环一次对每个样本进行操作


正如你所看到的,中间有一个显式的<代码> >循环。是否可以使用任何数组/矩阵函数来代替隐式循环?

循环可以简化为:

l1g.W = (data.X * (G .* (S{1} > 0).')).';
l1g.W = sum(some_structrue_created_by_vectorizing(g'*x'));
l1g.W = (data.X * (G .* (S{1} > 0).')).';
说明:

在矢量化中,我们应该避免不必要的操作。例如在

g = g * diag(l1 > 0);;
我们可以使用乘法来实现同样的目标:

g = g .* (l1.' > 0);
%or
g = g .* (l1 > 0).';
使用它,我们可以将一些操作置于循环之外:

l1g.W = zeros(m, d);

G = G .* (S{1} > 0).';

for i = 1:N
    x = data.X(:, i);
    g = G(i, :);
    l1g.W = l1g.W + g'*x';
end
所以我们有这样的东西:

W=0;
for i = 1:N
    W = W + something(i);
end
这可以写成:

W = sum(something);
我们的循环可以简化为:

l1g.W = (data.X * (G .* (S{1} > 0).')).';
l1g.W = sum(some_structrue_created_by_vectorizing(g'*x'));
l1g.W = (data.X * (G .* (S{1} > 0).')).';
我们可以使用诸如
bsxfun
之类的函数来创建这样的结构(即3D矩阵),但这种结构通常需要大量内存,循环可能比矢量化更有效。但是等一下,我们想求
g
x
的乘积之和,所以我们可以[而且应该一直]考虑使用向量矩阵或矩阵乘法,因为它们是非常快速的运算。 由于我们正在执行
g
x
的外积,因此矩阵乘法是正确的选择

G = G .* (S{1} > 0).';
l1g.W  = (data.X * G).'


循环可以简化为:

l1g.W = (data.X * (G .* (S{1} > 0).')).';
l1g.W = sum(some_structrue_created_by_vectorizing(g'*x'));
l1g.W = (data.X * (G .* (S{1} > 0).')).';
说明:

在矢量化中,我们应该避免不必要的操作。例如在

g = g * diag(l1 > 0);;
我们可以使用乘法来实现同样的目标:

g = g .* (l1.' > 0);
%or
g = g .* (l1 > 0).';
使用它,我们可以将一些操作置于循环之外:

l1g.W = zeros(m, d);

G = G .* (S{1} > 0).';

for i = 1:N
    x = data.X(:, i);
    g = G(i, :);
    l1g.W = l1g.W + g'*x';
end
所以我们有这样的东西:

W=0;
for i = 1:N
    W = W + something(i);
end
这可以写成:

W = sum(something);
我们的循环可以简化为:

l1g.W = (data.X * (G .* (S{1} > 0).')).';
l1g.W = sum(some_structrue_created_by_vectorizing(g'*x'));
l1g.W = (data.X * (G .* (S{1} > 0).')).';
我们可以使用诸如
bsxfun
之类的函数来创建这样的结构(即3D矩阵),但这种结构通常需要大量内存,循环可能比矢量化更有效。但是等一下,我们想求
g
x
的乘积之和,所以我们可以[而且应该一直]考虑使用向量矩阵或矩阵乘法,因为它们是非常快速的运算。 由于我们正在执行
g
x
的外积,因此矩阵乘法是正确的选择

G = G .* (S{1} > 0).';
l1g.W  = (data.X * G).'