Maximum Likelihood
Overview
This example demonstrates calculating a maximum likelihood estimate of a normal distribution given a set of samples from
the distribution.
We assume we have a number of data points. Each point has 4 properties, 3 factors and a value.
let sample = {
factor1:0.2,
factor2:1.2,
factor3:1,0,
value:3.4
}
We assume that the value is drawn from a normal distribution
{% f(x) = \sqrt{1/2\pi \sigma^2 } \times e ^{-0.5 [(x-\mu)/\sigma]^2} %}
Here we assume that {% \mu %} and {% \sigma %} are not constant, rather they are functions of the 3 factors.
Maximum Likelihood
The likelihood of the drawn sample of points is.
{% Likelihood = \Pi \sqrt{1/2\pi \sigma^2 } \times e ^{-0.5 [(x-\mu)/\sigma]^2} %}
The log likelihood is then given by
{% logLikelihood = \sum log[ \sqrt{1/2\pi \sigma^2 } \times e ^{-0.5 [(x-\mu)/\sigma]^2} ] %}
{% = \sum log(\sqrt{1/2\pi \sigma^2}) + log[ e ^{-0.5 [(x-\mu)/\sigma]^2} ] %}
{% = \sum log(\sqrt{1/2\pi \sigma^2}) + -0.5 [(x-\mu)/\sigma]^2 ] %}
A neural network can be constructed to forecast the {% \mu %} and {% \sigma %} of the distribution based on
the 3 factors. In order to do this, the neural network must have 3 inputs (one for each factor) and two
outputs, representing {% \mu %} and {% \sigma %}.
Lastly, a loss function must be chosen. Here there is a bit of complexity. Most api's assume that you provide a target value that you
can compare the predicted value to. In this case, the target values are unknown. Rather, we have to provide a loss function which
is the negative log likelihood.
Implementation
The following implementation uses the
numeric neural network library.
function loss(){
let weights = [...arguments]
let sum = 0;
for(let item of sample){
let predicted = network(item.factors, ...weights);
let mean = predicted[0][0];
let stdDev = predicted[1][0];
sum += Math.log(Math.sqrt(1/(2*Math.PI*stdDev*stdDev)));
let temp = (item.value - mean)/stdDev;
sum += -0.5 * temp*temp;
}
return -1*sum;
}
For the example, we generate a random sample of points. We arbitrarily choose a function of the factors to
represent the mean and standard deviation.
let sample = [];
for(let i=0;i<100;i++){
let point = [Math.random(),Math.random(),Math.random()];
let item = {
factors:point.map(p=>[p]),
mean:point[0]*point[0]+ point[1] - 0.5*point[2],
stdDev: 0.5*point[1] + 0.2 * point[2]
};
item.value = nm.random(item.mean, item.stdDev);
sample.push(item);
}
Try it!