Skip to content

Commit 95301b4

Browse files
committed
F1 matching policies (micro, macro and combined weighting) parameterized
1 parent 8520860 commit 95301b4

File tree

9 files changed

+226
-116
lines changed

9 files changed

+226
-116
lines changed

README.md

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# xmeasures - Extrinsic Clustering Measures
2-
Extremely fast evaluation of the extrinsic clustering measures: *various F1 measures (including F1-Score) for overlapping multi-resolution clusterings with unequal node base (and optional node base synchronization)* and standard NMI for non-overlapping clustering on a single resolution.
2+
Extremely fast evaluation of the extrinsic clustering measures: *various F1 measures (including F1-Score) for overlapping multi-resolution clusterings with unequal node base (and optional node base synchronization)* using various *matching policies (micro, macro and combined weighting)* and standard NMI for non-overlapping clustering on a single resolution.
33
`xmeasures` evaluates F1 and NMI for collections of hundreds thousands clusters withing a dozen seconds on an ordinary laptop using a single CPU core. The computational time is O(N) unlike O(N*C) of the existing state of the art implementations, where N is the number of nodes in the network and C is the number of clusters.
44
`xmeasures` is one of the utilities designed for the [PyCaBeM](https://github.com/eXascaleInfolab/PyCABeM) clustering benchmark to evaluate clustering of large networks.
5-
A paper about the implemented F1 measures (F1p is much more discriminative than the standard [Average F1-Score](https://cs.stanford.edu/people/jure/pubs/bigclam-wsdm13.pdf)), [NMI measures](www.jmlr.org/papers/volume11/vinh10a/vinh10a.pdf) and their applicability is being written now and the reference will be specified soon...
5+
A paper about the implemented F1 measures (F1p is much more indicative and discriminative than the standard [Average F1-Score](https://cs.stanford.edu/people/jure/pubs/bigclam-wsdm13.pdf)), [NMI measures](www.jmlr.org/papers/volume11/vinh10a/vinh10a.pdf) and their applicability is being written now and the reference will be specified soon...
66
> Standard NMI is implemented considering overlapping and multi-resolution clustering only to demonstrate non-applicability of the standard NMI for such cases, where it yields unfair results. See [GenConvNMI](https://github.com/eXascaleInfolab/GenConvNMI) for the fair generalized NMI evaluation.
77
88
Author (c) Artem Lutov <[email protected]>
@@ -36,30 +36,38 @@ Then `g++-5` should be installed and `Makefile` might need to be edited replacin
3636
Execution Options:
3737
```
3838
$ ../xmeasures -h
39-
xmeasures 3.0
39+
xmeasures 3.1
4040
4141
Extrinsic measures evaluation: F1 (prob, harm and score) for overlapping
4242
multi-resolution clusterings with possible unequal node base and standard NMI
4343
for non-overlapping clustering on a single resolution.
4444
45-
Usage: xmeasures [OPTIONS] clustering1 clustering2
45+
Usage: xmeasures [OPTIONS] clustering1 clustering2
4646
4747
clustering - input file, collection of the clusters to be evaluated.
48+
49+
Example:
50+
$ ./xmeasures -fp -kc networks/5K25.cnl tests/5K25_l0.825/5K25_l0.825_796.cnl
4851
4952
Extrinsic measures are evaluated, i.e. clustering (collection of clusters) is
50-
compared to another collection, which is typically the ground-truth.
53+
compared to another clustering, which can be the ground-truth.
54+
NOTE: Each cluster should contain unique members, which is verified only in the
55+
debug mode.
5156
Evaluating measures are:
57+
5258
- F1 - various F1 measures of the Greatest (Max) Match including the Average
53-
F1-Score with optional weighting;
59+
F1-Score with optional weighting.
60+
NOTE: There are 3 matching policies available for each kind of F1. The most
61+
representative evaluation is performed by the F1p with combined matching
62+
policy (considers both micro and macro weightings).
63+
5464
- NMI - Normalized Mutual Information, normalized by either max or also
5565
sqrt, avg and min information content denominators.
56-
ATTENTION: this is standard NMI, which should be used ONLY for the HARD
66+
ATTENTION: This is standard NMI, which should be used ONLY for the HARD
5767
partitioning evaluation (non-overlapping clustering on a single resolution).
58-
it penalizes overlapping and multi-resolution structures.
59-
NOTE: Unequal node base in the clusterings is allowed, it penalizes the match.
60-
Each cluster should contain unique members, which is verified only in the debug
61-
mode.
62-
Use [OvpNMI](https://github.com/eXascaleInfolab/OvpNMI) or
68+
It penalizes overlapping and multi-resolution structures.
69+
NOTE: Unequal node base in the clusterings is allowed, it penalizes the
70+
match.Use [OvpNMI](https://github.com/eXascaleInfolab/OvpNMI) or
6371
[GenConvNMI](https://github.com/eXascaleInfolab/GenConvNMI) for NMI evaluation
6472
in the arbitrary collections (still each cluster should contain unique
6573
members).
@@ -102,8 +110,12 @@ F1 Options:
102110
number of the Formal Constraints.
103111
(possible values="partprob", "harmonic",
104112
"standard" default=`partprob')
105-
-u, --unweighted evaluate simple average of the best matches instead
106-
of weighted by the cluster size (default=off)
113+
-k, --kind[=ENUM] kind of the matching policy:
114+
- w - weighted (default)
115+
- u - unweighed
116+
- c - combined: F1(w, u)
117+
(possible values="weighted", "unweighed",
118+
"combined" default=`weighted')
107119
108120
NMI Options:
109121
-n, --nmi evaluate NMI (Normalized Mutual Information)

args.ggo

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,42 @@
11
# Configuration file for the automatic generation of the input options parsing
22

33
package "xmeasures"
4-
version "3.0"
4+
version "3.1"
55

66
purpose "Extrinsic measures evaluation: F1 (prob, harm and score) for overlapping\
77
multi-resolution clusterings with possible unequal node base and standard NMI for\
88
non-overlapping clustering on a single resolution."
99

1010
description "Extrinsic measures are evaluated, i.e. clustering (collection of\
1111
clusters) is compared to another clustering, which can be the ground-truth.
12+
NOTE: Each cluster should contain unique members, which is verified only in the debug\
13+
mode.
1214
Evaluating measures are:
15+
1316
- F1 - various F1 measures of the Greatest (Max) Match including the Average\
14-
F1-Score with optional weighting;
17+
F1-Score with optional weighting.
18+
NOTE: There are 3 matching policies available for each kind of F1. The most\
19+
representative evaluation is performed by the F1p with combined matching\
20+
policy (considers both micro and macro weightings).
21+
1522
- NMI - Normalized Mutual Information, normalized by either max or also sqrt,\
1623
avg and min information content denominators.
17-
ATTENTION: this is standard NMI, which should be used ONLY for the HARD\
24+
ATTENTION: This is standard NMI, which should be used ONLY for the HARD\
1825
partitioning evaluation (non-overlapping clustering on a single resolution).\
1926
It penalizes overlapping and multi-resolution structures.
2027
NOTE: Unequal node base in the clusterings is allowed, it penalizes the match.\
21-
Each cluster should contain unique members, which is verified only in the debug\
22-
mode.
2328
Use [OvpNMI](https://github.com/eXascaleInfolab/OvpNMI) or\
2429
[GenConvNMI](https://github.com/eXascaleInfolab/GenConvNMI) for NMI evaluation\
2530
in the arbitrary collections (still each cluster should contain unique members).
2631
"
2732

2833
usage "xmeasures [OPTIONS] clustering1 clustering2
2934

30-
clustering - input file, collection of the clusters to be evaluated."
35+
clustering - input file, collection of the clusters to be evaluated.
36+
37+
Example:
38+
$ ./xmeasures -fp -kc networks/5K25.cnl tests/5K25_l0.825/5K25_l0.825_796.cnl
39+
"
3140

3241
option "ovp" o "evaluate overlapping instead of multi-resolution clusters, where\
3342
max matching for any shared member between R overlapping clusters is 1/R unlike 1\
@@ -58,8 +67,13 @@ NOTE: F1p <= F1h <= F1s, where:
5867
Formal Constraints.
5968
"
6069
values="partprob","harmonic","standard" enum default="partprob" argoptional
61-
option "unweighted" u "evaluate simple average of the best matches instead\
62-
of weighted by the cluster size" flag off dependon="f1"
70+
option "kind" k "kind of the matching policy:
71+
- w - weighted (default)
72+
- u - unweighed
73+
- c - combined: F1(w, u)
74+
"
75+
values ="weighted","unweighed","combined" enum default="weighted" argoptional
76+
dependon="f1"
6377

6478
section "NMI Options"
6579
option "nmi" n "evaluate NMI (Normalized Mutual Information)" flag off
@@ -75,6 +89,7 @@ args "--default-optional --unamed-opts=clusterings" # Set opional opions, allo
7589

7690

7791
# = Changelog =
92+
# v3.1.0 - Matching policy for the F measures parameterized (weighted, unweighted, combined)
7893
# v3.0.2 - NMI_sqrt added
7994
# v3.0 - Command line interface changed for F1
8095
# - Standard F1-Score added

autogen/cmdline.c

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@
2727

2828
const char *gengetopt_args_info_purpose = "Extrinsic measures evaluation: F1 (prob, harm and score) for overlapping\nmulti-resolution clusterings with possible unequal node base and standard NMI\nfor non-overlapping clustering on a single resolution.";
2929

30-
const char *gengetopt_args_info_usage = "Usage: xmeasures [OPTIONS] clustering1 clustering2\n\n clustering - input file, collection of the clusters to be evaluated.";
30+
const char *gengetopt_args_info_usage = "Usage: xmeasures [OPTIONS] clustering1 clustering2\n\n clustering - input file, collection of the clusters to be evaluated.\n \nExample:\n $ ./xmeasures -fp -kc networks/5K25.cnl tests/5K25_l0.825/5K25_l0.825_796.cnl\n";
3131

3232
const char *gengetopt_args_info_versiontext = "";
3333

34-
const char *gengetopt_args_info_description = "Extrinsic measures are evaluated, i.e. clustering (collection of clusters) is\ncompared to another clustering, which can be the ground-truth.\nEvaluating measures are:\n - F1 - various F1 measures of the Greatest (Max) Match including the Average\nF1-Score with optional weighting;\n - NMI - Normalized Mutual Information, normalized by either max or also\nsqrt, avg and min information content denominators.\nATTENTION: this is standard NMI, which should be used ONLY for the HARD\npartitioning evaluation (non-overlapping clustering on a single resolution).\nIt penalizes overlapping and multi-resolution structures.\nNOTE: Unequal node base in the clusterings is allowed, it penalizes the match.\nEach cluster should contain unique members, which is verified only in the debug\nmode.\nUse [OvpNMI](https://github.com/eXascaleInfolab/OvpNMI) or\n[GenConvNMI](https://github.com/eXascaleInfolab/GenConvNMI) for NMI evaluation\nin the arbitrary collections (still each cluster should contain unique\nmembers).\n";
34+
const char *gengetopt_args_info_description = "Extrinsic measures are evaluated, i.e. clustering (collection of clusters) is\ncompared to another clustering, which can be the ground-truth.\nNOTE: Each cluster should contain unique members, which is verified only in the\ndebug mode.\nEvaluating measures are:\n\n - F1 - various F1 measures of the Greatest (Max) Match including the Average\nF1-Score with optional weighting.\n NOTE: There are 3 matching policies available for each kind of F1. The most\nrepresentative evaluation is performed by the F1p with combined matching\npolicy (considers both micro and macro weightings). \n\n - NMI - Normalized Mutual Information, normalized by either max or also\nsqrt, avg and min information content denominators.\nATTENTION: This is standard NMI, which should be used ONLY for the HARD\npartitioning evaluation (non-overlapping clustering on a single resolution).\nIt penalizes overlapping and multi-resolution structures.\nNOTE: Unequal node base in the clusterings is allowed, it penalizes the\nmatch.Use [OvpNMI](https://github.com/eXascaleInfolab/OvpNMI) or\n[GenConvNMI](https://github.com/eXascaleInfolab/GenConvNMI) for NMI evaluation\nin the arbitrary collections (still each cluster should contain unique\nmembers).\n";
3535

3636
const char *gengetopt_args_info_help[] = {
3737
" -h, --help Print help and exit",
@@ -42,7 +42,7 @@ const char *gengetopt_args_info_help[] = {
4242
" -d, --detailed detailed (verbose) results output (default=off)",
4343
"\nF1 Options:",
4444
" -f, --f1[=ENUM] evaluate F1 of the [weighted] average of the greatest\n (maximal) match by F1 or partial probability.\n NOTE: F1p <= F1h <= F1s, where:\n - p (F1p) - Harmonic mean of the [weighted]\n average of Partial Probabilities, the most\n discriminative and satisfies the largest number of\n the Formal Constraints (homogeneity, completeness,\n rag bag, size/quantity, balance);\n - h (F1h) - Harmonic mean of the [weighted]\n average of F1s;\n - s (F1s) - Arithmetic mean (average) of the\n [weighted] average of F1s, Standard F1-Score, the\n least discriminative and satisfies the lowest\n number of the Formal Constraints.\n (possible values=\"partprob\", \"harmonic\",\n \"standard\" default=`partprob')",
45-
" -u, --unweighted evaluate simple average of the best matches instead\n of weighted by the cluster size (default=off)",
45+
" -k, --kind[=ENUM] kind of the matching policy:\n - w - weighted (default)\n - u - unweighed\n - c - combined: F1(w, u)\n (possible values=\"weighted\", \"unweighed\",\n \"combined\" default=`weighted')",
4646
"\nNMI Options:",
4747
" -n, --nmi evaluate NMI (Normalized Mutual Information)\n (default=off)",
4848
" -a, --all evaluate all NMIs using sqrt, avg and min\n denominators besides the max one (default=off)",
@@ -70,6 +70,7 @@ static int
7070
cmdline_parser_required2 (struct gengetopt_args_info *args_info, const char *prog_name, const char *additional_error);
7171

7272
const char *cmdline_parser_f1_values[] = {"partprob", "harmonic", "standard", 0}; /*< Possible values for f1. */
73+
const char *cmdline_parser_kind_values[] = {"weighted", "unweighed", "combined", 0}; /*< Possible values for kind. */
7374

7475
static char *
7576
gengetopt_strdup (const char *s);
@@ -84,7 +85,7 @@ void clear_given (struct gengetopt_args_info *args_info)
8485
args_info->membership_given = 0 ;
8586
args_info->detailed_given = 0 ;
8687
args_info->f1_given = 0 ;
87-
args_info->unweighted_given = 0 ;
88+
args_info->kind_given = 0 ;
8889
args_info->nmi_given = 0 ;
8990
args_info->all_given = 0 ;
9091
args_info->ln_given = 0 ;
@@ -102,7 +103,8 @@ void clear_args (struct gengetopt_args_info *args_info)
102103
args_info->detailed_flag = 0;
103104
args_info->f1_arg = f1_arg_partprob;
104105
args_info->f1_orig = NULL;
105-
args_info->unweighted_flag = 0;
106+
args_info->kind_arg = kind_arg_weighted;
107+
args_info->kind_orig = NULL;
106108
args_info->nmi_flag = 0;
107109
args_info->all_flag = 0;
108110
args_info->ln_flag = 0;
@@ -121,7 +123,7 @@ void init_args_info(struct gengetopt_args_info *args_info)
121123
args_info->membership_help = gengetopt_args_info_help[4] ;
122124
args_info->detailed_help = gengetopt_args_info_help[5] ;
123125
args_info->f1_help = gengetopt_args_info_help[7] ;
124-
args_info->unweighted_help = gengetopt_args_info_help[8] ;
126+
args_info->kind_help = gengetopt_args_info_help[8] ;
125127
args_info->nmi_help = gengetopt_args_info_help[10] ;
126128
args_info->all_help = gengetopt_args_info_help[11] ;
127129
args_info->ln_help = gengetopt_args_info_help[12] ;
@@ -215,6 +217,7 @@ cmdline_parser_release (struct gengetopt_args_info *args_info)
215217
free_string_field (&(args_info->sync_orig));
216218
free_string_field (&(args_info->membership_orig));
217219
free_string_field (&(args_info->f1_orig));
220+
free_string_field (&(args_info->kind_orig));
218221

219222

220223
for (i = 0; i < args_info->inputs_num; ++i)
@@ -305,8 +308,8 @@ cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info)
305308
write_into_file(outfile, "detailed", 0, 0 );
306309
if (args_info->f1_given)
307310
write_into_file(outfile, "f1", args_info->f1_orig, cmdline_parser_f1_values);
308-
if (args_info->unweighted_given)
309-
write_into_file(outfile, "unweighted", 0, 0 );
311+
if (args_info->kind_given)
312+
write_into_file(outfile, "kind", args_info->kind_orig, cmdline_parser_kind_values);
310313
if (args_info->nmi_given)
311314
write_into_file(outfile, "nmi", 0, 0 );
312315
if (args_info->all_given)
@@ -431,9 +434,9 @@ cmdline_parser_required2 (struct gengetopt_args_info *args_info, const char *pro
431434
/* checks for required options */
432435

433436
/* checks for dependences among options */
434-
if (args_info->unweighted_given && ! args_info->f1_given)
437+
if (args_info->kind_given && ! args_info->f1_given)
435438
{
436-
fprintf (stderr, "%s: '--unweighted' ('-u') option depends on option 'f1'%s\n", prog_name, (additional_error ? additional_error : ""));
439+
fprintf (stderr, "%s: '--kind' ('-k') option depends on option 'f1'%s\n", prog_name, (additional_error ? additional_error : ""));
437440
error_occurred = 1;
438441
}
439442
if (args_info->all_given && ! args_info->nmi_given)
@@ -625,14 +628,14 @@ cmdline_parser_internal (
625628
{ "membership", 1, NULL, 'm' },
626629
{ "detailed", 0, NULL, 'd' },
627630
{ "f1", 2, NULL, 'f' },
628-
{ "unweighted", 0, NULL, 'u' },
631+
{ "kind", 2, NULL, 'k' },
629632
{ "nmi", 0, NULL, 'n' },
630633
{ "all", 0, NULL, 'a' },
631634
{ "ln", 0, NULL, 'e' },
632635
{ 0, 0, 0, 0 }
633636
};
634637

635-
c = getopt_long (argc, argv, "hVos:m:df::unae", long_options, &option_index);
638+
c = getopt_long (argc, argv, "hVos:m:df::k::nae", long_options, &option_index);
636639

637640
if (c == -1) break; /* Exit from `while (1)' loop. */
638641

@@ -710,12 +713,18 @@ cmdline_parser_internal (
710713
goto failure;
711714

712715
break;
713-
case 'u': /* evaluate simple average of the best matches instead of weighted by the cluster size. */
716+
case 'k': /* kind of the matching policy:
717+
- w - weighted (default)
718+
- u - unweighed
719+
- c - combined: F1(w, u)
720+
. */
714721

715722

716-
if (update_arg((void *)&(args_info->unweighted_flag), 0, &(args_info->unweighted_given),
717-
&(local_args_info.unweighted_given), optarg, 0, 0, ARG_FLAG,
718-
check_ambiguity, override, 1, 0, "unweighted", 'u',
723+
if (update_arg( (void *)&(args_info->kind_arg),
724+
&(args_info->kind_orig), &(args_info->kind_given),
725+
&(local_args_info.kind_given), optarg, cmdline_parser_kind_values, "weighted", ARG_ENUM,
726+
check_ambiguity, override, 0, 0,
727+
"kind", 'k',
719728
additional_error))
720729
goto failure;
721730

0 commit comments

Comments
 (0)