diff --git a/data b/data index 5e34dcd6f20..56f6da41c92 160000 --- a/data +++ b/data @@ -1 +1 @@ -Subproject commit 5e34dcd6f2037a59c682bf5628c12e2d06060019 +Subproject commit 56f6da41c92ec82bc9461f53cacb9b614ca9d42a diff --git a/examples/meta/src/binary/linear_discriminant_analysis.sg b/examples/meta/src/binary/linear_discriminant_analysis.sg index 03af85ebeab..9f40cea2de3 100644 --- a/examples/meta/src/binary/linear_discriminant_analysis.sg +++ b/examples/meta/src/binary/linear_discriminant_analysis.sg @@ -1,13 +1,13 @@ -CSVFile f_feats_train("../../data/classifier_binary_2d_linear_features_train.dat") -CSVFile f_feats_test("../../data/classifier_binary_2d_linear_features_test.dat") -CSVFile f_labels_train("../../data/classifier_binary_2d_linear_labels_train.dat") -CSVFile f_labels_test("../../data/classifier_binary_2d_linear_labels_test.dat") +File f_feats_train = csv_file("../../data/classifier_binary_2d_linear_features_train.dat") +File f_feats_test = csv_file("../../data/classifier_binary_2d_linear_features_test.dat") +File f_labels_train = csv_file("../../data/classifier_binary_2d_linear_labels_train.dat") +File f_labels_test = csv_file("../../data/classifier_binary_2d_linear_labels_test.dat") #![create_features] Features features_train = features(f_feats_train) Features features_test = features(f_feats_test) -BinaryLabels labels_train(f_labels_train) -BinaryLabels labels_test(f_labels_test) +Labels labels_train = labels(f_labels_train) +Labels labels_test = labels(f_labels_test) #![create_features] #![create_instance] @@ -16,17 +16,15 @@ Machine lda = machine("LDA", labels=labels_train) #![train_and_apply] lda.train(features_train) -BinaryLabels labels_predict = lda.apply_binary(features_test) +Labels labels_predict = lda.apply(features_test) +RealVector labels = labels_predict.get_real_vector("labels") #![train_and_apply] #![extract_weights] -RealVector w = lda.get_real_vector("w") +RealVector weights = lda.get_real_vector("w") #![extract_weights] #![evaluate_accuracy] -AccuracyMeasure eval() +Evaluation eval = evaluation("AccuracyMeasure") real accuracy = eval.evaluate(labels_predict, labels_test) #![evaluate_accuracy] - -#additional integration testing variables -RealVector output = labels_predict.get_labels() diff --git a/src/shogun/classifier/LDA.cpp b/src/shogun/classifier/LDA.cpp index 71008896a23..0cc8842d8c2 100644 --- a/src/shogun/classifier/LDA.cpp +++ b/src/shogun/classifier/LDA.cpp @@ -49,9 +49,7 @@ void CLDA::init() SG_ADD( (machine_int_t*)&m_method, "m_method", "Method used for LDA calculation", MS_NOT_AVAILABLE); - SG_ADD( - (machine_int_t*)&m_gamma, "m_gamma", "Regularization parameter", - MS_NOT_AVAILABLE); + SG_ADD(&m_gamma, "m_gamma", "Regularization parameter", MS_AVAILABLE); SG_ADD(&m_bdc_svd, "m_bdc_svd", "Use BDC-SVD algorithm", MS_NOT_AVAILABLE); } @@ -62,10 +60,6 @@ CLDA::~CLDA() bool CLDA::train_machine(CFeatures *data) { REQUIRE(m_labels, "Labels for the given features are not specified!\n") - REQUIRE( - m_labels->get_label_type() == LT_BINARY, - "The labels should of type CBinaryLabels! Provided type is %s \n", - m_labels->get_name()) if(data) { @@ -78,12 +72,6 @@ bool CLDA::train_machine(CFeatures *data) REQUIRE(data, "Features have not been provided.\n") } - REQUIRE( - features->get_num_vectors() == m_labels->get_num_labels(), - "Number of training examples(%d) should be equal to number of labels " - "(%d)!\n", - features->get_num_vectors(), m_labels->get_num_labels()); - REQUIRE( features->get_feature_class() == C_DENSE, "LDA only works with dense features") @@ -117,14 +105,16 @@ template bool CLDA::solver_svd() { auto dense_feat = static_cast*>(features); + auto labels = multiclass_labels(m_labels); + REQUIRE( + labels->get_num_classes() == 2, "Number of classes (%d) must be 2\n", + labels->get_num_classes()) // keep just one dimension to do binary classification const index_t projection_dim = 1; auto solver = std::unique_ptr>( new LDACanVarSolver( - dense_feat, - new CMulticlassLabels(static_cast(m_labels)), - projection_dim, m_gamma, m_bdc_svd)); + dense_feat, labels, projection_dim, m_gamma, m_bdc_svd)); SGVector w_st(solver->get_eigenvectors()); @@ -150,13 +140,14 @@ template bool CLDA::solver_classic() { auto dense_feat = static_cast*>(features); + auto labels = multiclass_labels(m_labels); + REQUIRE( + labels->get_num_classes() == 2, "Number of classes (%d) must be 2\n", + labels->get_num_classes()) index_t num_feat = dense_feat->get_num_features(); auto solver = std::unique_ptr>( - new LDASolver( - dense_feat, - new CMulticlassLabels(static_cast(m_labels)), - m_gamma)); + new LDASolver(dense_feat, labels, m_gamma)); auto class_mean = solver->get_class_mean(); auto class_count = solver->get_class_count(); diff --git a/src/shogun/labels/MulticlassLabels.cpp b/src/shogun/labels/MulticlassLabels.cpp index c268b37d261..29fb932f7d2 100644 --- a/src/shogun/labels/MulticlassLabels.cpp +++ b/src/shogun/labels/MulticlassLabels.cpp @@ -235,6 +235,8 @@ namespace shogun orig->as()); case LT_DENSE_GENERIC: return to_multiclass(orig->as()); + case LT_BINARY: + return to_multiclass(orig->as()); default: SG_SNOTIMPLEMENTED } diff --git a/tests/unit/classifier/LDA_unittest.cc b/tests/unit/classifier/LDA_unittest.cc index 428cec62b19..9b506cee3c7 100644 --- a/tests/unit/classifier/LDA_unittest.cc +++ b/tests/unit/classifier/LDA_unittest.cc @@ -96,63 +96,23 @@ typedef ::testing::Types FloatTypes; TYPED_TEST_CASE(LDATest, FloatTypes); template -void FLD_test(SGVector &projection_FLD, SGVector &w_FLD) +void test_with_method( + SGVector& projection, SGVector& w, ELDAMethod method) { SGVector lab; SGMatrix feat; - CBinaryLabels* labels; - CDenseFeatures* features; - generate_test_data(lab, feat); - labels = new CBinaryLabels(lab); - features = new CDenseFeatures(feat); - - SG_REF(labels); - SG_REF(features); - - CLDA lda_FLD(0, features, labels, FLD_LDA); - lda_FLD.train(); + auto features = some>(feat); + auto labels = some(lab); - CRegressionLabels* results_FLD=(lda_FLD.apply_regression(features)); - SG_REF(results_FLD); - projection_FLD=results_FLD->get_labels(); - w_FLD = lda_FLD.get_w(); - SG_UNREF(results_FLD); + auto lda = some(0, features, labels, method); + lda->train(); - SG_UNREF(features); - SG_UNREF(labels); -} - -template -void SVD_test(SGVector &projection_SVD, SGVector &w_SVD) -{ - SGVector lab; - SGMatrix feat; - - CBinaryLabels* labels; - CDenseFeatures* features; - - generate_test_data(lab, feat); - - labels = new CBinaryLabels(lab); - features = new CDenseFeatures(feat); - - SG_REF(labels); - SG_REF(features); - - CLDA lda_SVD(0, features, labels, SVD_LDA); - lda_SVD.train(); - - CRegressionLabels* results_SVD=lda_SVD.apply_regression(features); - SG_REF(results_SVD); - projection_SVD=results_SVD->get_labels(); - w_SVD=lda_SVD.get_w(); - SG_UNREF(results_SVD); - - SG_UNREF(features); - SG_UNREF(labels); + auto results = lda->apply_regression(features); + projection = results->get_labels(); + w = lda->get_w(); } template @@ -161,7 +121,7 @@ void check_eigenvectors_fld() SGVector projection_FLD; SGVector w_FLD; - FLD_test(projection_FLD, w_FLD); + test_with_method(projection_FLD, w_FLD, FLD_LDA); // normalize 'w' since the magnitude is irrelevant w_FLD = linalg::scale(w_FLD, 1.0 / linalg::norm(w_FLD)); @@ -179,7 +139,7 @@ TEST(LDA, DISABLED_CheckProjection_FLD) SGVector projection_FLD; SGVector w_FLD; - FLD_test(projection_FLD, w_FLD); + test_with_method(projection_FLD, w_FLD, FLD_LDA); // No need of checking the binary labels if the following passes. float64_t epsilon=0.00000001; @@ -201,7 +161,7 @@ void check_eigenvectors_svd() SGVector projection_SVD; SGVector w_SVD; - SVD_test(projection_SVD, w_SVD); + test_with_method(projection_SVD, w_SVD, SVD_LDA); // comparing against the eigenvectors of the CanonVar implementation // in the brml toolbox, MATLAB. @@ -216,7 +176,7 @@ TEST(LDA, DISABLED_CheckProjection_SVD) SGVector projection_SVD; SGVector w_SVD; - FLD_test(projection_SVD, w_SVD); + test_with_method(projection_SVD, w_SVD, FLD_LDA); //comparing agianst the projections from the CanonVar implementation //in the brml toolbox, MATLAB. @@ -233,6 +193,20 @@ TEST(LDA, DISABLED_CheckProjection_SVD) EXPECT_NEAR(+7.96084156, projection_SVD[9], epsilon); } +// label type exception test +TEST(LDA, num_classes_in_labels_exception) +{ + SGVector lab{1, -1, 2}; + SGMatrix feat(1, 3); + auto labels = some(); + labels->set_labels(lab); + auto features = some>(feat); + auto lda = some(0, features, labels, SVD_LDA); + // should throw an incorrect number of classes exception (expected value is + // 2) + EXPECT_THROW(lda->train(), ShogunException); +} + //FLD template testing TYPED_TEST(LDATest, check_eigenvectors_fld) {