Skip to content

Commit 34a6d0b

Browse files
authored
Release 0.15.0 (#123)
* Remove python2 code * Remove python2 code again * Replace unittest with pytest * Bump version to 0.15.0 * Blackify
1 parent 5720213 commit 34a6d0b

20 files changed

+1570
-1796
lines changed

.travis.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ language: python
22

33
matrix:
44
include:
5-
- python: 2.7
6-
env: TOXENV=py27
75
- python: 3.5
86
env: TOXENV=py35
97
- python: 3.6

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
# Changelog
22
All notable changes to this project will be documented in this file.
33

4+
## [0.15.0] - 2020-03-10
5+
### Changed
6+
- Remove support of Python2.7 [#123](https://github.com/snipsco/snips-nlu-metrics/pull/123)
7+
48
## [0.14.6] - 2020-01-14
59
### Added
6-
- Support for python3.8
10+
- Support for python3.8 [#121](https://github.com/snipsco/snips-nlu-metrics/pull/121)
711

812
## [0.14.5] - 2019-08-20
913
### Fixed
@@ -60,6 +64,8 @@ All notable changes to this project will be documented in this file.
6064
- Samples
6165

6266

67+
[0.15.0]: https://github.com/snipsco/snips-nlu-metrics/compare/0.14.6...0.15.0
68+
[0.14.6]: https://github.com/snipsco/snips-nlu-metrics/compare/0.14.5...0.14.6
6369
[0.14.5]: https://github.com/snipsco/snips-nlu-metrics/compare/0.14.4...0.14.5
6470
[0.14.4]: https://github.com/snipsco/snips-nlu-metrics/compare/0.14.3...0.14.4
6571
[0.14.3]: https://github.com/snipsco/snips-nlu-metrics/compare/0.14.2...0.14.3

README.rst

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,7 @@ the ``Engine`` API:
5656

5757
.. code-block:: python
5858
59-
from builtins import object
60-
61-
class Engine(object):
59+
class Engine:
6260
def fit(self, dataset):
6361
# Perform training ...
6462
return self
@@ -117,7 +115,7 @@ You can also compute metrics on a custom NLU engine, here is a simple example:
117115
118116
from snips_nlu_metrics import compute_train_test_metrics
119117
120-
class MyNLUEngine(object):
118+
class MyNLUEngine:
121119
def fit(self, dataset):
122120
self.intent_list = list(dataset["intents"])
123121
return self

setup.py

Lines changed: 32 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,50 @@
1-
import io
2-
import os
1+
from pathlib import Path
32

43
from setuptools import setup, find_packages
54

65
packages = [p for p in find_packages() if "tests" not in p]
76

87
PACKAGE_NAME = "snips_nlu_metrics"
9-
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
10-
PACKAGE_PATH = os.path.join(ROOT_PATH, PACKAGE_NAME)
11-
README = os.path.join(ROOT_PATH, "README.rst")
8+
ROOT_PATH = Path(__file__).resolve().parent
9+
PACKAGE_PATH = ROOT_PATH / PACKAGE_NAME
10+
README = ROOT_PATH / "README.rst"
1211
VERSION = "__version__"
1312

14-
with io.open(os.path.join(PACKAGE_PATH, VERSION)) as f:
13+
with (PACKAGE_PATH / VERSION).open() as f:
1514
version = f.readline().strip()
1615

17-
with io.open(README, 'rt', encoding='utf8') as f:
16+
with README.open(encoding="utf8") as f:
1817
readme = f.read()
1918

2019
install_requires = [
21-
"future",
2220
"numpy>=1.7,<2.0",
2321
"scipy>=1.0,<2.0",
2422
"scikit-learn>=0.21.0,<0.23; python_version>='3.5'",
25-
"scikit-learn>=0.19,<0.21; python_version<'3.5'",
26-
"joblib>=0.13,<0.15"
23+
"joblib>=0.13,<0.15",
2724
]
2825

29-
extras_require = {
30-
"test": [
31-
"mock>=2.0,<3.0",
32-
]
33-
}
34-
35-
setup(name=PACKAGE_NAME,
36-
description="Python package to compute NLU metrics",
37-
long_description=readme,
38-
version=version,
39-
author="Adrien Ball",
40-
author_email="adrien.ball@snips.ai",
41-
license="Apache 2.0",
42-
url="https://github.com/snipsco/snips-nlu-metrics",
43-
classifiers=[
44-
"Programming Language :: Python :: 2",
45-
"Programming Language :: Python :: 2.7",
46-
"Programming Language :: Python :: 3",
47-
"Programming Language :: Python :: 3.5",
48-
"Programming Language :: Python :: 3.6",
49-
"Programming Language :: Python :: 3.7",
50-
"Programming Language :: Python :: 3.8",
51-
],
52-
keywords="metrics nlu nlp intent slots entity parsing",
53-
extras_require=extras_require,
54-
install_requires=install_requires,
55-
packages=packages,
56-
include_package_data=True,
57-
zip_safe=False)
26+
extras_require = {"test": ["mock>=2.0,<3.0", "pytest>=5.3.1,<6",]}
27+
28+
setup(
29+
name=PACKAGE_NAME,
30+
description="Python package to compute NLU metrics",
31+
long_description=readme,
32+
version=version,
33+
author="Adrien Ball",
34+
author_email="adrien.ball@snips.ai",
35+
license="Apache 2.0",
36+
url="https://github.com/snipsco/snips-nlu-metrics",
37+
classifiers=[
38+
"Programming Language :: Python :: 3",
39+
"Programming Language :: Python :: 3.5",
40+
"Programming Language :: Python :: 3.6",
41+
"Programming Language :: Python :: 3.7",
42+
"Programming Language :: Python :: 3.8",
43+
],
44+
keywords="metrics nlu nlp intent slots entity parsing",
45+
extras_require=extras_require,
46+
install_requires=install_requires,
47+
packages=packages,
48+
include_package_data=True,
49+
zip_safe=False,
50+
)

snips_nlu_metrics/__init__.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
from __future__ import absolute_import
2-
31
from snips_nlu_metrics.engine import Engine
4-
from snips_nlu_metrics.metrics import (compute_train_test_metrics,
5-
compute_cross_val_metrics)
2+
from snips_nlu_metrics.metrics import (
3+
compute_train_test_metrics,
4+
compute_cross_val_metrics,
5+
)

snips_nlu_metrics/__version__

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.14.6
1+
0.15.0

snips_nlu_metrics/engine.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
1-
from __future__ import unicode_literals
2-
31
from abc import ABCMeta, abstractmethod
4-
from builtins import object
5-
6-
from future.utils import with_metaclass
72

83

9-
class Engine(with_metaclass(ABCMeta, object)):
4+
class Engine(metaclass=ABCMeta):
105
"""Abstract class which represents an engine that can be used in the
116
metrics API. All engine classes must inherit from `Engine`.
127
"""

snips_nlu_metrics/metrics.py

Lines changed: 82 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,46 @@
1-
from __future__ import division, print_function, unicode_literals
2-
3-
import io
41
import json
52
import logging
3+
from pathlib import Path
64

7-
from future.utils import iteritems
85
from joblib import Parallel, delayed
9-
from past.builtins import basestring
106

117
from snips_nlu_metrics.utils.constants import (
12-
AVERAGE_METRICS, CONFUSION_MATRIX, INTENTS, INTENT_UTTERANCES, METRICS,
13-
PARSING_ERRORS, UTTERANCES)
8+
AVERAGE_METRICS,
9+
CONFUSION_MATRIX,
10+
INTENTS,
11+
INTENT_UTTERANCES,
12+
METRICS,
13+
PARSING_ERRORS,
14+
UTTERANCES,
15+
)
1416
from snips_nlu_metrics.utils.exception import NotEnoughDataError
1517
from snips_nlu_metrics.utils.metrics_utils import (
16-
aggregate_matrices, aggregate_metrics, compute_average_metrics,
17-
compute_engine_metrics, compute_precision_recall_f1, compute_split_metrics,
18-
create_shuffle_stratified_splits)
18+
aggregate_matrices,
19+
aggregate_metrics,
20+
compute_average_metrics,
21+
compute_engine_metrics,
22+
compute_precision_recall_f1,
23+
compute_split_metrics,
24+
create_shuffle_stratified_splits,
25+
)
1926

2027
logger = logging.getLogger(__name__)
2128

2229

2330
def compute_cross_val_metrics(
24-
dataset, engine_class, nb_folds=5, train_size_ratio=1.0,
25-
drop_entities=False, include_slot_metrics=True,
26-
slot_matching_lambda=None, progression_handler=None, num_workers=1,
27-
seed=None, out_of_domain_utterances=None, intents_filter=None):
31+
dataset,
32+
engine_class,
33+
nb_folds=5,
34+
train_size_ratio=1.0,
35+
drop_entities=False,
36+
include_slot_metrics=True,
37+
slot_matching_lambda=None,
38+
progression_handler=None,
39+
num_workers=1,
40+
seed=None,
41+
out_of_domain_utterances=None,
42+
intents_filter=None,
43+
):
2844
"""Compute end-to-end metrics on the dataset using cross validation
2945
3046
Args:
@@ -68,14 +84,20 @@ class must inherit from `Engine`
6884
- "average_metrics": the metrics averaged over all intents
6985
"""
7086

