An implementation of the beta distribution probability density function in Javascript.
This implementation overcomes the problem of large numbers being generated by the Beta function which can cause JS to return inf values.
where
A naive implementation of the beta distribution using the equations above will work as intended for smaller values of
function naiveBetaPDF(x, a, b) {
// Naive implementation of the beta pdf function
// Using factorials
return Math.pow(x, a-1)*Math.pow(1-x, b-1)/naiveBetaFunc(a,b)
}
function naiveBetaFunc(a ,b) {
// Naive implementation of the beta function
// using factorials
return factorial(a-1)*factorial(b-1)/factorial(a+b-1)
}
function factorial(x) {
if (x === 0) {
return 1;
}
return x * factorial(x-1);
}
console.log(naiveBetaPDF(x=0.5, a=10, b=10)) // 3.5239410400390625
console.log(naiveBetaPDF(x=0.5, a=100, b=100)) // NaN
console.log(naiveBetaPDF(x=0.5, a=1000, b=1000)) // NaN
The function fails at
To overcome this problem, we can use the log beta function instead to calculate
Therefore, the log beta pdf function becomes:
In code:
function betaPDF(x, a, b) {
// Beta probability density function impementation
// using logarithms, no factorials involved.
// Overcomes the problem with large integers
return Math.exp(lnBetaPDF(x, a, b))
}
function lnBetaPDF(x, a, b) {
// Log of the Beta Probability Density Function
return ((a-1)*Math.log(x) + (b-1)*Math.log(1-x)) - lnBetaFunc(a,b)
}
function lnBetaFunc(a, b) {
// Log Beta Function
// ln(Beta(x,y))
foo = 0.0;
for (i=0; i<a-2; i++) {
foo += Math.log(a-1-i);
}
for (i=0; i<b-2; i++) {
foo += Math.log(b-1-i);
}
for (i=0; i<a+b-2; i++) {
foo -= Math.log(a+b-1-i);
}
return foo
}
console.log(betaPDF(x=0.5, a=10, b=10)) // 3.5239410400390625
console.log(betaPDF(x=0.5, a=100, b=100)) // 11.269695801846181
console.log(betaPDF(x=0.5, a=1000, b=1000)) // 35.67802229201808
console.log(betaPDF(x=0.5, a=10000, b=10000)) // 112.83650628497722
Now the function is able to handle larger values of