ActivationFunction.cpp 12.0 KB
Newer Older
1
/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.
Z
zhangjinchao01 已提交
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

#include "ActivationFunction.h"

#include <algorithm>
#include <iostream>
Y
Yu Yang 已提交
19
#include <memory>
Z
zhangjinchao01 已提交
20 21
#include <string>
#include <thread>
Y
Yu Yang 已提交
22
#include <type_traits>
Z
zhangjinchao01 已提交
23
#include "paddle/parameter/Argument.h"
Y
Yu Yang 已提交
24
#include "paddle/utils/ClassRegistrar.h"
Z
zhangjinchao01 已提交
25 26
#include "paddle/utils/Logging.h"

27 28 29 30
#ifdef PADDLE_USE_MKLDNN
#include "MKLDNNActivation.h"
#endif

Z
zhangjinchao01 已提交
31 32 33
namespace paddle {

static ClassRegistrar<ActivationFunction> gActivationRegistrar;
Q
qijun 已提交
34 35 36 37 38 39
/**
 * @def ACTIVATION_CLASS_NAME
 * @brief Macro for getting derived activation class name
 * @note ACTIVATION_CLASS_NAME(softmax) softmax_;
 * means softmaxActivation softmax_;
 */
Z
zhangjinchao01 已提交
40
#define ACTIVATION_CLASS_NAME(ACTIVATION_NAME) ACTIVATION_NAME##Activation
Q
qijun 已提交
41 42 43 44
/**
 * @def BEGIN_DEFINE_ACTIVATION
 * @brief Macro for defining a devried activation class
 */
Z
zhangjinchao01 已提交
45 46 47 48 49 50 51
#define BEGIN_DEFINE_ACTIVATION(ACTIVATION_NAME)                             \
  class ACTIVATION_CLASS_NAME(ACTIVATION_NAME) : public ActivationFunction { \
  private:                                                                   \
    static const std::string name;                                           \
                                                                             \
  public:                                                                    \
    const std::string& getName() const { return name; }
Q
qijun 已提交
52 53 54 55
/**
 * @def END_DEFINE_ACTIVATION
 * @brief Macro for registering a derived activation class
 */
Z
zhangjinchao01 已提交
56
#define END_DEFINE_ACTIVATION(ACTIVATION_NAME)                     \
57 58
  }                                                                \
  ;                                                                \
Z
zhangjinchao01 已提交
59 60 61
  const std::string ACTIVATION_CLASS_NAME(ACTIVATION_NAME)::name = \
      #ACTIVATION_NAME;                                            \
  static InitFunction __reg_activation__##ACTIVATION_NAME([] {     \
62 63 64
    gActivationRegistrar                                           \
        .registerClass<ACTIVATION_CLASS_NAME(ACTIVATION_NAME)>(    \
            #ACTIVATION_NAME);                                     \
Z
zhangjinchao01 已提交
65 66 67 68 69 70 71 72 73 74
  });

/**
 * @brief The IdentityActivation class
 *
 * Do nothing when forward/backward.
 */
class IdentityActivation : public ActivationFunction {
public:
  static const std::string name;
Y
Yu Yang 已提交
75
  Error __must_check forward(Argument& act) {
76
    (void)act;
Y
Yu Yang 已提交
77
    return Error();
78
  }
Y
Yu Yang 已提交
79
  Error __must_check backward(Argument& act) {
80
    (void)act;
Y
Yu Yang 已提交
81
    return Error();
82
  }
Z
zhangjinchao01 已提交
83 84 85 86 87 88 89 90 91
  const std::string& getName() const { return name; }
};
const std::string IdentityActivation::name = "";
static InitFunction __reg_activation__identity([] {
  gActivationRegistrar.registerClass<IdentityActivation>("");
  gActivationRegistrar.registerClass<IdentityActivation>("linear");
});

/**
Q
qijun 已提交
92 93
 * @brief Sigmoid Activation
 * \f[
Z
zhangjinchao01 已提交
94
 * f(z) = \frac{1}{1+exp(-z)}
Q
qijun 已提交
95
 * \f]
Z
zhangjinchao01 已提交
96 97
 */
BEGIN_DEFINE_ACTIVATION(sigmoid)
Y
Yu Yang 已提交
98
Error __must_check forward(Argument& act) {
99
  act.value->sigmoid(*act.value);
Y
Yu Yang 已提交
100
  return Error();
101
}
Y
Yu Yang 已提交
102
Error __must_check backward(Argument& act) {
103
  act.grad->sigmoidDerivative(*act.value);
Y
Yu Yang 已提交
104
  return Error();
105
}
Z
zhangjinchao01 已提交
106 107 108
END_DEFINE_ACTIVATION(sigmoid)

/**
Q
qijun 已提交
109 110
 * @brief Softmax Activation
 * \f[
Z
zhangjinchao01 已提交
111
 * P(y=j|x) = \frac{e^{x^Tw_j}}{\sum^K_{k=1}e^{x^Tw_k}}
Q
qijun 已提交
112
 * \f]
Z
zhangjinchao01 已提交
113 114 115 116 117 118 119
 */
BEGIN_DEFINE_ACTIVATION(softmax)
private:
MatrixPtr sftMaxSum_;
MatrixPtr sftMaxDot_;

public:
Y
Yu Yang 已提交
120
Error __must_check forward(Argument& act) {
121
  act.value->softmax(*act.value);
Y
Yu Yang 已提交
122
  return Error();
123
}
Z
zhangjinchao01 已提交
124

Y
Yu Yang 已提交
125
Error __must_check backward(Argument& act) {
Z
zhangjinchao01 已提交
126 127 128 129 130 131 132
  MatrixPtr outputV = act.value;
  MatrixPtr outputG = act.grad;

  if (outputG->useGpu()) {
    outputG->softmaxBackward(*outputV);
  } else {
    SetDevice device(act.deviceId);
133 134
    Matrix::resizeOrCreate(sftMaxDot_,
                           outputG->getHeight(),
Z
zhangjinchao01 已提交
135
                           outputG->getWidth(),
136 137 138 139 140 141 142
                           /* trans */ false,
                           useGpu(act.deviceId));
    Matrix::resizeOrCreate(sftMaxSum_,
                           outputG->getHeight(),
                           1,
                           /* trans */ false,
                           useGpu(act.deviceId));
Z
zhangjinchao01 已提交
143 144 145 146 147 148

    sftMaxDot_->dotMul(*outputG, *outputV);
    sftMaxSum_->colMerge(*sftMaxDot_);

    act.grad->softmaxDerivative(*act.value, *sftMaxSum_);
  }
Y
Yu Yang 已提交
149
  return Error();
Z
zhangjinchao01 已提交
150 151 152
}
END_DEFINE_ACTIVATION(softmax)

Q
qijun 已提交
153 154 155 156 157
/**
 * @brief Sequence_softmax Activation
 * @note Softmax on all frames of one sequence.
 * Width of frame must be one.
 */
Z
zhangjinchao01 已提交
158 159 160 161 162 163
BEGIN_DEFINE_ACTIVATION(sequence_softmax)
private:
ACTIVATION_CLASS_NAME(softmax) softmax_;
Argument argument_;

public:
Y
Yu Yang 已提交
164
Error __must_check forward(Argument& act) {
165
  if (act.value->getWidth() != 1UL) {
Y
Yu Yang 已提交
166
    return Error(
167 168
        "Input width for each timestep of sequence softmax should be 1");
  }
Z
zhangjinchao01 已提交
169 170

  if (!argument_.value) {
171 172 173 174 175 176 177 178 179 180
    argument_.value = Matrix::create(nullptr,
                                     /* height= */ 1,
                                     1,
                                     /* trans= */ false,
                                     useGpu(act.deviceId));
    argument_.grad = Matrix::create(nullptr,
                                    /* height= */ 1,
                                    1,
                                    /* trans= */ false,
                                    useGpu(act.deviceId));
Z
zhangjinchao01 已提交
181 182
  }

183 184 185 186
  auto starts =
      act.hasSubseq()
          ? act.subSequenceStartPositions->getVector(useGpu(act.deviceId))
          : act.sequenceStartPositions->getVector(useGpu(act.deviceId));
Z
zhangjinchao01 已提交
187
  act.value->sequenceSoftmax(*act.value, *starts);
Y
Yu Yang 已提交
188
  return Error();
Z
zhangjinchao01 已提交
189 190
}

