local L1HingeEmbeddingCriterion, parent = torch.class('nn.L1HingeEmbeddingCriterion', 'nn.Criterion') function L1HingeEmbeddingCriterion:__init(margin) parent.__init(self) margin = margin or 1 self.margin = margin self.gradInput = {torch.Tensor(), torch.Tensor()} end function L1HingeEmbeddingCriterion:updateOutput(input,y) self.output=input[1]:dist(input[2],1); if y == -1 then self.output = math.max(0,self.margin - self.output); end return self.output end local function mathsign(t) if t>0 then return 1; end if t<0 then return -1; end return 2*torch.random(2)-3; end function L1HingeEmbeddingCriterion:updateGradInput(input, y) self.gradInput[1]:resizeAs(input[1]) self.gradInput[2]:resizeAs(input[2]) self.gradInput[1]:copy(input[1]) self.gradInput[1]:add(-1, input[2]) local dist = self.gradInput[1]:norm(1); self.gradInput[1]:apply(mathsign) -- L1 gradient if y == -1 then -- just to avoid a mul by 1 if dist > self.margin then self.gradInput[1]:zero() else self.gradInput[1]:mul(-1) end end self.gradInput[2]:zero():add(-1, self.gradInput[1]) return self.gradInput end