diff options
author | Soumith Chintala <soumith@gmail.com> | 2015-02-05 18:14:45 +0300 |
---|---|---|
committer | Soumith Chintala <soumith@gmail.com> | 2015-02-05 18:14:45 +0300 |
commit | 307532ab58a46c5b560a723418a1ab8ede9167fd (patch) | |
tree | 3c9d148f03510f38d1eb5462350ba819ce961493 | |
parent | 5137714bae52c59bc663c0a57dd730712130457d (diff) | |
parent | 227fedec91f6d7f38e8bb62fcfd32c2316af634f (diff) |
Merge pull request #157 from szagoruyko/multimargin
L2 MultiMarginCriterion
-rw-r--r-- | MultiMarginCriterion.lua | 6 | ||||
-rwxr-xr-x | doc/criterion.md | 4 | ||||
-rw-r--r-- | generic/MultiMarginCriterion.c | 9 | ||||
-rw-r--r-- | test.lua | 7 |
4 files changed, 20 insertions, 6 deletions
diff --git a/MultiMarginCriterion.lua b/MultiMarginCriterion.lua index e8de9d9..e308870 100644 --- a/MultiMarginCriterion.lua +++ b/MultiMarginCriterion.lua @@ -1,11 +1,15 @@ local MultiMarginCriterion, parent = torch.class('nn.MultiMarginCriterion', 'nn.Criterion') -function MultiMarginCriterion:__init() +function MultiMarginCriterion:__init(p) + assert(p == nil or p == 1 or p == 2, 'only p=1 and p=2 supported') + self.p = p or 1 parent.__init(self) self.sizeAverage = true end function MultiMarginCriterion:updateOutput(input, target) + -- backward compatibility + self.p = self.p or 1 return input.nn.MultiMarginCriterion_updateOutput(self, input, target) end diff --git a/doc/criterion.md b/doc/criterion.md index 586dba1..2fb7477 100755 --- a/doc/criterion.md +++ b/doc/criterion.md @@ -220,13 +220,13 @@ i.e. the mlp successfully separates the two data points such that they both have ## MultiMarginCriterion ## ```lua -criterion = MultiMarginCriterion() +criterion = MultiMarginCriterion(p) ``` Creates a criterion that optimizes a multi-class classification hinge loss (margin-based loss) between input `x` (a Tensor of dimension 1) and output `y` (which is a target class index, 1 <= y <= x:size(1)) : ```lua -loss(x,y) = forward(x,y) = sum_i(max(0, 1 - (x[y] - x[i]))) / x:size(1) +loss(x,y) = forward(x,y) = sum_i(max(0, 1 - (x[y] - x[i]))^p) / x:size(1) ``` where i = 1 to x:size(1) and i ~= y diff --git a/generic/MultiMarginCriterion.c b/generic/MultiMarginCriterion.c index 33f6e94..df7fc25 100644 --- a/generic/MultiMarginCriterion.c +++ b/generic/MultiMarginCriterion.c @@ -6,6 +6,7 @@ static int nn_(MultiMarginCriterion_updateOutput)(lua_State *L) { THTensor *input = luaT_checkudata(L, 2, torch_Tensor); int sizeAverage = luaT_getfieldcheckboolean(L, 1, "sizeAverage"); + int p = luaT_getfieldchecknumber(L, 1, "p"); real *input_data, *target_data; long nframe, dim; long t, d; @@ -54,7 +55,7 @@ static int nn_(MultiMarginCriterion_updateOutput)(lua_State *L) continue; if(z > 0) - sum += z; + sum += (p==1) ? z : z*z; } input_data += dim; } @@ -75,6 +76,7 @@ static int nn_(MultiMarginCriterion_updateGradInput)(lua_State *L) { THTensor *input = luaT_checkudata(L, 2, torch_Tensor); int sizeAverage = luaT_getfieldcheckboolean(L, 1, "sizeAverage"); + int p = luaT_getfieldchecknumber(L, 1, "p"); THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_Tensor); real *input_data; real *gradInput_data; @@ -127,8 +129,9 @@ static int nn_(MultiMarginCriterion_updateGradInput)(lua_State *L) if(z > 0) { - gradInput_target -= g; - gradInput_data[d] = g; + real h = (p == 1) ? g : 2*g*z; + gradInput_target -= h; + gradInput_data[d] = h; } else gradInput_data[d] = 0; @@ -693,6 +693,13 @@ function nntest.MarginCriterion() criterionJacobianTest1D(cri, input, target) end +function nntest.MultiMarginCriterion() + local input = torch.rand(100) + local target = math.random(1,100) + local cri = nn.MultiMarginCriterion(math.random(1,2)) + criterionJacobianTest1D(cri, input, target) +end + function nntest.WeightedMSECriterion() local input = torch.rand(10) local target = input:clone():add(torch.rand(10)) |