Y
Yu Yang 已提交
191
Error __must_check backward(Argument& act) {
192
  if (act.value->getWidth() != 1UL) {
Y
Yu Yang 已提交
193
    return Error(
194 195
        "Input width for each timestep of sequence softmax should be 1");
  }
Z
zhangjinchao01 已提交
196

197 198 199
  size_t numSequences =
      act.hasSubseq() ? act.getNumSubSequences() : act.getNumSequences();
  const int* starts = act.getCpuStartPositions();
Z
zhangjinchao01 已提交
200 201 202 203 204 205 206 207

  for (size_t i = 0; i < numSequences; ++i) {
    // TODO(Dangqingqing) optimization for GPU
    size_t offset = starts[i];
    size_t size = starts[i + 1] - starts[i];
    argument_.value->setData(act.value->getData() + offset, 1UL, size);
    argument_.grad->setData(act.grad->getData() + offset, 1UL, size);

Y
Yu Yang 已提交
208 209
    Error err = softmax_.backward(argument_);
    if (!err.isOK()) return err;
Z
zhangjinchao01 已提交
210
  }
Y
Yu Yang 已提交
211
  return Error();
Z
zhangjinchao01 已提交
212 213 214 215
}
END_DEFINE_ACTIVATION(sequence_softmax)

/**
Q
qijun 已提交
216
 * @brief Relu Activation.
Z
zhangjinchao01 已提交
217 218 219 220 221 222 223 224 225
 * forward. y = max(0, z)
 *
 * derivative of relu is:
 *
 *    1 if z > 0
 *
 *    0 otherwise.
 */
BEGIN_DEFINE_ACTIVATION(relu)
Y
Yu Yang 已提交
226
Error __must_check forward(Argument& act) {
227
  act.value->relu(*act.value);
Y
Yu Yang 已提交
228
  return Error();
229
}
Z
zhangjinchao01 已提交
230

Y
Yu Yang 已提交
231
Error __must_check backward(Argument& act) {
232
  act.grad->reluDerivative(*act.value);
Y
Yu Yang 已提交
233
  return Error();
234
}
Z
zhangjinchao01 已提交
235 236 237
END_DEFINE_ACTIVATION(relu)

/**
Q
qijun 已提交
238
 * @brief BRelu Activation.
Z
zhangjinchao01 已提交
239 240 241 242 243 244 245 246 247 248 249 250
 *
 * forward. y = min(24, max(0, z))
 *
 * derivative of brelu is:
 *
 *    1 if 0 < z < 24
 *
 *    0 otherwise.
 *
 * TODO(yuyang18): Remove magic number 24 or make it configuable.
 */
BEGIN_DEFINE_ACTIVATION(brelu)
Y
Yu Yang 已提交
251
Error __must_check forward(Argument& act) {
252
  act.value->brelu(*act.value);
Y
Yu Yang 已提交
253
  return Error();
254
}
Z
zhangjinchao01 已提交
255

Y
Yu Yang 已提交
256
Error __must_check backward(Argument& act) {
257
  act.grad->breluDerivative(*act.value);
Y
Yu Yang 已提交
258
  return Error();
259
}
Z
zhangjinchao01 已提交
260 261 262
END_DEFINE_ACTIVATION(brelu)

/**
Q
qijun 已提交
263 264
 * @brief Tanh Activation.
 * \f[
Z
zhangjinchao01 已提交
265
 * f(z) = tanh(z)=\frac{e^z-e^{-z}}{e^z+e^{-z}}
Q
qijun 已提交
266
 * \f]
Z
zhangjinchao01 已提交
267 268
 */
BEGIN_DEFINE_ACTIVATION(tanh)
Y
Yu Yang 已提交
269
Error __must_check forward(Argument& act) {
270
  act.value->tanh(*act.value);
Y
Yu Yang 已提交
271
  return Error();
272
}
Z
zhangjinchao01 已提交
273

Y
Yu Yang 已提交
274
Error __must_check backward(Argument& act) {
275
  act.grad->tanhDerivative(*act.value);
Y
Yu Yang 已提交
276
  return Error();
277
}
Z
zhangjinchao01 已提交
278 279 280
END_DEFINE_ACTIVATION(tanh)

