Commit ce0fbd2f authored by Joe Grimes's avatar Joe Grimes
Browse files

Test Loss for sil score and davies bouldin

parent c239dd15
Loading
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -23,9 +23,12 @@ LossFunctionCalinskiHarabasz::LossFunctionCalinskiHarabasz(const std::shared_ptr
}

double LossFunctionCalinskiHarabasz::test_loss(const std::vector<model_node_ptr>& feats) {
    init_mask("test");

    return (*this)(feats);
    //get the centroids first
    if (_label_mask.size() == 0){
        init_mask("train");
    }
    populate_from_feats(feats);
    //now get the goods
}


+1 −1
Original line number Diff line number Diff line
@@ -19,7 +19,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::vector<double> _label_mask; //!< Label mask for prop train
    std::vector<double> _label_mask; //!< Label mask for prop train or test
    std::vector<double> _curr_centroid; //!< Stores the current calculated centroid;
    std::vector<double> _other_centroid; //!< Stores data for another centroid to calculate euclidian distance
    std::vector<double> _ones; //!< Ones vector for ddot copying
+75 −1
Original line number Diff line number Diff line
@@ -34,10 +34,84 @@ double LossFunctionDaviesBouldin::operator()(const std::vector<model_node_ptr>&
}

double LossFunctionDaviesBouldin::test_loss(const std::vector<model_node_ptr>& feats) {
    if (_label_mask.size() == 0) {
        init_mask("train");
    }
    populate_from_feats(feats);

    std::vector<std::vector<double>> centroids(_n_class, std::vector<double>(_n_feat, 0.0));
    for (int cc = 0; cc < _n_class; ++cc) {
        const double* mask = &_label_mask[cc * _n_samp];
        int n_points = std::accumulate(mask, mask + _n_samp, 0.0);
        if (n_points == 0) continue;
        int inc_mask = 1;
        for (int f = 0; f < _n_feat; ++f) {
            centroids[cc][f] = ddot_(&_n_samp, &_a[f], &_n_feat, mask, &inc_mask);
            centroids[cc][f] /= n_points;
        }
    }
    //overwrite labelmask with test after calculating all the centroids
    init_mask("test");
    double dbi = 0.0;
    for (int key = 0; key < _n_class; key++) {
        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 = 0.0;
        for (int ii = 0; ii < _n_samp; ++ii) {
            if (_label_mask[key * _n_samp + ii] == 0) {
                continue;
            }
            curr_spread += std::sqrt(std::inner_product(
                centroids[key].begin(), centroids[key].end(), &_a[ii * _n_feat], 0.0,
                std::plus<>(),
                [](double a, double b){ return (a - b) * (a - b); }
                ));
        }
        curr_spread /= static_cast<double>(cluster_size);

    return (*this)(feats);
        double highest_ratio = 0.0;
        for (int other_key = 0; other_key < _n_class; other_key++) {
            if (other_key == key) {
                continue;
            }
            int n_other = std::accumulate(&_label_mask[other_key * _n_samp], &_label_mask[(other_key + 1) * _n_samp], 0);
            if (n_other == 0) {
                continue;
            }

            double dist = std::sqrt(std::inner_product(
                centroids[key].begin(), centroids[key].end(),
                centroids[other_key].begin(), 0.0,
                std::plus<>(),
                [](double a, double b){ return (a - b) * (a - b); }
                ));

            double other_spread = 0.0;
            for (int ii = 0; ii < _n_samp; ++ii) {
                if (_label_mask[other_key * _n_samp + ii] == 0) continue;
                other_spread += std::sqrt(std::inner_product(
                    centroids[other_key].begin(), centroids[other_key].end(), &_a[ii * _n_feat], 0.0,
                    std::plus<>(),
                    [](double a, double b){ return (a - b) * (a - b); }
                    ));
            }
            other_spread /= static_cast<double>(n_other);

            if (dist > 0.0) {
                double ratio = (curr_spread + other_spread) / dist;
                highest_ratio = std::max(highest_ratio, ratio);
            }
        }
        dbi += highest_ratio;
    }

    return dbi / static_cast<double>(_n_class);
}


