Add missing probit function for treeregressor (#619)

* added missing probit function for treeregressor

* corrected ml_logit to ml_logistic to reflect update of output

* Updated function names to comply with style guide

* use write_scores() to simplify code block
This commit is contained in:
jignparm 2019-03-19 17:55:26 -07:00 committed by GitHub
parent 9e323901b2
commit c366647262
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 22 additions and 29 deletions

View file

@ -159,7 +159,7 @@ enum class SVM_TYPE {
SVM_SVC
};
static inline float ml_inv_erf(float x) {
static inline float ErfInv(float x) {
float sgn = x < 0 ? -1.0f : 1.0f;
x = (1 - x) * (1 + x);
float log = std::log(x);
@ -224,19 +224,23 @@ static inline void multiclass_probability(int64_t classcount, const std::vector<
}
}
static inline float ml_logit(float val) {
static const float ml_sqrt2 = 1.41421356f;
static inline float ComputeLogistic(float val) {
float v = 1 / (1 + std::exp(-std::abs(val)));
return (val < 0) ? (1 - v) : v;
}
static inline float sigmoid_probability(float score, float proba, float probb) {
float val = score * proba + probb;
return 1 - ml_logit(val); // ref: https://github.com/arnaudsj/libsvm/blob/eaaefac5ebd32d0e07902e1ae740e038eaaf0826/svm.cpp#L1818
static inline float ComputeProbit(float val) {
return ml_sqrt2 * ErfInv(2 * val - 1);
}
static const float ml_sqrt2 = 1.41421356f;
static inline float sigmoid_probability(float score, float proba, float probb) {
float val = score * proba + probb;
return 1 - ComputeLogistic(val); // ref: https://github.com/arnaudsj/libsvm/blob/eaaefac5ebd32d0e07902e1ae740e038eaaf0826/svm.cpp#L1818
}
static inline void compute_softmax(std::vector<float>& values) {
static inline void ComputeSoftmax(std::vector<float>& values) {
std::vector<float> newscores;
// compute exp with negative number to be numerically stable
float v_max = -std::numeric_limits<float>::max();
@ -256,7 +260,7 @@ static inline void compute_softmax(std::vector<float>& values) {
}
//this function skips zero values (since exp(0) is non zero)
static inline void compute_softmax_zero(std::vector<float>& values) {
static inline void ComputeSoftmaxZero(std::vector<float>& values) {
std::vector<float> newscores;
// compute exp with negative number to be numerically stable
float v_max = -std::numeric_limits<float>::max();
@ -282,17 +286,17 @@ static inline void compute_softmax_zero(std::vector<float>& values) {
static inline void write_scores(std::vector<float>& scores, POST_EVAL_TRANSFORM post_transform, int64_t write_index, Tensor* Z, int add_second_class) {
if (post_transform == POST_EVAL_TRANSFORM::PROBIT && scores.size() == 1) {
scores[0] = ml_sqrt2 * ml_inv_erf(2 * scores[0] - 1);
scores[0] = ComputeProbit(scores[0]);
Z->template MutableData<float>()[write_index] = scores[0];
} else if (scores.size() >= 2) { //multiclass
if (post_transform == POST_EVAL_TRANSFORM::LOGISTIC) {
for (float& score : scores) {
score = ml_logit(score);
score = ComputeLogistic(score);
}
} else if (post_transform == POST_EVAL_TRANSFORM::SOFTMAX) {
compute_softmax(scores);
ComputeSoftmax(scores);
} else if (post_transform == POST_EVAL_TRANSFORM::SOFTMAX_ZERO) {
compute_softmax_zero(scores);
ComputeSoftmaxZero(scores);
}
} else { //binary case
if (add_second_class == 0 && scores.size() == 1) { //0=all positive weights, winning class is positive
@ -303,16 +307,16 @@ static inline void write_scores(std::vector<float>& scores, POST_EVAL_TRANSFORM
scores[0] = 1.f - scores[0]; //put opposite score in positive slot
} else if (add_second_class == 2 && scores.size() == 1) { //2 = mixed weights, winning class is positive
if (post_transform == POST_EVAL_TRANSFORM::LOGISTIC) {
scores.push_back(ml_logit(scores[0])); //ml_logit(scores[k]);
scores[0] = ml_logit(-scores[0]);
scores.push_back(ComputeLogistic(scores[0]));
scores[0] = ComputeLogistic(-scores[0]);
} else {
scores.push_back(scores[0]);
scores[0] = -scores[0];
}
} else if (add_second_class == 3 && scores.size() == 1) { //3 = mixed weights, winning class is negative
if (post_transform == POST_EVAL_TRANSFORM::LOGISTIC) {
scores.push_back(ml_logit(scores[0])); //ml_logit(scores[k]);
scores[0] = ml_logit(-scores[0]);
scores.push_back(ComputeLogistic(scores[0]));
scores[0] = ComputeLogistic(-scores[0]);
} else {
scores.push_back(-scores[0]);
}

View file

@ -257,19 +257,8 @@ common::Status TreeEnsembleRegressor<T>::Compute(OpKernelContext* context) const
}
outputs.push_back(val);
}
if (transform_ == ::onnxruntime::ml::POST_EVAL_TRANSFORM::LOGISTIC) {
for (float& output : outputs) {
output = ::onnxruntime::ml::ml_logit(output);
}
} else if (transform_ == ::onnxruntime::ml::POST_EVAL_TRANSFORM::SOFTMAX) {
::onnxruntime::ml::compute_softmax(outputs);
} else if (transform_ == ::onnxruntime::ml::POST_EVAL_TRANSFORM::SOFTMAX_ZERO) {
::onnxruntime::ml::compute_softmax_zero(outputs);
}
for (float output : outputs) {
Y->template MutableData<float>()[write_index] = output;
write_index++;
}
write_scores(outputs, transform_, write_index, Y, -1);
write_index += scores.size();
}
return Status::OK();
}