/**
Q
qijun 已提交
281 282
 * @brief Scaled Tanh Activation
 * \f[
Z
zhangjinchao01 已提交
283
 * f(z) = 1.7159 * tanh(2/3*z)
Q
qijun 已提交
284
 * \f]
Z
zhangjinchao01 已提交
285 286 287 288 289 290 291
 */
BEGIN_DEFINE_ACTIVATION(stanh)
private:
real a, b;

public:
ACTIVATION_CLASS_NAME(stanh)() : a(1.7159), b(2. / 3.) {}
Y
Yu Yang 已提交
292
Error __must_check forward(Argument& act) {
293
  act.value->scaledTanh(*act.value, a, b);
Y
Yu Yang 已提交
294
  return Error();
295
}
Z
zhangjinchao01 已提交
296

Y
Yu Yang 已提交
297
Error __must_check backward(Argument& act) {
Z
zhangjinchao01 已提交
298
  act.grad->scaledTanhDerivative(*act.value, a, b);
Y
Yu Yang 已提交
299
  return Error();
Z
zhangjinchao01 已提交
300 301 302 303
}
END_DEFINE_ACTIVATION(stanh)

/**
Q
qijun 已提交
304 305
 * @brief Soft Relu Activation.
 * \f[
Z
zhangjinchao01 已提交
306
 * f(z) = ln(1+e^z)
Q
qijun 已提交
307
 * \f]
Z
zhangjinchao01 已提交
308 309
 */
BEGIN_DEFINE_ACTIVATION(softrelu)
Y
Yu Yang 已提交
310
Error __must_check forward(Argument& act) {
311
  act.value->softrelu(*act.value);
Y
Yu Yang 已提交
312
  return Error();
313
}
Z
zhangjinchao01 已提交
314

Y
Yu Yang 已提交
315
Error __must_check backward(Argument& act) {
316
  act.grad->softreluDerivative(*act.value);
Y
Yu Yang 已提交
317
  return Error();
318
}
Z
zhangjinchao01 已提交
319 320 321
END_DEFINE_ACTIVATION(softrelu)

/**
Q
qijun 已提交
322
 * @brief Abs Activation.
Z
zhangjinchao01 已提交
323 324 325 326 327 328 329 330 331 332 333
 * Forward: f(z) = abs(z)
 *
 * Derivative:
 *
 *     1   if z>0
 *
 *    -1   if z<0
 *
 *     0   if z=0
 */
BEGIN_DEFINE_ACTIVATION(abs)
Y
Yu Yang 已提交
334
Error __must_check forward(Argument& act) {
Z
zhangjinchao01 已提交
335
  SetDevice device(act.deviceId);
336 337 338 339 340
  Matrix::resizeOrCreate(act.in,
                         act.value->getHeight(),
                         act.value->getWidth(),
                         /* trans */ false,
                         useGpu(act.deviceId));
Z
zhangjinchao01 已提交
341 342

  act.in->copyFrom(*act.value);
H
hedaoyuan 已提交
343
  act.value->abs2(*act.value);
Y
Yu Yang 已提交
344
  return Error();
Z
zhangjinchao01 已提交
345 346
}

Y
Yu Yang 已提交
347
Error __must_check backward(Argument& act) {
348
  act.grad->absDerivative(*act.in);
Y
Yu Yang 已提交
349
  return Error();
350
}
Z
zhangjinchao01 已提交
351 352 353
END_DEFINE_ACTIVATION(abs)

/**
Q
qijun 已提交
354 355
 * @brief Square Activation.
 * \f[
Z
zhangjinchao01 已提交
356
 * f(z) = z^2.
Q
qijun 已提交
357
 * \f]
Z
zhangjinchao01 已提交
358 359
 */
BEGIN_DEFINE_ACTIVATION(square)
Y
Yu Yang 已提交
360
Error __must_check forward(Argument& act) {
Z
zhangjinchao01 已提交
361
  SetDevice device(act.deviceId);
362 363 364 365 366
  Matrix::resizeOrCreate(act.in,
                         act.value->getHeight(),
                         act.value->getWidth(),
                         /* trans */ false,
                         useGpu(act.deviceId));
Z
zhangjinchao01 已提交
367 368

  act.in->copyFrom(*act.value);
H
hedaoyuan 已提交
369
  act.value->square2(*act.value);
Y
Yu Yang 已提交
370
  return Error();
Z
zhangjinchao01 已提交
371 372
}

