EDIT: see below- I used the pdf instead of the cdf for my likelihood. Fixed, but with a fun new problem!
This is a follow-up to a question I asked here.
For reasons explained earlier, I'm attempting to fit a variety of models to circular data: 1) Pure von Mises 2) Mixture model (uniform + von Mises) 3) Pure uniform
The tricky part is that the data is grouped into 8 bins with width π/4, and I have no way of recovering the true angles. I have to assume that each angle theta corresponds to an interval [theta - π/8, theta + π/8).
This my MATLAB implementation (errors is a vector containing angles from the set {-3π/4:π/4:π}):
% setup interval boundaries
left = errors - pi/8; % left boundary of intervals
right = errors + pi/8; % right boundary
% von mises function
vm_pdf = @(mu, kappa, x) 1/(2*pi*besseli(0,kappa))*exp(kappa*cos(x-mu));
% log likelihood function
ll_vm = @(mu, kappa, left, right) sum(log(vm_pdf(mu, kappa, right))...
- log(vm_pdf(mu, kappa, left)));
% initial estimate of mu and kappa
mu0 = circ_mean(errors); % circular mean of interval midpoints
kappa0 = 1/circ_var(errors); % kappa is equivalent to 1/variance
params0 = [mu0 kappa0];
% maximize ll_vm (aka minimize negative ll_vm)
options = optimset('Display','iter');
options.MaxFunctionEvaluations = 400;
f = @(params) -ll_vm(params(1), params(2), left, right);
[params_final,fval] = fminsearch(f, params0, options);
The values of f(x) obtained decrease with each iteration, but when I visualize the fit, it's comically bad:
Am I calculating the log likelihood of the intervals correctly? I'm using the explanation here as a guide. I'm fairly new to optimization problems- have I set up the problem incorrectly?
UPDATE: Ok, so evaluating the cdf isn't easy. Matlab's built-in cdf function doesn't handle a von mises, so I had to adapt this code, which seems to work. My new fit looks like this:
which is better, but I think the fact that the upper interval [theta - π/8, theta + π/8) where theta = π extends past the limit (technically it should "wrap" around the circle) might be skewing the estimation of my mean.