Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SPARK-5128][MLLib] Add common used log1pExp API in MLUtils #3915

Closed
wants to merge 7 commits into from
Closed

[SPARK-5128][MLLib] Add common used log1pExp API in MLUtils #3915

wants to merge 7 commits into from

Conversation

dbtsai
Copy link
Member

@dbtsai dbtsai commented Jan 6, 2015

When x is positive and large, computing math.log(1 + math.exp(x)) will lead to arithmetic
overflow. This will happen when x > 709.78 which is not a very large number.
It can be addressed by rewriting the formula into x + math.log1p(math.exp(-x)) when x > 0.

@SparkQA
Copy link

SparkQA commented Jan 6, 2015

Test build #25112 has started for PR 3915 at commit 6b3ca72.

  • This patch merges cleanly.

@SparkQA
Copy link

SparkQA commented Jan 6, 2015

Test build #25112 has finished for PR 3915 at commit 6b3ca72.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

@AmplabJenkins
Copy link

Test PASSed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins//job/SparkPullRequestBuilder/25112/
Test PASSed.

@SparkQA
Copy link

SparkQA commented Jan 6, 2015

Test build #25120 has started for PR 3915 at commit e4957d5.

  • This patch merges cleanly.

@SparkQA
Copy link

SparkQA commented Jan 7, 2015

Test build #25120 has finished for PR 3915 at commit e4957d5.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

@AmplabJenkins
Copy link

Test PASSed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins//job/SparkPullRequestBuilder/25120/
Test PASSed.

@dbtsai
Copy link
Member Author

dbtsai commented Jan 7, 2015

For MLOR case, it's not as simple as binary case, but I managed to address it. Will be in another PR.

Actually, this solves instability issue when the initial weights is not properly set.
Since in this case, the margin will be very large, and it's just overflow.

@@ -61,14 +62,27 @@ abstract class Gradient extends Serializable {
class LogisticGradient extends Gradient {
override def compute(data: Vector, label: Double, weights: Vector): (Vector, Double) = {
val margin = -1.0 * dot(data, weights)
val gradientMultiplier = (1.0 / (1.0 + math.exp(margin))) - label
/**
* gradientMultiplier = (1.0 / (1.0 + math.exp(margin))) - label
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it the logistic function? Maybe we should make create a function for it as well.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, but in MLOR, the formula is very different since we have k-1 margins, and we need to carry out the largest margin. As a result, it will be very hard to generalized for BLOR and MLOR. I plan to have it as it since we probably will not use it in other place. The following is the version for MLOR from the comment of my another PR.

 * `multiplier = exp(margins(i)) / (1 + \sum_k exp(margins(k))) -
 *    \alpha(label) * \delta_{label}{i+1}`
 *
 * where \alpha(label) = 1 if label != 0;
 *       \alpha(label) = 0 if label == 0, and
 *       \delta_{i}{j} = 1 if i == j;
 *       \delta_{i}{j} = 0 if i != j
 *
 * See the reference for the detailed mathematical derivation.
 *
 * However, the first part of multiplier will be likely suffered from arithmetic overflow,
 * if any one of the `margins` is larger than 709.78.
 *
 * Let's say the largest `margins(l)` is `maxMargin` and positive, then the formula can be
 * rewritten into equivalent formula with more numerical stability by
 *
 * exp(margins(i)) / (1 + \sum_k exp(margins(k))) =
 * exp(margins(i) / maxMargin) / (exp(-margins(l)) + \sum_k exp(margins(k) / maxMargin))
 *
 * If we define margins'(i) = margins(i) / maxMargin when i != l,
 * and margins'(l) = -margins(l), we will have equivalent numerically stable formula as
 *
 * `multiplier = exp(margins'(i)) / (1 + \sum_k exp(margins'(k))) -
 *    \alpha(label) * \delta_{label}{i+1}`
 *
 * Note that if the largest `margins` is negative, the original formula is stable;
 * as a result, we don't need to change it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PS, I'll add a test to test overflow later. It does happen quite often when there are outliners which are far away from the hyperplane, and I run into this situation before.

@SparkQA
Copy link

SparkQA commented Jan 7, 2015

Test build #25150 has started for PR 3915 at commit 23144f3.

  • This patch merges cleanly.

@SparkQA
Copy link

SparkQA commented Jan 7, 2015

Test build #25151 has started for PR 3915 at commit 3239541.

  • This patch merges cleanly.

@dbtsai dbtsai changed the title [SPARK-5101] Add common ML math functions [SPARK-5101] Add common used log1pExp API in MLUtils Jan 7, 2015
@SparkQA
Copy link

SparkQA commented Jan 7, 2015

Test build #25152 has started for PR 3915 at commit bec6a84.

  • This patch merges cleanly.

@dbtsai dbtsai changed the title [SPARK-5101] Add common used log1pExp API in MLUtils [SPARK-5128][MLLib] Add common used log1pExp API in MLUtils Jan 7, 2015
@SparkQA
Copy link

SparkQA commented Jan 7, 2015

Test build #25150 has finished for PR 3915 at commit 23144f3.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

@AmplabJenkins
Copy link

Test PASSed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins//job/SparkPullRequestBuilder/25150/
Test PASSed.

@SparkQA
Copy link

SparkQA commented Jan 7, 2015

Test build #25151 has finished for PR 3915 at commit 3239541.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

@AmplabJenkins
Copy link

Test PASSed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins//job/SparkPullRequestBuilder/25151/
Test PASSed.

@SparkQA
Copy link

SparkQA commented Jan 7, 2015

Test build #25152 has finished for PR 3915 at commit bec6a84.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

@AmplabJenkins
Copy link

Test PASSed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins//job/SparkPullRequestBuilder/25152/
Test PASSed.

@srowen
Copy link
Member

srowen commented Jan 7, 2015

LGTM. The method successfully avoids overflow in the intended way, there's a test, and from checking the old and new logic they should be identical.

@mengxr
Copy link
Contributor

mengxr commented Jan 7, 2015

Merged into master. Thanks!

@asfgit asfgit closed this in 60e2d9e Jan 7, 2015
@dbtsai dbtsai deleted the mathutil branch January 7, 2015 19:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants