Subtracting very small probabilities - How to compute?











up vote
3
down vote

favorite
2












This question is an extension of a related question about adding small probabilities. Suppose you have log-probabilities $ell_1 geqslant ell_2$, where the corresponding probabilities $exp(ell_1)$ and $exp(ell_2)$ are too small to be distinguished from zero in the initial computational facility being used (e.g., base R). We want to find the log-diffference of these probabilities, which we denote by:



$$ell_- equiv ln big( exp(ell_1) - exp(ell_2) big)$$



Questions: How can you effectively compute this log-difference? Can this be done in the base R? If not, what is the simplest way to do it with package extensions?










share|cite|improve this question


















  • 1




    Possible duplicate of Computation of likelihood when $n$ is very large, so likelihood gets very small?
    – Xi'an
    1 hour ago















up vote
3
down vote

favorite
2












This question is an extension of a related question about adding small probabilities. Suppose you have log-probabilities $ell_1 geqslant ell_2$, where the corresponding probabilities $exp(ell_1)$ and $exp(ell_2)$ are too small to be distinguished from zero in the initial computational facility being used (e.g., base R). We want to find the log-diffference of these probabilities, which we denote by:



$$ell_- equiv ln big( exp(ell_1) - exp(ell_2) big)$$



Questions: How can you effectively compute this log-difference? Can this be done in the base R? If not, what is the simplest way to do it with package extensions?










share|cite|improve this question


















  • 1




    Possible duplicate of Computation of likelihood when $n$ is very large, so likelihood gets very small?
    – Xi'an
    1 hour ago













up vote
3
down vote

favorite
2









up vote
3
down vote

favorite
2






2





This question is an extension of a related question about adding small probabilities. Suppose you have log-probabilities $ell_1 geqslant ell_2$, where the corresponding probabilities $exp(ell_1)$ and $exp(ell_2)$ are too small to be distinguished from zero in the initial computational facility being used (e.g., base R). We want to find the log-diffference of these probabilities, which we denote by:



$$ell_- equiv ln big( exp(ell_1) - exp(ell_2) big)$$



Questions: How can you effectively compute this log-difference? Can this be done in the base R? If not, what is the simplest way to do it with package extensions?










share|cite|improve this question













This question is an extension of a related question about adding small probabilities. Suppose you have log-probabilities $ell_1 geqslant ell_2$, where the corresponding probabilities $exp(ell_1)$ and $exp(ell_2)$ are too small to be distinguished from zero in the initial computational facility being used (e.g., base R). We want to find the log-diffference of these probabilities, which we denote by:



$$ell_- equiv ln big( exp(ell_1) - exp(ell_2) big)$$



Questions: How can you effectively compute this log-difference? Can this be done in the base R? If not, what is the simplest way to do it with package extensions?







r computational-statistics underflow






share|cite|improve this question













share|cite|improve this question











share|cite|improve this question




share|cite|improve this question










asked 2 hours ago









Ben

21k22499




21k22499








  • 1




    Possible duplicate of Computation of likelihood when $n$ is very large, so likelihood gets very small?
    – Xi'an
    1 hour ago














  • 1




    Possible duplicate of Computation of likelihood when $n$ is very large, so likelihood gets very small?
    – Xi'an
    1 hour ago








1




1




Possible duplicate of Computation of likelihood when $n$ is very large, so likelihood gets very small?
– Xi'an
1 hour ago




Possible duplicate of Computation of likelihood when $n$ is very large, so likelihood gets very small?
– Xi'an
1 hour ago










1 Answer
1






active

oldest

votes

















up vote
2
down vote













To see how to deal with differences of this kind, we first note a useful mathematical result concerning differences of exponentials:



$$begin{equation} begin{aligned}
exp(ell_1) - exp(ell_2)
&= exp(ell_1) (1 - exp(-(ell_1 - ell_2))). \[6pt]
end{aligned} end{equation}$$



This result converts the difference to a product, which allows us to present the log-difference as:



$$begin{equation} begin{aligned}
ell_-
&= ln big( exp(ell_1) - exp(ell_2) big) \[6pt]
&= ln big( exp(ell_1) (1 - exp(-(ell_1 - ell_2))) big) \[6pt]
&= ell_1 + ln (1 - exp(-(ell_1 - ell_2))). \[6pt]
end{aligned} end{equation}$$



In the case where $ell_1 = ell_2$ we obtain the expression $ell_+ = ell_1 + ln 0 = -infty$. Using the Maclaurin series expansion for $ln(1-x)$ we obtain the formula:



$$begin{equation} begin{aligned}
ell_-
&= ell_1 - sum_{k=1}^infty frac{exp(-k(ell_1 - ell_2))}{k} quad quad quad text{for } ell_1 neq ell_2. \[6pt]
end{aligned} end{equation}$$



Since $exp(-(ell_1 - ell_2)) < 1$ the terms in this expansion diminish rapidly (faster than exponential decay). If $ell_1 - ell_2$ is large then the terms diminish particularly rapid. In any case, this expression allows us to compute the log-sum to any desired level of accuracy by truncating the infinite sum to a desired number of terms.





Implementation in base R: It is possible to compute this log-difference accurately in base R using the log1p function. This is a primitive function in the base package that computes the value of $ln(1+x)$ for an argument $x$ (with accurate computation even for $x ll 1$). This primitive function can be used to give a simple function for the log-difference:



logdiff <- function(l1, l2) { l1 + log1p(-exp(-(l1-l2))); }


Implementation with VGAM package: Machler (2012) analyses accuracy issues in evaluating the function $ln(1-exp(-|x|))$, and suggests that use of the base R functions may involve a loss of accuracy. It is possible to compute this log-difference more accurately in using the log1mexp function in the VGAM package. This gives you the an alternative function for the log-difference:



logdiff <- function(l1, l2) { l1 + VGAM::log1mexp(l1-l2); }





share|cite|improve this answer





















    Your Answer





    StackExchange.ifUsing("editor", function () {
    return StackExchange.using("mathjaxEditing", function () {
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["$", "$"], ["\\(","\\)"]]);
    });
    });
    }, "mathjax-editing");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "65"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstats.stackexchange.com%2fquestions%2f383523%2fsubtracting-very-small-probabilities-how-to-compute%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    2
    down vote













    To see how to deal with differences of this kind, we first note a useful mathematical result concerning differences of exponentials:



    $$begin{equation} begin{aligned}
    exp(ell_1) - exp(ell_2)
    &= exp(ell_1) (1 - exp(-(ell_1 - ell_2))). \[6pt]
    end{aligned} end{equation}$$



    This result converts the difference to a product, which allows us to present the log-difference as:



    $$begin{equation} begin{aligned}
    ell_-
    &= ln big( exp(ell_1) - exp(ell_2) big) \[6pt]
    &= ln big( exp(ell_1) (1 - exp(-(ell_1 - ell_2))) big) \[6pt]
    &= ell_1 + ln (1 - exp(-(ell_1 - ell_2))). \[6pt]
    end{aligned} end{equation}$$



    In the case where $ell_1 = ell_2$ we obtain the expression $ell_+ = ell_1 + ln 0 = -infty$. Using the Maclaurin series expansion for $ln(1-x)$ we obtain the formula:



    $$begin{equation} begin{aligned}
    ell_-
    &= ell_1 - sum_{k=1}^infty frac{exp(-k(ell_1 - ell_2))}{k} quad quad quad text{for } ell_1 neq ell_2. \[6pt]
    end{aligned} end{equation}$$



    Since $exp(-(ell_1 - ell_2)) < 1$ the terms in this expansion diminish rapidly (faster than exponential decay). If $ell_1 - ell_2$ is large then the terms diminish particularly rapid. In any case, this expression allows us to compute the log-sum to any desired level of accuracy by truncating the infinite sum to a desired number of terms.





    Implementation in base R: It is possible to compute this log-difference accurately in base R using the log1p function. This is a primitive function in the base package that computes the value of $ln(1+x)$ for an argument $x$ (with accurate computation even for $x ll 1$). This primitive function can be used to give a simple function for the log-difference:



    logdiff <- function(l1, l2) { l1 + log1p(-exp(-(l1-l2))); }


    Implementation with VGAM package: Machler (2012) analyses accuracy issues in evaluating the function $ln(1-exp(-|x|))$, and suggests that use of the base R functions may involve a loss of accuracy. It is possible to compute this log-difference more accurately in using the log1mexp function in the VGAM package. This gives you the an alternative function for the log-difference:



    logdiff <- function(l1, l2) { l1 + VGAM::log1mexp(l1-l2); }





    share|cite|improve this answer

























      up vote
      2
      down vote













      To see how to deal with differences of this kind, we first note a useful mathematical result concerning differences of exponentials:



      $$begin{equation} begin{aligned}
      exp(ell_1) - exp(ell_2)
      &= exp(ell_1) (1 - exp(-(ell_1 - ell_2))). \[6pt]
      end{aligned} end{equation}$$



      This result converts the difference to a product, which allows us to present the log-difference as:



      $$begin{equation} begin{aligned}
      ell_-
      &= ln big( exp(ell_1) - exp(ell_2) big) \[6pt]
      &= ln big( exp(ell_1) (1 - exp(-(ell_1 - ell_2))) big) \[6pt]
      &= ell_1 + ln (1 - exp(-(ell_1 - ell_2))). \[6pt]
      end{aligned} end{equation}$$



      In the case where $ell_1 = ell_2$ we obtain the expression $ell_+ = ell_1 + ln 0 = -infty$. Using the Maclaurin series expansion for $ln(1-x)$ we obtain the formula:



      $$begin{equation} begin{aligned}
      ell_-
      &= ell_1 - sum_{k=1}^infty frac{exp(-k(ell_1 - ell_2))}{k} quad quad quad text{for } ell_1 neq ell_2. \[6pt]
      end{aligned} end{equation}$$



      Since $exp(-(ell_1 - ell_2)) < 1$ the terms in this expansion diminish rapidly (faster than exponential decay). If $ell_1 - ell_2$ is large then the terms diminish particularly rapid. In any case, this expression allows us to compute the log-sum to any desired level of accuracy by truncating the infinite sum to a desired number of terms.





      Implementation in base R: It is possible to compute this log-difference accurately in base R using the log1p function. This is a primitive function in the base package that computes the value of $ln(1+x)$ for an argument $x$ (with accurate computation even for $x ll 1$). This primitive function can be used to give a simple function for the log-difference:



      logdiff <- function(l1, l2) { l1 + log1p(-exp(-(l1-l2))); }


      Implementation with VGAM package: Machler (2012) analyses accuracy issues in evaluating the function $ln(1-exp(-|x|))$, and suggests that use of the base R functions may involve a loss of accuracy. It is possible to compute this log-difference more accurately in using the log1mexp function in the VGAM package. This gives you the an alternative function for the log-difference:



      logdiff <- function(l1, l2) { l1 + VGAM::log1mexp(l1-l2); }





      share|cite|improve this answer























        up vote
        2
        down vote










        up vote
        2
        down vote









        To see how to deal with differences of this kind, we first note a useful mathematical result concerning differences of exponentials:



        $$begin{equation} begin{aligned}
        exp(ell_1) - exp(ell_2)
        &= exp(ell_1) (1 - exp(-(ell_1 - ell_2))). \[6pt]
        end{aligned} end{equation}$$



        This result converts the difference to a product, which allows us to present the log-difference as:



        $$begin{equation} begin{aligned}
        ell_-
        &= ln big( exp(ell_1) - exp(ell_2) big) \[6pt]
        &= ln big( exp(ell_1) (1 - exp(-(ell_1 - ell_2))) big) \[6pt]
        &= ell_1 + ln (1 - exp(-(ell_1 - ell_2))). \[6pt]
        end{aligned} end{equation}$$



        In the case where $ell_1 = ell_2$ we obtain the expression $ell_+ = ell_1 + ln 0 = -infty$. Using the Maclaurin series expansion for $ln(1-x)$ we obtain the formula:



        $$begin{equation} begin{aligned}
        ell_-
        &= ell_1 - sum_{k=1}^infty frac{exp(-k(ell_1 - ell_2))}{k} quad quad quad text{for } ell_1 neq ell_2. \[6pt]
        end{aligned} end{equation}$$



        Since $exp(-(ell_1 - ell_2)) < 1$ the terms in this expansion diminish rapidly (faster than exponential decay). If $ell_1 - ell_2$ is large then the terms diminish particularly rapid. In any case, this expression allows us to compute the log-sum to any desired level of accuracy by truncating the infinite sum to a desired number of terms.





        Implementation in base R: It is possible to compute this log-difference accurately in base R using the log1p function. This is a primitive function in the base package that computes the value of $ln(1+x)$ for an argument $x$ (with accurate computation even for $x ll 1$). This primitive function can be used to give a simple function for the log-difference:



        logdiff <- function(l1, l2) { l1 + log1p(-exp(-(l1-l2))); }


        Implementation with VGAM package: Machler (2012) analyses accuracy issues in evaluating the function $ln(1-exp(-|x|))$, and suggests that use of the base R functions may involve a loss of accuracy. It is possible to compute this log-difference more accurately in using the log1mexp function in the VGAM package. This gives you the an alternative function for the log-difference:



        logdiff <- function(l1, l2) { l1 + VGAM::log1mexp(l1-l2); }





        share|cite|improve this answer












        To see how to deal with differences of this kind, we first note a useful mathematical result concerning differences of exponentials:



        $$begin{equation} begin{aligned}
        exp(ell_1) - exp(ell_2)
        &= exp(ell_1) (1 - exp(-(ell_1 - ell_2))). \[6pt]
        end{aligned} end{equation}$$



        This result converts the difference to a product, which allows us to present the log-difference as:



        $$begin{equation} begin{aligned}
        ell_-
        &= ln big( exp(ell_1) - exp(ell_2) big) \[6pt]
        &= ln big( exp(ell_1) (1 - exp(-(ell_1 - ell_2))) big) \[6pt]
        &= ell_1 + ln (1 - exp(-(ell_1 - ell_2))). \[6pt]
        end{aligned} end{equation}$$



        In the case where $ell_1 = ell_2$ we obtain the expression $ell_+ = ell_1 + ln 0 = -infty$. Using the Maclaurin series expansion for $ln(1-x)$ we obtain the formula:



        $$begin{equation} begin{aligned}
        ell_-
        &= ell_1 - sum_{k=1}^infty frac{exp(-k(ell_1 - ell_2))}{k} quad quad quad text{for } ell_1 neq ell_2. \[6pt]
        end{aligned} end{equation}$$



        Since $exp(-(ell_1 - ell_2)) < 1$ the terms in this expansion diminish rapidly (faster than exponential decay). If $ell_1 - ell_2$ is large then the terms diminish particularly rapid. In any case, this expression allows us to compute the log-sum to any desired level of accuracy by truncating the infinite sum to a desired number of terms.





        Implementation in base R: It is possible to compute this log-difference accurately in base R using the log1p function. This is a primitive function in the base package that computes the value of $ln(1+x)$ for an argument $x$ (with accurate computation even for $x ll 1$). This primitive function can be used to give a simple function for the log-difference:



        logdiff <- function(l1, l2) { l1 + log1p(-exp(-(l1-l2))); }


        Implementation with VGAM package: Machler (2012) analyses accuracy issues in evaluating the function $ln(1-exp(-|x|))$, and suggests that use of the base R functions may involve a loss of accuracy. It is possible to compute this log-difference more accurately in using the log1mexp function in the VGAM package. This gives you the an alternative function for the log-difference:



        logdiff <- function(l1, l2) { l1 + VGAM::log1mexp(l1-l2); }






        share|cite|improve this answer












        share|cite|improve this answer



        share|cite|improve this answer










        answered 2 hours ago









        Ben

        21k22499




        21k22499






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Cross Validated!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            Use MathJax to format equations. MathJax reference.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstats.stackexchange.com%2fquestions%2f383523%2fsubtracting-very-small-probabilities-how-to-compute%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            flock() on closed filehandle LOCK_FILE at /usr/bin/apt-mirror

            Mangá

             ⁒  ․,‪⁊‑⁙ ⁖, ⁇‒※‌, †,⁖‗‌⁝    ‾‸⁘,‖⁔⁣,⁂‾
”‑,‥–,‬ ,⁀‹⁋‴⁑ ‒ ,‴⁋”‼ ⁨,‷⁔„ ‰′,‐‚ ‥‡‎“‷⁃⁨⁅⁣,⁔
⁇‘⁔⁡⁏⁌⁡‿‶‏⁨ ⁣⁕⁖⁨⁩⁥‽⁀  ‴‬⁜‟ ⁃‣‧⁕‮ …‍⁨‴ ⁩,⁚⁖‫ ,‵ ⁀,‮⁝‣‣ ⁑  ⁂– ․, ‾‽ ‏⁁“⁗‸ ‾… ‹‡⁌⁎‸‘ ‡⁏⁌‪ ‵⁛ ‎⁨ ―⁦⁤⁄⁕