diff options
author | Ronan Collobert <ronan@collobert.com> | 2012-01-25 17:55:20 +0400 |
---|---|---|
committer | Ronan Collobert <ronan@collobert.com> | 2012-01-25 17:55:20 +0400 |
commit | 4df3893abd1b9f840f1d9a8c1859799ccbf941de (patch) | |
tree | e8a1e1cc1b6ea6e47855347b157eaf419fdb357b /generic |
initial revamp of torch7 tree
Diffstat (limited to 'generic')
-rw-r--r-- | generic/Abs.c | 43 | ||||
-rw-r--r-- | generic/AbsCriterion.c | 54 | ||||
-rw-r--r-- | generic/Exp.c | 43 | ||||
-rw-r--r-- | generic/HardShrink.c | 50 | ||||
-rw-r--r-- | generic/HardTanh.c | 50 | ||||
-rw-r--r-- | generic/LogSigmoid.c | 49 | ||||
-rw-r--r-- | generic/LogSoftMax.c | 111 | ||||
-rw-r--r-- | generic/MSECriterion.c | 54 | ||||
-rw-r--r-- | generic/Max.c | 100 | ||||
-rw-r--r-- | generic/Min.c | 100 | ||||
-rw-r--r-- | generic/MultiLabelMarginCriterion.c | 185 | ||||
-rw-r--r-- | generic/MultiMarginCriterion.c | 162 | ||||
-rw-r--r-- | generic/Sigmoid.c | 44 | ||||
-rw-r--r-- | generic/SoftMax.c | 114 | ||||
-rw-r--r-- | generic/SoftPlus.c | 44 | ||||
-rw-r--r-- | generic/SoftShrink.c | 50 | ||||
-rw-r--r-- | generic/SparseLinear.c | 130 | ||||
-rw-r--r-- | generic/SpatialConvolution.c | 201 | ||||
-rw-r--r-- | generic/SpatialConvolutionMap.c | 229 | ||||
-rw-r--r-- | generic/SpatialMaxPooling.c | 163 | ||||
-rw-r--r-- | generic/SpatialSubSampling.c | 278 | ||||
-rw-r--r-- | generic/Sqrt.c | 46 | ||||
-rw-r--r-- | generic/Square.c | 45 | ||||
-rw-r--r-- | generic/Tanh.c | 45 | ||||
-rw-r--r-- | generic/TemporalConvolution.c | 194 | ||||
-rw-r--r-- | generic/TemporalSubSampling.c | 139 | ||||
-rw-r--r-- | generic/Threshold.c | 47 | ||||
-rw-r--r-- | generic/VolumetricConvolution.c | 118 |
28 files changed, 2888 insertions, 0 deletions
diff --git a/generic/Abs.c b/generic/Abs.c new file mode 100644 index 0000000..8c65813 --- /dev/null +++ b/generic/Abs.c @@ -0,0 +1,43 @@ +#ifndef TH_GENERIC_FILE +#define TH_GENERIC_FILE "generic/Abs.c" +#else + +static int nn_(Abs_updateOutput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + + THTensor_(resizeAs)(output, input); + + TH_TENSOR_APPLY2(real, output, real, input, \ + *output_data = fabs(*input_data);) + return 1; +} + +static int nn_(Abs_updateGradInput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id)); + THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id)); + + THTensor_(resizeAs)(gradInput, input); + TH_TENSOR_APPLY3(real, gradInput, real, gradOutput, real, input, \ + real z = *input_data; \ + *gradInput_data = *gradOutput_data * (z >= 0 ? 1 : -1);) + return 1; +} + +static const struct luaL_Reg nn_(Abs__) [] = { + {"Abs_updateOutput", nn_(Abs_updateOutput)}, + {"Abs_updateGradInput", nn_(Abs_updateGradInput)}, + {NULL, NULL} +}; + +static void nn_(Abs_init)(lua_State *L) +{ + luaT_pushmetaclass(L, torch_(Tensor_id)); + luaT_registeratname(L, nn_(Abs__), "nn"); + lua_pop(L,1); +} + +#endif diff --git a/generic/AbsCriterion.c b/generic/AbsCriterion.c new file mode 100644 index 0000000..b9b948d --- /dev/null +++ b/generic/AbsCriterion.c @@ -0,0 +1,54 @@ +#ifndef TH_GENERIC_FILE +#define TH_GENERIC_FILE "generic/AbsCriterion.c" +#else + +static int nn_(AbsCriterion_updateOutput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *target = luaT_checkudata(L, 3, torch_(Tensor_id)); + int sizeAverage = luaT_getfieldcheckboolean(L, 1, "sizeAverage"); + real sum; + + sum = 0; + TH_TENSOR_APPLY2(real, input, real, target, + sum += fabs(*input_data - *target_data);) + + if(sizeAverage) + sum /= THTensor_(nElement)(input); + + lua_pushnumber(L, sum); + lua_setfield(L, 1, "output"); + + lua_pushnumber(L, sum); + return 1; +} + +static int nn_(AbsCriterion_updateGradInput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *target = luaT_checkudata(L, 3, torch_(Tensor_id)); + int sizeAverage = luaT_getfieldcheckboolean(L, 1, "sizeAverage"); + THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id)); + real norm = (sizeAverage ? 1./((real)THTensor_(nElement)(input)) : 1.); + + THTensor_(resizeAs)(gradInput, input); + TH_TENSOR_APPLY3(real, gradInput, real, input, real, target, + *gradInput_data = ( (*input_data - *target_data) >= 0 ? norm : -norm);) + + return 1; +} + +static const struct luaL_Reg nn_(AbsCriterion__) [] = { + {"AbsCriterion_updateOutput", nn_(AbsCriterion_updateOutput)}, + {"AbsCriterion_updateGradInput", nn_(AbsCriterion_updateGradInput)}, + {NULL, NULL} +}; + +static void nn_(AbsCriterion_init)(lua_State *L) +{ + luaT_pushmetaclass(L, torch_(Tensor_id)); + luaT_registeratname(L, nn_(AbsCriterion__), "nn"); + lua_pop(L,1); +} + +#endif diff --git a/generic/Exp.c b/generic/Exp.c new file mode 100644 index 0000000..b56f379 --- /dev/null +++ b/generic/Exp.c @@ -0,0 +1,43 @@ +#ifndef TH_GENERIC_FILE +#define TH_GENERIC_FILE "generic/Exp.c" +#else + +static int nn_(Exp_updateOutput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + + THTensor_(resizeAs)(output, input); + + TH_TENSOR_APPLY2(real, output, real, input, \ + *output_data = exp(*input_data);) + + return 1; +} + +static int nn_(Exp_updateGradInput)(lua_State *L) +{ + THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id)); + THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id)); + + THTensor_(resizeAs)(gradInput, output); + TH_TENSOR_APPLY3(real, gradInput, real, gradOutput, real, output, \ + *gradInput_data = *gradOutput_data * *output_data;); + return 1; +} + +static const struct luaL_Reg nn_(Exp__) [] = { + {"Exp_updateOutput", nn_(Exp_updateOutput)}, + {"Exp_updateGradInput", nn_(Exp_updateGradInput)}, + {NULL, NULL} +}; + +static void nn_(Exp_init)(lua_State *L) +{ + luaT_pushmetaclass(L, torch_(Tensor_id)); + luaT_registeratname(L, nn_(Exp__), "nn"); + lua_pop(L,1); +} + +#endif diff --git a/generic/HardShrink.c b/generic/HardShrink.c new file mode 100644 index 0000000..be98ddc --- /dev/null +++ b/generic/HardShrink.c @@ -0,0 +1,50 @@ +#ifndef TH_GENERIC_FILE +#define TH_GENERIC_FILE "generic/HardShrink.c" +#else + +static int nn_(HardShrink_updateOutput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + real lambda = luaT_getfieldchecknumber(L, 1, "lambda"); + THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + + THTensor_(resizeAs)(output, input); + + TH_TENSOR_APPLY2(real, output, real, input, \ + if ((*input_data) > lambda) *output_data = *input_data; \ + else if ((*input_data) < -lambda) *output_data = *input_data; \ + else *output_data = 0;); + return 1; +} + +static int nn_(HardShrink_updateGradInput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + real lambda = luaT_getfieldchecknumber(L, 1, "lambda"); + THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id)); + THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id)); + + THTensor_(resizeAs)(gradInput, input); + TH_TENSOR_APPLY3(real, gradInput, real, gradOutput, real, input, \ + if ((*input_data) > lambda || (*input_data) < -lambda) \ + *gradInput_data = (*gradOutput_data); \ + else \ + *gradInput_data = 0; \ + ); + return 1; +} + +static const struct luaL_Reg nn_(HardShrink__) [] = { + {"HardShrink_updateOutput", nn_(HardShrink_updateOutput)}, + {"HardShrink_updateGradInput", nn_(HardShrink_updateGradInput)}, + {NULL, NULL} +}; + +static void nn_(HardShrink_init)(lua_State *L) +{ + luaT_pushmetaclass(L, torch_(Tensor_id)); + luaT_registeratname(L, nn_(HardShrink__), "nn"); + lua_pop(L,1); +} + +#endif diff --git a/generic/HardTanh.c b/generic/HardTanh.c new file mode 100644 index 0000000..3764095 --- /dev/null +++ b/generic/HardTanh.c @@ -0,0 +1,50 @@ +#ifndef TH_GENERIC_FILE +#define TH_GENERIC_FILE "generic/HardTanh.c" +#else + +static int nn_(HardTanh_updateOutput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + + THTensor_(resizeAs)(output, input); + + TH_TENSOR_APPLY2(real, output, real, input, \ + if(*input_data < -1) \ + *output_data = -1; \ + else if(*input_data <= 1) \ + *output_data = *input_data; \ + else \ + *output_data = 1;) + return 1; +} + +static int nn_(HardTanh_updateGradInput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id)); + THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id)); + + THTensor_(resizeAs)(gradInput, input); + TH_TENSOR_APPLY3(real, gradInput, real, gradOutput, real, input, \ + if(*input_data < -1 || *input_data > 1) \ + *gradInput_data = 0; \ + else \ + *gradInput_data = *gradOutput_data;); + return 1; +} + +static const struct luaL_Reg nn_(HardTanh__) [] = { + {"HardTanh_updateOutput", nn_(HardTanh_updateOutput)}, + {"HardTanh_updateGradInput", nn_(HardTanh_updateGradInput)}, + {NULL, NULL} +}; + +static void nn_(HardTanh_init)(lua_State *L) +{ + luaT_pushmetaclass(L, torch_(Tensor_id)); + luaT_registeratname(L, nn_(HardTanh__), "nn"); + lua_pop(L,1); +} + +#endif diff --git a/generic/LogSigmoid.c b/generic/LogSigmoid.c new file mode 100644 index 0000000..b5bdae4 --- /dev/null +++ b/generic/LogSigmoid.c @@ -0,0 +1,49 @@ +#ifndef TH_GENERIC_FILE +#define TH_GENERIC_FILE "generic/LogSigmoid.c" +#else + +static int nn_(LogSigmoid_updateOutput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *buffer = luaT_getfieldcheckudata(L, 1, "buffer", torch_(Tensor_id)); + THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + + THTensor_(resizeAs)(output, input); + THTensor_(resizeAs)(buffer, input); + + TH_TENSOR_APPLY3(real, output, real, input, real, buffer, \ + real z = exp(-*input_data); \ + *buffer_data = z; \ + *output_data = -log(1. + z);) + + return 1; +} + +static int nn_(LogSigmoid_updateGradInput)(lua_State *L) +{ + THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id)); + THTensor *buffer = luaT_getfieldcheckudata(L, 1, "buffer", torch_(Tensor_id)); + THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id)); + + THTensor_(resizeAs)(gradInput, buffer); + TH_TENSOR_APPLY3(real, gradInput, real, gradOutput, real, buffer, \ + real z = *buffer_data; \ + *gradInput_data = *gradOutput_data * z / (1. + z);) + + return 1; +} + +static const struct luaL_Reg nn_(LogSigmoid__) [] = { + {"LogSigmoid_updateOutput", nn_(LogSigmoid_updateOutput)}, + {"LogSigmoid_updateGradInput", nn_(LogSigmoid_updateGradInput)}, + {NULL, NULL} +}; + +static void nn_(LogSigmoid_init)(lua_State *L) +{ + luaT_pushmetaclass(L, torch_(Tensor_id)); + luaT_registeratname(L, nn_(LogSigmoid__), "nn"); + lua_pop(L,1); +} + +#endif diff --git a/generic/LogSoftMax.c b/generic/LogSoftMax.c new file mode 100644 index 0000000..5d4dbfc --- /dev/null +++ b/generic/LogSoftMax.c @@ -0,0 +1,111 @@ +#ifndef TH_GENERIC_FILE +#define TH_GENERIC_FILE "generic/LogSoftMax.c" +#else + +static int nn_(LogSoftMax_updateOutput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + real *input_data, *output_data; + long nframe = 0, dim = 0; + long t, d; + + if(input->nDimension == 1) + { + nframe = 1; + dim = input->size[0]; + } + else if(input->nDimension == 2) + { + nframe = input->size[0]; + dim = input->size[1]; + } + else + THArgCheck(0, 2, "vector or matrix expected"); + + input = THTensor_(newContiguous)(input); + THTensor_(resizeAs)(output, input); + + input_data = THTensor_(data)(input); + output_data = THTensor_(data)(output); + for(t = 0; t < nframe; t++) + { + accreal logsum = 0; + real maxInput = -THInf; + + for(d = 0; d < dim; d++) + maxInput = THMax(maxInput, input_data[d]); + + for(d = 0; d < dim; d++) + logsum += THExpMinusApprox(maxInput-input_data[d]); + logsum = maxInput + log(logsum); + + for(d = 0; d < dim; d++) + output_data[d] = input_data[d] - logsum; + + input_data += dim; + output_data += dim; + } + + THTensor_(free)(input); + + return 1; +} + +static int nn_(LogSoftMax_updateGradInput)(lua_State *L) +{ + THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id)); + THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id)); + real *gradInput_data, *gradOutput_data, *output_data; + long nframe = 0, dim = 0; + long t, d; + + if(output->nDimension == 1) + { + nframe = 1; + dim = output->size[0]; + } + else if(output->nDimension == 2) + { + nframe = output->size[0]; + dim = output->size[1]; + } + else + THError("vector or matrix expected"); + + THTensor_(resizeAs)(gradInput, output); + gradInput_data = THTensor_(data)(gradInput); + output_data = THTensor_(data)(output); + gradOutput_data = THTensor_(data)(gradOutput); + for(t = 0; t < nframe; t++) + { + accreal sum = 0; + for(d = 0; d < dim; d++) + sum += gradOutput_data[d]; + + for(d = 0; d < dim; d++) + gradInput_data[d] = gradOutput_data[d] - exp(output_data[d])*sum; + + gradInput_data += dim; + output_data += dim; + gradOutput_data += dim; + } + + return 1; +} + +static const struct luaL_Reg nn_(LogSoftMax__) [] = { + {"LogSoftMax_updateOutput", nn_(LogSoftMax_updateOutput)}, + {"LogSoftMax_updateGradInput", nn_(LogSoftMax_updateGradInput)}, + {NULL, NULL} +}; + +void nn_(LogSoftMax_init)(lua_State *L) +{ + luaT_pushmetaclass(L, torch_(Tensor_id)); + luaT_registeratname(L, nn_(LogSoftMax__), "nn"); + lua_pop(L,1); +} + +#endif diff --git a/generic/MSECriterion.c b/generic/MSECriterion.c new file mode 100644 index 0000000..c53735c --- /dev/null +++ b/generic/MSECriterion.c @@ -0,0 +1,54 @@ +#ifndef TH_GENERIC_FILE +#define TH_GENERIC_FILE "generic/MSECriterion.c" +#else + +static int nn_(MSECriterion_updateOutput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *target = luaT_checkudata(L, 3, torch_(Tensor_id)); + int sizeAverage = luaT_getfieldcheckboolean(L, 1, "sizeAverage"); + real sum; + + sum = 0; + TH_TENSOR_APPLY2(real, input, real, target, + real z = (*input_data - *target_data); + sum += z*z;) + + if(sizeAverage) + sum /= THTensor_(nElement)(input); + + lua_pushnumber(L, sum); + lua_setfield(L, 1, "output"); + + lua_pushnumber(L, sum); + return 1; +} + +static int nn_(MSECriterion_updateGradInput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *target = luaT_checkudata(L, 3, torch_(Tensor_id)); + int sizeAverage = luaT_getfieldcheckboolean(L, 1, "sizeAverage"); + THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id)); + real norm = (sizeAverage ? 2./((real)THTensor_(nElement)(input)) : 2.); + + THTensor_(resizeAs)(gradInput, input); + TH_TENSOR_APPLY3(real, gradInput, real, input, real, target, + *gradInput_data = norm * (*input_data - *target_data);) + return 1; +} + +static const struct luaL_Reg nn_(MSECriterion__) [] = { + {"MSECriterion_updateOutput", nn_(MSECriterion_updateOutput)}, + {"MSECriterion_updateGradInput", nn_(MSECriterion_updateGradInput)}, + {NULL, NULL} +}; + +static void nn_(MSECriterion_init)(lua_State *L) +{ + luaT_pushmetaclass(L, torch_(Tensor_id)); + luaT_registeratname(L, nn_(MSECriterion__), "nn"); + lua_pop(L,1); +} + +#endif diff --git a/generic/Max.c b/generic/Max.c new file mode 100644 index 0000000..87f52f1 --- /dev/null +++ b/generic/Max.c @@ -0,0 +1,100 @@ +#ifndef TH_GENERIC_FILE +#define TH_GENERIC_FILE "generic/Max.c" +#else + +static int nn_(Max_updateOutput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + int dimension = luaT_getfieldcheckint(L, 1, "dimension")-1; + THTensor *indices = luaT_getfieldcheckudata(L, 1, "indices", torch_(Tensor_id)); + THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + + THLongStorage *dim; + long i; + + luaL_argcheck(L, dimension >= 0 && dimension < input->nDimension, 2, "dimension out of range"); + + dim = THLongStorage_newWithSize(input->nDimension); + for(i = 0; i < input->nDimension; i++) + dim->data[i] = input->size[i]; + dim->data[dimension] = 1; + THTensor_(resize)(output, dim, NULL); + THTensor_(resize)(indices, dim, NULL); + THLongStorage_free(dim); + + TH_TENSOR_DIM_APPLY3(real, output, real, input, real, indices, dimension, + long theIndex = 0; + real theMax = input_data[0]; + for(i = 1; i < input_size; i++) + { + if(input_data[i*input_stride] > theMax) + { + theIndex = i; + theMax = input_data[i*input_stride]; + } + } + *indices_data = theIndex+1; + *output_data = theMax;) + + THTensor_(select)(output, NULL, dimension, 0); + + return 1; +} + +static int nn_(Max_updateGradInput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id)); + THTensor *indices = luaT_getfieldcheckudata(L, 1, "indices", torch_(Tensor_id)); + int dimension = luaT_getfieldcheckint(L, 1, "dimension")-1; + THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id)); + + THTensor *gradOutputPlusOneDim; + THLongStorage *dim, *str; + int i, j; + + THTensor_(resizeAs)(gradInput, input); + THTensor_(zero)(gradInput); + + dim = THLongStorage_newWithSize(gradOutput->nDimension+1); + str = THLongStorage_newWithSize(gradOutput->nDimension+1); + for(i = 0, j = 0; j < gradOutput->nDimension+1; j++) + { + if(j == dimension) + { + dim->data[j] = input->size[dimension]; + str->data[j] = 0; + continue; + } + + dim->data[j] = gradOutput->size[i]; + str->data[j] = gradOutput->stride[i]; + i++; + } + + gradOutputPlusOneDim = THTensor_(newWithStorage)(gradOutput->storage, gradOutput->storageOffset, dim, str); + THLongStorage_free(dim); + THLongStorage_free(str); + + TH_TENSOR_DIM_APPLY3(real, gradInput, real, gradOutputPlusOneDim, real, indices, dimension, + gradInput_data[ ((long)(*indices_data)-1)*gradInput_stride ] = *gradOutputPlusOneDim_data;) + + THTensor_(free)(gradOutputPlusOneDim); + + return 1; +} + +static const struct luaL_Reg nn_(Max__) [] = { + {"Max_updateOutput", nn_(Max_updateOutput)}, + {"Max_updateGradInput", nn_(Max_updateGradInput)}, + {NULL, NULL} +}; + +static void nn_(Max_init)(lua_State *L) +{ + luaT_pushmetaclass(L, torch_(Tensor_id)); + luaT_registeratname(L, nn_(Max__), "nn"); + lua_pop(L,1); +} + +#endif diff --git a/generic/Min.c b/generic/Min.c new file mode 100644 index 0000000..d3309df --- /dev/null +++ b/generic/Min.c @@ -0,0 +1,100 @@ +#ifndef TH_GENERIC_FILE +#define TH_GENERIC_FILE "generic/Min.c" +#else + +static int nn_(Min_updateOutput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + int dimension = luaT_getfieldcheckint(L, 1, "dimension")-1; + THTensor *indices = luaT_getfieldcheckudata(L, 1, "indices", torch_(Tensor_id)); + THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + + THLongStorage *dim; + long i; + + luaL_argcheck(L, dimension >= 0 && dimension < input->nDimension, 2, "dimension out of range"); + + dim = THLongStorage_newWithSize(input->nDimension); + for(i = 0; i < input->nDimension; i++) + dim->data[i] = input->size[i]; + dim->data[dimension] = 1; + THTensor_(resize)(output, dim, NULL); + THTensor_(resize)(indices, dim, NULL); + THLongStorage_free(dim); + + TH_TENSOR_DIM_APPLY3(real, output, real, input, real, indices, dimension, + long theIndex = 0; + real theMin = input_data[0]; + for(i = 1; i < input_size; i++) + { + if(input_data[i*input_stride] < theMin) + { + theIndex = i; + theMin = input_data[i*input_stride]; + } + } + *indices_data = theIndex+1; + *output_data = theMin;) + + THTensor_(select)(output, NULL, dimension, 0); + + return 1; +} + +static int nn_(Min_updateGradInput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id)); + THTensor *indices = luaT_getfieldcheckudata(L, 1, "indices", torch_(Tensor_id)); + int dimension = luaT_getfieldcheckint(L, 1, "dimension")-1; + THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id)); + + THTensor *gradOutputPlusOneDim; + THLongStorage *dim, *str; + int i, j; + + THTensor_(resizeAs)(gradInput, input); + THTensor_(zero)(gradInput); + + dim = THLongStorage_newWithSize(gradOutput->nDimension+1); + str = THLongStorage_newWithSize(gradOutput->nDimension+1); + for(i = 0, j = 0; j < gradOutput->nDimension+1; j++) + { + if(j == dimension) + { + dim->data[j] = input->size[dimension]; + str->data[j] = 0; + continue; + } + + dim->data[j] = gradOutput->size[i]; + str->data[j] = gradOutput->stride[i]; + i++; + } + + gradOutputPlusOneDim = THTensor_(newWithStorage)(gradOutput->storage, gradOutput->storageOffset, dim, str); + THLongStorage_free(dim); + THLongStorage_free(str); + + TH_TENSOR_DIM_APPLY3(real, gradInput, real, gradOutputPlusOneDim, real, indices, dimension, + gradInput_data[ ((long)(*indices_data)-1)*gradInput_stride ] = *gradOutputPlusOneDim_data;) + + THTensor_(free)(gradOutputPlusOneDim); + + return 1; +} + +static const struct luaL_Reg nn_(Min__) [] = { + {"Min_updateOutput", nn_(Min_updateOutput)}, + {"Min_updateGradInput", nn_(Min_updateGradInput)}, + {NULL, NULL} +}; + +static void nn_(Min_init)(lua_State *L) +{ + luaT_pushmetaclass(L, torch_(Tensor_id)); + luaT_registeratname(L, nn_(Min__), "nn"); + lua_pop(L,1); +} + +#endif diff --git a/generic/MultiLabelMarginCriterion.c b/generic/MultiLabelMarginCriterion.c new file mode 100644 index 0000000..f4c3914 --- /dev/null +++ b/generic/MultiLabelMarginCriterion.c @@ -0,0 +1,185 @@ +#ifndef TH_GENERIC_FILE +#define TH_GENERIC_FILE "generic/MultiLabelMarginCriterion.c" +#else + +static int nn_(MultiLabelMarginCriterion_updateOutput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + int sizeAverage = luaT_getfieldcheckboolean(L, 1, "sizeAverage"); + real *input_data, *target_data; + long nframe, dim; + long t, d, dt, ddt; + THTensor *target; + real sum; + + THArgCheck((input->nDimension == 1) || (input->nDimension == 2), 2, "vector or matrix expected"); + + if(input->nDimension == 1) + { + nframe = 1; + dim = input->size[0]; + target = luaT_checkudata(L, 3, torch_(Tensor_id)); + THArgCheck((target->nDimension == 1) && (target->size[0] == dim), 3, "inconsistent target size"); + } + else + { + nframe = input->size[0]; + dim = input->size[1]; + target = luaT_checkudata(L, 3, torch_(Tensor_id)); + THArgCheck((target->nDimension == 2) && (target->size[0] == nframe) && (target->size[1] == dim), 3, "inconsistent target size"); + } + + THArgCheck(THTensor_(minall)(target) >= 0, 3, "target out of range"); + THArgCheck(THTensor_(maxall)(target) <= dim, 3, "target out of range"); + + target = THTensor_(newContiguous)(target); + input = THTensor_(newContiguous)(input); + input_data = THTensor_(data)(input); + target_data = THTensor_(data)(target); + + sum = 0; + for(t = 0; t < nframe; t++) + { + for(dt = 0; dt < dim; dt++) + { + long target_idx = (long)target_data[dt]-1; + real input_target; + if(target_idx < 0) + break; + + input_target = input_data[target_idx]; + for(d = 0; d < dim; d++) + { + int istarget = 0; + for(ddt = 0; ddt < dim; ddt++) + { + if(!target_data[ddt]) + break; + if(((long)target_data[ddt])-1 == d) + istarget = 1; + } + + if(!istarget) + { + real z = 1 - input_target + input_data[d]; + if(z > 0) + sum += z; + } + } + } + input_data += dim; + target_data += dim; + } + + if(sizeAverage) + sum /= dim; + + lua_pushnumber(L, sum); + lua_setfield(L, 1, "output"); + + THTensor_(free)(input); + THTensor_(free)(target); + lua_pushnumber(L, sum); + return 1; +} + +static int nn_(MultiLabelMarginCriterion_updateGradInput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + int sizeAverage = luaT_getfieldcheckboolean(L, 1, "sizeAverage"); + THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id)); + real *input_data; + real *gradInput_data; + real *target_data; + long nframe, dim; + long t, d, dt, ddt; + THTensor *target; + real g; + + THArgCheck((input->nDimension == 1) || (input->nDimension == 2), 2, "vector or matrix expected"); + + if(input->nDimension == 1) + { + nframe = 1; + dim = input->size[0]; + target = luaT_checkudata(L, 3, torch_(Tensor_id)); + THArgCheck((target->nDimension == 1) && (target->size[0] == dim), 3, "inconsistent target size"); + } + else + { + nframe = input->size[0]; + dim = input->size[1]; + target = luaT_checkudata(L, 3, torch_(Tensor_id)); + THArgCheck((target->nDimension == 2) && (target->size[0] == nframe) && (target->size[1] == dim), 3, "inconsistent target size"); + } + + THArgCheck(THTensor_(minall)(target) >= 0, 3, "target out of range"); + THArgCheck(THTensor_(maxall)(target) <= dim, 3, "target out of range"); + + target = THTensor_(newContiguous)(target); + input = THTensor_(newContiguous)(input); + input_data = THTensor_(data)(input); + target_data = THTensor_(data)(target); + + g = (sizeAverage ? 1./((real)dim) : 1.); + + THTensor_(resizeAs)(gradInput, input); + THTensor_(zero)(gradInput); + gradInput_data = THTensor_(data)(gradInput); + + for(t = 0; t < nframe; t++) + { + for(dt = 0; dt < dim; dt++) + { + long target_idx = (long)target_data[dt]-1; + real input_target; + if(target_idx < 0) + break; + + input_target = input_data[target_idx]; + for(d = 0; d < dim; d++) + { + int istarget = 0; + for(ddt = 0; ddt < dim; ddt++) + { + if(!target_data[ddt]) + break; + if(((long)target_data[ddt])-1 == d) + istarget = 1; + } + + if(!istarget) + { + real z = 1 - input_target + input_data[d]; + if(z > 0) + { + gradInput_data[target_idx] -= g; + gradInput_data[d] += g; + } + } + } + } + input_data += dim; + target_data += dim; + gradInput_data += dim; + } + + THTensor_(free)(input); + THTensor_(free)(target); + return 1; +} + +static const struct luaL_Reg nn_(MultiLabelMarginCriterion__) [] = { + {"MultiLabelMarginCriterion_updateOutput", nn_(MultiLabelMarginCriterion_updateOutput)}, + {"MultiLabelMarginCriterion_updateGradInput", nn_(MultiLabelMarginCriterion_updateGradInput)}, + {NULL, NULL} +}; + +static void nn_(MultiLabelMarginCriterion_init)(lua_State *L) +{ + luaT_pushmetaclass(L, torch_(Tensor_id)); + luaT_registeratname(L, nn_(MultiLabelMarginCriterion__), "nn"); + lua_pop(L,1); +} + +#endif diff --git a/generic/MultiMarginCriterion.c b/generic/MultiMarginCriterion.c new file mode 100644 index 0000000..ca73bc9 --- /dev/null +++ b/generic/MultiMarginCriterion.c @@ -0,0 +1,162 @@ +#ifndef TH_GENERIC_FILE +#define TH_GENERIC_FILE "generic/MultiMarginCriterion.c" +#else + +static int nn_(MultiMarginCriterion_updateOutput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + int sizeAverage = luaT_getfieldcheckboolean(L, 1, "sizeAverage"); + real *input_data, *target_data; + long nframe, dim; + long t, d; + real target_; + THTensor *target; + real sum; + + THArgCheck((input->nDimension == 1) || (input->nDimension == 2), 2, "vector or matrix expected"); + + if(input->nDimension == 1) + { + nframe = 1; + dim = input->size[0]; + target_ = luaL_checknumber(L, 3); + target = THTensor_(newWithSize1d)(1); + THTensor_(fill)(target, target_); + } + else + { + nframe = input->size[0]; + dim = input->size[1]; + target = luaT_checkudata(L, 3, torch_(Tensor_id)); + THArgCheck((target->nDimension == 1) && (target->size[0] == nframe), 3, "inconsistent target size"); + target = THTensor_(newContiguous)(target); + } + + for(t = 0; t < nframe; t++) + { + real idx = THTensor_(get1d)(target, t); + THArgCheck((idx >= 1) && (idx <= dim), 3, "target out of range"); + } + + input = THTensor_(newContiguous)(input); + input_data = THTensor_(data)(input); + target_data = THTensor_(data)(target); + + sum = 0; + for(t = 0; t < nframe; t++) + { + long target_idx = (long)(target_data[t]-1); + real input_target = input_data[target_idx]; + for(d = 0; d < dim; d++) + { + real z = 1 - input_target + input_data[d]; + if(d == target_idx) + continue; + + if(z > 0) + sum += z; + } + input_data += dim; + } + + if(sizeAverage) + sum /= dim; + + lua_pushnumber(L, sum); + lua_setfield(L, 1, "output"); + + THTensor_(free)(input); + THTensor_(free)(target); + lua_pushnumber(L, sum); + return 1; +} + +static int nn_(MultiMarginCriterion_updateGradInput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + int sizeAverage = luaT_getfieldcheckboolean(L, 1, "sizeAverage"); + THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id)); + real *input_data; + real *gradInput_data; + real *target_data; + THTensor *target; + long nframe, dim; + long t, d; + real target_; + real g; + real sum; + + THArgCheck((input->nDimension == 1) || (input->nDimension == 2), 2, "vector or matrix expected"); + + if(input->nDimension == 1) + { + nframe = 1; + dim = input->size[0]; + target_ = luaL_checknumber(L, 3); + target = THTensor_(newWithSize1d)(1); + THTensor_(fill)(target, target_); + } + else + { + nframe = input->size[0]; + dim = input->size[1]; + target = luaT_checkudata(L, 3, torch_(Tensor_id)); + THArgCheck((target->nDimension == 1) && (target->size[0] == nframe), 3, "inconsistent target size"); + target = THTensor_(newContiguous)(target); + } + + g = (sizeAverage ? 1./((real)dim) : 1.); + + input = THTensor_(newContiguous)(input); + input_data = THTensor_(data)(input); + + THTensor_(resizeAs)(gradInput, input); + gradInput_data = THTensor_(data)(gradInput); + + target_data = THTensor_(data)(target); + + for(t = 0; t < nframe; t++) + { + long target_idx = (long)(target_data[t])-1; + real input_target = input_data[target_idx]; + real gradInput_target = 0; + for(d = 0; d < dim; d++) + { + real z = 1 - input_target + input_data[d]; + if(d == target_idx) + continue; + + if(z > 0) + { + gradInput_target -= g; + gradInput_data[d] = g; + } + else + gradInput_data[d] = 0; + } + gradInput_data[target_idx] = gradInput_target; + + input_data += dim; + gradInput_data += dim; + } + + + THTensor_(free)(input); + THTensor_(free)(target); + return 1; +} + +static const struct luaL_Reg nn_(MultiMarginCriterion__) [] = { + {"MultiMarginCriterion_updateOutput", nn_(MultiMarginCriterion_updateOutput)}, + {"MultiMarginCriterion_updateGradInput", nn_(MultiMarginCriterion_updateGradInput)}, + {NULL, NULL} +}; + +static void nn_(MultiMarginCriterion_init)(lua_State *L) +{ + luaT_pushmetaclass(L, torch_(Tensor_id)); + luaT_registeratname(L, nn_(MultiMarginCriterion__), "nn"); + lua_pop(L,1); +} + +#endif diff --git a/generic/Sigmoid.c b/generic/Sigmoid.c new file mode 100644 index 0000000..20348b9 --- /dev/null +++ b/generic/Sigmoid.c @@ -0,0 +1,44 @@ +#ifndef TH_GENERIC_FILE +#define TH_GENERIC_FILE "generic/Sigmoid.c" +#else + +static int nn_(Sigmoid_updateOutput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + + THTensor_(resizeAs)(output, input); + + TH_TENSOR_APPLY2(real, output, real, input, \ + *output_data = 1./(1.+ exp(- *input_data));) + + return 1; +} + +static int nn_(Sigmoid_updateGradInput)(lua_State *L) +{ + THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id)); + THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id)); + + THTensor_(resizeAs)(gradInput, output); + TH_TENSOR_APPLY3(real, gradInput, real, gradOutput, real, output, \ + real z = *output_data; \ + *gradInput_data = *gradOutput_data * (1. - z) * z;) + return 1; +} + +static const struct luaL_Reg nn_(Sigmoid__) [] = { + {"Sigmoid_updateOutput", nn_(Sigmoid_updateOutput)}, + {"Sigmoid_updateGradInput", nn_(Sigmoid_updateGradInput)}, + {NULL, NULL} +}; + +static void nn_(Sigmoid_init)(lua_State *L) +{ + luaT_pushmetaclass(L, torch_(Tensor_id)); + luaT_registeratname(L, nn_(Sigmoid__), "nn"); + lua_pop(L,1); +} + +#endif diff --git a/generic/SoftMax.c b/generic/SoftMax.c new file mode 100644 index 0000000..3aaae65 --- /dev/null +++ b/generic/SoftMax.c @@ -0,0 +1,114 @@ +#ifndef TH_GENERIC_FILE +#define TH_GENERIC_FILE "generic/SoftMax.c" +#else + +static int nn_(SoftMax_updateOutput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + real *input_data, *output_data; + long nframe = 0, dim = 0; + long t, d; + + if(input->nDimension == 1) + { + nframe = 1; + dim = input->size[0]; + } + else if(input->nDimension == 2) + { + nframe = input->size[0]; + dim = input->size[1]; + } + else + THArgCheck(0, 2, "vector or matrix expected"); + + input = THTensor_(newContiguous)(input); + THTensor_(resizeAs)(output, input); + + input_data = THTensor_(data)(input); + output_data = THTensor_(data)(output); + for(t = 0; t < nframe; t++) + { + real inputMax = -THInf; + for(d = 0; d < dim; d++) { + if (input_data[d] >= inputMax) inputMax = input_data[d]; + } + + accreal sum = 0; + for(d = 0; d < dim; d++) { + real z = THExpMinusApprox(inputMax - input_data[d]); + output_data[d] = z; + sum += z; + } + + for(d = 0; d < dim; d++) { + output_data[d] *= 1/sum; + } + + input_data += dim; + output_data += dim; + } + + THTensor_(free)(input); + + return 1; +} + +static int nn_(SoftMax_updateGradInput)(lua_State *L) +{ + THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id)); + THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id)); + real *gradInput_data, *gradOutput_data, *output_data; + long nframe = 0, dim = 0; + long t, d; + + if(output->nDimension == 1) + { + nframe = 1; + dim = output->size[0]; + } + else if(output->nDimension == 2) + { + nframe = output->size[0]; + dim = output->size[1]; + } + else + THError("vector or matrix expected"); + + THTensor_(resizeAs)(gradInput, output); + gradInput_data = THTensor_(data)(gradInput); + output_data = THTensor_(data)(output); + gradOutput_data = THTensor_(data)(gradOutput); + for(t = 0; t < nframe; t++) + { + accreal sum = 0; + for(d = 0; d < dim; d++) + sum += (accreal)gradOutput_data[d] * output_data[d]; + + for(d = 0; d < dim; d++) + gradInput_data[d] = output_data[d] * (gradOutput_data[d] - sum); + + gradInput_data += dim; + output_data += dim; + gradOutput_data += dim; + } + + return 1; +} + +static const struct luaL_Reg nn_(SoftMax__) [] = { + {"SoftMax_updateOutput", nn_(SoftMax_updateOutput)}, + {"SoftMax_updateGradInput", nn_(SoftMax_updateGradInput)}, + {NULL, NULL} +}; + +static void nn_(SoftMax_init)(lua_State *L) +{ + luaT_pushmetaclass(L, torch_(Tensor_id)); + luaT_registeratname(L, nn_(SoftMax__), "nn"); + lua_pop(L,1); +} + +#endif diff --git a/generic/SoftPlus.c b/generic/SoftPlus.c new file mode 100644 index 0000000..7a097fb --- /dev/null +++ b/generic/SoftPlus.c @@ -0,0 +1,44 @@ +#ifndef TH_GENERIC_FILE +#define TH_GENERIC_FILE "generic/SoftPlus.c" +#else + +static int nn_(SoftPlus_updateOutput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + + THTensor_(resizeAs)(output, input); + + TH_TENSOR_APPLY2(real, output, real, input, \ + *output_data = log1p(exp(*input_data));) + + return 1; +} + +static int nn_(SoftPlus_updateGradInput)(lua_State *L) +{ + THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id)); + THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id)); + + THTensor_(resizeAs)(gradInput, output); + TH_TENSOR_APPLY3(real, gradInput, real, gradOutput, real, output, \ + real z = exp(*output_data); \ + *gradInput_data = *gradOutput_data * (z - 1.)/z;) + return 1; +} + +static const struct luaL_Reg nn_(SoftPlus__) [] = { + {"SoftPlus_updateOutput", nn_(SoftPlus_updateOutput)}, + {"SoftPlus_updateGradInput", nn_(SoftPlus_updateGradInput)}, + {NULL, NULL} +}; + +static void nn_(SoftPlus_init)(lua_State *L) +{ + luaT_pushmetaclass(L, torch_(Tensor_id)); + luaT_registeratname(L, nn_(SoftPlus__), "nn"); + lua_pop(L,1); +} + +#endif diff --git a/generic/SoftShrink.c b/generic/SoftShrink.c new file mode 100644 index 0000000..0bc4075 --- /dev/null +++ b/generic/SoftShrink.c @@ -0,0 +1,50 @@ +#ifndef TH_GENERIC_FILE +#define TH_GENERIC_FILE "generic/SoftShrink.c" +#else + +static int nn_(SoftShrink_updateOutput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + real lambda = luaT_getfieldchecknumber(L, 1, "lambda"); + THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + + THTensor_(resizeAs)(output, input); + + TH_TENSOR_APPLY2(real, output, real, input, \ + if ((*input_data) > lambda) *output_data = *input_data - lambda; \ + else if ((*input_data) < -lambda) *output_data = *input_data + lambda; \ + else *output_data = 0;); + return 1; +} + +static int nn_(SoftShrink_updateGradInput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + real lambda = luaT_getfieldchecknumber(L, 1, "lambda"); + THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id)); + THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id)); + + THTensor_(resizeAs)(gradInput, input); + TH_TENSOR_APPLY3(real, gradInput, real, gradOutput, real, input, \ + if ((*input_data) > lambda || (*input_data) < -lambda) \ + *gradInput_data = (*gradOutput_data); \ + else \ + *gradInput_data = 0; \ + ); + return 1; +} + +static const struct luaL_Reg nn_(SoftShrink__) [] = { + {"SoftShrink_updateOutput", nn_(SoftShrink_updateOutput)}, + {"SoftShrink_updateGradInput", nn_(SoftShrink_updateGradInput)}, + {NULL, NULL} +}; + +static void nn_(SoftShrink_init)(lua_State *L) +{ + luaT_pushmetaclass(L, torch_(Tensor_id)); + luaT_registeratname(L, nn_(SoftShrink__), "nn"); + lua_pop(L,1); +} + +#endif diff --git a/generic/SparseLinear.c b/generic/SparseLinear.c new file mode 100644 index 0000000..d29a1aa --- /dev/null +++ b/generic/SparseLinear.c @@ -0,0 +1,130 @@ +#ifndef TH_GENERIC_FILE +#define TH_GENERIC_FILE "generic/SparseLinear.c" +#else + +static int nn_(SparseLinear_updateOutput)(lua_State *L) +{ + long i; + THTensor * input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor * weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id)); + THTensor * bias = luaT_getfieldcheckudata(L, 1, "bias", torch_(Tensor_id)); + THTensor * output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + long dim = weight->size[0]; /* number of weights.. */ + + THTensor_(copy)(output, bias); + for(i = 0; i < input->size[1]; i++) + { + long offset = (long)(THTensor_(get2d)(input, 0, i))-1; + + if(offset >= 0 && offset < dim) /* make sure indices are in bounds.. */ + { + real val = THTensor_(get2d)(input, 1, i); + THBlas_(axpy)(output->size[0], + val, + THTensor_(data)(weight)+offset*weight->stride[0], + weight->stride[1], + THTensor_(data)(output), + output->stride[0]); + } + else + luaL_error(L, "index out of bound"); + } + return 1; +} + +static int nn_(SparseLinear_accGradParameters)(lua_State *L) +{ + long i; + THTensor * input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor * gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id)); + real scale = luaL_optnumber(L, 4, 1); + THTensor * weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id)); + THTensor * output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + THTensor * gradBias = luaT_getfieldcheckudata(L, 1, "gradBias", torch_(Tensor_id)); + THTensor * gradWeight = luaT_getfieldcheckudata(L, 1, "gradWeight", torch_(Tensor_id)); + THTensor * lastInput = luaT_getfieldcheckudata(L, 1, "lastInput", torch_(Tensor_id)); + real weightDecay = luaT_getfieldchecknumber(L, 1, "weightDecay"); + long dim = gradWeight->size[0]; /* number of weights.. */ + + for(i = 0; i < input->size[1]; i++) + { + long offset = (long)(THTensor_(get2d)(input, 0, i))-1; + + if(offset >= 0 && offset < dim) /* make sure indices are in bounds.. */ + { + real val = scale*THTensor_(get2d)(input, 1, i); + THBlas_(scal)(gradOutput->size[0], + 0, + THTensor_(data)(gradWeight)+offset*gradWeight->stride[0], + gradWeight->stride[1]); /* zero */ + + THBlas_(axpy)(gradOutput->size[0], + val, + THTensor_(data)(gradOutput), + gradOutput->stride[0], + THTensor_(data)(gradWeight)+offset*gradWeight->stride[0], + gradWeight->stride[1]); + } + else + luaL_error(L, "index out of bound"); + } + + THTensor_(cadd)(gradBias, gradBias, 1, gradOutput); + + if(weightDecay != 0) + THTensor_(cadd)(gradWeight, gradWeight, weightDecay, weight); + + THTensor_(resizeAs)(lastInput, input); + THTensor_(copy)(lastInput, input); + + return 0; +} + +int nn_(SparseLinear_updateParameters)(lua_State *L) +{ + long i; + real learningRate = luaL_checknumber(L, 2); + THTensor * weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id)); + THTensor * output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + THTensor * bias = luaT_getfieldcheckudata(L, 1, "bias", torch_(Tensor_id)); + THTensor * gradBias = luaT_getfieldcheckudata(L, 1, "gradBias", torch_(Tensor_id)); + THTensor * gradWeight = luaT_getfieldcheckudata(L, 1, "gradWeight", torch_(Tensor_id)); + THTensor * lastInput = luaT_getfieldcheckudata(L, 1, "lastInput", torch_(Tensor_id)); + real weightDecay = luaT_getfieldchecknumber(L, 1, "weightDecay"); + + long dim = weight->size[0]; /* number of weights.. */ + THTensor_(cadd)(bias, bias, -learningRate, gradBias); + + for(i = 0; i < lastInput->size[1]; i++) + { + long offset = (long)(THTensor_(get2d)(lastInput, 0, i))-1; + + if(offset >= 0 && offset < dim) /* make sure indices are in bounds.. */ + { + THBlas_(axpy)(bias->size[0], + -learningRate, + THTensor_(data)(gradWeight)+offset*gradWeight->stride[0], + gradWeight->stride[1], + THTensor_(data)(weight)+offset*weight->stride[0], + weight->stride[1]); + } + else + luaL_error(L, "index out of bound"); + } + return 0; +} + +static const struct luaL_Reg nn_(SparseLinear__) [] = { + {"SparseLinear_updateOutput", nn_(SparseLinear_updateOutput)}, + {"SparseLinear_updateParameters", nn_(SparseLinear_updateParameters)}, + {NULL, NULL} +}; + +void nn_(SparseLinear_init)(lua_State *L) +{ + luaT_pushmetaclass(L, torch_(Tensor_id)); + luaT_registeratname(L, nn_(SparseLinear__), "nn"); + lua_pop(L,1); +} + +#endif diff --git a/generic/SpatialConvolution.c b/generic/SpatialConvolution.c new file mode 100644 index 0000000..de0de1d --- /dev/null +++ b/generic/SpatialConvolution.c @@ -0,0 +1,201 @@ +#ifndef TH_GENERIC_FILE +#define TH_GENERIC_FILE "generic/SpatialConvolution.c" +#else + +static void nn_(convolution_updateOutput_)(THTensor *input, THTensor *output, THTensor *weight, THTensor *bias, int dH, int dW) +{ + /* add bias */ + long i; + THTensor *outn = THTensor_(new)(); + for (i=0; i<bias->size[0]; i++) { + THTensor_(select)(outn,output,0,i); + THTensor_(fill)(outn, THTensor_(get1d)(bias, i)); + } + THTensor_(free)(outn); + + /* do convolutions */ + THTensor_(conv2Dmv)(output, 1.0, 1.0, input, weight, dH, dW, "V","X"); +} + +static int nn_(SpatialConvolution_updateOutput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + int dW = luaT_getfieldcheckint(L, 1, "dW"); + int dH = luaT_getfieldcheckint(L, 1, "dH"); + + THTensor *weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id)); + THTensor *bias = luaT_getfieldcheckudata(L, 1, "bias", torch_(Tensor_id)); + THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + + luaL_argcheck(L, input->nDimension == 3 || input->nDimension == 4, 2, "3D or 4D(batch mode) tensor expected"); + + int dimw = 2; + int dimh = 1; + if (input->nDimension == 4) { + dimw++; + dimh++; + } + + long nOutputPlane = weight->size[0]; + long nInputPlane = weight->size[1]; + long kW = weight->size[3]; + long kH = weight->size[2]; + long inputWidth = input->size[dimw]; + long inputHeight = input->size[dimh]; + long outputWidth = (inputWidth - kW) / dW + 1; + long outputHeight = (inputHeight - kH) / dH + 1; + + if (input->nDimension == 3) + { + THTensor_(resize3d)(output, nOutputPlane, outputHeight, outputWidth); +/* printf("\n*************\nstochastic\n"); */ +/* printf("no=%d\n",output->nDimension); */ +/* printf("no=%ld,%ld,%ld\n",nOutputPlane,outputHeight,outputWidth); */ +/* printf("ni=%d\n",input->nDimension); */ + nn_(convolution_updateOutput_)(input,output,weight,bias,dH,dW); +/* printf("stochastic\n");*/ + } + else + { + THTensor_(resize4d)(output, input->size[0], nOutputPlane, outputHeight, outputWidth); + THTensor *outn = THTensor_(new)(); + THTensor *inpn = THTensor_(new)(); + long i; + for (i=0; i<input->size[0]; i++) + { + THTensor_(select)(outn,output,0,i); + THTensor_(select)(inpn,input,0,i); + nn_(convolution_updateOutput_)(inpn,outn,weight,bias,dH,dW); + } + THTensor_(free)(outn); + THTensor_(free)(inpn); + } + +/* /\* add bias *\/ */ +/* long i; */ +/* THTensor *outn = THTensor_(new)(); */ +/* for (i=0; i<bias->size[0]; i++) { */ +/* THTensor_(select)(outn,output,0,i); */ +/* THTensor_(fill)(outn, THTensor_(get1d)(bias, i)); */ +/* } */ +/* THTensor_(free)(outn); */ + +/* /\* do convolutions *\/ */ +/* THTensor_(conv2Dmv)(output, 1.0, 1.0, input, weight, dH, dW, "vx"); */ + + return 1; +} + + +static int nn_(SpatialConvolution_updateGradInput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id)); + int dW = luaT_getfieldcheckint(L, 1, "dW"); + int dH = luaT_getfieldcheckint(L, 1, "dH"); + int nOutputPlane = luaT_getfieldcheckint(L, 1, "nOutputPlane"); + + THTensor *weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id)); + THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id)); + + THArgCheck( nOutputPlane == gradOutput->size[input->nDimension == 4 ? 1 : 0], 1, "Number of output features is not equal to nOutputPlane" ); + + long k; + + /* gradient to input */ + THTensor *tweight = THTensor_(newTranspose)(weight,0,1); + + if(input->nDimension == 3) + { + THTensor_(conv2Dmv)(gradInput, 0.0, 1.0, gradOutput, tweight, dH, dW, "F", "C"); + } + else + { + + THTensor_(resizeAs)(gradInput,input); + THTensor *outn = THTensor_(new)(); + THTensor *inpn = THTensor_(new)(); + long i; + for (i=0; i<input->size[0]; i++) + { + THTensor_(select)(outn,gradOutput,0,i); + THTensor_(select)(inpn,gradInput,0,i); + THTensor_(conv2Dmv)(inpn, 0.0, 1.0, outn, tweight, dH, dW, "F", "C"); + } + THTensor_(free)(outn); + THTensor_(free)(inpn); + } + THTensor_(free)(tweight); + + return 1; +} + +static void nn_(convolution_accGradParameters_)(THTensor *input, THTensor *gradOutput, THTensor *gradWeight, THTensor *gradBias, real scale, int dH, int dW) +{ + long k; + + /* gradient to bias */ + real *gradBias_data = THTensor_(data)(gradBias); + THTensor* gradOutSlice = THTensor_(new)(); + for(k = 0; k < gradOutput->size[0]; k++) + { + THTensor_(select)(gradOutSlice, gradOutput, 0, k); + gradBias_data[k] += scale*THTensor_(sumall)(gradOutSlice); + } + THTensor_(free)(gradOutSlice); + + /* gradient to kernels */ + THTensor_(conv2DRevger)(gradWeight, 1.0, scale, input, gradOutput, dH, dW); +} + +static int nn_(SpatialConvolution_accGradParameters)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id)); + real scale = luaL_optnumber(L, 4, 1); + int dW = luaT_getfieldcheckint(L, 1, "dW"); + int dH = luaT_getfieldcheckint(L, 1, "dH"); + int nOutputPlane = luaT_getfieldcheckint(L, 1, "nOutputPlane"); + + THTensor *gradWeight = luaT_getfieldcheckudata(L, 1, "gradWeight", torch_(Tensor_id)); + THTensor *gradBias = luaT_getfieldcheckudata(L, 1, "gradBias", torch_(Tensor_id)); + + THArgCheck( nOutputPlane == gradOutput->size[input->nDimension == 4 ? 1 : 0], 1, "Number of output features is not equal to nOutputPlane" ); + + if(input->nDimension == 3) + { + nn_(convolution_accGradParameters_)(input,gradOutput,gradWeight,gradBias,scale,dH,dW); + } + else + { + THTensor *outn = THTensor_(new)(); + THTensor *inpn = THTensor_(new)(); + long i; + for (i=0; i<input->size[0]; i++) + { + THTensor_(select)(outn,gradOutput,0,i); + THTensor_(select)(inpn,input,0,i); + nn_(convolution_accGradParameters_)(inpn,outn,gradWeight,gradBias,scale,dH,dW); + } + THTensor_(free)(outn); + THTensor_(free)(inpn); + } + + return 0; +} + +static const struct luaL_Reg nn_(SpatialConvolution__) [] = { + {"SpatialConvolution_updateOutput", nn_(SpatialConvolution_updateOutput)}, + {"SpatialConvolution_updateGradInput", nn_(SpatialConvolution_updateGradInput)}, + {"SpatialConvolution_accGradParameters", nn_(SpatialConvolution_accGradParameters)}, + {NULL, NULL} +}; + +static void nn_(SpatialConvolution_init)(lua_State *L) +{ + luaT_pushmetaclass(L, torch_(Tensor_id)); + luaT_registeratname(L, nn_(SpatialConvolution__), "nn"); + lua_pop(L,1); +} + +#endif diff --git a/generic/SpatialConvolutionMap.c b/generic/SpatialConvolutionMap.c new file mode 100644 index 0000000..ff7d8ca --- /dev/null +++ b/generic/SpatialConvolutionMap.c @@ -0,0 +1,229 @@ +#ifndef TH_GENERIC_FILE +#define TH_GENERIC_FILE "generic/SpatialConvolutionMap.c" +#else + +static int nn_(SpatialConvolutionMap_updateOutput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + int kW = luaT_getfieldcheckint(L, 1, "kW"); + int kH = luaT_getfieldcheckint(L, 1, "kH"); + int dW = luaT_getfieldcheckint(L, 1, "dW"); + int dH = luaT_getfieldcheckint(L, 1, "dH"); + int nInputPlane = luaT_getfieldcheckint(L, 1, "nInputPlane"); + int nOutputPlane = luaT_getfieldcheckint(L, 1, "nOutputPlane"); + + THTensor *connTable = luaT_getfieldcheckudata(L, 1, "connTable", torch_(Tensor_id)); + THTensor *weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id)); + THTensor *bias = luaT_getfieldcheckudata(L, 1, "bias", torch_(Tensor_id)); + THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + + luaL_argcheck(L, input->nDimension == 3, 2, "3D tensor expected"); + luaL_argcheck(L, input->size[0] == nInputPlane, 2, "invalid number of input planes"); + luaL_argcheck(L, input->size[2] >= kW && input->size[1] >= kH, 2, "input image smaller than kernel size"); + + THTensor_(resize3d)(output, nOutputPlane, + (input->size[1] - kH) / dH + 1, + (input->size[2] - kW) / dW + 1); + + // contiguous + input = THTensor_(newContiguous)(input); + output = THTensor_(newContiguous)(output); + + // get raw pointers + real *input_data = THTensor_(data)(input); + real *output_data = THTensor_(data)(output); + real *weight_data = THTensor_(data)(weight); + + // and dims + long input_n = input->size[0]; + long input_h = input->size[1]; + long input_w = input->size[2]; + long output_n = output->size[0]; + long output_h = output->size[1]; + long output_w = output->size[2]; + long weight_n = weight->size[0]; + long weight_h = weight->size[1]; + long weight_w = weight->size[2]; + + // add bias + THTensor *outputPlane = THTensor_(new)(); + int k; + for (k = 0; k < nOutputPlane; k++) { + THTensor_(select)(outputPlane,output,0,k); + THTensor_(fill)(outputPlane, THTensor_(get1d)(bias, k)); + } + THTensor_(free)(outputPlane); + + // convolve all maps + int i,o; + int nweight = connTable->size[0]; + for (k = 0; k < nweight; k++) { + // get offsets for input/output + o = (int)THTensor_(get2d)(connTable,k,1)-1; + i = (int)THTensor_(get2d)(connTable,k,0)-1; + + // convolve each map + THTensor_(validXCorr2Dptr)(output_data + o*output_w*output_h, + 1.0, + input_data + i*input_w*input_h, input_h, input_w, + weight_data + k*weight_w*weight_h, weight_h, weight_w, + dH, dW); + } + + // clean up + THTensor_(free)(input); + THTensor_(free)(output); + + return 1; +} + +static int nn_(SpatialConvolutionMap_updateGradInput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id)); + int kW = luaT_getfieldcheckint(L, 1, "kW"); + int kH = luaT_getfieldcheckint(L, 1, "kH"); + int dW = luaT_getfieldcheckint(L, 1, "dW"); + int dH = luaT_getfieldcheckint(L, 1, "dH"); + int nInputPlane = luaT_getfieldcheckint(L, 1, "nInputPlane"); + int nOutputPlane = luaT_getfieldcheckint(L, 1, "nOutputPlane"); + + THTensor *connTable = luaT_getfieldcheckudata(L, 1, "connTable", torch_(Tensor_id)); + THTensor *weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id)); + THTensor *gradWeight = luaT_getfieldcheckudata(L, 1, "gradWeight", torch_(Tensor_id)); + THTensor *gradBias = luaT_getfieldcheckudata(L, 1, "gradBias", torch_(Tensor_id)); + THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id)); + + // contiguous + gradInput = THTensor_(newContiguous)(gradInput); + gradOutput = THTensor_(newContiguous)(gradOutput); + + // Resize/Zero + THTensor_(resizeAs)(gradInput, input); + THTensor_(zero)(gradInput); + + // get raw pointers + real *gradInput_data = THTensor_(data)(gradInput); + real *gradOutput_data = THTensor_(data)(gradOutput); + real *weight_data = THTensor_(data)(weight); + real *gradWeight_data = THTensor_(data)(gradWeight); + + // and dims + long input_n = input->size[0]; + long input_h = input->size[1]; + long input_w = input->size[2]; + long output_n = gradOutput->size[0]; + long output_h = gradOutput->size[1]; + long output_w = gradOutput->size[2]; + long weight_n = weight->size[0]; + long weight_h = weight->size[1]; + long weight_w = weight->size[2]; + + // updateGradInput all + int k; + int nkernel = connTable->size[0]; + for(k = 0; k < nkernel; k++) + { + int o = (int)THTensor_(get2d)(connTable,k,1)-1; + int i = (int)THTensor_(get2d)(connTable,k,0)-1; + + // gradient to input + THTensor_(fullConv2Dptr)(gradInput_data + i*input_w*input_h, + 1.0, + gradOutput_data + o*output_w*output_h, output_h, output_w, + weight_data + k*weight_w*weight_h, weight_h, weight_w, + dH, dW); + } + + // clean up + THTensor_(free)(gradInput); + THTensor_(free)(gradOutput); + + return 1; +} + +static int nn_(SpatialConvolutionMap_accGradParameters)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id)); + int kW = luaT_getfieldcheckint(L, 1, "kW"); + int kH = luaT_getfieldcheckint(L, 1, "kH"); + int dW = luaT_getfieldcheckint(L, 1, "dW"); + int dH = luaT_getfieldcheckint(L, 1, "dH"); + int nInputPlane = luaT_getfieldcheckint(L, 1, "nInputPlane"); + int nOutputPlane = luaT_getfieldcheckint(L, 1, "nOutputPlane"); + real scale = luaL_optnumber(L, 4, 1); + + THTensor *connTable = luaT_getfieldcheckudata(L, 1, "connTable", torch_(Tensor_id)); + THTensor *weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id)); + THTensor *gradWeight = luaT_getfieldcheckudata(L, 1, "gradWeight", torch_(Tensor_id)); + THTensor *gradBias = luaT_getfieldcheckudata(L, 1, "gradBias", torch_(Tensor_id)); + THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id)); + + // contiguous + input = THTensor_(newContiguous)(input); + gradOutput = THTensor_(newContiguous)(gradOutput); + + // get raw pointers + real *input_data = THTensor_(data)(input); + real *gradOutput_data = THTensor_(data)(gradOutput); + real *weight_data = THTensor_(data)(weight); + real *gradWeight_data = THTensor_(data)(gradWeight); + + // and dims + long input_n = input->size[0]; + long input_h = input->size[1]; + long input_w = input->size[2]; + long output_n = gradOutput->size[0]; + long output_h = gradOutput->size[1]; + long output_w = gradOutput->size[2]; + long weight_n = weight->size[0]; + long weight_h = weight->size[1]; + long weight_w = weight->size[2]; + + // gradients wrt bias + int k; + THTensor *gradOutputPlane = THTensor_(new)(); + real *gradBias_data = THTensor_(data)(gradBias); + for(k = 0; k < nOutputPlane; k++) { + THTensor_(select)(gradOutputPlane, gradOutput, 0, k); + gradBias_data[k] += scale * THTensor_(sumall)(gradOutputPlane); + } + THTensor_(free)(gradOutputPlane); + + // gradients wrt weight + int nkernel = connTable->size[0]; + for(k = 0; k < nkernel; k++) + { + int o = (int)THTensor_(get2d)(connTable,k,1)-1; + int i = (int)THTensor_(get2d)(connTable,k,0)-1; + + // gradient to kernel + THTensor_(validXCorr2DRevptr)(gradWeight_data + k*weight_w*weight_h, + scale, + input_data + i*input_w*input_h, input_h, input_w, + gradOutput_data + o*output_w*output_h, output_h, output_w, + dH, dW); + } + + // clean up + THTensor_(free)(input); + THTensor_(free)(gradOutput); + return 0; +} + +static const struct luaL_Reg nn_(SpatialConvolutionMap__) [] = { + {"SpatialConvolutionMap_updateOutput", nn_(SpatialConvolutionMap_updateOutput)}, + {"SpatialConvolutionMap_updateGradInput", nn_(SpatialConvolutionMap_updateGradInput)}, + {"SpatialConvolutionMap_accGradParameters", nn_(SpatialConvolutionMap_accGradParameters)}, + {NULL, NULL} +}; + +static void nn_(SpatialConvolutionMap_init)(lua_State *L) +{ + luaT_pushmetaclass(L, torch_(Tensor_id)); + luaT_registeratname(L, nn_(SpatialConvolutionMap__), "nn"); + lua_pop(L,1); +} + +#endif diff --git a/generic/SpatialMaxPooling.c b/generic/SpatialMaxPooling.c new file mode 100644 index 0000000..b9fab3b --- /dev/null +++ b/generic/SpatialMaxPooling.c @@ -0,0 +1,163 @@ +#ifndef TH_GENERIC_FILE +#define TH_GENERIC_FILE "generic/SpatialMaxPooling.c" +#else + +static int nn_(SpatialMaxPooling_updateOutput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + int kW = luaT_getfieldcheckint(L, 1, "kW"); + int kH = luaT_getfieldcheckint(L, 1, "kH"); + int dW = luaT_getfieldcheckint(L, 1, "dW"); + int dH = luaT_getfieldcheckint(L, 1, "dH"); + THTensor *indices = luaT_getfieldcheckudata(L, 1, "indices", torch_(Tensor_id)); + THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + + luaL_argcheck(L, input->nDimension == 3, 2, "3D tensor expected"); + luaL_argcheck(L, input->size[2] >= kW && input->size[1] >= kH, 2, "input image smaller than kernel size"); + + // sizes + long nslices = input->size[0]; + long iheight = input->size[1]; + long iwidth = input->size[2]; + long oheight = (iheight - kH) / dH + 1; + long owidth = (iwidth - kW) / dW + 1; + + // get contiguous input + input = THTensor_(newContiguous)(input); + + // resize output + THTensor_(resize3d)(output, nslices, oheight, owidth); + + // indices will contain i,j locatyions for each output point + THTensor_(resize4d)(indices, 2, nslices, oheight, owidth); + + // get raw pointers + real *input_data = THTensor_(data)(input); + real *output_data = THTensor_(data)(output); + real *indices_data = THTensor_(data)(indices); + + // compute max pooling for each input slice + long k; + for (k = 0; k < nslices; k++) { + // pointers to slices + real *input_p = input_data + k*iwidth*iheight; + real *output_p = output_data + k*owidth*oheight; + real *indy_p = indices_data + k*owidth*oheight; + real *indx_p = indices_data + (k+nslices)*owidth*oheight; + + // loop over output + int i,j; + for(i = 0; i < oheight; i++) { + for(j = 0; j < owidth; j++) { + // local pointers + real *ip = input_p + i*iwidth*dH + j*dW; + real *op = output_p + i*owidth + j; + real *indyp = indy_p + i*owidth + j; + real *indxp = indx_p + i*owidth + j; + + // compute local max: + long maxindex = -1; + real maxval = -THInf; + long tcntr = 0; + int x,y; + for(y = 0; y < kH; y++) { + for(x = 0; x < kW; x++) { + real val = *(ip + y*iwidth + x); + if (val > maxval) { + maxval = val; + maxindex = tcntr; + } + tcntr++; + } + } + + // set output to local max + *op = maxval; + + // store location of max (x,y) + *indyp = (int)(maxindex / dW)+1; + *indxp = (maxindex % dW) +1; + } + } + } + + // cleanup + THTensor_(free)(input); + + return 1; +} + +static int nn_(SpatialMaxPooling_updateGradInput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id)); + int kW = luaT_getfieldcheckint(L, 1, "kW"); + int kH = luaT_getfieldcheckint(L, 1, "kH"); + int dW = luaT_getfieldcheckint(L, 1, "dW"); + int dH = luaT_getfieldcheckint(L, 1, "dH"); + THTensor *indices = luaT_getfieldcheckudata(L, 1, "indices", torch_(Tensor_id)); + THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id)); + + // get contiguous gradOutput + gradOutput = THTensor_(newContiguous)(gradOutput); + + // resize + THTensor_(resizeAs)(gradInput, input); + THTensor_(zero)(gradInput); + + // sizes + int ichannels = input->size[0]; + int iheight = input->size[1]; + int iwidth = input->size[2]; + int ochannels = ichannels; + int oheight = gradOutput->size[1]; + int owidth = gradOutput->size[2]; + + // get raw pointers + real *gradInput_data = THTensor_(data)(gradInput); + real *gradOutput_data = THTensor_(data)(gradOutput); + real *indices_data = THTensor_(data)(indices); + + // backprop + long k; + for (k = 0; k < input->size[0]; k++) { + // pointers to slices + real *gradOutput_p = gradOutput_data + k*owidth*oheight; + real *gradInput_p = gradInput_data + k*iwidth*iheight; + real *indy_p = indices_data + k*owidth*oheight; + real *indx_p = indices_data + (k+ochannels)*owidth*oheight; + + // calculate max points + int i,j; + for(i = 0; i < oheight; i++) { + for(j = 0; j < owidth; j++) { + // retrieve position of max + long maxi = *(indy_p + i*owidth + j) - 1 + i*dH; + long maxj = *(indx_p + i*owidth + j) - 1 + j*dW; + + // update gradient + *(gradInput_p + maxi*iwidth + maxj) += *(gradOutput_p + i*owidth + j); + } + } + } + + // cleanup + THTensor_(free)(gradOutput); + + return 1; +} + +static const struct luaL_Reg nn_(SpatialMaxPooling__) [] = { + {"SpatialMaxPooling_updateOutput", nn_(SpatialMaxPooling_updateOutput)}, + {"SpatialMaxPooling_updateGradInput", nn_(SpatialMaxPooling_updateGradInput)}, + {NULL, NULL} +}; + +static void nn_(SpatialMaxPooling_init)(lua_State *L) +{ + luaT_pushmetaclass(L, torch_(Tensor_id)); + luaT_registeratname(L, nn_(SpatialMaxPooling__), "nn"); + lua_pop(L,1); +} + +#endif diff --git a/generic/SpatialSubSampling.c b/generic/SpatialSubSampling.c new file mode 100644 index 0000000..705253f --- /dev/null +++ b/generic/SpatialSubSampling.c @@ -0,0 +1,278 @@ +#ifndef TH_GENERIC_FILE +#define TH_GENERIC_FILE "generic/SpatialSubSampling.c" +#else + +static int nn_(SpatialSubSampling_updateOutput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + int kW = luaT_getfieldcheckint(L, 1, "kW"); + int kH = luaT_getfieldcheckint(L, 1, "kH"); + int dW = luaT_getfieldcheckint(L, 1, "dW"); + int dH = luaT_getfieldcheckint(L, 1, "dH"); + int nInputPlane = luaT_getfieldcheckint(L, 1, "nInputPlane"); + + THTensor *weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id)); + THTensor *bias = luaT_getfieldcheckudata(L, 1, "bias", torch_(Tensor_id)); + THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + + real *weight_data = THTensor_(data)(weight); + real *bias_data = THTensor_(data)(bias); + real *output_data; + real *input_data; + + + luaL_argcheck(L, input->nDimension == 3 || input->nDimension == 4, 2, "3D or 4D(batch mode) tensor expected"); + + int dimw = 2; + int dimh = 1; + if (input->nDimension == 4) { + dimw++; + dimh++; + } + + long inputWidth = input->size[dimw]; + long inputHeight = input->size[dimh]; + long outputWidth = (inputWidth - kW) / dW + 1; + long outputHeight = (inputHeight - kH) / dH + 1; + + + luaL_argcheck(L, input->size[dimh-1] == nInputPlane, 2, "invalid number of input planes"); + luaL_argcheck(L, inputWidth >= kW && inputHeight >= kH, 2, "input image smaller than kernel size"); + + input = THTensor_(newContiguous)(input); + input_data = THTensor_(data)(input); + + long nbatch = 1; + if (input->nDimension == 3) + { + THTensor_(resize3d)(output, nInputPlane, outputHeight, outputWidth); + } + else + { + nbatch = input->size[0]; + THTensor_(resize4d)(output, nbatch, nInputPlane, outputHeight, outputWidth); + } + + output_data = THTensor_(data)(output); + + long i, k, p; + + for(p = 0; p < nbatch; p++) + { + //input_data += p*nInputPlane*inputWidth*inputHeight; + //output_data += p*nInputPlane*outputHeight*outputWidth; + for(k = 0; k < nInputPlane; k++) + { + real *ptr_output; + long xx, yy; + + /* Get the good mask for (k,i) (k out, i in) */ + real the_weight = weight_data[k]; + + /* Initialize to the bias */ + real z = bias_data[k]; + for(i = 0; i < outputWidth*outputHeight; i++) + output_data[i] = z; + + /* For all output pixels... */ + ptr_output = output_data; + for(yy = 0; yy < outputHeight; yy++) + { + for(xx = 0; xx < outputWidth; xx++) + { + // Compute the mean of the input image... + real *ptr_input = input_data+yy*dH*inputWidth+xx*dW; + real sum = 0; + long kx, ky; + + for(ky = 0; ky < kH; ky++) + { + for(kx = 0; kx < kW; kx++) + sum += ptr_input[kx]; + ptr_input += inputWidth; // next input line + } + + // Update output + *ptr_output++ += the_weight*sum; + } + } + + // Next input/output plane + output_data += outputWidth*outputHeight; + input_data += inputWidth*inputHeight; + } + } + + THTensor_(free)(input); + + return 1; +} + +static int nn_(SpatialSubSampling_updateGradInput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id)); + int kW = luaT_getfieldcheckint(L, 1, "kW"); + int kH = luaT_getfieldcheckint(L, 1, "kH"); + int dW = luaT_getfieldcheckint(L, 1, "dW"); + int dH = luaT_getfieldcheckint(L, 1, "dH"); + int nInputPlane = luaT_getfieldcheckint(L, 1, "nInputPlane"); + + THTensor *weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id)); + THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id)); + + int dimw = 2; + int dimh = 1; + long nbatch = 1; + if (input->nDimension == 4) { + dimw++; + dimh++; + nbatch = input->size[0]; + } + + long inputWidth = input->size[dimw]; + long inputHeight = input->size[dimh]; + long outputWidth = (inputWidth - kW) / dW + 1; + long outputHeight = (inputHeight - kH) / dH + 1; + + real *weight_data = THTensor_(data)(weight); + real *gradOutput_data = THTensor_(data)(gradOutput); + real *gradInput_data; + + THTensor_(resizeAs)(gradInput, input); + THTensor_(zero)(gradInput); + gradInput_data = THTensor_(data)(gradInput); + gradOutput_data = THTensor_(data)(gradOutput); + + long i, k, p; + + for(p = 0; p < nbatch; p++) + { + //gradInput_data += p*nInputPlane*inputWidth*inputHeight; + //gradOutput_data += p*nInputPlane*outputWidth*outputHeight; + for(k = 0; k < nInputPlane; k++) + { + real the_weight = weight_data[k]; + real *ptr_gradOutput = gradOutput_data; + long xx, yy; + + for(yy = 0; yy < outputHeight; yy++) + { + for(xx = 0; xx < outputWidth; xx++) + { + real *ptr_gradInput = gradInput_data+yy*dH*inputWidth+xx*dW; + real z = *ptr_gradOutput++ * the_weight; + long kx, ky; + + for(ky = 0; ky < kH; ky++) + { + for(kx = 0; kx < kW; kx++) + ptr_gradInput[kx] += z; + ptr_gradInput += inputWidth; + } + } + } + gradOutput_data += outputWidth*outputHeight; + gradInput_data += inputWidth*inputHeight; + } + } + + return 1; +} + +static int nn_(SpatialSubSampling_accGradParameters)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id)); + real scale = luaL_optnumber(L, 4, 1); + int kW = luaT_getfieldcheckint(L, 1, "kW"); + int kH = luaT_getfieldcheckint(L, 1, "kH"); + int dW = luaT_getfieldcheckint(L, 1, "dW"); + int dH = luaT_getfieldcheckint(L, 1, "dH"); + int nInputPlane = luaT_getfieldcheckint(L, 1, "nInputPlane"); + + THTensor *gradWeight = luaT_getfieldcheckudata(L, 1, "gradWeight", torch_(Tensor_id)); + THTensor *gradBias = luaT_getfieldcheckudata(L, 1, "gradBias", torch_(Tensor_id)); + + int dimw = 2; + int dimh = 1; + long nbatch = 1; + if (input->nDimension == 4) { + dimw++; + dimh++; + nbatch = input->size[0]; + } + + long inputWidth = input->size[dimw]; + long inputHeight = input->size[dimh]; + long outputWidth = (inputWidth - kW) / dW + 1; + long outputHeight = (inputHeight - kH) / dH + 1; + + real *gradWeight_data = THTensor_(data)(gradWeight); + real *gradBias_data = THTensor_(data)(gradBias); + real *gradOutput_data = THTensor_(data)(gradOutput); + real *input_data; + + input = THTensor_(newContiguous)(input); + input_data = THTensor_(data)(input); + + long i, k, p; + for(p = 0; p < nbatch; p++) + { + //input_data += p*nInputPlane*inputWidth*inputHeight; + //gradOutput_data += p*nInputPlane*inputWidth*inputHeight; + for(k = 0; k < nInputPlane; k++) + { + real *ptr_gradOutput = gradOutput_data; + real sum; + long xx, yy; + + sum = 0; + for(i = 0; i < outputWidth*outputHeight; i++) + sum += gradOutput_data[i]; + gradBias_data[k] += scale*sum; + + sum = 0; + for(yy = 0; yy < outputHeight; yy++) + { + for(xx = 0; xx < outputWidth; xx++) + { + real *ptr_input = input_data+yy*dH*inputWidth+xx*dW; + real z = *ptr_gradOutput++; + long kx, ky; + + for(ky = 0; ky < kH; ky++) + { + for(kx = 0; kx < kW; kx++) + sum += z * ptr_input[kx]; + ptr_input += inputWidth; + } + } + } + gradWeight_data[k] += scale*sum; + gradOutput_data += outputWidth*outputHeight; + input_data += inputWidth*inputHeight; + } + } + + + THTensor_(free)(input); + + return 0; +} + +static const struct luaL_Reg nn_(SpatialSubSampling__) [] = { + {"SpatialSubSampling_updateOutput", nn_(SpatialSubSampling_updateOutput)}, + {"SpatialSubSampling_updateGradInput", nn_(SpatialSubSampling_updateGradInput)}, + {"SpatialSubSampling_accGradParameters", nn_(SpatialSubSampling_accGradParameters)}, + {NULL, NULL} +}; + +static void nn_(SpatialSubSampling_init)(lua_State *L) +{ + luaT_pushmetaclass(L, torch_(Tensor_id)); + luaT_registeratname(L, nn_(SpatialSubSampling__), "nn"); + lua_pop(L,1); +} + +#endif diff --git a/generic/Sqrt.c b/generic/Sqrt.c new file mode 100644 index 0000000..a739e96 --- /dev/null +++ b/generic/Sqrt.c @@ -0,0 +1,46 @@ +#ifndef TH_GENERIC_FILE +#define TH_GENERIC_FILE "generic/Sqrt.c" +#else + +static int nn_(Sqrt_updateOutput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + + THTensor_(resizeAs)(output, input); + + TH_TENSOR_APPLY2(real, output, real, input, \ + *output_data = sqrt(*input_data);); + + return 1; +} + +static int nn_(Sqrt_updateGradInput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id)); + THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id)); + + THTensor_(resizeAs)(gradInput, input); + + TH_TENSOR_APPLY3(real, gradInput, real, gradOutput, real, output, \ + *gradInput_data = 0.5 * (*gradOutput_data / *output_data);); + + return 1; +} + +static const struct luaL_Reg nn_(Sqrt__) [] = { + {"Sqrt_updateOutput", nn_(Sqrt_updateOutput)}, + {"Sqrt_updateGradInput", nn_(Sqrt_updateGradInput)}, + {NULL, NULL} +}; + +static void nn_(Sqrt_init)(lua_State *L) +{ + luaT_pushmetaclass(L, torch_(Tensor_id)); + luaT_registeratname(L, nn_(Sqrt__), "nn"); + lua_pop(L,1); +} + +#endif diff --git a/generic/Square.c b/generic/Square.c new file mode 100644 index 0000000..409055d --- /dev/null +++ b/generic/Square.c @@ -0,0 +1,45 @@ +#ifndef TH_GENERIC_FILE +#define TH_GENERIC_FILE "generic/Square.c" +#else + +static int nn_(Square_updateOutput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + + THTensor_(resizeAs)(output, input); + + TH_TENSOR_APPLY2(real, output, real, input, \ + *output_data = *input_data * *input_data;); + + return 1; +} + +static int nn_(Square_updateGradInput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id)); + THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id)); + + THTensor_(resizeAs)(gradInput, input); + + TH_TENSOR_APPLY3(real, gradInput, real, gradOutput, real, input, \ + *gradInput_data = 2.0 * (*gradOutput_data) * (*input_data);); + + return 1; +} + +static const struct luaL_Reg nn_(Square__) [] = { + {"Square_updateOutput", nn_(Square_updateOutput)}, + {"Square_updateGradInput", nn_(Square_updateGradInput)}, + {NULL, NULL} +}; + +static void nn_(Square_init)(lua_State *L) +{ + luaT_pushmetaclass(L, torch_(Tensor_id)); + luaT_registeratname(L, nn_(Square__), "nn"); + lua_pop(L,1); +} + +#endif diff --git a/generic/Tanh.c b/generic/Tanh.c new file mode 100644 index 0000000..5c24d15 --- /dev/null +++ b/generic/Tanh.c @@ -0,0 +1,45 @@ +#ifndef TH_GENERIC_FILE +#define TH_GENERIC_FILE "generic/Tanh.c" +#else + +static int nn_(Tanh_updateOutput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + + THTensor_(resizeAs)(output, input); + + TH_TENSOR_APPLY2(real, output, real, input, \ + *output_data = tanh(*input_data);) + + return 1; +} + +static int nn_(Tanh_updateGradInput)(lua_State *L) +{ + THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id)); + THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id)); + + THTensor_(resizeAs)(gradInput, output); + TH_TENSOR_APPLY3(real, gradInput, real, gradOutput, real, output, \ + real z = *output_data; \ + *gradInput_data = *gradOutput_data * (1. - z*z);); + return 1; +} + +static const struct luaL_Reg nn_(Tanh__) [] = { + {"Tanh_updateOutput", nn_(Tanh_updateOutput)}, + {"Tanh_updateGradInput", nn_(Tanh_updateGradInput)}, + {NULL, NULL} +}; + +static void nn_(Tanh_init)(lua_State *L) +{ + luaT_pushmetaclass(L, torch_(Tensor_id)); + luaT_registeratname(L, nn_(Tanh__), "nn"); + lua_pop(L,1); + +} + +#endif diff --git a/generic/TemporalConvolution.c b/generic/TemporalConvolution.c new file mode 100644 index 0000000..fa14a22 --- /dev/null +++ b/generic/TemporalConvolution.c @@ -0,0 +1,194 @@ +#ifndef TH_GENERIC_FILE +#define TH_GENERIC_FILE "generic/TemporalConvolution.c" +#else + +static int nn_(TemporalConvolution_updateOutput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + int kW = luaT_getfieldcheckint(L, 1, "kW"); + int dW = luaT_getfieldcheckint(L, 1, "dW"); + int inputFrameSize = luaT_getfieldcheckint(L, 1, "inputFrameSize"); + int outputFrameSize = luaT_getfieldcheckint(L, 1, "outputFrameSize"); + + THTensor *weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id)); + THTensor *bias = luaT_getfieldcheckudata(L, 1, "bias", torch_(Tensor_id)); + THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + + THTensor *outputWindow, *inputWindow; + int nInputFrame, nOutputFrame; + long k; + + luaL_argcheck(L, input->nDimension == 2, 2, "2D tensor expected"); + luaL_argcheck(L, input->size[1] == inputFrameSize, 2, "invalid input frame size"); + luaL_argcheck(L, input->size[0] >= kW, 2, "input sequence smaller than kernel size"); + + input = THTensor_(newContiguous)(input); + outputWindow = THTensor_(new)(); + inputWindow = THTensor_(new)(); + + nInputFrame = input->size[0]; + nOutputFrame = (nInputFrame - kW) / dW + 1; + + THTensor_(resize2d)(output, + nOutputFrame, + outputFrameSize); + + /* bias first */ + for(k = 0; k < nOutputFrame; k++) + { + THTensor_(select)(outputWindow, output, 0, k); + THTensor_(copy)(outputWindow, bias); + } + + /* ouch */ + for(k = 0; nOutputFrame > 0; k++) + { + long outputFrameStride = (kW-1)/dW+1; + long inputFrameStride = outputFrameStride*dW; + long nFrame = (nInputFrame-k*dW-kW)/inputFrameStride + 1; + nOutputFrame -= nFrame; + + THTensor_(setStorage2d)(inputWindow, input->storage, + input->storageOffset+k*dW*input->size[1], + nFrame, inputFrameStride*input->size[1], + kW*input->size[1], 1); + + THTensor_(setStorage2d)(outputWindow, output->storage, + output->storageOffset + k*output->size[1], + nFrame, outputFrameStride*output->size[1], + output->size[1], 1); + + THTensor_(transpose)(weight, NULL, 0, 1); + THTensor_(addmm)(outputWindow, 1, outputWindow, 1, inputWindow, weight); + THTensor_(transpose)(weight, NULL, 0, 1); + } + + THTensor_(free)(outputWindow); + THTensor_(free)(inputWindow); + THTensor_(free)(input); + + return 1; +} + +static int nn_(TemporalConvolution_updateGradInput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id)); + int kW = luaT_getfieldcheckint(L, 1, "kW"); + int dW = luaT_getfieldcheckint(L, 1, "dW"); + long nInputFrame = input->size[0]; + long nOutputFrame = gradOutput->size[0]; + + THTensor *weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id)); + THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id)); + + THTensor *gradOutputWindow; + THTensor *gradInputWindow; + long k; + + gradOutputWindow = THTensor_(new)(); + gradInputWindow = THTensor_(new)(); + + THTensor_(resizeAs)(gradInput, input); + THTensor_(zero)(gradInput); + + /* ouch */ + for(k = 0; nOutputFrame > 0; k++) + { + long outputFrameStride = (kW-1)/dW+1; + long inputFrameStride = outputFrameStride*dW; + long nFrame = (nInputFrame-k*dW-kW)/inputFrameStride + 1; + nOutputFrame -= nFrame; + + THTensor_(setStorage2d)(gradOutputWindow, gradOutput->storage, + gradOutput->storageOffset + k*gradOutput->size[1], + nFrame, outputFrameStride*gradOutput->size[1], + gradOutput->size[1], 1); + + THTensor_(setStorage2d)(gradInputWindow, gradInput->storage, + gradInput->storageOffset+k*dW*gradInput->size[1], + nFrame, inputFrameStride*gradInput->size[1], + kW*gradInput->size[1], 1); + + THTensor_(addmm)(gradInputWindow, 1, gradInputWindow, 1, gradOutputWindow, weight); + } + + THTensor_(free)(gradOutputWindow); + THTensor_(free)(gradInputWindow); + + return 1; +} + +static int nn_(TemporalConvolution_accGradParameters)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id)); + real scale = luaL_optnumber(L, 4, 1); + int kW = luaT_getfieldcheckint(L, 1, "kW"); + int dW = luaT_getfieldcheckint(L, 1, "dW"); + long nInputFrame = input->size[0]; + long nOutputFrame = gradOutput->size[0]; + + THTensor *gradWeight = luaT_getfieldcheckudata(L, 1, "gradWeight", torch_(Tensor_id)); + THTensor *gradBias = luaT_getfieldcheckudata(L, 1, "gradBias", torch_(Tensor_id)); + + THTensor *gradOutputWindow; + THTensor *inputWindow; + long k; + + input = THTensor_(newContiguous)(input); + gradOutputWindow = THTensor_(new)(); + inputWindow = THTensor_(new)(); + + /* bias first */ + for(k = 0; k < nOutputFrame; k++) + { + THTensor_(select)(gradOutputWindow, gradOutput, 0, k); + THTensor_(cadd)(gradBias, gradBias, scale, gradOutputWindow); + } + + /* ouch */ + for(k = 0; nOutputFrame > 0; k++) + { + long outputFrameStride = (kW-1)/dW+1; + long inputFrameStride = outputFrameStride*dW; + long nFrame = (nInputFrame-k*dW-kW)/inputFrameStride + 1; + nOutputFrame -= nFrame; + + THTensor_(setStorage2d)(inputWindow, input->storage, + input->storageOffset+k*dW*input->size[1], + nFrame, inputFrameStride*input->size[1], + kW*input->size[1], 1); + + THTensor_(setStorage2d)(gradOutputWindow, gradOutput->storage, + gradOutput->storageOffset + k*gradOutput->size[1], + nFrame, outputFrameStride*gradOutput->size[1], + gradOutput->size[1], 1); + + THTensor_(transpose)(gradOutputWindow, NULL, 0, 1); + THTensor_(addmm)(gradWeight, 1, gradWeight, scale, gradOutputWindow, inputWindow); + THTensor_(transpose)(gradOutputWindow, NULL, 0, 1); + } + + THTensor_(free)(gradOutputWindow); + THTensor_(free)(inputWindow); + THTensor_(free)(input); + + return 0; +} + +static const struct luaL_Reg nn_(TemporalConvolution__) [] = { + {"TemporalConvolution_updateOutput", nn_(TemporalConvolution_updateOutput)}, + {"TemporalConvolution_updateGradInput", nn_(TemporalConvolution_updateGradInput)}, + {"TemporalConvolution_accGradParameters", nn_(TemporalConvolution_accGradParameters)}, + {NULL, NULL} +}; + +static void nn_(TemporalConvolution_init)(lua_State *L) +{ + luaT_pushmetaclass(L, torch_(Tensor_id)); + luaT_registeratname(L, nn_(TemporalConvolution__), "nn"); + lua_pop(L,1); +} + +#endif diff --git a/generic/TemporalSubSampling.c b/generic/TemporalSubSampling.c new file mode 100644 index 0000000..39e7f3b --- /dev/null +++ b/generic/TemporalSubSampling.c @@ -0,0 +1,139 @@ +#ifndef TH_GENERIC_FILE +#define TH_GENERIC_FILE "generic/TemporalSubSampling.c" +#else + +static int nn_(TemporalSubSampling_updateOutput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + int kW = luaT_getfieldcheckint(L, 1, "kW"); + int dW = luaT_getfieldcheckint(L, 1, "dW"); + int inputFrameSize = luaT_getfieldcheckint(L, 1, "inputFrameSize"); + + THTensor *weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id)); + THTensor *bias = luaT_getfieldcheckudata(L, 1, "bias", torch_(Tensor_id)); + THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + + THTensor *outputFrame, *inputWindow; + int nInputFrame, nOutputFrame; + long k; + + luaL_argcheck(L, input->nDimension == 2, 2, "2D tensor expected"); + luaL_argcheck(L, input->size[1] == inputFrameSize, 2, "invalid input frame size"); + luaL_argcheck(L, input->size[0] >= kW, 2, "input sequence smaller than kernel size"); + + outputFrame = THTensor_(new)(); + inputWindow = THTensor_(new)(); + + nInputFrame = input->size[0]; + nOutputFrame = (nInputFrame - kW) / dW + 1; + + THTensor_(resize2d)(output, + nOutputFrame, + inputFrameSize); + + for(k = 0; k < nOutputFrame; k++) + { + THTensor_(narrow)(inputWindow, input, 0, k*dW, kW); + THTensor_(select)(outputFrame, output, 0, k); + THTensor_(sum)(outputFrame, inputWindow, 0); + THTensor_(cmul)(outputFrame, outputFrame, weight); + THTensor_(cadd)(outputFrame, outputFrame, 1, bias); + } + + THTensor_(free)(outputFrame); + THTensor_(free)(inputWindow); + + return 1; +} + +static int nn_(TemporalSubSampling_updateGradInput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id)); + int kW = luaT_getfieldcheckint(L, 1, "kW"); + int dW = luaT_getfieldcheckint(L, 1, "dW"); + + THTensor *weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id)); + THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id)); + + THTensor *gradOutputFrame; + THTensor *gradInputWindow, *buffer, *kwunit; + long k; + + gradOutputFrame = THTensor_(new)(); + gradInputWindow = THTensor_(new)(); + buffer = THTensor_(new)(); + kwunit = THTensor_(newWithSize1d)(kW); + + THTensor_(fill)(kwunit, 1); + THTensor_(resizeAs)(gradInput, input); + THTensor_(zero)(gradInput); + + for(k = 0; k < gradOutput->size[0]; k++) + { + THTensor_(narrow)(gradInputWindow, gradInput, 0, k*dW, kW); + THTensor_(select)(gradOutputFrame, gradOutput, 0, k); + THTensor_(cmul)(buffer, weight, gradOutputFrame); + THTensor_(addr)(gradInputWindow, 1, gradInputWindow, 1, kwunit, buffer); + } + + THTensor_(free)(gradOutputFrame); + THTensor_(free)(gradInputWindow); + THTensor_(free)(buffer); + THTensor_(free)(kwunit); + + return 1; +} + +static int nn_(TemporalSubSampling_accGradParameters)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id)); + real scale = luaL_optnumber(L, 4, 1); + + int kW = luaT_getfieldcheckint(L, 1, "kW"); + int dW = luaT_getfieldcheckint(L, 1, "dW"); + + THTensor *gradWeight = luaT_getfieldcheckudata(L, 1, "gradWeight", torch_(Tensor_id)); + THTensor *gradBias = luaT_getfieldcheckudata(L, 1, "gradBias", torch_(Tensor_id)); + + THTensor *gradOutputFrame; + THTensor *inputWindow, *buffer; + long k; + + + gradOutputFrame = THTensor_(new)(); + inputWindow = THTensor_(new)(); + buffer = THTensor_(new)(); + + for(k = 0; k < gradOutput->size[0]; k++) + { + THTensor_(narrow)(inputWindow, input, 0, k*dW, kW); + THTensor_(select)(gradOutputFrame, gradOutput, 0, k); + THTensor_(sum)(buffer, inputWindow, 0); + THTensor_(addcmul)(gradWeight, gradWeight, scale, buffer, gradOutputFrame); + THTensor_(cadd)(gradBias, gradBias, scale, gradOutputFrame); + } + + THTensor_(free)(gradOutputFrame); + THTensor_(free)(inputWindow); + THTensor_(free)(buffer); + + return 0; +} + +static const struct luaL_Reg nn_(TemporalSubSampling__) [] = { + {"TemporalSubSampling_updateOutput", nn_(TemporalSubSampling_updateOutput)}, + {"TemporalSubSampling_updateGradInput", nn_(TemporalSubSampling_updateGradInput)}, + {"TemporalSubSampling_accGradParameters", nn_(TemporalSubSampling_accGradParameters)}, + {NULL, NULL} +}; + +static void nn_(TemporalSubSampling_init)(lua_State *L) +{ + luaT_pushmetaclass(L, torch_(Tensor_id)); + luaT_registeratname(L, nn_(TemporalSubSampling__), "nn"); + lua_pop(L,1); +} + +#endif diff --git a/generic/Threshold.c b/generic/Threshold.c new file mode 100644 index 0000000..760e842 --- /dev/null +++ b/generic/Threshold.c @@ -0,0 +1,47 @@ +#ifndef TH_GENERIC_FILE +#define TH_GENERIC_FILE "generic/Threshold.c" +#else + +static int nn_(Threshold_updateOutput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + real val = luaT_getfieldchecknumber(L, 1, "val"); + real threshold = luaT_getfieldchecknumber(L, 1, "threshold"); + THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + + THTensor_(resizeAs)(output, input); + TH_TENSOR_APPLY2(real, output, real, input, \ + *output_data = (*input_data > threshold) ? *input_data : val;); + + return 1; +} + +static int nn_(Threshold_updateGradInput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id)); + real threshold = luaT_getfieldchecknumber(L, 1, "threshold"); + THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id)); + + THTensor_(resizeAs)(gradInput, input); + TH_TENSOR_APPLY3(real, gradInput, real, gradOutput, real, input, \ + if ((*input_data) > threshold) *gradInput_data = 1; \ + else *gradInput_data = 0; \ + *gradInput_data = (*gradOutput_data) * (*gradInput_data);); + return 1; +} + +static const struct luaL_Reg nn_(Threshold__) [] = { + {"Threshold_updateOutput", nn_(Threshold_updateOutput)}, + {"Threshold_updateGradInput", nn_(Threshold_updateGradInput)}, + {NULL, NULL} +}; + +static void nn_(Threshold_init)(lua_State *L) +{ + luaT_pushmetaclass(L, torch_(Tensor_id)); + luaT_registeratname(L, nn_(Threshold__), "nn"); + lua_pop(L,1); +} + +#endif diff --git a/generic/VolumetricConvolution.c b/generic/VolumetricConvolution.c new file mode 100644 index 0000000..0ec2247 --- /dev/null +++ b/generic/VolumetricConvolution.c @@ -0,0 +1,118 @@ +#ifndef TH_GENERIC_FILE +#define TH_GENERIC_FILE "generic/VolumetricConvolution.c" +#else + +static int nn_(VolumetricConvolution_updateOutput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + int dT = luaT_getfieldcheckint(L, 1, "dT"); + int dW = luaT_getfieldcheckint(L, 1, "dW"); + int dH = luaT_getfieldcheckint(L, 1, "dH"); + + THTensor *weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id)); + THTensor *bias = luaT_getfieldcheckudata(L, 1, "bias", torch_(Tensor_id)); + THTensor *output = luaT_getfieldcheckudata(L, 1, "output", torch_(Tensor_id)); + + luaL_argcheck(L, input->nDimension == 4, 2, "4D tensor expected"); + + long nOutputPlane = weight->size[0]; + long nInputPlane = weight->size[1]; + long kT = weight->size[2]; + long kH = weight->size[3]; + long kW = weight->size[4]; + long inputDepth = input->size[1]; + long inputHeight = input->size[2]; + long inputWidth = input->size[3]; + long outputDepth = (inputDepth - kT) / dT + 1; + long outputWidth = (inputWidth - kW) / dW + 1; + long outputHeight = (inputHeight - kH) / dH + 1; + + THTensor_(resize4d)(output, nOutputPlane, outputDepth, outputHeight, outputWidth); + + /* add bias */ + long i; + THTensor *outn = THTensor_(new)(); + for (i=0; i<bias->size[0]; i++) { + THTensor_(select)(outn,output,0,i); + THTensor_(fill)(outn, THTensor_(get1d)(bias, i)); + } + THTensor_(free)(outn); + + /* do convolutions */ + THTensor_(conv3Dmv)(output, 1.0, 1.0, input, weight, dT, dH, dW, "V", "X"); + + return 1; +} + + +static int nn_(VolumetricConvolution_updateGradInput)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id)); + int dT = luaT_getfieldcheckint(L, 1, "dT"); + int dW = luaT_getfieldcheckint(L, 1, "dW"); + int dH = luaT_getfieldcheckint(L, 1, "dH"); + int nOutputPlane = luaT_getfieldcheckint(L, 1, "nOutputPlane"); + + THTensor *weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id)); + THTensor *gradInput = luaT_getfieldcheckudata(L, 1, "gradInput", torch_(Tensor_id)); + + THArgCheck( nOutputPlane == gradOutput->size[0], 1, "Number of output features is not equal to nOutputPlane" ); + + /* gradient to input */ + THTensor *tweight = THTensor_(newTranspose)(weight,0,1); + THTensor_(conv3Dmv)(gradInput, 0.0, 1.0, gradOutput, tweight, dT, dH, dW, "F", "C"); + THTensor_(free)(tweight); + + return 1; +} + +static int nn_(VolumetricConvolution_accGradParameters)(lua_State *L) +{ + THTensor *input = luaT_checkudata(L, 2, torch_(Tensor_id)); + THTensor *gradOutput = luaT_checkudata(L, 3, torch_(Tensor_id)); + real scale = luaL_optnumber(L, 4, 1); + int dT = luaT_getfieldcheckint(L, 1, "dT"); + int dW = luaT_getfieldcheckint(L, 1, "dW"); + int dH = luaT_getfieldcheckint(L, 1, "dH"); + int nOutputPlane = luaT_getfieldcheckint(L, 1, "nOutputPlane"); + + THTensor *weight = luaT_getfieldcheckudata(L, 1, "weight", torch_(Tensor_id)); + THTensor *gradWeight = luaT_getfieldcheckudata(L, 1, "gradWeight", torch_(Tensor_id)); + THTensor *gradBias = luaT_getfieldcheckudata(L, 1, "gradBias", torch_(Tensor_id)); + + THArgCheck( nOutputPlane == gradOutput->size[0], 1, "Number of output features is not equal to nOutputPlane" ); + + long k; + + /* gradient to bias */ + real *gradBias_data = THTensor_(data)(gradBias); + THTensor* gradOutSlice = THTensor_(new)(); + for(k = 0; k < nOutputPlane; k++) + { + THTensor_(select)(gradOutSlice, gradOutput, 0, k); + gradBias_data[k] += scale*THTensor_(sumall)(gradOutSlice); + } + THTensor_(free)(gradOutSlice); + + /* gradient to kernels */ + THTensor_(conv3DRevger)(gradWeight, 1.0, scale, input, gradOutput, dT, dH, dW); + + return 0; +} + +static const struct luaL_Reg nn_(VolumetricConvolution__) [] = { + {"VolumetricConvolution_updateOutput", nn_(VolumetricConvolution_updateOutput)}, + {"VolumetricConvolution_updateGradInput", nn_(VolumetricConvolution_updateGradInput)}, + {"VolumetricConvolution_accGradParameters", nn_(VolumetricConvolution_accGradParameters)}, + {NULL, NULL} +}; + +static void nn_(VolumetricConvolution_init)(lua_State *L) +{ + luaT_pushmetaclass(L, torch_(Tensor_id)); + luaT_registeratname(L, nn_(VolumetricConvolution__), "nn"); + lua_pop(L,1); +} + +#endif |