Loading src/loss_function/LossFunctionCalinskiHarabasz.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -45,7 +45,7 @@ double LossFunctionCalinskiHarabasz::compute_w() { std::vector<double> centroid = get_centroid(cluster_label); for (size_t sample_idx = 0; sample_idx < _n_samp; sample_idx++) { int mask_idx = cluster_label * _n_samp + sample_idx; if (!label_mask[mask_idx]) continue; if (!_label_mask[mask_idx]) continue; const double* sample = &_a[sample_idx * _n_feat]; double dist2 = 0.0; for (int f = 0; f < _n_feat; ++f) { Loading Loading @@ -74,7 +74,7 @@ double LossFunctionCalinskiHarabasz::compute_b() { int n_k = 0; for (size_t sample_idx = 0; sample_idx < _n_samp; sample_idx++) { int mask_idx = cluster_label * _n_samp + sample_idx; if (label_mask[mask_idx]) { if (_label_mask[mask_idx]) { n_k++; } } Loading src/loss_function/LossFunctionClustering.cpp +20 −28 Original line number Diff line number Diff line Loading @@ -13,7 +13,8 @@ LossFunctionClustering::LossFunctionClustering(std::vector<double> prop_train, int n_feat) : LossFunction(prop_train, prop_test, task_sizes_train, std::move(task_sizes_test), false, n_feat), _n_class_per_task(task_sizes_train.size(), 0), _n_class(0) _n_class(0), _curr_centroid(_n_feat,0.0) { for (auto& pt : _prop_test) { Loading Loading @@ -91,18 +92,18 @@ LossFunctionClustering::LossFunctionClustering(const std::shared_ptr<LossFunctio void LossFunctionClustering::init_mask(){ int length = _n_samp * _n_class; label_mask.resize(length); std::fill_n(label_mask.begin(), length, 0); _label_mask.resize(_n_samp * _n_class, 0.0); for (int i = 0; i < _n_class; i++) { // each cluster for (int j = 0; j < _n_samp; j++) { // each sample label_mask[i * _n_samp + j] = static_cast<int>(_prop_train[j]) == i; } //use daxpy now in lapack to do calculations for (int i = 0; i < _n_class; i++) { std::transform(_prop_train.begin(), _prop_train.end(), &_label_mask[i * _n_samp], [i](double prop){return static_cast<double>(static_cast<int>(prop) == i);} ); } } void LossFunctionClustering::set_nfeat(int n_feat) { _n_feat = n_feat; Loading @@ -113,6 +114,7 @@ void LossFunctionClustering::set_nfeat(int n_feat) return tot + nc * (nc - 1) / 2; }); _coefs.resize(n_class_combos * _n_dim, 0.0); } double LossFunctionClustering::operator()(const std::vector<int>& inds) { return 0.0; Loading Loading @@ -141,27 +143,17 @@ void LossFunctionClustering::populate_from_feats(const std::vector<model_node_pt std::vector<double> LossFunctionClustering::get_centroid(int cluster_label) { std::vector<double> centroid(_n_feat, 0.0); int n_samples_in_cluster = 0; int n = _n_feat; double alpha = 1.0; int inc = 1; for (size_t sample_idx = 0; sample_idx < _n_samp; sample_idx++) { if (!label_mask[cluster_label * _n_samp + sample_idx]) { continue; const double* mask = &_label_mask[cluster_label * _n_samp]; int n_samples_in_cluster = std::accumulate(mask, mask + _n_samp, 0.0); if (n_samples_in_cluster == 0){ return _curr_centroid; } daxpy_(&n, &alpha, &_a[sample_idx * _n_feat], &inc, centroid.data(), &inc); n_samples_in_cluster++; int inc_mask = 1; for (int ff = 0; ff < _n_feat; ++ff) { _curr_centroid[ff] = ddot_(&_n_samp, &_a[ff], &_n_feat, mask, &inc_mask); _curr_centroid[ff] /= n_samples_in_cluster; } if (n_samples_in_cluster > 0) { double scale = 1.0 / n_samples_in_cluster; dscal_(&n, &scale, centroid.data(), &inc); } return centroid; return _curr_centroid; } double LossFunctionClustering::test_loss(const std::vector<model_node_ptr>& feats) { Loading src/loss_function/LossFunctionClustering.hpp +2 −1 Original line number Diff line number Diff line Loading @@ -19,7 +19,8 @@ protected: std::vector<int> _n_class_per_task; //!< Number of classes in the property int _n_class; //!< Number of classes in the property std::vector<double> _a; //!< matrix to copy values from the D_Matrix std::vector<double> label_mask; //!< Label mask for prop train std::vector<double> _label_mask; //!< Label mask for prop train std::vector<double> _curr_centroid; //!< Stores the current calculated centroid; public: /** Loading src/loss_function/LossFunctionDaviesBouldin.cpp +33 −41 Original line number Diff line number Diff line Loading @@ -41,41 +41,33 @@ double LossFunctionDaviesBouldin::get_dbi() { double worst_spread_avg = 0.0; for (int key = 0; key < _n_class; key++) { int cluster_size = 0; for (int s = 0; s < _n_samp; s++) { int mask_idx = key * _n_samp + s; if (label_mask[mask_idx]) { cluster_size++; } } int cluster_size = std::accumulate(_label_mask.begin() + key * _n_samp, _label_mask.begin() + (key + 1) * _n_samp, 0); if (cluster_size == 0) { continue; } double curr_spread = cent_avg_dist(key); std::vector<double> c1 = get_centroid(key); double curr_spread = cent_avg_dist(key, c1); double highest_ratio = 0.0; for (int other_key = 0; other_key < _n_class; other_key++) { if (other_key == key) { continue; } int n_other = 0; for (int s = 0; s < _n_samp; s++) { int mask_idx = other_key * _n_samp +s; if (label_mask[mask_idx]) n_other++; } if (n_other == 0) { int n_other = std::accumulate(&_label_mask[other_key * _n_samp], &_label_mask[(other_key + 1) * _n_samp], 0); if (n_other == 0) { continue; } std::vector<double> c1 = get_centroid(key); std::vector<double> c2 = get_centroid(other_key); double dist = 0.0; for (int f = 0; f < _n_feat; f++) { double d = c1[f] - c2[f]; dist += d * d; } dist = std::sqrt(dist); double other_spread = cent_avg_dist(other_key); double dist = std::sqrt(std::inner_product( c1.begin(), c1.end(), c2.begin(), 0.0, std::plus<>(), [](double a, double b){ return (a - b) * (a - b); } )); double other_spread = cent_avg_dist(other_key, c2); if (dist > 0.0) { double ratio = (curr_spread + other_spread) / dist; highest_ratio = std::max(highest_ratio, ratio); Loading @@ -86,26 +78,26 @@ double LossFunctionDaviesBouldin::get_dbi() { return worst_spread_avg / static_cast<double>(_n_class); } double LossFunctionDaviesBouldin::cent_avg_dist(size_t cluster_label) { std::vector<double> centroid = get_centroid(cluster_label); std::vector<int> cluster_samples; for (int s = 0; s < _n_samp; s++) { int mask_idx = cluster_label * _n_samp + s; if (label_mask[mask_idx]) { cluster_samples.push_back(s); } } int n_samples = static_cast<int>(cluster_samples.size()); if (n_samples <= 1) return 0.0; double LossFunctionDaviesBouldin::cent_avg_dist(size_t cluster_label, std::vector<double> centroid) { int n_samples = std::accumulate( &_label_mask[cluster_label * _n_samp], &_label_mask[(cluster_label + 1) * _n_samp], 0 ); double avg = 0.0; for (int samp : cluster_samples) { const double* p = &_a[samp * _n_feat]; double dist_sq = 0.0; for (int f = 0; f < _n_feat; f++) { double d = p[f] - centroid[f]; dist_sq += d * d; for (int ii = 0; ii < _n_samp; ++ii) { if (_label_mask[cluster_label * _n_samp + ii] == 0) { continue; } avg += std::sqrt(dist_sq); avg += std::sqrt(std::inner_product( centroid.begin(), centroid.end(), &_a[ii * _n_feat], 0.0, std::plus<>(), [](double a, double b){ return (a - b) * (a - b); } )); } return avg / static_cast<double>(n_samples); } No newline at end of file src/loss_function/LossFunctionDaviesBouldin.hpp +1 −1 Original line number Diff line number Diff line Loading @@ -77,7 +77,7 @@ public: /** * @brief Average distance of how spread out a cluster is */ virtual double cent_avg_dist(size_t cluster_label); virtual double cent_avg_dist(size_t cluster_label, std::vector<double> centroid); }; Loading Loading
src/loss_function/LossFunctionCalinskiHarabasz.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -45,7 +45,7 @@ double LossFunctionCalinskiHarabasz::compute_w() { std::vector<double> centroid = get_centroid(cluster_label); for (size_t sample_idx = 0; sample_idx < _n_samp; sample_idx++) { int mask_idx = cluster_label * _n_samp + sample_idx; if (!label_mask[mask_idx]) continue; if (!_label_mask[mask_idx]) continue; const double* sample = &_a[sample_idx * _n_feat]; double dist2 = 0.0; for (int f = 0; f < _n_feat; ++f) { Loading Loading @@ -74,7 +74,7 @@ double LossFunctionCalinskiHarabasz::compute_b() { int n_k = 0; for (size_t sample_idx = 0; sample_idx < _n_samp; sample_idx++) { int mask_idx = cluster_label * _n_samp + sample_idx; if (label_mask[mask_idx]) { if (_label_mask[mask_idx]) { n_k++; } } Loading
src/loss_function/LossFunctionClustering.cpp +20 −28 Original line number Diff line number Diff line Loading @@ -13,7 +13,8 @@ LossFunctionClustering::LossFunctionClustering(std::vector<double> prop_train, int n_feat) : LossFunction(prop_train, prop_test, task_sizes_train, std::move(task_sizes_test), false, n_feat), _n_class_per_task(task_sizes_train.size(), 0), _n_class(0) _n_class(0), _curr_centroid(_n_feat,0.0) { for (auto& pt : _prop_test) { Loading Loading @@ -91,18 +92,18 @@ LossFunctionClustering::LossFunctionClustering(const std::shared_ptr<LossFunctio void LossFunctionClustering::init_mask(){ int length = _n_samp * _n_class; label_mask.resize(length); std::fill_n(label_mask.begin(), length, 0); _label_mask.resize(_n_samp * _n_class, 0.0); for (int i = 0; i < _n_class; i++) { // each cluster for (int j = 0; j < _n_samp; j++) { // each sample label_mask[i * _n_samp + j] = static_cast<int>(_prop_train[j]) == i; } //use daxpy now in lapack to do calculations for (int i = 0; i < _n_class; i++) { std::transform(_prop_train.begin(), _prop_train.end(), &_label_mask[i * _n_samp], [i](double prop){return static_cast<double>(static_cast<int>(prop) == i);} ); } } void LossFunctionClustering::set_nfeat(int n_feat) { _n_feat = n_feat; Loading @@ -113,6 +114,7 @@ void LossFunctionClustering::set_nfeat(int n_feat) return tot + nc * (nc - 1) / 2; }); _coefs.resize(n_class_combos * _n_dim, 0.0); } double LossFunctionClustering::operator()(const std::vector<int>& inds) { return 0.0; Loading Loading @@ -141,27 +143,17 @@ void LossFunctionClustering::populate_from_feats(const std::vector<model_node_pt std::vector<double> LossFunctionClustering::get_centroid(int cluster_label) { std::vector<double> centroid(_n_feat, 0.0); int n_samples_in_cluster = 0; int n = _n_feat; double alpha = 1.0; int inc = 1; for (size_t sample_idx = 0; sample_idx < _n_samp; sample_idx++) { if (!label_mask[cluster_label * _n_samp + sample_idx]) { continue; const double* mask = &_label_mask[cluster_label * _n_samp]; int n_samples_in_cluster = std::accumulate(mask, mask + _n_samp, 0.0); if (n_samples_in_cluster == 0){ return _curr_centroid; } daxpy_(&n, &alpha, &_a[sample_idx * _n_feat], &inc, centroid.data(), &inc); n_samples_in_cluster++; int inc_mask = 1; for (int ff = 0; ff < _n_feat; ++ff) { _curr_centroid[ff] = ddot_(&_n_samp, &_a[ff], &_n_feat, mask, &inc_mask); _curr_centroid[ff] /= n_samples_in_cluster; } if (n_samples_in_cluster > 0) { double scale = 1.0 / n_samples_in_cluster; dscal_(&n, &scale, centroid.data(), &inc); } return centroid; return _curr_centroid; } double LossFunctionClustering::test_loss(const std::vector<model_node_ptr>& feats) { Loading
src/loss_function/LossFunctionClustering.hpp +2 −1 Original line number Diff line number Diff line Loading @@ -19,7 +19,8 @@ protected: std::vector<int> _n_class_per_task; //!< Number of classes in the property int _n_class; //!< Number of classes in the property std::vector<double> _a; //!< matrix to copy values from the D_Matrix std::vector<double> label_mask; //!< Label mask for prop train std::vector<double> _label_mask; //!< Label mask for prop train std::vector<double> _curr_centroid; //!< Stores the current calculated centroid; public: /** Loading
src/loss_function/LossFunctionDaviesBouldin.cpp +33 −41 Original line number Diff line number Diff line Loading @@ -41,41 +41,33 @@ double LossFunctionDaviesBouldin::get_dbi() { double worst_spread_avg = 0.0; for (int key = 0; key < _n_class; key++) { int cluster_size = 0; for (int s = 0; s < _n_samp; s++) { int mask_idx = key * _n_samp + s; if (label_mask[mask_idx]) { cluster_size++; } } int cluster_size = std::accumulate(_label_mask.begin() + key * _n_samp, _label_mask.begin() + (key + 1) * _n_samp, 0); if (cluster_size == 0) { continue; } double curr_spread = cent_avg_dist(key); std::vector<double> c1 = get_centroid(key); double curr_spread = cent_avg_dist(key, c1); double highest_ratio = 0.0; for (int other_key = 0; other_key < _n_class; other_key++) { if (other_key == key) { continue; } int n_other = 0; for (int s = 0; s < _n_samp; s++) { int mask_idx = other_key * _n_samp +s; if (label_mask[mask_idx]) n_other++; } if (n_other == 0) { int n_other = std::accumulate(&_label_mask[other_key * _n_samp], &_label_mask[(other_key + 1) * _n_samp], 0); if (n_other == 0) { continue; } std::vector<double> c1 = get_centroid(key); std::vector<double> c2 = get_centroid(other_key); double dist = 0.0; for (int f = 0; f < _n_feat; f++) { double d = c1[f] - c2[f]; dist += d * d; } dist = std::sqrt(dist); double other_spread = cent_avg_dist(other_key); double dist = std::sqrt(std::inner_product( c1.begin(), c1.end(), c2.begin(), 0.0, std::plus<>(), [](double a, double b){ return (a - b) * (a - b); } )); double other_spread = cent_avg_dist(other_key, c2); if (dist > 0.0) { double ratio = (curr_spread + other_spread) / dist; highest_ratio = std::max(highest_ratio, ratio); Loading @@ -86,26 +78,26 @@ double LossFunctionDaviesBouldin::get_dbi() { return worst_spread_avg / static_cast<double>(_n_class); } double LossFunctionDaviesBouldin::cent_avg_dist(size_t cluster_label) { std::vector<double> centroid = get_centroid(cluster_label); std::vector<int> cluster_samples; for (int s = 0; s < _n_samp; s++) { int mask_idx = cluster_label * _n_samp + s; if (label_mask[mask_idx]) { cluster_samples.push_back(s); } } int n_samples = static_cast<int>(cluster_samples.size()); if (n_samples <= 1) return 0.0; double LossFunctionDaviesBouldin::cent_avg_dist(size_t cluster_label, std::vector<double> centroid) { int n_samples = std::accumulate( &_label_mask[cluster_label * _n_samp], &_label_mask[(cluster_label + 1) * _n_samp], 0 ); double avg = 0.0; for (int samp : cluster_samples) { const double* p = &_a[samp * _n_feat]; double dist_sq = 0.0; for (int f = 0; f < _n_feat; f++) { double d = p[f] - centroid[f]; dist_sq += d * d; for (int ii = 0; ii < _n_samp; ++ii) { if (_label_mask[cluster_label * _n_samp + ii] == 0) { continue; } avg += std::sqrt(dist_sq); avg += std::sqrt(std::inner_product( centroid.begin(), centroid.end(), &_a[ii * _n_feat], 0.0, std::plus<>(), [](double a, double b){ return (a - b) * (a - b); } )); } return avg / static_cast<double>(n_samples); } No newline at end of file
src/loss_function/LossFunctionDaviesBouldin.hpp +1 −1 Original line number Diff line number Diff line Loading @@ -77,7 +77,7 @@ public: /** * @brief Average distance of how spread out a cluster is */ virtual double cent_avg_dist(size_t cluster_label); virtual double cent_avg_dist(size_t cluster_label, std::vector<double> centroid); }; Loading