Example #1
0
def _entropy_scores(cm):
    """Given a ClusteringMetrics object, calculate three entropy-based metrics

    (Alternative implementation for testing)
    """
    H_C = fentropy(cm.row_totals)
    H_K = fentropy(cm.col_totals)
    H_CK = sum(fentropy(col) for col in cm.iter_cols())
    H_KC = sum(fentropy(row) for row in cm.iter_rows())
    # The '<=' comparisons below both prevent division by zero errors
    # and ensure that the scores are non-negative.
    homogeneity = 0.0 if H_C <= H_CK else (H_C - H_CK) / H_C
    completeness = 0.0 if H_K <= H_KC else (H_K - H_KC) / H_K
    nmi_score = harmonic_mean(homogeneity, completeness)
    return homogeneity, completeness, nmi_score
Example #2
0
def test_2x2_invariants():
    """Alternative implementations should coincide for 2x2 matrices
    """

    for _ in xrange(100):
        cm = ConfusionMatrix2.from_random_counts(low=0, high=10)

        # object idempotency
        assert_equal(
            cm.to_ccw(),
            ConfusionMatrix2.from_ccw(*cm.to_ccw()).to_ccw(),
            msg="must be able to convert to tuple and create from tuple")

        # pairwise H, C, V
        h, c, v = cm.pairwise_hcv()[:3]
        check_with_nans(v, geometric_mean(h, c), ensure_nans=False)

        # informedness
        actual_info = cm.informedness()
        expected_info_1 = cm.TPR() + cm.TNR() - 1.0
        expected_info_2 = cm.TPR() - cm.FPR()
        check_with_nans(actual_info, expected_info_1, 4, ensure_nans=False)
        check_with_nans(actual_info, expected_info_2, 4, ensure_nans=False)

        # markedness
        actual_mark = cm.markedness()
        expected_mark_1 = cm.PPV() + cm.NPV() - 1.0
        expected_mark_2 = cm.PPV() - cm.FOR()
        check_with_nans(actual_mark, expected_mark_1, 4, ensure_nans=False)
        check_with_nans(actual_mark, expected_mark_2, 4, ensure_nans=False)

        # matthews corr coeff
        # actual_mcc = cm.matthews_corr()
        # expected_mcc = geometric_mean(actual_info, actual_mark)
        # check_with_nans(actual_mcc, expected_mcc, 4, ensure_nans=False)

        # kappas
        actual_kappa = cm.kappa()

        # kappa is the same as harmonic mean of kappa components
        expected_kappa_1 = harmonic_mean(*cm.kappas()[:2])
        check_with_nans(actual_kappa, expected_kappa_1, 4, ensure_nans=False)

        # kappa is the same as accuracy adjusted for chance
        expected_kappa_2 = harmonic_mean(*cm.adjust_to_null(cm.accuracy, model='m3'))
        check_with_nans(actual_kappa, expected_kappa_2, 4, ensure_nans=False)

        # kappa is the same as Dice coeff adjusted for chance
        expected_kappa_3 = harmonic_mean(*cm.adjust_to_null(cm.dice_coeff, model='m3'))
        check_with_nans(actual_kappa, expected_kappa_3, 4, ensure_nans=False)

        # odds ratio and Yule's Q
        actual_odds_ratio = cm.DOR()
        actual_yule_q = cm.yule_q()
        expected_yule_q = _div(actual_odds_ratio - 1.0, actual_odds_ratio + 1.0)
        expected_odds_ratio = _div(cm.PLL(), cm.NLL())
        check_with_nans(actual_odds_ratio, expected_odds_ratio, 4, ensure_nans=False)
        check_with_nans(actual_yule_q, expected_yule_q, 4, ensure_nans=False)

        # F-score and Dice
        expected_f = harmonic_mean(cm.precision(), cm.recall())
        actual_f = cm.fscore()
        check_with_nans(expected_f, actual_f, 6)
        check_with_nans(expected_f, cm.dice_coeff(), 6, ensure_nans=False)

        # association coefficients (1)
        dice = cm.dice_coeff()
        expected_jaccard = _div(dice, 2.0 - dice)
        actual_jaccard = cm.jaccard_coeff()
        check_with_nans(actual_jaccard, expected_jaccard, 6, ensure_nans=False)

        # association coefficients (2)
        jaccard = cm.jaccard_coeff()
        expected_ss2 = _div(jaccard, 2.0 - jaccard)
        actual_ss2 = cm.sokal_sneath_coeff()
        check_with_nans(actual_ss2, expected_ss2, 6, ensure_nans=False)

        # adjusted ochiai
        actual = cm.ochiai_coeff_adj()
        expected = harmonic_mean(*cm.adjust_to_null(cm.ochiai_coeff, model='m3'))
        check_with_nans(actual, expected, 6, ensure_nans=False)