Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/torch/nn.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSoumith Chintala <soumith@gmail.com>2015-02-05 18:14:45 +0300
committerSoumith Chintala <soumith@gmail.com>2015-02-05 18:14:45 +0300
commit307532ab58a46c5b560a723418a1ab8ede9167fd (patch)
tree3c9d148f03510f38d1eb5462350ba819ce961493
parent5137714bae52c59bc663c0a57dd730712130457d (diff)
parent227fedec91f6d7f38e8bb62fcfd32c2316af634f (diff)
Merge pull request #157 from szagoruyko/multimargin
L2 MultiMarginCriterion
-rw-r--r--MultiMarginCriterion.lua6
-rwxr-xr-xdoc/criterion.md4
-rw-r--r--generic/MultiMarginCriterion.c9
-rw-r--r--test.lua7
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;
diff --git a/test.lua b/test.lua
index f555b50..a8f81f5 100644
--- a/test.lua
+++ b/test.lua
@@ -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))