Y
Yu Yang 已提交
373
Error __must_check backward(Argument& act) {
374
  act.grad->squareDerivative(*act.in);
Y
Yu Yang 已提交
375
  return Error();
376
}
Z
zhangjinchao01 已提交
377
END_DEFINE_ACTIVATION(square)
378

Q
qijun 已提交
379 380 381 382 383 384
/**
 * @brief Exponential Activation.
 * \f[
 * f(z) = e^z
 * \f]
 */
Z
zhangjinchao01 已提交
385
BEGIN_DEFINE_ACTIVATION(exponential)
Y
Yu Yang 已提交
386
Error __must_check forward(Argument& act) {
387
  act.value->exp2(*act.value);
Y
Yu Yang 已提交
388
  return Error();
389
}
Z
zhangjinchao01 已提交
390

Y
Yu Yang 已提交
391
Error __must_check backward(Argument& act) {
392
  act.grad->expDerivative(*act.value);
Y
Yu Yang 已提交
393
  return Error();
394
}
Z
zhangjinchao01 已提交
395 396
END_DEFINE_ACTIVATION(exponential)

X
xuwei06 已提交
397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434
/**
 * @brief Reciprocal Activation.
 * \f[
 * f(z) = 1/z
 * \f]
 */
BEGIN_DEFINE_ACTIVATION(reciprocal)
Error __must_check forward(Argument& act) {
  act.value->reciprocal2();
  return Error();
}

Error __must_check backward(Argument& act) {
  act.grad->dotMulSquare(*act.value);
  act.grad->neg();
  return Error();
}
END_DEFINE_ACTIVATION(reciprocal)

/**
 * @brief Square Root Activation.
 * \f[
 * f(z) = sqrt(z)
 * \f]
 */
BEGIN_DEFINE_ACTIVATION(sqrt)
Error __must_check forward(Argument& act) {
  act.value->sqrt2();
  return Error();
}

Error __must_check backward(Argument& act) {
  act.grad->dotDiv(*act.grad, *act.value);
  act.grad->mulScalar(0.5);
  return Error();
}
END_DEFINE_ACTIVATION(sqrt)

435 436 437 438 439 440 441
/**
 * @brief Logarithm Activation.
 * \f[
 * f(z) = log(z)
 * \f]
 */
BEGIN_DEFINE_ACTIVATION(log)
Y
Yu Yang 已提交
442
Error __must_check forward(Argument& act) {
443
  SetDevice device(act.deviceId);
444 445 446 447 448
  Matrix::resizeOrCreate(act.in,
                         act.value->getHeight(),
                         act.value->getWidth(),
                         /* trans */ false,
                         useGpu(act.deviceId));
449 450

  act.in->copyFrom(*act.value);
H
hedaoyuan 已提交
451
  act.value->log2(*act.value);
Y
Yu Yang 已提交
452
  return Error();
453 454
}

Y
Yu Yang 已提交
455
Error __must_check backward(Argument& act) {
456
  act.grad->dotDiv(*act.grad, *act.in);
Y
Yu Yang 已提交
457
  return Error();
458
}
459 460
END_DEFINE_ACTIVATION(log)

Z
zhangjinchao01 已提交
461
ActivationFunction* ActivationFunction::create(const std::string& type) {
462 463 464 465 466 467
#ifdef PADDLE_USE_MKLDNN
  if (!type.empty() && type.compare(0, 7, "mkldnn_") == 0) {
    return MKLDNNActivation::create(type);
  }
#endif

Z
zhangjinchao01 已提交
468 469 470
  return gActivationRegistrar.createByType(type);
}

471 472
std::vector<std::string> ActivationFunction::getAllRegisteredTypes() {
  std::vector<std::string> types;
473 474
  gActivationRegistrar.forEachType(
      [&](const std::string& type) { types.push_back(type); });
475 476 477
  return types;
}

Z
zhangjinchao01 已提交
478
}  // namespace paddle