| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- ///////////////////////////////////////////////////////////////////////
- // File: functions.h
- // Description: Collection of function-objects used by the network layers.
- // Author: Ray Smith
- //
- // (C) Copyright 2014, Google Inc.
- // 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.
- ///////////////////////////////////////////////////////////////////////
- #ifndef TESSERACT_LSTM_FUNCTIONS_H_
- #define TESSERACT_LSTM_FUNCTIONS_H_
- #include "helpers.h"
- // Setting this to 1 or more causes massive dumps of debug data: weights,
- // updates, internal calculations etc, and reduces the number of test iterations
- // to a small number, so outputs can be diffed.
- #define DEBUG_DETAIL 0
- #if DEBUG_DETAIL > 0
- #undef _OPENMP // Disable open mp to get the outputs in sync.
- #endif
- namespace tesseract {
- // Size of static tables.
- constexpr int kTableSize = 4096;
- // Scale factor for float arg to int index.
- constexpr double kScaleFactor = 256.0;
- #if __cplusplus < 201402 || defined(__clang__) // C++11
- extern double TanhTable[];
- extern double LogisticTable[];
- #else // C++14 or newer
- typedef double (*LUT_FUNCTION)(int i);
- constexpr double LUTFuncTanh(int i) {
- return std::tanh(i / kScaleFactor);
- }
- constexpr double LUTFuncLog(int i) {
- return 1 / (1 + std::exp(-i / kScaleFactor));
- }
- template<int n, LUT_FUNCTION f>
- struct LUTTempl {
- constexpr LUTTempl() : table_() {
- for (auto i = 0; i < n; ++i) {
- table_[i] = f(i);
- }
- }
- const double& operator[](size_t i) const {
- return table_[i];
- }
- double table_[n];
- };
- extern const LUTTempl<kTableSize, LUTFuncTanh> TanhTable;
- extern const LUTTempl<kTableSize, LUTFuncLog> LogisticTable;
- #endif
- // Non-linearity (sigmoid) functions with cache tables and clipping.
- inline double Tanh(double x) {
- if (x < 0.0) return -Tanh(-x);
- x *= kScaleFactor;
- int index = static_cast<int>(x);
- if (index >= (kTableSize - 1)) return 1.0;
- double tanh_i0 = TanhTable[index];
- double tanh_i1 = TanhTable[index + 1];
- // Linear interpolation.
- return tanh_i0 + (tanh_i1 - tanh_i0) * (x - index);
- }
- inline double Logistic(double x) {
- if (x < 0.0) return 1.0 - Logistic(-x);
- x *= kScaleFactor;
- int index = static_cast<int>(x);
- if (index >= (kTableSize - 1)) return 1.0;
- double l0 = LogisticTable[index];
- double l1 = LogisticTable[index + 1];
- // Linear interpolation.
- return l0 + (l1 - l0) * (x - index);
- }
- // Non-linearity (sigmoid) functions and their derivatives.
- struct FFunc {
- inline double operator()(double x) const { return Logistic(x); }
- };
- struct FPrime {
- inline double operator()(double y) const { return y * (1.0 - y); }
- };
- struct ClipFFunc {
- inline double operator()(double x) const {
- if (x <= 0.0) return 0.0;
- if (x >= 1.0) return 1.0;
- return x;
- }
- };
- struct ClipFPrime {
- inline double operator()(double y) const {
- return 0.0 < y && y < 1.0 ? 1.0 : 0.0;
- }
- };
- struct Relu {
- inline double operator()(double x) const {
- if (x <= 0.0) return 0.0;
- return x;
- }
- };
- struct ReluPrime {
- inline double operator()(double y) const { return 0.0 < y ? 1.0 : 0.0; }
- };
- struct GFunc {
- inline double operator()(double x) const { return Tanh(x); }
- };
- struct GPrime {
- inline double operator()(double y) const { return 1.0 - y * y; }
- };
- struct ClipGFunc {
- inline double operator()(double x) const {
- if (x <= -1.0) return -1.0;
- if (x >= 1.0) return 1.0;
- return x;
- }
- };
- struct ClipGPrime {
- inline double operator()(double y) const {
- return -1.0 < y && y < 1.0 ? 1.0 : 0.0;
- }
- };
- struct HFunc {
- inline double operator()(double x) const { return Tanh(x); }
- };
- struct HPrime {
- inline double operator()(double y) const {
- double u = Tanh(y);
- return 1.0 - u * u;
- }
- };
- struct UnityFunc {
- inline double operator()(double /*x*/) const { return 1.0; }
- };
- struct IdentityFunc {
- inline double operator()(double x) const { return x; }
- };
- // Applies Func in-place to inout, of size n.
- template <class Func>
- inline void FuncInplace(int n, double* inout) {
- Func f;
- for (int i = 0; i < n; ++i) {
- inout[i] = f(inout[i]);
- }
- }
- // Applies Func to u and multiplies the result by v component-wise,
- // putting the product in out, all of size n.
- template <class Func>
- inline void FuncMultiply(const double* u, const double* v, int n, double* out) {
- Func f;
- for (int i = 0; i < n; ++i) {
- out[i] = f(u[i]) * v[i];
- }
- }
- // Applies the Softmax function in-place to inout, of size n.
- template <typename T>
- inline void SoftmaxInPlace(int n, T* inout) {
- if (n <= 0) return;
- // A limit on the negative range input to exp to guarantee non-zero output.
- const T kMaxSoftmaxActivation = 86.0f;
- T max_output = inout[0];
- for (int i = 1; i < n; i++) {
- T output = inout[i];
- if (output > max_output) max_output = output;
- }
- T prob_total = 0.0;
- for (int i = 0; i < n; i++) {
- T prob = inout[i] - max_output;
- prob = exp(ClipToRange(prob, -kMaxSoftmaxActivation, static_cast<T>(0)));
- prob_total += prob;
- inout[i] = prob;
- }
- if (prob_total > 0.0) {
- for (int i = 0; i < n; i++) inout[i] /= prob_total;
- }
- }
- // Copies n values of the given src vector to dest.
- inline void CopyVector(int n, const double* src, double* dest) {
- memcpy(dest, src, n * sizeof(dest[0]));
- }
- // Adds n values of the given src vector to dest.
- inline void AccumulateVector(int n, const double* src, double* dest) {
- for (int i = 0; i < n; ++i) dest[i] += src[i];
- }
- // Multiplies n values of inout in-place element-wise by the given src vector.
- inline void MultiplyVectorsInPlace(int n, const double* src, double* inout) {
- for (int i = 0; i < n; ++i) inout[i] *= src[i];
- }
- // Multiplies n values of u by v, element-wise, accumulating to out.
- inline void MultiplyAccumulate(int n, const double* u, const double* v,
- double* out) {
- for (int i = 0; i < n; i++) {
- out[i] += u[i] * v[i];
- }
- }
- // Sums the given 5 n-vectors putting the result into sum.
- inline void SumVectors(int n, const double* v1, const double* v2,
- const double* v3, const double* v4, const double* v5,
- double* sum) {
- for (int i = 0; i < n; ++i) {
- sum[i] = v1[i] + v2[i] + v3[i] + v4[i] + v5[i];
- }
- }
- // Sets the given n-vector vec to 0.
- template <typename T>
- inline void ZeroVector(int n, T* vec) {
- memset(vec, 0, n * sizeof(*vec));
- }
- // Clips the given vector vec, of size n to [lower, upper].
- template <typename T>
- inline void ClipVector(int n, T lower, T upper, T* vec) {
- for (int i = 0; i < n; ++i) vec[i] = ClipToRange(vec[i], lower, upper);
- }
- // Converts the given n-vector to a binary encoding of the maximum value,
- // encoded as vector of nf binary values.
- inline void CodeInBinary(int n, int nf, double* vec) {
- if (nf <= 0 || n < nf) return;
- int index = 0;
- double best_score = vec[0];
- for (int i = 1; i < n; ++i) {
- if (vec[i] > best_score) {
- best_score = vec[i];
- index = i;
- }
- }
- int mask = 1;
- for (int i = 0; i < nf; ++i, mask *= 2) {
- vec[i] = (index & mask) ? 1.0 : 0.0;
- }
- }
- } // namespace tesseract.
- #endif // TESSERACT_LSTM_FUNCTIONS_H_
|