Skip to content

Commit af222cd

Browse files
authored
Merge pull request #94 from boeddeker/main
add more normalizers, "lower,rm([^a-z0-9 ])" and chime6/7/8
2 parents 8377855 + 425ef24 commit af222cd

3 files changed

Lines changed: 88 additions & 12 deletions

File tree

meeteval/wer/__main__.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import os
66
import re
77
import decimal
8+
import textwrap
89
from pathlib import Path
910

1011
import meeteval.io
@@ -608,13 +609,11 @@ def add_argument(self, command_parser, name, p):
608609
nargs='+', action=self.extend_action,
609610
)
610611
elif name == 'normalizer':
612+
from meeteval.wer.api import normalizers
611613
command_parser.add_argument(
612614
'--normalizer',
613-
help='A normalizer that is applied to the transcript.\n'
614-
'Choices:\n'
615-
'- None: Do nothing (default)\n'
616-
'- lower,rm(.?!,): Lowercase the transcript and remove punctuations (.,?!).',
617-
choices=[None, 'lower,rm(.?!,)'],
615+
help=textwrap.dedent(normalizers.__doc__),
616+
choices=[None, *normalizers.keys()],
618617
)
619618
elif name == 'partial':
620619
command_parser.add_argument(

meeteval/wer/api.py

Lines changed: 82 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,87 @@ def _maybe_load(paths, file_format) -> meeteval.io.SegLST:
3939
raise TypeError(type(paths), paths) from e
4040

4141

42+
class _Normalizers:
43+
"""
44+
A normalizer that is applied to the transcript.
45+
Choices:
46+
- None: Do nothing (default)
47+
- lower,rm(.?!,): Lowercase the transcript and remove punctuations (.,?!).
48+
- lower,rm([^a-z0-9 ]): Lowercase the transcript and remove all characters that are not a-z, 0-9, or space.
49+
- chime6: Normalize the transcript according to the CHiME-6 challenge.
50+
- chime7: Normalize the transcript according to the CHiME-7 challenge.
51+
In contrast to chime6, words like "hmm" are normalized,
52+
e.g. "hm", "hmm" and "hmmm" get "hmmm".
53+
- chime8: Normalize the transcript according to the CHiME-8 challenge.
54+
Removes words like "hmm", converts integers to words,
55+
and much more.
56+
"""
57+
# Note: The text above is used as CLI help text.
58+
# So the None is not a real option for this class, but the default
59+
# value for the normalizer argument.
60+
61+
def keys(self):
62+
return [
63+
'lower,rm(.?!,)',
64+
'lower,rm([^a-z0-9 ])',
65+
'chime6',
66+
'chime7',
67+
'chime8',
68+
]
69+
70+
def __getitem__(self, normalizer):
71+
"""
72+
>>> def test(normalizer):
73+
... seg = {'words': 'Hello, World! äèア😊 hm hmm hmmm [noise] [inaudible] wi-fi word-word 1.1 11 Mr. then,\" said'}
74+
... return _Normalizers()[normalizer](seg)['words']
75+
>>> test('lower,rm(.?!,)')
76+
'hello world äèア😊 hm hmm hmmm [noise] [inaudible] wi-fi word-word 11 11 mr then" said'
77+
>>> test('lower,rm([^a-z0-9 ])')
78+
'hello world hm hmm hmmm noise inaudible wifi wordword 11 11 mr then said'
79+
>>> test('chime8')
80+
'hello world aeア wifi word word 1.1 eleven mister then said'
81+
>>> test('chime7')
82+
'hello world äèア😊 hmmm hmmm hmmm wi-fi word-word 11 11 mr then said'
83+
>>> test('chime6')
84+
'hello world äèア😊 hm hmm hmmm wi-fi word-word 11 11 mr then said'
85+
"""
86+
if normalizer == 'lower,rm(.?!,)':
87+
def normalizer(seg):
88+
seg['words'] = seg['words'].lower().replace('.', '').replace('?', '').replace('!', '').replace(',', '')
89+
return seg
90+
elif normalizer == 'lower,rm([^a-z0-9 ])':
91+
r = re.compile('[^a-z0-9 ]')
92+
r2 = re.compile(r'\s{2,}')
93+
def normalizer(seg):
94+
seg['words'] = r2.sub(' ', r.sub('', seg['words'].lower()).strip())
95+
return seg
96+
elif normalizer in ['chime8', 'chime7', 'chime6']:
97+
from chime_utils.text_norm import get_txt_norm # pip install git+https://github.com/chimechallenge/chime-utils
98+
chime_utils_normalizer = get_txt_norm(normalizer)
99+
100+
# Note:
101+
# chime6 and chime7 remove all words, when [redacted] is
102+
# present.
103+
104+
def normalizer(seg):
105+
words = chime_utils_normalizer(seg['words'])
106+
if words != chime_utils_normalizer(seg['words']):
107+
raise RuntimeError(
108+
f'You discovered an idempotence bug in the chime_utils normalizer: {normalizer!r}.\n'
109+
f'Original: {seg["words"]}\n'
110+
f'Normalized: {words}\n'
111+
f'Normalized again: {chime_utils_normalizer(words)}'
112+
)
113+
seg['words'] = words
114+
return seg
115+
else:
116+
raise ValueError(f'Unknown normalizer: {normalizer}. Available normalizers: {self.keys()}')
117+
return normalizer
118+
119+
120+
normalizers = _Normalizers()
121+
122+
42123
def _load_texts(
43124
reference_paths: 'list[str]',
44125
hypothesis_paths: 'list[str]',
@@ -89,12 +170,7 @@ def filter(s):
89170
hypothesis = hypothesis.filter_by_uem(uem)
90171

91172
if normalizer is not None:
92-
if normalizer == 'lower,rm(.?!,)':
93-
def normalizer(seg):
94-
seg['words'] = seg['words'].lower().replace('.', '').replace('?', '').replace('!', '').replace(',', '')
95-
return seg
96-
else:
97-
raise NotImplementedError(normalizer)
173+
normalizer = normalizers[normalizer]
98174
reference = reference.map(normalizer)
99175
hypothesis = hypothesis.map(normalizer)
100176

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
editdistance
22
pytest
3-
hypothesis
3+
hypothesis
4+
chime-utils @ git+https://github.com/chimechallenge/chime-utils

0 commit comments

Comments
 (0)