jogonba2 commited on
Commit
bdeb145
1 Parent(s): 96d620b
Files changed (3) hide show
  1. app.py +3 -3
  2. clustering_evaluator.py +14 -4
  3. gradio_tst.py +140 -0
app.py CHANGED
@@ -1,5 +1,5 @@
1
  import evaluate
2
- from evaluate.utils import launch_gradio_widget
3
 
4
- module = evaluate.load("symanto/clustering_evaluator")
5
- launch_gradio_widget(module)
 
1
  import evaluate
2
+ from gradio_tst import launch_gradio_widget2
3
 
4
+ module = evaluate.load("regression_evaluator.py")
5
+ launch_gradio_widget2(module)
clustering_evaluator.py CHANGED
@@ -29,6 +29,8 @@ _CITATION = """
29
 
30
  _DESCRIPTION = """\
31
  This evaluator computes multiple clustering metrics to assess the quality of a clustering.
 
 
32
  """
33
 
34
 
@@ -36,11 +38,19 @@ _KWARGS_DESCRIPTION = """
36
  Computes the quality of clustering results.
37
  Args:
38
  samples' vector representations
39
- y: computed cluster labels
 
40
  Returns:
41
- silhouete_score (float): cohesiveness and separation between clusters
42
- davies_bouldin_score (float): average similarity measure of each cluster with its most similar cluster
43
- calinski_harabasz_score (float): ratio of the sum of between-cluster dispersion and of within-cluster dispersion
 
 
 
 
 
 
 
44
  """
45
 
46
 
 
29
 
30
  _DESCRIPTION = """\
31
  This evaluator computes multiple clustering metrics to assess the quality of a clustering.
32
+ By default, the evaluator works as in an unsupervised setting, evaluating the clustering just from
33
+ the samples and the predictions. However, it allows to compute additional metrics when truth labels are passed too.
34
  """
35
 
36
 
 
38
  Computes the quality of clustering results.
39
  Args:
40
  samples' vector representations
41
+ predictions: computed cluster labels
42
+ truth_labels (optional): truth labels to compute additional metrics
43
  Returns:
44
+ silhouete_score
45
+ davies_bouldin_score
46
+ calinski_harabasz_score
47
+ completeness_score
48
+ davies_bouldin_score
49
+ fowlkes_mallows_score
50
+ homogeneity_score
51
+ silhouette_score
52
+ contingency_matrix
53
+ pair_confusion_matrix
54
  """
55
 
56
 
gradio_tst.py ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import logging
3
+ import os
4
+ import re
5
+ import sys
6
+ from pathlib import Path
7
+
8
+ import numpy as np
9
+ from datasets import Value
10
+
11
+ REGEX_YAML_BLOCK = re.compile(r"---[\n\r]+([\S\s]*?)[\n\r]+---[\n\r]")
12
+
13
+
14
+ def infer_gradio_input_types(feature_types):
15
+ """
16
+ Maps metric feature types to input types for gradio Dataframes:
17
+ - float/int -> numbers
18
+ - string -> strings
19
+ - any other -> json
20
+ Note that json is not a native gradio type but will be treated as string that
21
+ is then parsed as a json.
22
+ """
23
+ input_types = []
24
+ for feature_type in feature_types:
25
+ input_type = "json"
26
+ if isinstance(feature_type, Value):
27
+ if feature_type.dtype.startswith(
28
+ "int"
29
+ ) or feature_type.dtype.startswith("float"):
30
+ input_type = "number"
31
+ elif feature_type.dtype == "string":
32
+ input_type = "str"
33
+ input_types.append(input_type)
34
+ return input_types
35
+
36
+
37
+ def json_to_string_type(input_types):
38
+ """Maps json input type to str."""
39
+ return ["str" if i == "json" else i for i in input_types]
40
+
41
+
42
+ def parse_readme(filepath):
43
+ """Parses a repositories README and removes"""
44
+ if not os.path.exists(filepath):
45
+ return "No README.md found."
46
+ with open(filepath, "r") as f:
47
+ text = f.read()
48
+ match = REGEX_YAML_BLOCK.search(text)
49
+ if match:
50
+ text = text[match.end() :]
51
+ return text
52
+
53
+
54
+ def parse_gradio_data(data, input_types):
55
+ """Parses data from gradio Dataframe for use in metric."""
56
+ metric_inputs = {}
57
+ data.replace("", np.nan, inplace=True)
58
+ data.dropna(inplace=True)
59
+ for feature_name, input_type in zip(data, input_types):
60
+ if input_type == "json":
61
+ metric_inputs[feature_name] = [
62
+ json.loads(d) for d in data[feature_name].to_list()
63
+ ]
64
+ elif input_type == "str":
65
+ metric_inputs[feature_name] = [
66
+ d.strip('"') for d in data[feature_name].to_list()
67
+ ]
68
+ else:
69
+ metric_inputs[feature_name] = data[feature_name]
70
+ return metric_inputs
71
+
72
+
73
+ def parse_test_cases(test_cases, feature_names, input_types):
74
+ """
75
+ Parses test cases to be used in gradio Dataframe. Note that an apostrophe is added
76
+ to strings to follow the format in json.
77
+ """
78
+ if len(test_cases) == 0:
79
+ return None
80
+ examples = []
81
+ for test_case in test_cases:
82
+ parsed_cases = []
83
+ for feat, input_type in zip(feature_names, input_types):
84
+ if input_type == "json":
85
+ parsed_cases.append(
86
+ [str(element) for element in test_case[feat]]
87
+ )
88
+ elif input_type == "str":
89
+ parsed_cases.append(
90
+ ['"' + element + '"' for element in test_case[feat]]
91
+ )
92
+ else:
93
+ parsed_cases.append(test_case[feat])
94
+ examples.append([list(i) for i in zip(*parsed_cases)])
95
+ return examples
96
+
97
+
98
+ def launch_gradio_widget2(metric):
99
+ """Launches `metric` widget with Gradio."""
100
+
101
+ try:
102
+ import gradio as gr
103
+ except ImportError as error:
104
+ logging.error(
105
+ "To create a metric widget with Gradio make sure gradio is installed."
106
+ )
107
+ raise error
108
+
109
+ local_path = Path(sys.path[0])
110
+ # if there are several input types, use first as default.
111
+ if isinstance(metric.features, list):
112
+ (feature_names, feature_types) = zip(*metric.features[0].items())
113
+ else:
114
+ (feature_names, feature_types) = zip(*metric.features.items())
115
+ gradio_input_types = infer_gradio_input_types(feature_types)
116
+
117
+ def compute(data):
118
+ return metric.compute(**parse_gradio_data(data, gradio_input_types))
119
+
120
+ iface = gr.Interface(
121
+ fn=compute,
122
+ inputs=gr.Dataframe(
123
+ headers=feature_names,
124
+ col_count=len(feature_names),
125
+ row_count=1,
126
+ datatype=json_to_string_type(gradio_input_types),
127
+ ),
128
+ outputs=gr.Textbox(label=metric.name),
129
+ description=(
130
+ metric.info.description
131
+ + "\nIf this is a text-based metric, make sure to wrap you input in double quotes."
132
+ " Alternatively you can use a JSON-formatted list as input."
133
+ ),
134
+ title=f"Metric: {metric.name}",
135
+ article=parse_readme(local_path / "README.md"),
136
+ # TODO: load test cases and use them to populate examples
137
+ # examples=[parse_test_cases(test_cases, feature_names, gradio_input_types)]
138
+ )
139
+
140
+ iface.launch(share=True)