71-
if isinstance(dataset, basestring):
72-
with io.open(dataset, encoding="utf8") as f:
87+
if isinstance(dataset, (str, Path)):
88+
with Path(dataset).open(encoding="utf8") as f:
7389
dataset = json.load(f)
7490

7591
try:
7692
splits = create_shuffle_stratified_splits(
77-
dataset, nb_folds, train_size_ratio, drop_entities,
78-
seed, out_of_domain_utterances, intents_filter)
93+
dataset,
94+
nb_folds,
95+
train_size_ratio,
96+
drop_entities,
97+
seed,
98+
out_of_domain_utterances,
99+
intents_filter,
100+
)
79101
except NotEnoughDataError as e:
80102
logger.warning("Not enough data, skipping metrics computation: %r", e)
81103
return {
@@ -94,8 +116,13 @@ class must inherit from `Engine`
94116
def compute_metrics(split_):
95117
logger.info("Computing metrics for dataset split ...")
96118
return compute_split_metrics(
97-
engine_class, split_, intent_list, include_slot_metrics,
98-
slot_matching_lambda, intents_filter)
119+
engine_class,
120+
split_,
121+
intent_list,
122+
include_slot_metrics,
123+
slot_matching_lambda,
124+
intents_filter,
125+
)
99126

100127
effective_num_workers = min(num_workers, len(splits))
101128
if effective_num_workers > 1:
@@ -107,26 +134,28 @@ def compute_metrics(split_):
107134
for result in enumerate(results):
108135
split_index, (split_metrics, errors, confusion_matrix) = result
109136
global_metrics = aggregate_metrics(
110-
global_metrics, split_metrics, include_slot_metrics)
137+
global_metrics, split_metrics, include_slot_metrics
138+
)
111139
global_confusion_matrix = aggregate_matrices(
112-
global_confusion_matrix, confusion_matrix)
140+
global_confusion_matrix, confusion_matrix
141+
)
113142
global_errors += errors
114-
logger.info("Done computing %d/%d splits"
115-
% (split_index + 1, total_splits))
143+
logger.info("Done computing %d/%d splits" % (split_index + 1, total_splits))
116144

