| #ifndef TH_GENERIC_FILE |
| #define TH_GENERIC_FILE "generic/LogSigmoid.c" |
| #else |
| |
| void THNN_(LogSigmoid_updateOutput)( |
| THNNState *state, |
| THTensor *input, |
| THTensor *output, |
| THTensor *buffer) |
| { |
| THTensor_(resizeAs)(output, input); |
| THTensor_(resizeAs)(buffer, input); |
| //Use the LogSumExp trick to make this stable against overflow |
| TH_TENSOR_APPLY3(real, output, real, input, real, buffer, |
| real max_elem = fmax(0, -*input_data); |
| real z = exp(-max_elem) + exp(-*input_data - max_elem); |
| *buffer_data = z; |
| *output_data = -(max_elem + log(z)); |
| ); |
| } |
| |
| void THNN_(LogSigmoid_updateGradInput)( |
| THNNState *state, |
| THTensor *input, |
| THTensor *gradOutput, |
| THTensor *gradInput, |
| THTensor *buffer) |
| { |
| THNN_CHECK_NELEMENT(input, gradOutput); |
| THTensor_(resizeAs)(gradInput, buffer); |
| /* deriv of -max(0,-x) - log(e(0 - max(0,-x)) + e(-x - max(0,-x)) is |
| * -max_deriv - (-max_deriv*e(0-max(0,-x)) + (-1 - max_deriv)*e(-x - max(0,-x)))/z |
| * where z = e(0 - max(0,-x)) + e(-x - max(0,-x)) |
| * which simplifies to |
| * -max_deriv - (z-1)/z if x is >= 0 or |
| * -max_deriv + (z-1)/z if x is < 0 |
| */ |
| TH_TENSOR_APPLY3(real, input, real, gradInput, real, buffer, |
| real z = *buffer_data; |
| real max_deriv = 0.0; |
| real sign = -1.0; |
| if (*input_data < 0){ |
| max_deriv = -1.0; |
| sign = 1.0; |
| } |
| *gradInput_data = -max_deriv - sign*((z - 1.0)/ z); |
| ); |
| THTensor_(cmul)(gradInput, gradOutput, gradInput); |
| } |
| |
| #endif |