inline void clustering (const unsigned int num_iteration = 10000) { unsigned int iteration = 0; while (!updateMembership () && iteration++ < num_iteration) { computeCentroids2(); } }
void Fuzzy::initKmeansPP () { // // k-means++の手法で初期化する場合 // srand ((unsigned int) time (NULL)); std::vector<int> center_indexes (0); std::vector<bool> already_selected_indexes (number_points_, false); // random centroid initialization assign int first_index = rand () % number_points_; center_indexes.push_back (first_index); already_selected_indexes[first_index] = true; while (center_indexes.size () < number_clusters_) { // すべてのデータ点に対して // 最近傍の重心を見つけその距離を算出 std::vector<float> nearest_distances (number_points_, 0.0); for (int p = 0; p < number_points_; ++p) { // 既にcentroidsとして選択済みの場合は考えない if (already_selected_indexes[p]) continue; // pは各点のindexに対応 cv::Mat point = rows_.row (p); std::vector<float> distances_from_centers (0); // 全ての重心との距離を計算 for (int c = 0; c < center_indexes.size (); ++c) { int center_index = center_indexes[c]; cv::Mat center = rows_.row (center_index); float dist = calc_dist (point, center, kSoftCDistL2); distances_from_centers.push_back (dist); } // 最近傍の重心を見つける int nearest_center_index = center_indexes[0]; float min = distances_from_centers[0]; for (int c = 1; c < distances_from_centers.size (); ++c) { float dist = distances_from_centers[c]; if (dist < min) { min = dist; nearest_center_index = center_indexes[c]; } } nearest_distances[p] = min; } assert (nearest_distances.size () == number_points_); // 上記のうち距離が最長のものを重心に加える float max = nearest_distances[0]; float max_index = 0; for (int p = 1; p < nearest_distances.size (); ++p) { float dist = nearest_distances[p]; if (dist > max) { max = dist; max_index = p; } } // 重心として選択 center_indexes.push_back (max_index); already_selected_indexes[max_index] = true; } // centroidsを上記の点にセットする for (int j = 0; j < center_indexes.size (); ++j) { // FIXME // めっちゃworkaroundだが,完全一致だとupdate_membershipで // 分母が0になってしまったときに問題が... for (int d = 0; d < dimension_; ++d) { centroids_.at<float> (j, d) = rows_.at<float> (center_indexes[j], d) + 0.001; } } // membershipをアップデート updateMembership (); // 初期化からははみ出るが,ふたたびcenroids算出 computeCentroids2(); }