117145
if progression_handler is not None:
118-
progression_handler(
119-
float(split_index + 1) / float(total_splits))
146+
progression_handler(float(split_index + 1) / float(total_splits))
120147

121148
global_metrics = compute_precision_recall_f1(global_metrics)
122149

123150
average_metrics = compute_average_metrics(
124151
global_metrics,
125-
ignore_none_intent=True if out_of_domain_utterances is None else False)
152+
ignore_none_intent=True if out_of_domain_utterances is None else False,
153+
)
126154

127-
nb_utterances = {intent: len(data[UTTERANCES])
128-
for intent, data in iteritems(dataset[INTENTS])}
129-
for intent, metrics in iteritems(global_metrics):
155+
nb_utterances = {
156+
intent: len(data[UTTERANCES]) for intent, data in dataset[INTENTS].items()
157+
}
158+
for intent, metrics in global_metrics.items():
130159
metrics[INTENT_UTTERANCES] = nb_utterances.get(intent, 0)
131160

132161
return {
@@ -138,8 +167,13 @@ def compute_metrics(split_):
138167

139168

140169
def compute_train_test_metrics(
141-
train_dataset, test_dataset, engine_class, include_slot_metrics=True,
142-
slot_matching_lambda=None, intents_filter=None):
170+
train_dataset,
171+
test_dataset,
172+
engine_class,
173+
include_slot_metrics=True,
174+
slot_matching_lambda=None,
175+
intents_filter=None,
176+
):
143177
"""Compute end-to-end metrics on `test_dataset` after having trained on
144178
`train_dataset`
145179
@@ -171,12 +205,12 @@ class must inherit from `Engine`
171205
- "average_metrics": the metrics averaged over all intents
172206
"""
173207

