Home | History | Annotate | Download | only in native
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 // Stochastic Linear Ranking algorithms.
     18 // This class will implement a set of incremental algorithms for ranking tasks
     19 // They support both L1 and L2 regularizations.
     20 
     21 
     22 #ifndef LEARNING_STOCHASTIC_LINEAR_STOCHASTIC_LINEAR_RANKER_H_
     23 #define LEARNING_STOCHASTIC_LINEAR_STOCHASTIC_LINEAR_RANKER_H_
     24 
     25 #include <cmath>
     26 #include <hash_map>
     27 #include <string>
     28 
     29 #include <sys/types.h>
     30 #include "cutils/log.h"
     31 #include "common_defs.h"
     32 #include "learning_rate_controller-inl.h"
     33 #include "sparse_weight_vector.h"
     34 
     35 namespace learning_stochastic_linear {
     36 
     37 // NOTE: This Stochastic Linear Ranker supports only the following update types:
     38 // SL: Stochastic Linear
     39 // CS: Constraint Satisfaction
     40 template<class Key = std::string, class Hash = std::hash_map<std::string, double> >
     41 class StochasticLinearRanker {
     42  public:
     43   // initialize lambda_ and constraint to a meaningful default. Will give
     44   // equal weight to the error and regularizer.
     45   StochasticLinearRanker() {
     46     iteration_num_ = 0;
     47     lambda_ = 1.0;
     48     learning_rate_controller_.SetLambda(lambda_);
     49     mini_batch_size_ = 1;
     50     learning_rate_controller_.SetMiniBatchSize(mini_batch_size_);
     51     adaptation_mode_ = INV_LINEAR;
     52     learning_rate_controller_.SetAdaptationMode(adaptation_mode_);
     53     update_type_ = SL;
     54     regularization_type_ = L2;
     55     kernel_type_ = LINEAR;
     56     kernel_param_ = 1.0;
     57     kernel_gain_ = 1.0;
     58     kernel_bias_ = 0.0;
     59     rank_loss_type_ = PAIRWISE;
     60     acceptence_probability_ = 0.1;
     61     mini_batch_counter_ = 0;
     62     gradient_l0_norm_ = -1;
     63     norm_constraint_ = 1.0;
     64   }
     65 
     66   ~StochasticLinearRanker() {}
     67   // Getters and setters
     68   double GetIterationNumber() const {
     69     return iteration_num_;
     70   }
     71   double GetNormContraint() const {
     72     return norm_constraint_;
     73   }
     74   RegularizationType GetRegularizationType() const {
     75     return regularization_type_;
     76   }
     77   double GetLambda() const {
     78     return lambda_;
     79   }
     80   uint64 GetMiniBatchSize() const {
     81     return mini_batch_size_;
     82   }
     83   int32 GetGradientL0Norm() const {
     84     return gradient_l0_norm_;
     85   }
     86   UpdateType GetUpdateType() const {
     87     return update_type_;
     88   }
     89   AdaptationMode GetAdaptationMode() const {
     90     return adaptation_mode_;
     91   }
     92   KernelType GetKernelType() const {
     93     return kernel_type_;
     94   }
     95   // This function returns the basic kernel parameter. In case of
     96   // polynomial kernel, it implies the degree of the polynomial.  In case of
     97   // RBF kernel, it implies the sigma parameter. In case of linear kernel,
     98   // it is not used.
     99   double GetKernelParam() const {
    100     return kernel_param_;
    101   }
    102   double GetKernelGain() const {
    103     return kernel_gain_;;
    104   }
    105   double GetKernelBias() const {
    106     return kernel_bias_;
    107   }
    108   RankLossType GetRankLossType() const {
    109     return rank_loss_type_;
    110   }
    111   double GetAcceptanceProbability() const {
    112     return acceptence_probability_;
    113   }
    114   void SetIterationNumber(uint64 num) {
    115     iteration_num_=num;
    116   }
    117   void SetNormConstraint(const double norm) {
    118     norm_constraint_ = norm;
    119   }
    120   void SetRegularizationType(const RegularizationType r) {
    121     regularization_type_ = r;
    122   }
    123   void SetLambda(double l) {
    124     lambda_ = l;
    125     learning_rate_controller_.SetLambda(l);
    126   }
    127   void SetMiniBatchSize(const uint64 msize) {
    128     mini_batch_size_ = msize;
    129     learning_rate_controller_.SetMiniBatchSize(msize);
    130   }
    131   void SetAdaptationMode(AdaptationMode m) {
    132     adaptation_mode_ = m;
    133     learning_rate_controller_.SetAdaptationMode(m);
    134   }
    135   void SetKernelType(KernelType k ) {
    136     kernel_type_ = k;
    137   }
    138   // This function sets the basic kernel parameter. In case of
    139   // polynomial kernel, it implies the degree of the polynomial. In case of
    140   // RBF kernel, it implies the sigma parameter. In case of linear kernel,
    141   // it is not used.
    142   void SetKernelParam(double param) {
    143     kernel_param_ = param;
    144   }
    145   // This function sets the kernel gain. NOTE: in most use cases, gain should
    146   // be set to 1.0.
    147   void SetKernelGain(double gain) {
    148     kernel_gain_ = gain;
    149   }
    150   // This function sets the kernel bias. NOTE: in most use cases, bias should
    151   // be set to 0.0.
    152   void SetKernelBias(double bias) {
    153     kernel_bias_ = bias;
    154   }
    155   void SetUpdateType(UpdateType u) {
    156     update_type_ = u;
    157   }
    158   void SetRankLossType(RankLossType r) {
    159     rank_loss_type_ = r;
    160   }
    161   void SetAcceptanceProbability(double p) {
    162     acceptence_probability_ = p;
    163   }
    164   void SetGradientL0Norm(const int32 gradient_l0_norm) {
    165     gradient_l0_norm_ = gradient_l0_norm;
    166   }
    167   // Load an existing model
    168   void LoadWeights(const SparseWeightVector<Key, Hash> &model) {
    169     weight_.LoadWeightVector(model);
    170   }
    171   // Save current model
    172   void SaveWeights(SparseWeightVector<Key, Hash> *model) {
    173     model->LoadWeightVector(weight_);
    174   }
    175   // Scoring
    176   double ScoreSample(const SparseWeightVector<Key, Hash> &sample) {
    177     const double dot = weight_.DotProduct(sample);
    178     double w_square;
    179     double s_square;
    180     switch (kernel_type_) {
    181       case LINEAR:
    182         return dot;
    183       case POLY:
    184         return pow(kernel_gain_ * dot + kernel_bias_, kernel_param_);
    185       case RBF:
    186         w_square = weight_.L2Norm();
    187         s_square = sample.L2Norm();
    188         return exp(-1 * kernel_param_ * (w_square + s_square - 2 * dot));
    189       default:
    190       ALOGE("unsupported kernel: %d", kernel_type_);
    191     }
    192     return -1;
    193   }
    194   // Learning Functions
    195   // Return values:
    196   // 1 :full update went through
    197   // 2 :partial update went through (for SL only)
    198   // 0 :no update necessary.
    199   // -1:error.
    200   int UpdateClassifier(const SparseWeightVector<Key, Hash> &positive,
    201                        const SparseWeightVector<Key, Hash> &negative);
    202 
    203  private:
    204   SparseWeightVector<Key, Hash> weight_;
    205   double norm_constraint_;
    206   double lambda_;
    207   RegularizationType regularization_type_;
    208   AdaptationMode adaptation_mode_;
    209   UpdateType update_type_;
    210   RankLossType rank_loss_type_;
    211   KernelType kernel_type_;
    212   // Kernel gain and bias are typically multiplicative and additive factors to
    213   // the dot product while calculating the kernel function. Kernel param is
    214   // kernel-specific. In case of polynomial kernel, it is the degree of the
    215   // polynomial.
    216   double kernel_param_;
    217   double kernel_gain_;
    218   double kernel_bias_;
    219   double acceptence_probability_;
    220   SparseWeightVector<Key, Hash> current_negative_;
    221   LearningRateController learning_rate_controller_;
    222   uint64 iteration_num_;
    223   // We average out gradient updates for mini_batch_size_ samples
    224   // before performing an iteration of the algorithm.
    225   uint64 mini_batch_counter_;
    226   uint64 mini_batch_size_;
    227   // Specifies the number of non-zero entries allowed in a gradient.
    228   // Default is -1 which means we take the gradient as given by data without
    229   // adding any new constraints. positive number is treated as an L0 constraint
    230   int32 gradient_l0_norm_;
    231   // Sub-Gradient Updates
    232   // Pure Sub-Gradient update without any reprojection
    233   // Note that a form of L2 regularization is built into this
    234   void UpdateSubGradient(const SparseWeightVector<Key, Hash> &positive,
    235                          const SparseWeightVector<Key, Hash> &negative,
    236                          const double learning_rate,
    237                          const double positive_score,
    238                          const double negative_score,
    239                          const int32 gradient_l0_norm);
    240 
    241 };
    242 }  // namespace learning_stochastic_linear
    243 #endif  // LEARNING_STOCHASTIC_LINEAR_STOCHASTIC_LINEAR_RANKER_H_
    244