% Calculation of gradient and objective for All-Threshold SHC % MMMF. % % function [obj,grad,lossobj,regobj] = m3fshc(v,Y,lambda,l,varargin) % v - vector of parameters [n*p+m*p+n*(l-1),1] % Y - rating matrix (labels) [n,m] % lambda - regularization parameter [scalar] % l - # of unique rating values (1..l) % obj - value of objective at v [scalar] % grad - gradient at v [n*p+m*p+n*(l-1),1] % lossobj - loss component of objective [scalar] % regobj - regularization component of objective [scalar] % % Written by Jason Rennie, January 2005 % Last modified: Tue Jan 16 09:25:25 2007 function [obj,grad,lossobj,regobj] = m3fshc(v,Y,lambda,l,varargin) fn = mfilename; if nargin < 4 error('insufficient parameters') end % Parameters that can be set via varargin verbose = 1; % Process varargin paramgt; t0 = clock; [n,m] = size(Y); p = (length(v)-n.*(l-1))./(n+m); if p ~= floor(p) | p < 1 error('dimensions of v and Y don''t match l'); end U = reshape(v(1:n*p),n,p); V = reshape(v(n*p+1:n*p+m*p),m,p); theta = reshape(v(n*p+m*p+1:n*p+m*p+n*(l-1)),n,l-1); clear v; X = U*V'; Ygt0 = Y>0; BX = X.*Ygt0; %reallyzero = (X==0).*Ygt0; %fprintf(1,'m3fshc: sum(sum(reallyzero))=%d\n',full(sum(sum(reallyzero)))); clear X; dU = lambda.*U; % [n,p] dV = lambda.*V; % [m,p] dtheta = zeros(n,l-1); % [n,l-1] regobj = lambda.*(sum(U(:).^2)+sum(V(:).^2))./2; % [scalar] lossobj = 0; for k=1:l-1 S = Ygt0-2.*(Y>k); % Next line is the memory bottleneck BZ = (theta(:,k)*ones(1,m)).*S-BX.*S; % [n,m] (sparse) lossobj = lossobj + sum(sum(h(BZ))); tmp = hprime(BZ).*S; % [n,m] clear BZ S; dU = dU - tmp*V; % [n,p] dV = dV - tmp'*U; % [m,p] dtheta(:,k) = tmp*ones(m,1); clear tmp; end obj = regobj + lossobj; grad = [dU(:); dV(:); dtheta(:)]; if verbose fprintf(1,'%s: lambda=%.2e obj=%.2e grad''*grad=%.2e time=%.1f\n',fn,lambda,obj,grad'*grad,etime(clock,t0)); end % ret = (z>0).*(z<1).*((1-z).^2)/2.0 + (z<=0).*(0.5-z); function [ret] = h(z) zin01 = (z>0)-(z>=1); zle0 = z<0; ret = zin01./2 - zin01.*z + zin01.*z.^2./2 + zle0./2 - zle0.*z; % ret = (z>0).*(z<1).*(z-1) - (z<=0); function [ret] = hprime(z) zin01 = (z>0)-(z>=1); zle0 = z<0; ret = zin01.*z - zin01 - zle0; % ChangeLog % 12/8/06 - remove reallyzero (print warning if it would be necessary) % 3/23/05 - made calcultions take better advantage of sparseness % 3/18/05 - fixed bug in objective (wasn't squaring fro norms) % 3/1/05 - added objective calculation % 2/23/05 - fixed bug in hprime()