1 /*! 2 * Copyright 2019-2020 by Contributors 3 * \file probability_distribution.h 4 * \brief Implementation of a few useful probability distributions 5 * \author Avinash Barnwal and Hyunsu Cho 6 */ 7 8 #ifndef XGBOOST_COMMON_PROBABILITY_DISTRIBUTION_H_ 9 #define XGBOOST_COMMON_PROBABILITY_DISTRIBUTION_H_ 10 11 #include <cmath> 12 13 namespace xgboost { 14 namespace common { 15 16 #ifndef __CUDACC__ 17 18 using std::exp; 19 using std::sqrt; 20 using std::isinf; 21 using std::isnan; 22 23 #endif // __CUDACC__ 24 25 /*! \brief Constant PI */ 26 constexpr double kPI = 3.14159265358979323846; 27 /*! \brief The Euler-Mascheroni_constant */ 28 constexpr double kEulerMascheroni = 0.57721566490153286060651209008240243104215933593992; 29 30 /*! \brief Enum encoding possible choices of probability distribution */ 31 enum class ProbabilityDistributionType : int { 32 kNormal = 0, kLogistic = 1, kExtreme = 2 33 }; 34 35 struct NormalDistribution { PDFNormalDistribution36 XGBOOST_DEVICE static double PDF(double z) { 37 return exp(-z * z / 2.0) / sqrt(2.0 * kPI); 38 } 39 CDFNormalDistribution40 XGBOOST_DEVICE static double CDF(double z) { 41 return 0.5 * (1 + erf(z / sqrt(2.0))); 42 } 43 GradPDFNormalDistribution44 XGBOOST_DEVICE static double GradPDF(double z) { 45 return -z * PDF(z); 46 } 47 HessPDFNormalDistribution48 XGBOOST_DEVICE static double HessPDF(double z) { 49 return (z * z - 1.0) * PDF(z); 50 } 51 TypeNormalDistribution52 XGBOOST_DEVICE static ProbabilityDistributionType Type() { 53 return ProbabilityDistributionType::kNormal; 54 } 55 }; 56 57 struct LogisticDistribution { PDFLogisticDistribution58 XGBOOST_DEVICE static double PDF(double z) { 59 const double w = exp(z); 60 const double sqrt_denominator = 1 + w; 61 if (isinf(w) || isinf(w * w)) { 62 return 0.0; 63 } else { 64 return w / (sqrt_denominator * sqrt_denominator); 65 } 66 } 67 CDFLogisticDistribution68 XGBOOST_DEVICE static double CDF(double z) { 69 const double w = exp(z); 70 return isinf(w) ? 1.0 : (w / (1 + w)); 71 } 72 GradPDFLogisticDistribution73 XGBOOST_DEVICE static double GradPDF(double z) { 74 const double w = exp(z); 75 return isinf(w) ? 0.0 : (PDF(z) * (1 - w) / (1 + w)); 76 } 77 HessPDFLogisticDistribution78 XGBOOST_DEVICE static double HessPDF(double z) { 79 const double w = exp(z); 80 if (isinf(w) || isinf(w * w)) { 81 return 0.0; 82 } else { 83 return PDF(z) * (w * w - 4 * w + 1) / ((1 + w) * (1 + w)); 84 } 85 } 86 TypeLogisticDistribution87 XGBOOST_DEVICE static ProbabilityDistributionType Type() { 88 return ProbabilityDistributionType::kLogistic; 89 } 90 }; 91 92 struct ExtremeDistribution { PDFExtremeDistribution93 XGBOOST_DEVICE static double PDF(double z) { 94 const double w = exp(z); 95 return isinf(w) ? 0.0 : (w * exp(-w)); 96 } 97 CDFExtremeDistribution98 XGBOOST_DEVICE static double CDF(double z) { 99 const double w = exp(z); 100 return 1 - exp(-w); 101 } 102 GradPDFExtremeDistribution103 XGBOOST_DEVICE static double GradPDF(double z) { 104 const double w = exp(z); 105 return isinf(w) ? 0.0 : ((1 - w) * PDF(z)); 106 } 107 HessPDFExtremeDistribution108 XGBOOST_DEVICE static double HessPDF(double z) { 109 const double w = exp(z); 110 if (isinf(w) || isinf(w * w)) { 111 return 0.0; 112 } else { 113 return (w * w - 3 * w + 1) * PDF(z); 114 } 115 } 116 TypeExtremeDistribution117 XGBOOST_DEVICE static ProbabilityDistributionType Type() { 118 return ProbabilityDistributionType::kExtreme; 119 } 120 }; 121 122 } // namespace common 123 } // namespace xgboost 124 125 #endif // XGBOOST_COMMON_PROBABILITY_DISTRIBUTION_H_ 126