void operator()(std::size_t begin, std::size_t end) { for(std::size_t j = begin; j < end; j++){ ArrayXd d = s2*a_prec(j) + s1*e_prec(j); ArrayXd mlam = b.col(j).array() / d; effects.col(j) = U * (mlam + randn_draws.col(j) / sqrt(d)).matrix(); } }
bool KmeansClusterer::updateClusterCentersUntilConverged(RefArrayXXd sample, RefArrayXXd centers, RefArrayXd clusterSizes, vector<int> &clusterIndices, double &sumOfDistancesToClosestCenter, double relTolerance) { unsigned int Npoints = sample.cols(); unsigned int Ndimensions = sample.rows(); unsigned int Nclusters = centers.cols(); ArrayXXd updatedCenters = ArrayXXd::Zero(Ndimensions, Nclusters); // coordinates of each of the new cluster centers // Perform the k-means clustering iteration, each time improving the cluster centers, // and redetermining which points belongs to which cluster bool stopIterations = false; bool convergenceReached; unsigned int indexOfClosestCenter; double oldSumOfDistances = 0.0; double newSumOfDistances = 0.0; double distanceToClosestCenter; double distance; while (!stopIterations) { // Find for each point the closest cluster center. // At the same time recompute/update the new cluster centers, which is simply // the barycenter of all points belonging to the cluster. clusterSizes.setZero(); updatedCenters.setZero(); for (int n = 0; n < Npoints; ++n) { distanceToClosestCenter = numeric_limits<double>::max(); for (int i = 0; i < Nclusters; ++i) { distance = metric.distance(sample.col(n), centers.col(i)); if (distance < distanceToClosestCenter) { indexOfClosestCenter = i; distanceToClosestCenter = distance; } } newSumOfDistances += distanceToClosestCenter; updatedCenters.col(indexOfClosestCenter) += sample.col(n); clusterSizes(indexOfClosestCenter) += 1; clusterIndices[n] = indexOfClosestCenter; } // Assert that all clusters contain at least 2 points. If not we probably started // with an unfortunate set of initial cluster centers. Flag this by immediately // returning false. if (!(clusterSizes > 1).all()) { convergenceReached = false; return convergenceReached; } // Finish computing the new updated centers. Given the check above, we are sure // that none of the clusters is empty. updatedCenters.rowwise() /= clusterSizes.transpose(); centers = updatedCenters; // A new set of clusters has been determined. // Decide whether the algorithm has converged. Convergence occurs when // the sum of all distances of all points to their cluster center does // not change significantly anymore. // Note: in order for this criterion to work properly, the coordinate // space should be normalized, so that one particular coordinate // cannot numerically dominate all other coordinates. if (oldSumOfDistances == 0.0) { // This is the first center-updating iteration, so there is nothing to compare yet. // Simply set the variables. oldSumOfDistances = newSumOfDistances; newSumOfDistances = 0.0; } else { // If the relative change in sumOfDistances between old and new was smaller than // the threshold set by the user, stop the iteration loop. if (fabs(newSumOfDistances - oldSumOfDistances) / oldSumOfDistances < relTolerance) { sumOfDistancesToClosestCenter = newSumOfDistances; // will be returned to user stopIterations = true; } else { oldSumOfDistances = newSumOfDistances; newSumOfDistances = 0.0; } } } // end k-means center-updating loop // Convergence was properly reached, so return convergenceReached = true; return convergenceReached; }