Commit 0ae73fca authored by Joe Grimes's avatar Joe Grimes
Browse files

Tinkering with clustering

parent 33873966
Loading
Loading
Loading
Loading
Loading
+57 −100
Original line number Diff line number Diff line
@@ -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) {
@@ -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() {
@@ -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;
//    }
}
+2 −5
Original line number Diff line number Diff line
@@ -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:
    /**
@@ -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);


};

+2 −12
Original line number Diff line number Diff line
@@ -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(); }
@@ -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;
@@ -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};
@@ -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);
}