double LossFunctionDaviesBouldin::get_dbi() {
    double worst_spread_avg = 0.0;
+43 −5
Original line number Diff line number Diff line
@@ -13,9 +13,10 @@ LossFunctionSilhouetteScore::LossFunctionSilhouetteScore(
    bool fix_intercept,
    int n_feat)
    : LossFunctionClustering(prop_train, prop_test, task_sizes_train, std::move(task_sizes_test), fix_intercept, n_feat),
      _silhouette_scores(_n_samp, 0),
      _euclidean_distance(_n_samp * _n_samp, 0.0),
      _ai_bi(_n_class, 0.0),
      _silhouette_scores(_n_samp, 0)
      _ai_bi(_n_class, 0.0)


{
}
@@ -45,13 +46,50 @@ double LossFunctionSilhouetteScore::operator()(const std::vector<model_node_ptr>
}

double LossFunctionSilhouetteScore::test_loss(const std::vector<model_node_ptr>& feats) {
    if (_label_mask.size() == 0) {
        init_mask("train");
    }
    std::vector<double> train_mask = _label_mask;
    populate_from_feats(feats);
    //store the centroids from prop_train, that will be used with prop_test
    std::vector<std::vector<double>> centroids(_n_class, std::vector<double>(_n_feat, 0.0));
    for (int cc = 0; cc < _n_class; ++cc) {
        const double* mask = &train_mask[cc * _n_samp];
        int n_points = std::accumulate(mask, mask + _n_samp, 0.0);
        if (n_points == 0) continue;
        int inc_mask = 1;
        for (int f = 0; f < _n_feat; ++f) {
            centroids[cc][f] = ddot_(&_n_samp, &_a[f], &_n_feat, mask, &inc_mask);
            centroids[cc][f] /= n_points;
        }
    }
    //init mask for test now
    init_mask("test");
    for (int s1 = 0; s1 < _n_samp; ++s1) {
        for (int cc = 0; cc < _n_class; ++cc) {
            _ai_bi[cc] = euclidean_distance(&_a[s1 * _n_feat], centroids[cc].data());
        }
        int own_cluster = -1;
        for (int cc = 0; cc < _n_class; ++cc) {
            if (_label_mask[cc * _n_samp + s1] == 1) {
                own_cluster = cc;
                break;
            }
        }
        if (own_cluster == -1) {
            own_cluster = 0;
        }
        double ai = _ai_bi[own_cluster];
        _ai_bi[own_cluster] = std::numeric_limits<double>::infinity();
        double bi = *std::min_element(_ai_bi.begin(), _ai_bi.end());
        _silhouette_scores[s1] = (bi - ai) / std::max(ai, bi);
    }
    return std::accumulate(_silhouette_scores.begin(), _silhouette_scores.end(), 0.0) /
           static_cast<double>(_silhouette_scores.size());
}



    return (*this)(feats);
}

double LossFunctionSilhouetteScore::euclidean_distance(const double* p1, const double* p2) {
    return std::sqrt(std::inner_product(
        p1,
+5 −1
Original line number Diff line number Diff line
@@ -92,6 +92,7 @@ protected:
        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(); }
@@ -173,7 +174,7 @@ TEST_F(LossFunctionDaviesBouldinTests, MultiClassTest)
    _model_phi.push_back(std::make_shared<ModelNode>(_phi[1]));

    _prop_train = {0,0,0, 1,1,1, 2,2,2, 3,3,3};
    _prop_test = _prop_train;
    _prop_test  = {0,1,0, 1,0,1, 2,3,2, 3,2,3};

    LossFunctionDaviesBouldin loss(
        _prop_train, _prop_test, _task_sizes_train, _task_sizes_test, false, 2);
@@ -181,5 +182,8 @@ TEST_F(LossFunctionDaviesBouldinTests, MultiClassTest)
    loss(_model_phi);
    double dbi_feats_mulitclass = loss.get_dbi();
    EXPECT_NEAR(dbi_feats_mulitclass, 0.06262969036057972, 0.0001);

    std::cout << "regular pipeline" << dbi_feats_mulitclass << std::endl;
    std::cout << "test_loss " << loss.test_loss(_model_phi) << std::endl;
}
}
 No newline at end of file
Loading