unsigned int som::competition(const std::vector<double> * pattern) const { unsigned int index = 0; double minimum = euclidean_distance_sqrt((*weights)[0], pattern); for (unsigned int i = 1; i < size; i++) { double candidate = euclidean_distance_sqrt((*weights)[i], pattern); if (candidate < minimum) { index = i; minimum = candidate; } } return index; }
double xmeans::update_centers(std::vector<std::vector<unsigned int> *> * analysed_clusters, std::vector<std::vector<double> > * analysed_centers) { double maximum_change = 0; /* for each cluster */ for (unsigned int index_cluster = 0; index_cluster < analysed_clusters->size(); index_cluster++) { std::vector<long double> total((*analysed_centers)[index_cluster].size(), 0); /* for each object in cluster */ for (std::vector<unsigned int>::const_iterator object_index_iterator = (*analysed_clusters)[index_cluster]->begin(); object_index_iterator < (*analysed_clusters)[index_cluster]->end(); object_index_iterator++) { /* for each dimension */ for (unsigned int dimension = 0; dimension < total.size(); dimension++) { total[dimension] += (*dataset)[*object_index_iterator][dimension]; } } /* average for each dimension */ for (std::vector<long double>::iterator dimension_iterator = total.begin(); dimension_iterator != total.end(); dimension_iterator++) { *dimension_iterator = *dimension_iterator / (*analysed_clusters)[index_cluster]->size(); } #ifdef FAST_SOLUTION double distance = euclidean_distance_sqrt( &(*analysed_centers)[index_cluster], (std::vector<double> *) &total ); #else double distance = euclidean_distance( &(*analysed_centers)[index_cluster], (std::vector<double> *) &total ); #endif if (distance > maximum_change) { maximum_change = distance; } std::copy(total.begin(), total.end(), (*analysed_centers)[index_cluster].begin()); } return maximum_change; }
void kmeans::update_clusters(void) { /* clear content of clusters. */ for (std::vector<std::vector<unsigned int> *>::iterator iter = clusters->begin(); iter != clusters->end(); iter++) { (*iter)->clear(); } /* fill clusters again in line with centers. */ for (unsigned int index_object = 0; index_object < dataset->size(); index_object++) { double minimum_distance = std::numeric_limits<double>::max(); unsigned int suitable_index_cluster = 0; for (unsigned int index_cluster = 0; index_cluster < clusters->size(); index_cluster++) { #ifdef FAST_SOLUTION double distance = euclidean_distance_sqrt( &(*centers)[index_cluster], &(*dataset)[index_object] ); #else double distance = euclidean_distance( &(*centers)[index_cluster], &(*dataset)[index_object] ); #endif if (distance < minimum_distance) { minimum_distance = distance; suitable_index_cluster = index_cluster; } } (*clusters)[suitable_index_cluster]->push_back(index_object); } /* if there is clusters that are not able to capture objects */ for (size_t index_cluster = clusters->size() - 1; index_cluster != (size_t) -1; index_cluster--) { if ((*clusters)[index_cluster]->empty()) { clusters->erase(clusters->begin() + index_cluster); } } }
void agglomerative::merge_by_average_link(void) { double minimum_average_distance = std::numeric_limits<double>::max(); const std::vector<point> & data = *m_ptr_data; size_t index1 = 0; size_t index2 = 1; for (size_t index_cluster1 = 0; index_cluster1 < m_ptr_clusters->size(); index_cluster1++) { for (size_t index_cluster2 = index_cluster1 + 1; index_cluster2 < m_ptr_clusters->size(); index_cluster2++) { double candidate_average_distance = 0.0; for (auto index_object1 : (*m_ptr_clusters)[index_cluster1]) { for (auto index_object2 : (*m_ptr_clusters)[index_cluster2]) { candidate_average_distance += euclidean_distance_sqrt(&data[index_object1], &data[index_object2]); } } candidate_average_distance /= ((*m_ptr_clusters)[index_cluster1].size() + (*m_ptr_clusters)[index_cluster2].size()); if (candidate_average_distance < minimum_average_distance) { minimum_average_distance = candidate_average_distance; index1 = index_cluster1; index2 = index_cluster2; } } } (*m_ptr_clusters)[index1].insert((*m_ptr_clusters)[index1].end(), (*m_ptr_clusters)[index2].begin(), (*m_ptr_clusters)[index2].end()); m_ptr_clusters->erase(m_ptr_clusters->begin() + index2); }
void kmedians::update_clusters() { m_clusters.clear(); m_clusters.resize(m_medians.size()); const std::vector<point> & data = *m_ptr_data; for (size_t index_point = 0; index_point < data.size(); index_point++) { size_t index_cluster_optim = 0; double distance_optim = std::numeric_limits<double>::max(); for (size_t index_cluster = 0; index_cluster < m_medians.size(); index_cluster++) { double distance = euclidean_distance_sqrt(&data[index_point], &m_medians[index_cluster]); if (distance < distance_optim) { index_cluster_optim = index_cluster; distance_optim = distance; } } m_clusters[index_cluster_optim].push_back(index_point); } /* Check for clusters that are not able to capture object */ for (size_t index_cluster = m_clusters.size() - 1; index_cluster != (size_t) -1; index_cluster--) { if (m_clusters[index_cluster].empty()) { m_clusters.erase(m_clusters.begin() + index_cluster); } } }
unsigned int xmeans::find_proper_cluster(std::vector<std::vector<double> > * analysed_centers, const std::vector<double> * const point) const { unsigned int index_optimum = 0; double distance_optimum = std::numeric_limits<double>::max(); for (unsigned int index_cluster = 0; index_cluster < analysed_centers->size(); index_cluster++) { #ifdef FAST_SOLUTION double distance = euclidean_distance_sqrt( point, &(*analysed_centers)[index_cluster] ); #else double distance = euclidean_distance( point, &(*analysed_centers)[index_cluster] ); #endif if (distance < distance_optimum) { index_optimum = index_cluster; distance_optimum = distance; } } return index_optimum; }
double kmedians::update_medians() { const std::vector<point> & data = *m_ptr_data; const size_t dimension = data[0].size(); std::vector<point> prev_medians(m_medians); m_medians.clear(); m_medians.resize(m_clusters.size(), point(dimension, 0.0)); double maximum_change = 0.0; for (size_t index_cluster = 0; index_cluster < m_clusters.size(); index_cluster++) { for (size_t index_dimension = 0; index_dimension < dimension; index_dimension++) { cluster & current_cluster = m_clusters[index_cluster]; std::sort(current_cluster.begin(), current_cluster.end(), [this](unsigned int index_object1, unsigned int index_object2) { return (*m_ptr_data)[index_object1] > (*m_ptr_data)[index_object2]; }); size_t relative_index_median = (size_t) floor(current_cluster.size() / 2.0); size_t index_median = current_cluster[relative_index_median]; if (current_cluster.size() % 2) { size_t index_median_second = current_cluster[relative_index_median + 1]; m_medians[index_cluster][index_dimension] = (data[index_median][index_dimension] + data[index_median_second][index_dimension]) / 2.0; } else { m_medians[index_cluster][index_dimension] = data[index_median][index_dimension]; } } double change = euclidean_distance_sqrt(&prev_medians[index_cluster], &m_medians[index_cluster]); if (change > maximum_change) { maximum_change = change; } } return maximum_change; }
void kdtree_searcher::recursive_nearest_nodes(kdnode * node) { double minimum = node->get_value() - distance; double maximum = node->get_value() + distance; if (node->get_right() != nullptr) { if ((*search_point)[node->get_discriminator()] >= minimum) { recursive_nearest_nodes(node->get_right()); } } if (node->get_left() != nullptr) { if ((*search_point)[node->get_discriminator()] < maximum) { recursive_nearest_nodes(node->get_left()); } } double candidate_distance = euclidean_distance_sqrt(search_point, node->get_data()); if (candidate_distance <= sqrt_distance) { nearest_nodes->push_back(node); nodes_distance->push_back(candidate_distance); } }
void agglomerative::merge_by_centroid_link(void) { double minimum_average_distance = std::numeric_limits<double>::max(); size_t index_cluster1 = 0; size_t index_cluster2 = 1; for (size_t index1 = 0; index1 < m_centers.size(); index1++) { for (size_t index2 = index1 + 1; index2 < m_centers.size(); index2++) { double distance = euclidean_distance_sqrt(&m_centers[index1], &m_centers[index2]); if (distance < minimum_average_distance) { minimum_average_distance = distance; index_cluster1 = index1; index_cluster2 = index2; } } } (*m_ptr_clusters)[index_cluster1].insert((*m_ptr_clusters)[index_cluster1].end(), (*m_ptr_clusters)[index_cluster2].begin(), (*m_ptr_clusters)[index_cluster2].end()); calculate_center((*m_ptr_clusters)[index_cluster1], m_centers[index_cluster2]); m_ptr_clusters->erase(m_ptr_clusters->begin() + index_cluster2); m_centers.erase(m_centers.begin() + index_cluster2); }
som::som(std::vector<std::vector<double> > * input_data, const unsigned int num_rows, const unsigned int num_cols, const unsigned int num_epochs, const som_conn_type type_conn, const som_parameters * parameters) { previous_weights = NULL; neighbors = NULL; data = input_data; rows = num_rows; cols = num_cols; size = cols * rows; epouchs = num_epochs; conn_type = type_conn; if (parameters != nullptr) { params.init_type = parameters->init_type; params.init_learn_rate = parameters->init_learn_rate; params.adaptation_threshold = parameters->adaptation_threshold; params.init_radius = parameters->init_radius; } /* location */ location = new std::vector<std::vector<double> * >(size, NULL); for (unsigned int i = 0; i < rows; i++) { for (unsigned int j = 0; j < cols; j++) { std::vector<double> * neuron_location = new std::vector<double>(2, 0); (*neuron_location)[0] = i; (*neuron_location)[1] = j; (*location)[i * cols + j] = neuron_location; } } /* awards */ awards = new std::vector<unsigned int>(size, 0); /* distances */ sqrt_distances = new std::vector<std::vector<double> * >(size, NULL); for (unsigned int i = 0; i < size; i++) { std::vector<double> * column_distances = new std::vector<double>(size, 0); (*sqrt_distances)[i] = column_distances; } for (unsigned int i = 0; i < size; i++) { for (unsigned int j = i; j < size; j++) { double distance = euclidean_distance_sqrt((*location)[i], (*location)[j]); (*(*sqrt_distances)[i])[j] = distance; (*(*sqrt_distances)[j])[i] = distance; } } /* captured objects */ capture_objects = new std::vector<std::vector<unsigned int> * >(size, NULL); for (unsigned int i = 0; i < size; i++) { (*capture_objects)[i] = new std::vector<unsigned int>(); } /* connections */ if (type_conn != som_conn_type::SOM_FUNC_NEIGHBOR) { create_connections(type_conn); } /* weights */ create_initial_weights(params.init_type); }