open source pkg v1
This commit is contained in:
92
pkg/OpenFace/model_training/CCNF/CCRF/lib/gradientCCRF.m
Normal file
92
pkg/OpenFace/model_training/CCNF/CCRF/lib/gradientCCRF.m
Normal file
@@ -0,0 +1,92 @@
|
||||
function [ logGradientAlphas, logGradientBetas, SigmaInv, ChDecomp ] = gradientCCRF( alphas, betas, lambda_a, lambda_b, precalcQ2withoutBeta, xq, yq, mask, precalcYQ, useIndicator, PrecalcQ2Flat)
|
||||
%GRADIENTPRF Summary of this function goes here
|
||||
% Detailed explanation goes here
|
||||
|
||||
% Calculate the Sigma inverse now
|
||||
% [SigmaInv2] = CalcSigmaCCRF(alphas, betas, precalcQ2withoutBeta, mask);
|
||||
|
||||
% This is an optimised version as it does not use the whole matrix but
|
||||
% a lower diagonal part due to symmetry
|
||||
numElemsInSeq = size(precalcQ2withoutBeta{1}, 1);
|
||||
[SigmaInv] = CalcSigmaCCRFflat(alphas, betas, numElemsInSeq, PrecalcQ2Flat, mask, useIndicator);
|
||||
|
||||
% Get the actual sigma from out SigmaInv
|
||||
|
||||
% Sigma = inv(SigmaInv);
|
||||
% Below is an optimised version of the above using Cholesky decomposition
|
||||
% which decomposes a matrix into a upper triangular (R) and its
|
||||
% conjugate transpose R'; A = R'*R for real numbers, thus
|
||||
% inv(A) = inv(R)inv(R')
|
||||
ChDecomp=chol(SigmaInv);
|
||||
I=eye(size(SigmaInv));
|
||||
|
||||
% Rinv = (R\I);
|
||||
% Sigma = Rinv*Rinv';
|
||||
% This is a very slightly faster version of the above
|
||||
Sigma=ChDecomp\(ChDecomp'\I);
|
||||
|
||||
b = CalcbCCRF(alphas, xq, mask, useIndicator);
|
||||
|
||||
% mu = SigmaInv \ b = Sigma * b;
|
||||
% as we've calculate Sigma already, this is equivalent of the above
|
||||
mu = Sigma * b;
|
||||
|
||||
logGradientAlphas = zeros(size(alphas));
|
||||
logGradientBetas = zeros(size(betas));
|
||||
|
||||
K1 = numel(alphas);
|
||||
K2 = numel(betas);
|
||||
|
||||
% calculating the derivative of L with respect to alpha_k
|
||||
for k = 1:K1
|
||||
|
||||
if(useIndicator)
|
||||
dQ1da = diag(mask(:,k));
|
||||
dbda = xq(:,k).*mask(:,k);
|
||||
gaussGradient = -yq'*dQ1da*yq +2*yq'*dbda -2 * dbda' * mu + mu'*dQ1da*mu;
|
||||
zGradient = Sigma(:)'*dQ1da(:);
|
||||
else
|
||||
% if we don't use the masks here's a speedup
|
||||
gaussGradient = -yq'*yq +2*yq'*xq(:,k) -2 * xq(:,k)' * mu + sum(mu.^2);
|
||||
|
||||
% simplification as trace(Sigma * I) = trace(Sigma)
|
||||
zGradient = trace(Sigma);
|
||||
end
|
||||
|
||||
% add the Z derivative now
|
||||
dLda = zGradient + gaussGradient;
|
||||
|
||||
% add regularisation
|
||||
dLda = dLda - lambda_a * alphas(k);
|
||||
|
||||
logGradientAlphas(k) = alphas(k) * dLda;
|
||||
|
||||
end
|
||||
|
||||
% This was done for gradient checking
|
||||
% [alphasG, betaG] = gradientAnalytical(nFrames, S, alphas, beta, xq, yq, mask);
|
||||
|
||||
% calculating the derivative of log(L) with respect to the betas
|
||||
for k=1:K2
|
||||
|
||||
% Bs = Bs(:,:,k);
|
||||
% dSdb = q2./betas(k); we precalculate this, as it does not change
|
||||
% over the course of optimisation (dSdb - dSigma/dbeta)
|
||||
dSdb = precalcQ2withoutBeta{k};
|
||||
|
||||
% -yq'*dSdb*yq can be precalculated as they don't change through
|
||||
% iterations (precalcQ2withoutBeta is dSdb
|
||||
% gaussGradient = -yq'*dSdb*yq + mu'*dSdb*mu;
|
||||
% this does the above line
|
||||
gaussGradient = precalcYQ(k) + mu'*dSdb*mu;
|
||||
|
||||
% zGradient = trace(Sigma*dSdb);
|
||||
zGradient = Sigma(:)'*dSdb(:); % equivalent but faster to the above line
|
||||
dLdb = gaussGradient + zGradient;
|
||||
|
||||
% add regularisation term
|
||||
dLdb = dLdb - lambda_b * betas(k);
|
||||
|
||||
logGradientBetas(k) = betas(k) * dLdb;
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user