Commit 595c545a authored by Joe Grimes's avatar Joe Grimes
Browse files

Updated python script, multi class testing for sil scoring

parent 432d31ab
Loading
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -88,6 +88,7 @@ LossFunctionSilhouetteScore::LossFunctionSilhouetteScore(const std::shared_ptr<L

void LossFunctionSilhouetteScore::set_nfeat(int n_feat)
{
    _silhouette_scores.clear();
    _n_feat = n_feat;
    _a.resize(_n_feat * _n_samp);
    _n_dim = n_feat + 1;
@@ -145,7 +146,7 @@ double LossFunctionSilhouetteScore::calculate_a_i(size_t samp_idx, int cluster_l
    return sum / static_cast<double>(n_samples_in_cluster - 1);
}

// b_i for sample samp_idx: min average distance to other clusters

double LossFunctionSilhouetteScore::calculate_b_i(size_t sample_idx, int cluster_label) {
    const double* p1 = &_a[sample_idx * _n_feat];
    double best_avg = std::numeric_limits<double>::infinity();
@@ -174,7 +175,7 @@ void LossFunctionSilhouetteScore::populate_sil_score() {
    for (auto& [cluster_label, indices] : _cluster_indices) {
        // step by _n_feat to visit each sample once
        for (size_t i = 0; i < indices.size(); i += _n_feat) {
            size_t sample_idx = indices[i] / _n_feat;  // recover row/sample index
            size_t sample_idx = indices[i] / _n_feat;
            a_i = calculate_a_i(sample_idx, cluster_label);
            b_i = calculate_b_i(sample_idx, cluster_label);
            double s_i = 0.0;
@@ -210,6 +211,7 @@ double LossFunctionSilhouetteScore::test_loss(const std::vector<model_node_ptr>&
}

double LossFunctionSilhouetteScore::get_silhouette_average() {
    std::cout << std::endl;
    if (_silhouette_scores.empty()) return 0.0;
    return std::accumulate(_silhouette_scores.begin(), _silhouette_scores.end(), 0.0)
           / static_cast<double>(_silhouette_scores.size());
+21 −6
Original line number Diff line number Diff line
@@ -60,22 +60,37 @@ def run_feature_testing(train_feat1, train_feat2, cluster_labels):


if __name__ == "__main__":
    #Double cluster tests:
    labels = np.array([0, 0, 1, 1])
    if True:
    if False:
        #For feats ~0.466666666
        train_feat1 = np.array([4.0, 5.0, 6.0, 7.0])
        train_feat2 = np.array([2.0, 3.0, 4.0, 5.0])

        run_feature_testing(train_feat1, train_feat2, labels)

    if True:
    if False:
        #values ripped from d_matrix
        dat = np.array([
            [-1.86846, -1.9923, -1.95254, -1.56359],
            [-1.78104, -1.31323, -1.24359, -1.72509],
            [-1.06531, -1.47307, -1.01745, -1.10234],
            [-1.96543, -1.29881, -1.92731, -1.49548]
            [-1.86846, -1.9923],
            [-1.78104, -1.31323],
            [-1.06531, -1.47307],
            [-1.96543, -1.29881]
        ])

        score = silhouette_score(dat, labels)
        print("Silhouette score for inds:", score)
    if True:
        X = np.array([
            [1.0, 2.0], [1.2, 2.1], [0.8, 1.9],
            [5.0, 5.0], [5.1, 5.2], [4.9, 4.8],
            [9.0, 1.0], [9.1, 1.1], [8.9, 0.9],
            [2.0, 8.0], [2.1, 8.2], [1.9, 7.8]
        ])

        # Cluster labels
        labels = np.array([0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3])

        # Compute silhouette score
        sil_score = silhouette_score(X, labels)
        print("Silhouette Score:", sil_score)
 No newline at end of file
+34 −0
Original line number Diff line number Diff line
@@ -197,6 +197,40 @@ TEST_F(LossFunctionSilhouetteScoreTests, ManualDeterminationFeats)
    EXPECT_NEAR(silhouette_score,0.466666, 0.0001);
}

TEST_F(LossFunctionSilhouetteScoreTests, MultiClassTest)
{
    _task_sizes_train = {12};
    _task_sizes_test = {12};
    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,1.2,0.8, 5.0,5.1,4.9, 9.0,9.1,8.9, 2.0,2.1,1.9};
    std::vector<double> train_feat2 = {2.0,2.1,1.9, 5.0,5.2,4.8, 1.0,1.1,0.9, 8.0,8.2,7.8};

    std::vector<double> test_feat1 = train_feat1;
    std::vector<double> test_feat2 = train_feat2;

    _phi.clear();
    _model_phi.clear();

    _phi.push_back(std::make_shared<FeatureNode>(0, "Feature1", train_feat1, test_feat1, Unit("m")));
    _phi.push_back(std::make_shared<FeatureNode>(1, "Feature2", train_feat2, test_feat2, Unit("m")));

    _model_phi.push_back(std::make_shared<ModelNode>(_phi[0]));
    _model_phi.push_back(std::make_shared<ModelNode>(_phi[1]));

    // 4 classes
    _prop_train = {0,0,0, 1,1,1, 2,2,2, 3,3,3};
    _prop_test = _prop_train;

    LossFunctionSilhouetteScore loss(
        _prop_train, _prop_test, _task_sizes_train, _task_sizes_test, false, 2);

    double silhouette_score = loss(_model_phi);

    EXPECT_NEAR(silhouette_score, 0.941, 0.001);
}

}