I'm trying to re-implement the Ckmeans.1D.DP algorithm in Python. I have the actual dynamic optimization part down, but I'm a little confused by the BIC computation they use for selecting the number of clusters. I'm not concerned right now about whether this is the best technique; I'm just trying to achieve parity with their implementation.
In particular, this variance computation (performed inside each cluster) is baffling:
double mean = 0.0;
double variance = 0.0;
for (size_t i = indexLeft; i <= indexRight; ++i) {
mean += x[i];
variance += x[i] * x[i];
}
mean /= numPointsInBin;
if (numPointsInBin > 1) {
variance = (variance - numPointsInBin * mean * mean) / (numPointsInBin - 1);
} else {
variance = 0;
}
I read this as follows: $$\begin{align} \hat \mu_k &= \frac{1}{n_k} \sum_{i=i_\text{left}}^{i_\text{right}} x_i \\ \hat \sigma^2_k &= \begin{cases} \frac{1}{n_k - 1} \sum_{i=1_\text{left}}^{i_\text{right}} \left( x_i^2 - \hat \mu_k^2 \right) &,\ n_k > 1 \\ 0 &,\ n_k = 1 \end{cases} \end{align}$$
where $\hat \mu_k$ is a cluster mean, $\hat \sigma^2_k$ is a cluster variance, $n_k$ is a cluster size, and $k$ indexes the clusters.
This is totally bizarre: the maximum likelihood estimator for variance is $\frac{1}{n - 1} \sum_i \left(x_i - \hat \mu\right)^2$ (for generic $n$, $i$, and $\hat \mu$), and it's pretty clear that $\left(x_i - \hat \mu\right)^2 = x_i^2 - 2 x_i \hat\mu + \hat\mu^2 \neq xi^2 - \hat\mu^2$. What gives?