Loading src/loss_function/LossFunctionSilhouetteScore.cpp +57 −100 Original line number Diff line number Diff line Loading @@ -101,55 +101,40 @@ void LossFunctionSilhouetteScore::set_nfeat(int n_feat) } double LossFunctionSilhouetteScore::operator()(const std::vector<int>& inds) { for (int ii = 0; ii < inds.size(); ++ii) { std::copy_n( node_value_arrs::get_d_matrix_ptr(inds[ii]), _n_samp, _a.data() + ii * _n_samp ); //store the double*, double in the centroid map centroid_map[node_value_arrs::get_d_matrix_ptr(inds[ii])] = compute_centroid(node_value_arrs::get_d_matrix_ptr(ii), _n_samp); silhouette_scores.clear(); for (int i = 0; i < inds.size(); i++){ //grab the svm values double* res = node_value_arrs::get_d_matrix_ptr(i); //assuming prop train will match with the svm list for (int j = 0; j < _prop_train.size(); j++ ) { int target_idx = _prop_train[j]; double curr_pt = res[j]; if (centroid_map.find(target_idx) == centroid_map.end()) { centroid_map[target_idx].push_back(curr_pt); centroid_map[target_idx].push_back(1); } calculate_centroid_differences(_prop_train); return get_silhouette_average(); else { centroid_map[target_idx][0] += curr_pt; centroid_map[target_idx][1] += 1; } } } calculate_centroid_differences(); double res = get_silhouette_average(); return res; } double LossFunctionSilhouetteScore::operator()(const std::vector<model_node_ptr>& feats) { silhouette_scores.clear(); get_all_centroids(feats); calculate_centroid_differences(_prop_train); return get_silhouette_average(); //this should be moved to the classifier //int start = 0, start_test = 0, start_coefs = 0; // for (size_t tt = 0; tt < _task_sizes_train.size(); ++tt) // { // std::vector<double*> node_val_ptrs(_n_feat); // std::vector<double*> node_test_val_ptrs(_n_feat); // // for (int dd = 0; dd < _n_feat; ++dd) // { // node_val_ptrs[dd] = feats[dd]->value_ptr() + start; // node_test_val_ptrs[dd] = feats[dd]->test_value_ptr() + start_test; // } // // _svm[tt]->train(node_val_ptrs); // // const auto& coefs = _svm[tt]->coefs(); // for (size_t cc = 0; cc < coefs.size(); ++cc) // { // std::copy_n(coefs[cc].data(), coefs[cc].size(), &_coefs[start_coefs * _n_dim]); // _coefs[start_coefs * _n_dim + _n_feat] = _svm[tt]->intercept()[cc]; // ++start_coefs; // } // // std::copy_n(_svm[tt]->y_estimate().begin(), _task_sizes_train[tt], _prop_train_est.begin() + start); // std::copy_n(_svm[tt]->predict(_task_sizes_test[tt], node_test_val_ptrs).begin(), // _task_sizes_test[tt], // _prop_test_est.begin() + start_test); // // start += _task_sizes_train[tt]; // start_test += _task_sizes_test[tt]; calculate_centroid_differences(); double res = get_silhouette_average(); return res; } double LossFunctionSilhouetteScore::test_loss(const std::vector<model_node_ptr>& feats) { Loading @@ -160,38 +145,42 @@ double LossFunctionSilhouetteScore::test_loss(const std::vector<model_node_ptr>& //Afterwards we can re-iterate and calculate the differences to grab the silhouettescore void LossFunctionSilhouetteScore::get_all_centroids(const std::vector<model_node_ptr>& feats) { for (model_node_ptr model : feats) { //Map the pointer centroid_map[model->svm_value_ptr()] = compute_centroid(model->svm_value_ptr(), model->svm_value().size()); for (int i = 0; i < feats.size(); i++){ model_node_ptr feat = feats[i]; auto values = feat->svm_value(); for (int j = 0; j < values.size(); j++){ int target_idx = _prop_train[j]; double curr_pt = values[j]; //key does not yet exist if (centroid_map.find(target_idx) == centroid_map.end()){ centroid_map[target_idx].push_back(curr_pt); centroid_map[target_idx].push_back(1); } else{ centroid_map[target_idx][0] += curr_pt; centroid_map[target_idx][1] += 1; } } } //now average all values for (auto& [idx, vec] : centroid_map) { vec[0] = vec[0] / vec[1]; } } void LossFunctionSilhouetteScore::calculate_centroid_differences(std::vector<double> input_values) { populate_centroid_points(input_values); for (int i = 0; i < input_values.size(); i++) void LossFunctionSilhouetteScore::calculate_centroid_differences() { double min = std::numeric_limits<double>::max(); for (const auto& pair : centroid_map) { double centroid_value = pair.second; //Find the closest centroid //abs(b-a)/max(a,b) double curr_diff = std::abs(input_values[i] - centroid_value)/(std::max(input_values[i], centroid_value)); if (curr_diff < min) { min = curr_diff; //the differences should be the value of each centroid avg minus the others for (auto& [idx, vec] : centroid_map){ double curr_avg = vec[0]; for (auto& [comp_idx, comp_vec] : centroid_map){ if (comp_idx > idx){ double comp_avg = centroid_map[comp_idx][0]; silhouette_scores.push_back(std::abs(curr_avg-comp_avg)/std::max(curr_avg, comp_avg)); } } silhouette_scores.push_back(min); } // for (int i = 0; i < input_values.size(); i++){ // double curr_val = input_values[i]; // for (const auto& pair : centroid_map){ // // } // } } double LossFunctionSilhouetteScore::get_silhouette_average() { Loading @@ -199,35 +188,3 @@ double LossFunctionSilhouetteScore::get_silhouette_average() { return std::accumulate(silhouette_scores.begin(), silhouette_scores.end(), 0.0) / static_cast<double>(silhouette_scores.size()); } No newline at end of file double LossFunctionSilhouetteScore::compute_centroid(double* data, int len){ return std::accumulate(data, data+len, 0.0) / static_cast<double>(len); } void LossFunctionSilhouetteScore::populate_centroid_points(const std::vector<double> input_data) { centroid_points.clear(); for (int i = 0; i < input_data.size(); i++) { double min_dist = std::numeric_limits<double>::max(); double closest_centroid = 0.0; for (const auto& pair : centroid_map) { double centroid = pair.second; double dist = std::abs(centroid - input_data[i]); if (dist < min_dist) { min_dist = dist; closest_centroid = centroid; } } centroid_points[closest_centroid].push_back(input_data[i]); } // for (const auto& pair : centroid_points) { // std::cout << "---------------------------------------" << std::endl; // std::cout << "centroid value: " << pair.first << std::endl; // std::cout << "vector of closest points: "; // for (double val : pair.second) { // std::cout << val << " "; // } // std::cout << std::endl; // std::cout << "---------------------------------------" << std::endl; // } } src/loss_function/LossFunctionSilhouetteScore.hpp +2 −5 Original line number Diff line number Diff line Loading @@ -21,8 +21,7 @@ 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::map<double*, double> centroid_map; std::map<double, std::vector<double>> centroid_points; std::map<long, std::vector<double>> centroid_map; public: /** Loading Loading @@ -93,14 +92,12 @@ public: virtual double get_silhouette_average(); virtual void calculate_centroid_differences(std::vector<double> input_values); virtual void calculate_centroid_differences(); std::vector<double> get_silhouette_scores(){ return silhouette_scores; } void populate_centroid_points(std::vector<double> input_data); }; Loading tests/googletest/loss_function/test_silhouette_score_loss.cc +2 −12 Original line number Diff line number Diff line Loading @@ -101,10 +101,12 @@ protected: std::fill_n(_prop_train.begin() + 40, 20, 2.0); std::fill_n(_prop_train.begin() + 60, 20, 3.0); _prop_test.resize(_task_sizes_test[0], 0.0); std::fill_n(_prop_test.begin() + 5, 5, 1.0); std::fill_n(_prop_test.begin() + 10, 5, 2.0); std::fill_n(_prop_test.begin() + 15, 5, 3.0); } void TearDown() override { node_value_arrs::finalize_values_arr(); } Loading Loading @@ -155,15 +157,9 @@ TEST_F(LossFunctionSilhouetteScoreTests, ManualDetermination) _task_sizes_test = {4}; node_value_arrs::finalize_values_arr(); node_value_arrs::initialize_values_arr(_task_sizes_train, _task_sizes_test, 2, 2, false); // std::vector<double> train_feat1 = {1.0, 2.0, 3.0, 4.0}; //normalized scored //0, 0.333, 0.6666, 1 //centroid should be about 1.99999 / 4 = 0.5 std::vector<double> train_feat2 = {3.0, 5.0, 7.0, 10.0}; //0, 0.28,0.57,1 //centroid should be ~0.46 std::vector<double> test_feat1 = train_feat1; std::vector<double> test_feat2 = train_feat2; Loading @@ -180,9 +176,6 @@ TEST_F(LossFunctionSilhouetteScoreTests, ManualDetermination) _model_phi.push_back(std::make_shared<ModelNode>(_phi[1])); _prop_train = {0.0, 0.0, 1.0, 1.0}; // abs(0-.46)/max(0,.46) = .46/.46 = 1 // abs(1-.5)/max(1,.5) = .5/1 = .5 //sil score values should be 1,1,.5.5 = 3/4 = 0.75 _prop_test = _prop_train; _task_sizes_train = {4}; Loading @@ -191,10 +184,7 @@ TEST_F(LossFunctionSilhouetteScoreTests, ManualDetermination) LossFunctionSilhouetteScore loss( _prop_train, _prop_test, _task_sizes_train, _task_sizes_test, false, 2); double silhouette_score = loss(_model_phi); std::cout << "Here is the score " << silhouette_score << std::endl; EXPECT_EQ(silhouette_score,0.75); } Loading Loading
src/loss_function/LossFunctionSilhouetteScore.cpp +57 −100 Original line number Diff line number Diff line Loading @@ -101,55 +101,40 @@ void LossFunctionSilhouetteScore::set_nfeat(int n_feat) } double LossFunctionSilhouetteScore::operator()(const std::vector<int>& inds) { for (int ii = 0; ii < inds.size(); ++ii) { std::copy_n( node_value_arrs::get_d_matrix_ptr(inds[ii]), _n_samp, _a.data() + ii * _n_samp ); //store the double*, double in the centroid map centroid_map[node_value_arrs::get_d_matrix_ptr(inds[ii])] = compute_centroid(node_value_arrs::get_d_matrix_ptr(ii), _n_samp); silhouette_scores.clear(); for (int i = 0; i < inds.size(); i++){ //grab the svm values double* res = node_value_arrs::get_d_matrix_ptr(i); //assuming prop train will match with the svm list for (int j = 0; j < _prop_train.size(); j++ ) { int target_idx = _prop_train[j]; double curr_pt = res[j]; if (centroid_map.find(target_idx) == centroid_map.end()) { centroid_map[target_idx].push_back(curr_pt); centroid_map[target_idx].push_back(1); } calculate_centroid_differences(_prop_train); return get_silhouette_average(); else { centroid_map[target_idx][0] += curr_pt; centroid_map[target_idx][1] += 1; } } } calculate_centroid_differences(); double res = get_silhouette_average(); return res; } double LossFunctionSilhouetteScore::operator()(const std::vector<model_node_ptr>& feats) { silhouette_scores.clear(); get_all_centroids(feats); calculate_centroid_differences(_prop_train); return get_silhouette_average(); //this should be moved to the classifier //int start = 0, start_test = 0, start_coefs = 0; // for (size_t tt = 0; tt < _task_sizes_train.size(); ++tt) // { // std::vector<double*> node_val_ptrs(_n_feat); // std::vector<double*> node_test_val_ptrs(_n_feat); // // for (int dd = 0; dd < _n_feat; ++dd) // { // node_val_ptrs[dd] = feats[dd]->value_ptr() + start; // node_test_val_ptrs[dd] = feats[dd]->test_value_ptr() + start_test; // } // // _svm[tt]->train(node_val_ptrs); // // const auto& coefs = _svm[tt]->coefs(); // for (size_t cc = 0; cc < coefs.size(); ++cc) // { // std::copy_n(coefs[cc].data(), coefs[cc].size(), &_coefs[start_coefs * _n_dim]); // _coefs[start_coefs * _n_dim + _n_feat] = _svm[tt]->intercept()[cc]; // ++start_coefs; // } // // std::copy_n(_svm[tt]->y_estimate().begin(), _task_sizes_train[tt], _prop_train_est.begin() + start); // std::copy_n(_svm[tt]->predict(_task_sizes_test[tt], node_test_val_ptrs).begin(), // _task_sizes_test[tt], // _prop_test_est.begin() + start_test); // // start += _task_sizes_train[tt]; // start_test += _task_sizes_test[tt]; calculate_centroid_differences(); double res = get_silhouette_average(); return res; } double LossFunctionSilhouetteScore::test_loss(const std::vector<model_node_ptr>& feats) { Loading @@ -160,38 +145,42 @@ double LossFunctionSilhouetteScore::test_loss(const std::vector<model_node_ptr>& //Afterwards we can re-iterate and calculate the differences to grab the silhouettescore void LossFunctionSilhouetteScore::get_all_centroids(const std::vector<model_node_ptr>& feats) { for (model_node_ptr model : feats) { //Map the pointer centroid_map[model->svm_value_ptr()] = compute_centroid(model->svm_value_ptr(), model->svm_value().size()); for (int i = 0; i < feats.size(); i++){ model_node_ptr feat = feats[i]; auto values = feat->svm_value(); for (int j = 0; j < values.size(); j++){ int target_idx = _prop_train[j]; double curr_pt = values[j]; //key does not yet exist if (centroid_map.find(target_idx) == centroid_map.end()){ centroid_map[target_idx].push_back(curr_pt); centroid_map[target_idx].push_back(1); } else{ centroid_map[target_idx][0] += curr_pt; centroid_map[target_idx][1] += 1; } } } //now average all values for (auto& [idx, vec] : centroid_map) { vec[0] = vec[0] / vec[1]; } } void LossFunctionSilhouetteScore::calculate_centroid_differences(std::vector<double> input_values) { populate_centroid_points(input_values); for (int i = 0; i < input_values.size(); i++) void LossFunctionSilhouetteScore::calculate_centroid_differences() { double min = std::numeric_limits<double>::max(); for (const auto& pair : centroid_map) { double centroid_value = pair.second; //Find the closest centroid //abs(b-a)/max(a,b) double curr_diff = std::abs(input_values[i] - centroid_value)/(std::max(input_values[i], centroid_value)); if (curr_diff < min) { min = curr_diff; //the differences should be the value of each centroid avg minus the others for (auto& [idx, vec] : centroid_map){ double curr_avg = vec[0]; for (auto& [comp_idx, comp_vec] : centroid_map){ if (comp_idx > idx){ double comp_avg = centroid_map[comp_idx][0]; silhouette_scores.push_back(std::abs(curr_avg-comp_avg)/std::max(curr_avg, comp_avg)); } } silhouette_scores.push_back(min); } // for (int i = 0; i < input_values.size(); i++){ // double curr_val = input_values[i]; // for (const auto& pair : centroid_map){ // // } // } } double LossFunctionSilhouetteScore::get_silhouette_average() { Loading @@ -199,35 +188,3 @@ double LossFunctionSilhouetteScore::get_silhouette_average() { return std::accumulate(silhouette_scores.begin(), silhouette_scores.end(), 0.0) / static_cast<double>(silhouette_scores.size()); } No newline at end of file double LossFunctionSilhouetteScore::compute_centroid(double* data, int len){ return std::accumulate(data, data+len, 0.0) / static_cast<double>(len); } void LossFunctionSilhouetteScore::populate_centroid_points(const std::vector<double> input_data) { centroid_points.clear(); for (int i = 0; i < input_data.size(); i++) { double min_dist = std::numeric_limits<double>::max(); double closest_centroid = 0.0; for (const auto& pair : centroid_map) { double centroid = pair.second; double dist = std::abs(centroid - input_data[i]); if (dist < min_dist) { min_dist = dist; closest_centroid = centroid; } } centroid_points[closest_centroid].push_back(input_data[i]); } // for (const auto& pair : centroid_points) { // std::cout << "---------------------------------------" << std::endl; // std::cout << "centroid value: " << pair.first << std::endl; // std::cout << "vector of closest points: "; // for (double val : pair.second) { // std::cout << val << " "; // } // std::cout << std::endl; // std::cout << "---------------------------------------" << std::endl; // } }
src/loss_function/LossFunctionSilhouetteScore.hpp +2 −5 Original line number Diff line number Diff line Loading @@ -21,8 +21,7 @@ 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::map<double*, double> centroid_map; std::map<double, std::vector<double>> centroid_points; std::map<long, std::vector<double>> centroid_map; public: /** Loading Loading @@ -93,14 +92,12 @@ public: virtual double get_silhouette_average(); virtual void calculate_centroid_differences(std::vector<double> input_values); virtual void calculate_centroid_differences(); std::vector<double> get_silhouette_scores(){ return silhouette_scores; } void populate_centroid_points(std::vector<double> input_data); }; Loading
tests/googletest/loss_function/test_silhouette_score_loss.cc +2 −12 Original line number Diff line number Diff line Loading @@ -101,10 +101,12 @@ protected: std::fill_n(_prop_train.begin() + 40, 20, 2.0); std::fill_n(_prop_train.begin() + 60, 20, 3.0); _prop_test.resize(_task_sizes_test[0], 0.0); std::fill_n(_prop_test.begin() + 5, 5, 1.0); std::fill_n(_prop_test.begin() + 10, 5, 2.0); std::fill_n(_prop_test.begin() + 15, 5, 3.0); } void TearDown() override { node_value_arrs::finalize_values_arr(); } Loading Loading @@ -155,15 +157,9 @@ TEST_F(LossFunctionSilhouetteScoreTests, ManualDetermination) _task_sizes_test = {4}; node_value_arrs::finalize_values_arr(); node_value_arrs::initialize_values_arr(_task_sizes_train, _task_sizes_test, 2, 2, false); // std::vector<double> train_feat1 = {1.0, 2.0, 3.0, 4.0}; //normalized scored //0, 0.333, 0.6666, 1 //centroid should be about 1.99999 / 4 = 0.5 std::vector<double> train_feat2 = {3.0, 5.0, 7.0, 10.0}; //0, 0.28,0.57,1 //centroid should be ~0.46 std::vector<double> test_feat1 = train_feat1; std::vector<double> test_feat2 = train_feat2; Loading @@ -180,9 +176,6 @@ TEST_F(LossFunctionSilhouetteScoreTests, ManualDetermination) _model_phi.push_back(std::make_shared<ModelNode>(_phi[1])); _prop_train = {0.0, 0.0, 1.0, 1.0}; // abs(0-.46)/max(0,.46) = .46/.46 = 1 // abs(1-.5)/max(1,.5) = .5/1 = .5 //sil score values should be 1,1,.5.5 = 3/4 = 0.75 _prop_test = _prop_train; _task_sizes_train = {4}; Loading @@ -191,10 +184,7 @@ TEST_F(LossFunctionSilhouetteScoreTests, ManualDetermination) LossFunctionSilhouetteScore loss( _prop_train, _prop_test, _task_sizes_train, _task_sizes_test, false, 2); double silhouette_score = loss(_model_phi); std::cout << "Here is the score " << silhouette_score << std::endl; EXPECT_EQ(silhouette_score,0.75); } Loading