174-
if isinstance(train_dataset, basestring):
175-
with io.open(train_dataset, encoding="utf8") as f:
208+
if isinstance(train_dataset, (str, Path)):
209+
with Path(train_dataset).open(encoding="utf8") as f:
176210
train_dataset = json.load(f)
177211

178-
if isinstance(test_dataset, basestring):
179-
with io.open(test_dataset, encoding="utf8") as f:
212+
if isinstance(test_dataset, (str, Path)):
213+
with Path(test_dataset).open(encoding="utf8") as f:
180214
test_dataset = json.load(f)
181215

182216
intent_list = set(train_dataset["intents"])
@@ -188,20 +222,26 @@ class must inherit from `Engine`
188222
engine.fit(train_dataset)
189223
test_utterances = [
190224
(intent_name, utterance)
191-
for intent_name, intent_data in iteritems(test_dataset[INTENTS])
225+
for intent_name, intent_data in test_dataset[INTENTS].items()
192226
for utterance in intent_data[UTTERANCES]
193227
if intents_filter is None or intent_name in intents_filter
194228
]
195229

196230
logger.info("Computing metrics...")
197231
metrics, errors, confusion_matrix = compute_engine_metrics(
198-
engine, test_utterances, intent_list, include_slot_metrics,
199-
slot_matching_lambda, intents_filter)
232+
engine,
233+
test_utterances,
234+
intent_list,
235+
include_slot_metrics,
236+
slot_matching_lambda,
237+
intents_filter,
238+
)
200239
metrics = compute_precision_recall_f1(metrics)
201240
average_metrics = compute_average_metrics(metrics)
202-
nb_utterances = {intent: len(data[UTTERANCES])
203-
for intent, data in iteritems(train_dataset[INTENTS])}
204-
for intent, intent_metrics in iteritems(metrics):
241+
nb_utterances = {
242+
intent: len(data[UTTERANCES]) for intent, data in train_dataset[INTENTS].items()
243+
}
244+
for intent, intent_metrics in metrics.items():
205245
intent_metrics[INTENT_UTTERANCES] = nb_utterances.get(intent, 0)
206246
return {
207247
CONFUSION_MATRIX: confusion_matrix,

0 commit comments

Comments
 (0)