mirror of
https://github.com/storytold/storyteller-ml.git
synced 2026-10-17 00:23:14 +00:00
Introduce code from Rust monorepo. This is a mess
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
**nemo_text_processing**
|
||||
==========================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
NeMo's `nemo_text_processing` is a Python package that is installed with the `nemo_toolkit`.
|
||||
See [documentation](https://docs.nvidia.com/deeplearning/nemo/user-guide/docs/en/main/) for details.
|
||||
@@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
@@ -0,0 +1,12 @@
|
||||
Inverse Text Normalization system for english, e.g. `one hundred twenty three kilograms` -> `123 kg`
|
||||
Offers prediction and evaluation on text normalization data, e.g. [Google text normalization dataset](https://www.kaggle.com/richardwilliamsproat/text-normalization-for-english-russian-and-polish).
|
||||
|
||||
|
||||
Install dependencies:
|
||||
bash setup.sh
|
||||
|
||||
Example prediction run:
|
||||
python run_predict.py --input=`INPUT_FILE` --output=`OUTPUT_FILE` [--verbose]
|
||||
|
||||
Example evaluation run:
|
||||
python run_evaluate.py --input=./en_with_types/output-00001-of-00100 [--cat CATEGORY] [--filter]
|
||||
@@ -0,0 +1,32 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from nemo_text_processing.inverse_text_normalization.taggers.tokenize_and_classify import ClassifyFst
|
||||
from nemo_text_processing.inverse_text_normalization.verbalizers.verbalize import VerbalizeFst
|
||||
from nemo_text_processing.inverse_text_normalization.verbalizers.verbalize_final import VerbalizeFinalFst
|
||||
|
||||
from nemo.utils import logging
|
||||
|
||||
try:
|
||||
import pynini
|
||||
|
||||
PYNINI_AVAILABLE = True
|
||||
except (ModuleNotFoundError, ImportError):
|
||||
logging.warning(
|
||||
"`pynini` is not installed ! \n"
|
||||
"Please run the `nemo_text_processing/setup.sh` script"
|
||||
"prior to usage of this toolkit."
|
||||
)
|
||||
|
||||
PYNINI_AVAILABLE = False
|
||||
@@ -0,0 +1,342 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from typing import List
|
||||
|
||||
import regex as re
|
||||
from nemo_text_processing.text_normalization.data_loader_utils import (
|
||||
EOS_TYPE,
|
||||
Instance,
|
||||
load_files,
|
||||
training_data_to_sentences,
|
||||
)
|
||||
|
||||
|
||||
"""
|
||||
This file is for evaluation purposes.
|
||||
filter_loaded_data() cleans data (list of instances) for inverse text normalization. Filters and cleaners can be specified for each semiotic class individually.
|
||||
For example, normalized text should only include characters and whitespace characters but no punctuation.
|
||||
Cardinal unnormalized instances should contain at least one integer and all other characters are removed.
|
||||
"""
|
||||
|
||||
|
||||
class Filter:
|
||||
"""
|
||||
Filter class
|
||||
|
||||
Args:
|
||||
class_type: semiotic class used in dataset
|
||||
process_func: function to transform text
|
||||
filter_func: function to filter text
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, class_type: str, process_func: object, filter_func: object):
|
||||
self.class_type = class_type
|
||||
self.process_func = process_func
|
||||
self.filter_func = filter_func
|
||||
|
||||
def filter(self, instance: Instance) -> bool:
|
||||
"""
|
||||
filter function
|
||||
|
||||
Args:
|
||||
filters given instance with filter function
|
||||
|
||||
Returns: True if given instance fulfills criteria or does not belong to class type
|
||||
"""
|
||||
if instance.token_type != self.class_type:
|
||||
return True
|
||||
return self.filter_func(instance)
|
||||
|
||||
def process(self, instance: Instance) -> Instance:
|
||||
"""
|
||||
process function
|
||||
|
||||
Args:
|
||||
processes given instance with process function
|
||||
|
||||
Returns: processed instance if instance belongs to expected class type or original instance
|
||||
"""
|
||||
if instance.token_type != self.class_type:
|
||||
return instance
|
||||
return self.process_func(instance)
|
||||
|
||||
|
||||
def filter_cardinal_1(instance: Instance) -> bool:
|
||||
ok = re.search(r"[0-9]", instance.un_normalized)
|
||||
return ok
|
||||
|
||||
|
||||
def process_cardinal_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
normalized = instance.normalized
|
||||
un_normalized = re.sub(r"[^0-9]", "", un_normalized)
|
||||
normalized = re.sub(r"[^a-z ]", "", normalized)
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
def filter_ordinal_1(instance: Instance) -> bool:
|
||||
ok = re.search(r"(st|nd|rd|th)\s*$", instance.un_normalized)
|
||||
return ok
|
||||
|
||||
|
||||
def process_ordinal_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
normalized = instance.normalized
|
||||
un_normalized = re.sub(r"[,\s]", "", un_normalized)
|
||||
normalized = re.sub(r"[^a-z ]", "", normalized)
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
def filter_decimal_1(instance: Instance) -> bool:
|
||||
ok = re.search(r"[0-9]", instance.un_normalized)
|
||||
return ok
|
||||
|
||||
|
||||
def process_decimal_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
un_normalized = re.sub(r",", "", un_normalized)
|
||||
normalized = instance.normalized
|
||||
normalized = re.sub(r"[^a-z ]", "", normalized)
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
def filter_measure_1(instance: Instance) -> bool:
|
||||
ok = True
|
||||
return ok
|
||||
|
||||
|
||||
def process_measure_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
normalized = instance.normalized
|
||||
un_normalized = re.sub(r",", "", un_normalized)
|
||||
un_normalized = re.sub(r"m2", "m²", un_normalized)
|
||||
un_normalized = re.sub(r"(\d)([^\d.\s])", r"\1 \2", un_normalized)
|
||||
normalized = re.sub(r"[^a-z\s]", "", normalized)
|
||||
normalized = re.sub(r"per ([a-z\s]*)s$", r"per \1", normalized)
|
||||
normalized = re.sub(r"[^a-z ]", "", normalized)
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
def filter_money_1(instance: Instance) -> bool:
|
||||
ok = re.search(r"[0-9]", instance.un_normalized)
|
||||
return ok
|
||||
|
||||
|
||||
def process_money_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
normalized = instance.normalized
|
||||
un_normalized = re.sub(r",", "", un_normalized)
|
||||
un_normalized = re.sub(r"a\$", r"$", un_normalized)
|
||||
un_normalized = re.sub(r"us\$", r"$", un_normalized)
|
||||
un_normalized = re.sub(r"(\d)m\s*$", r"\1 million", un_normalized)
|
||||
un_normalized = re.sub(r"(\d)bn?\s*$", r"\1 billion", un_normalized)
|
||||
normalized = re.sub(r"[^a-z ]", "", normalized)
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
def filter_time_1(instance: Instance) -> bool:
|
||||
ok = re.search(r"[0-9]", instance.un_normalized)
|
||||
return ok
|
||||
|
||||
|
||||
def process_time_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
un_normalized = re.sub(r": ", ":", un_normalized)
|
||||
un_normalized = re.sub(r"(\d)\s?a\s?m\s?", r"\1 a.m.", un_normalized)
|
||||
un_normalized = re.sub(r"(\d)\s?p\s?m\s?", r"\1 p.m.", un_normalized)
|
||||
normalized = instance.normalized
|
||||
normalized = re.sub(r"[^a-z ]", "", normalized)
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
def filter_plain_1(instance: Instance) -> bool:
|
||||
ok = True
|
||||
return ok
|
||||
|
||||
|
||||
def process_plain_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
normalized = instance.normalized
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
def filter_punct_1(instance: Instance) -> bool:
|
||||
ok = True
|
||||
return ok
|
||||
|
||||
|
||||
def process_punct_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
normalized = instance.normalized
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
def filter_date_1(instance: Instance) -> bool:
|
||||
ok = True
|
||||
return ok
|
||||
|
||||
|
||||
def process_date_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
un_normalized = re.sub(r",", "", un_normalized)
|
||||
normalized = instance.normalized
|
||||
normalized = re.sub(r"[^a-z ]", "", normalized)
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
def filter_letters_1(instance: Instance) -> bool:
|
||||
ok = True
|
||||
return ok
|
||||
|
||||
|
||||
def process_letters_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
normalized = instance.normalized
|
||||
normalized = re.sub(r"[^a-z ]", "", normalized)
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
def filter_verbatim_1(instance: Instance) -> bool:
|
||||
ok = True
|
||||
return ok
|
||||
|
||||
|
||||
def process_verbatim_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
normalized = instance.normalized
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
def filter_digit_1(instance: Instance) -> bool:
|
||||
ok = re.search(r"[0-9]", instance.un_normalized)
|
||||
return ok
|
||||
|
||||
|
||||
def process_digit_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
normalized = instance.normalized
|
||||
normalized = re.sub(r"[^a-z ]", "", normalized)
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
def filter_telephone_1(instance: Instance) -> bool:
|
||||
ok = re.search(r"[0-9]", instance.un_normalized)
|
||||
return ok
|
||||
|
||||
|
||||
def process_telephone_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
normalized = instance.normalized
|
||||
normalized = re.sub(r"[^a-z ]", "", normalized)
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
def filter_electronic_1(instance: Instance) -> bool:
|
||||
ok = re.search(r"[0-9]", instance.un_normalized)
|
||||
return ok
|
||||
|
||||
|
||||
def process_electronic_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
normalized = instance.normalized
|
||||
normalized = re.sub(r"[^a-z ]", "", normalized)
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
def filter_fraction_1(instance: Instance) -> bool:
|
||||
ok = re.search(r"[0-9]", instance.un_normalized)
|
||||
return ok
|
||||
|
||||
|
||||
def process_fraction_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
normalized = instance.normalized
|
||||
normalized = re.sub(r"[^a-z ]", "", normalized)
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
def filter_address_1(instance: Instance) -> bool:
|
||||
ok = True
|
||||
return ok
|
||||
|
||||
|
||||
def process_address_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
normalized = instance.normalized
|
||||
normalized = re.sub(r"[^a-z ]", "", normalized)
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
filters = []
|
||||
filters.append(Filter(class_type="CARDINAL", process_func=process_cardinal_1, filter_func=filter_cardinal_1))
|
||||
filters.append(Filter(class_type="ORDINAL", process_func=process_ordinal_1, filter_func=filter_ordinal_1))
|
||||
filters.append(Filter(class_type="DECIMAL", process_func=process_decimal_1, filter_func=filter_decimal_1))
|
||||
filters.append(Filter(class_type="MEASURE", process_func=process_measure_1, filter_func=filter_measure_1))
|
||||
filters.append(Filter(class_type="MONEY", process_func=process_money_1, filter_func=filter_money_1))
|
||||
filters.append(Filter(class_type="TIME", process_func=process_time_1, filter_func=filter_time_1))
|
||||
|
||||
filters.append(Filter(class_type="DATE", process_func=process_date_1, filter_func=filter_date_1))
|
||||
filters.append(Filter(class_type="PLAIN", process_func=process_plain_1, filter_func=filter_plain_1))
|
||||
filters.append(Filter(class_type="PUNCT", process_func=process_punct_1, filter_func=filter_punct_1))
|
||||
filters.append(Filter(class_type="LETTERS", process_func=process_letters_1, filter_func=filter_letters_1))
|
||||
filters.append(Filter(class_type="VERBATIM", process_func=process_verbatim_1, filter_func=filter_verbatim_1))
|
||||
filters.append(Filter(class_type="DIGIT", process_func=process_digit_1, filter_func=filter_digit_1))
|
||||
filters.append(Filter(class_type="TELEPHONE", process_func=process_telephone_1, filter_func=filter_telephone_1))
|
||||
filters.append(Filter(class_type="ELECTRONIC", process_func=process_electronic_1, filter_func=filter_electronic_1))
|
||||
filters.append(Filter(class_type="FRACTION", process_func=process_fraction_1, filter_func=filter_fraction_1))
|
||||
filters.append(Filter(class_type="ADDRESS", process_func=process_address_1, filter_func=filter_address_1))
|
||||
filters.append(Filter(class_type=EOS_TYPE, process_func=lambda x: x, filter_func=lambda x: True))
|
||||
|
||||
|
||||
def filter_loaded_data(data: List[Instance], verbose: bool = False) -> List[Instance]:
|
||||
"""
|
||||
Filters list of instances
|
||||
|
||||
Args:
|
||||
data: list of instances
|
||||
|
||||
Returns: filtered and transformed list of instances
|
||||
"""
|
||||
updates_instances = []
|
||||
for instance in data:
|
||||
updated_instance = False
|
||||
for fil in filters:
|
||||
if fil.class_type == instance.token_type and fil.filter(instance):
|
||||
instance = fil.process(instance)
|
||||
updated_instance = True
|
||||
if updated_instance:
|
||||
if verbose:
|
||||
print(instance)
|
||||
updates_instances.append(instance)
|
||||
return updates_instances
|
||||
|
||||
|
||||
def parse_args():
|
||||
parser = ArgumentParser()
|
||||
parser.add_argument("--input", help="input file path", type=str, default='./en_with_types/output-00001-of-00100')
|
||||
parser.add_argument("--verbose", help="print filtered instances", action='store_true')
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
args = parse_args()
|
||||
file_path = args.input
|
||||
|
||||
print("Loading training data: " + file_path)
|
||||
instance_list = load_files([file_path]) # List of instances
|
||||
filtered_instance_list = filter_loaded_data(instance_list, args.verbose)
|
||||
training_data_to_sentences(filtered_instance_list)
|
||||
@@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
@@ -0,0 +1,35 @@
|
||||
$ dollar
|
||||
$ us dollar
|
||||
$ united states dollar
|
||||
£ pound
|
||||
€ euro
|
||||
₩ won
|
||||
nzd new zealand dollar
|
||||
rs rupee
|
||||
chf swiss franc
|
||||
dkk danish kroner
|
||||
fim finnish markka
|
||||
aed arab emirates dirham
|
||||
¥ yen
|
||||
czk czech koruna
|
||||
mro mauritanian ouguiya
|
||||
pkr pakistani rupee
|
||||
crc costa rican colon
|
||||
hk$ hong kong dollar
|
||||
npr nepalese rupee
|
||||
awg aruban florin
|
||||
nok norwegian kroner
|
||||
tzs tanzanian shilling
|
||||
sek swedish kronor
|
||||
cyp cypriot pound
|
||||
r real
|
||||
sar saudi riyal
|
||||
cve cape verde escudo
|
||||
rsd serbian dinar
|
||||
dm german mark
|
||||
shp saint helena pounds
|
||||
php philippine peso
|
||||
cad canadian dollar
|
||||
ssp south sudanese pound
|
||||
scr seychelles rupee
|
||||
mvr maldivian rufiyaa
|
||||
|
@@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
@@ -0,0 +1 @@
|
||||
com com
|
||||
|
+2
@@ -0,0 +1,2 @@
|
||||
gmail g mail
|
||||
nvidia n vidia
|
||||
|
@@ -0,0 +1,4 @@
|
||||
k thousand
|
||||
m million
|
||||
b billion
|
||||
t trillion
|
||||
|
@@ -0,0 +1,110 @@
|
||||
f fahrenheit
|
||||
c celsius
|
||||
km kilometer
|
||||
m meter
|
||||
cm centimeter
|
||||
mm millimeter
|
||||
ha hectare
|
||||
mi mile
|
||||
m² square meter
|
||||
km² square kilometer
|
||||
ft foot
|
||||
% percent
|
||||
hz hertz
|
||||
kw kilowatt
|
||||
hp horsepower
|
||||
mg milligram
|
||||
kg kilogram
|
||||
ghz gigahertz
|
||||
khz kilohertz
|
||||
mhz megahertz
|
||||
lb pound
|
||||
v volt
|
||||
h hour
|
||||
mc mega coulomb
|
||||
s second
|
||||
nm nanometer
|
||||
rpm revolution per minute
|
||||
min minute
|
||||
mA milli ampere
|
||||
% per cent
|
||||
kwh kilo watt hour
|
||||
m³ cubic meter
|
||||
mph mile per hour
|
||||
tw tera watt
|
||||
mv milli volt
|
||||
mw megawatt
|
||||
μm micrometer
|
||||
" inch
|
||||
tb terabyte
|
||||
cc c c
|
||||
g gram
|
||||
da dalton
|
||||
atm atmosphere
|
||||
ω ohm
|
||||
db decibel
|
||||
ps peta second
|
||||
oz ounce
|
||||
hl hecto liter
|
||||
μg microgram
|
||||
pg petagram
|
||||
gb gigabyte
|
||||
kb kilobit
|
||||
ev electron volt
|
||||
mb megabyte
|
||||
kb kilobyte
|
||||
kbps kilobit per second
|
||||
mbps megabit per second
|
||||
st stone
|
||||
kl kilo liter
|
||||
tj tera joule
|
||||
kv kilo volt
|
||||
mv mega volt
|
||||
kn kilonewton
|
||||
mm megameter
|
||||
au astronomical unit
|
||||
yd yard
|
||||
rad radian
|
||||
lm lumen
|
||||
hs hecto second
|
||||
mol mole
|
||||
gpa giga pascal
|
||||
ml milliliter
|
||||
gw gigawatt
|
||||
ma mega ampere
|
||||
kt knot
|
||||
kgf kilogram force
|
||||
ng nano gram
|
||||
ns nanosecond
|
||||
ms mega siemens
|
||||
bar bar
|
||||
gl giga liter
|
||||
μs microsecond
|
||||
da deci ampere
|
||||
pa pascal
|
||||
ds deci second
|
||||
ms milli second
|
||||
dm deci meter
|
||||
dm³ cubic deci meter
|
||||
amu atomic mass unit
|
||||
mb megabit
|
||||
mf mega farad
|
||||
bq becquerel
|
||||
pb petabit
|
||||
mm² square millimeter
|
||||
cm² square centimeter
|
||||
sq mi square mile
|
||||
sq ft square foot
|
||||
kpa kilopascal
|
||||
cd candela
|
||||
tl tera liter
|
||||
ms mega second
|
||||
mpa megapascal
|
||||
pm peta meter
|
||||
pb peta byte
|
||||
gwh giga watt hour
|
||||
kcal kilo calory
|
||||
gy gray
|
||||
sv sievert
|
||||
cwt hundredweight
|
||||
cc c c
|
||||
|
Can't render this file because it contains an unexpected character in line 110 and column 8.
|
@@ -0,0 +1,12 @@
|
||||
january
|
||||
february
|
||||
march
|
||||
april
|
||||
may
|
||||
june
|
||||
july
|
||||
august
|
||||
september
|
||||
october
|
||||
november
|
||||
december
|
||||
|
@@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
@@ -0,0 +1,9 @@
|
||||
one 1
|
||||
two 2
|
||||
three 3
|
||||
four 4
|
||||
five 5
|
||||
six 6
|
||||
seven 7
|
||||
eight 8
|
||||
nine 9
|
||||
|
@@ -0,0 +1 @@
|
||||
hundred
|
||||
|
@@ -0,0 +1,10 @@
|
||||
ten 10
|
||||
eleven 11
|
||||
twelve 12
|
||||
thirteen 13
|
||||
fourteen 14
|
||||
fifteen 15
|
||||
sixteen 16
|
||||
seventeen 17
|
||||
eighteen 18
|
||||
nineteen 19
|
||||
|
@@ -0,0 +1,22 @@
|
||||
thousand
|
||||
million
|
||||
billion
|
||||
trillion
|
||||
quadrillion
|
||||
quintillion
|
||||
sextillion
|
||||
septillion
|
||||
octillion
|
||||
nonillion
|
||||
decillion
|
||||
undecillion
|
||||
duodecillion
|
||||
tredecillion
|
||||
quattuordecillion
|
||||
quindecillion
|
||||
sexdecillion
|
||||
septendecillion
|
||||
octodecillion
|
||||
novemdecillion
|
||||
vigintillion
|
||||
centillion
|
||||
|
@@ -0,0 +1,9 @@
|
||||
twenty 2
|
||||
thirty 3
|
||||
forty 4
|
||||
fourty 4
|
||||
fifty 5
|
||||
sixty 6
|
||||
seventy 7
|
||||
eighty 8
|
||||
ninety 9
|
||||
|
@@ -0,0 +1 @@
|
||||
zero 0
|
||||
|
@@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
@@ -0,0 +1,9 @@
|
||||
first one
|
||||
second two
|
||||
third three
|
||||
fourth four
|
||||
fifth five
|
||||
sixth sixth
|
||||
seventh seven
|
||||
eighth eight
|
||||
ninth nine
|
||||
|
@@ -0,0 +1 @@
|
||||
twelfth twelve
|
||||
|
@@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
@@ -0,0 +1,8 @@
|
||||
p m p.m.
|
||||
pm p.m.
|
||||
p.m.
|
||||
p.m p.m.
|
||||
am a.m.
|
||||
a.m.
|
||||
a.m a.m.
|
||||
a m a.m.
|
||||
|
@@ -0,0 +1,12 @@
|
||||
one 12
|
||||
two 1
|
||||
three 2
|
||||
four 3
|
||||
five 4
|
||||
six 5
|
||||
seven 6
|
||||
eigh 7
|
||||
nine 8
|
||||
ten 9
|
||||
eleven 10
|
||||
twelve 11
|
||||
|
@@ -0,0 +1,7 @@
|
||||
cst c s t
|
||||
cet c e t
|
||||
pst p s t
|
||||
est e s t
|
||||
pt p t
|
||||
et e t
|
||||
gmt g m t
|
||||
|
@@ -0,0 +1,10 @@
|
||||
e.g. for example
|
||||
i.e. that is
|
||||
dr. doctor
|
||||
mr. mister
|
||||
mrs. misses
|
||||
ms. miss
|
||||
st. saint
|
||||
7-eleven seven eleven
|
||||
es3 e s three
|
||||
s&p s and p
|
||||
|
@@ -0,0 +1,71 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from typing import List
|
||||
|
||||
from nemo_text_processing.inverse_text_normalization.taggers.tokenize_and_classify import ClassifyFst
|
||||
from nemo_text_processing.inverse_text_normalization.verbalizers.verbalize_final import VerbalizeFinalFst
|
||||
from nemo_text_processing.text_normalization.normalize import Normalizer
|
||||
from nemo_text_processing.text_normalization.token_parser import TokenParser
|
||||
|
||||
|
||||
class InverseNormalizer(Normalizer):
|
||||
"""
|
||||
Inverse normalizer that converts text from spoken to written form. Useful for ASR postprocessing.
|
||||
Input is expected to have no punctuation and be lower cased.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.tagger = ClassifyFst()
|
||||
self.verbalizer = VerbalizeFinalFst()
|
||||
self.parser = TokenParser()
|
||||
|
||||
def inverse_normalize_list(self, texts: List[str], verbose=False) -> List[str]:
|
||||
"""
|
||||
NeMo inverse text normalizer
|
||||
|
||||
Args:
|
||||
texts: list of input strings
|
||||
verbose: whether to print intermediate meta information
|
||||
|
||||
Returns converted list of input strings
|
||||
"""
|
||||
return self.normalize_list(texts=texts, verbose=verbose)
|
||||
|
||||
def inverse_normalize(self, text: str, verbose: bool) -> str:
|
||||
"""
|
||||
Main function. Inverse normalizes tokens from spoken to written form
|
||||
e.g. twelve kilograms -> 12 kg
|
||||
|
||||
Args:
|
||||
text: string that may include semiotic classes
|
||||
verbose: whether to print intermediate meta information
|
||||
|
||||
Returns: written form
|
||||
"""
|
||||
return self.normalize(text=text, verbose=verbose)
|
||||
|
||||
|
||||
def parse_args():
|
||||
parser = ArgumentParser()
|
||||
parser.add_argument("input_string", help="input string", type=str)
|
||||
parser.add_argument("--verbose", help="print info for debugging", action='store_true')
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
args = parse_args()
|
||||
inverse_normalizer = InverseNormalizer()
|
||||
print(inverse_normalizer.inverse_normalize(args.input_string, verbose=args.verbose))
|
||||
@@ -0,0 +1,109 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from argparse import ArgumentParser
|
||||
|
||||
from nemo_text_processing.inverse_text_normalization.clean_eval_data import filter_loaded_data
|
||||
from nemo_text_processing.inverse_text_normalization.inverse_normalize import InverseNormalizer
|
||||
from nemo_text_processing.text_normalization.data_loader_utils import (
|
||||
evaluate,
|
||||
known_types,
|
||||
load_files,
|
||||
training_data_to_sentences,
|
||||
training_data_to_tokens,
|
||||
)
|
||||
|
||||
|
||||
'''
|
||||
Runs Evaluation on data in the format of : <semiotic class>\t<unnormalized text>\t<`self` if trivial class or normalized text>
|
||||
like the Google text normalization data https://www.kaggle.com/richardwilliamsproat/text-normalization-for-english-russian-and-polish
|
||||
'''
|
||||
|
||||
|
||||
def parse_args():
|
||||
parser = ArgumentParser()
|
||||
parser.add_argument("--input", help="input file path", type=str)
|
||||
parser.add_argument(
|
||||
"--cat",
|
||||
dest="category",
|
||||
help="focus on class only (" + ", ".join(known_types) + ")",
|
||||
type=str,
|
||||
default=None,
|
||||
choices=known_types,
|
||||
)
|
||||
parser.add_argument("--filter", action='store_true', help="clean data for inverse normalization purposes")
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Example usage:
|
||||
# python run_evaluate.py --input=<INPUT> --cat=<CATEGORY> --filter
|
||||
args = parse_args()
|
||||
file_path = args.input
|
||||
inverse_normalizer = InverseNormalizer()
|
||||
|
||||
print("Loading training data: " + file_path)
|
||||
training_data = load_files([file_path])
|
||||
|
||||
if args.filter:
|
||||
training_data = filter_loaded_data(training_data)
|
||||
|
||||
if args.category is None:
|
||||
print("Sentence level evaluation...")
|
||||
sentences_un_normalized, sentences_normalized, _ = training_data_to_sentences(training_data)
|
||||
print("- Data: " + str(len(sentences_normalized)) + " sentences")
|
||||
sentences_prediction = inverse_normalizer.inverse_normalize_list(sentences_normalized)
|
||||
print("- Denormalized. Evaluating...")
|
||||
sentences_accuracy = evaluate(
|
||||
preds=sentences_prediction, labels=sentences_un_normalized, input=sentences_normalized
|
||||
)
|
||||
print("- Accuracy: " + str(sentences_accuracy))
|
||||
|
||||
print("Token level evaluation...")
|
||||
tokens_per_type = training_data_to_tokens(training_data, category=args.category)
|
||||
token_accuracy = {}
|
||||
for token_type in tokens_per_type:
|
||||
print("- Token type: " + token_type)
|
||||
tokens_un_normalized, tokens_normalized = tokens_per_type[token_type]
|
||||
print(" - Data: " + str(len(tokens_normalized)) + " tokens")
|
||||
tokens_prediction = inverse_normalizer.inverse_normalize_list(tokens_normalized)
|
||||
print(" - Denormalized. Evaluating...")
|
||||
token_accuracy[token_type] = evaluate(tokens_prediction, tokens_un_normalized, input=tokens_normalized)
|
||||
print(" - Accuracy: " + str(token_accuracy[token_type]))
|
||||
token_count_per_type = {token_type: len(tokens_per_type[token_type][0]) for token_type in tokens_per_type}
|
||||
token_weighted_accuracy = [
|
||||
token_count_per_type[token_type] * accuracy for token_type, accuracy in token_accuracy.items()
|
||||
]
|
||||
print("- Accuracy: " + str(sum(token_weighted_accuracy) / sum(token_count_per_type.values())))
|
||||
|
||||
print(" - Total: " + str(sum(token_count_per_type.values())), '\n')
|
||||
|
||||
for token_type in token_accuracy:
|
||||
if token_type not in known_types:
|
||||
raise ValueError("Unexpected token type: " + token_type)
|
||||
|
||||
if args.category is None:
|
||||
c1 = ['Class', 'sent level'] + known_types
|
||||
c2 = ['Num Tokens', len(sentences_normalized)] + [
|
||||
token_count_per_type[known_type] if known_type in tokens_per_type else '0' for known_type in known_types
|
||||
]
|
||||
c3 = ["Denormalization", sentences_accuracy] + [
|
||||
token_accuracy[known_type] if known_type in token_accuracy else '0' for known_type in known_types
|
||||
]
|
||||
|
||||
for i in range(len(c1)):
|
||||
print(f'{str(c1[i]):10s} | {str(c2[i]):10s} | {str(c3[i]):5s}')
|
||||
else:
|
||||
print(f'numbers\t{token_count_per_type[args.category]}')
|
||||
print(f'Denormalization\t{token_accuracy[args.category]}')
|
||||
@@ -0,0 +1,75 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from typing import List
|
||||
|
||||
from nemo_text_processing.inverse_text_normalization.inverse_normalize import InverseNormalizer
|
||||
|
||||
|
||||
'''
|
||||
Runs inverse text normalization on text data
|
||||
'''
|
||||
|
||||
|
||||
def load_file(file_path: str) -> List[str]:
|
||||
"""
|
||||
Load given text file into list of string.
|
||||
|
||||
Args:
|
||||
file_path: file path
|
||||
|
||||
Returns: flat list of string
|
||||
"""
|
||||
res = []
|
||||
with open(file_path, 'r') as fp:
|
||||
for line in fp:
|
||||
res.append(line)
|
||||
return res
|
||||
|
||||
|
||||
def write_file(file_path: str, data: List[str]):
|
||||
"""
|
||||
Writes out list of string to file.
|
||||
|
||||
Args:
|
||||
file_path: file path
|
||||
data: list of string
|
||||
|
||||
"""
|
||||
with open(file_path, 'w') as fp:
|
||||
for line in data:
|
||||
fp.write(line + '\n')
|
||||
|
||||
|
||||
def parse_args():
|
||||
parser = ArgumentParser()
|
||||
parser.add_argument("--input", help="input file path", required=True, type=str)
|
||||
parser.add_argument("--output", help="output file path", required=True, type=str)
|
||||
parser.add_argument("--verbose", help="print denormalization info. For debugging", action='store_true')
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
args = parse_args()
|
||||
file_path = args.input
|
||||
inverse_normalizer = InverseNormalizer()
|
||||
|
||||
print("Loading data: " + file_path)
|
||||
data = load_file(file_path)
|
||||
|
||||
print("- Data: " + str(len(data)) + " sentences")
|
||||
inverse_normalizer_prediction = inverse_normalizer.inverse_normalize_list(data, verbose=args.verbose)
|
||||
write_file(args.output, inverse_normalizer_prediction)
|
||||
print(f"- Denormalized. Writing out to {args.output}")
|
||||
@@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
@@ -0,0 +1,134 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright 2015 and onwards Google, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
from nemo_text_processing.inverse_text_normalization.utils import get_abs_path, num_to_word
|
||||
from nemo_text_processing.text_normalization.graph_utils import (
|
||||
NEMO_DIGIT,
|
||||
NEMO_SIGMA,
|
||||
NEMO_SPACE,
|
||||
GraphFst,
|
||||
delete_space,
|
||||
)
|
||||
|
||||
try:
|
||||
import pynini
|
||||
from pynini.lib import pynutil
|
||||
|
||||
PYNINI_AVAILABLE = True
|
||||
except (ModuleNotFoundError, ImportError):
|
||||
PYNINI_AVAILABLE = False
|
||||
|
||||
|
||||
class CardinalFst(GraphFst):
|
||||
"""
|
||||
Finite state transducer for classifying cardinals
|
||||
e.g. minus twenty three -> cardinal { integer: "23" negative: "-" } }
|
||||
Numbers below thirteen are not converted.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(name="cardinal", kind="classify")
|
||||
graph_zero = pynini.string_file(get_abs_path("data/numbers/zero.tsv"))
|
||||
graph_digit = pynini.string_file(get_abs_path("data/numbers/digit.tsv"))
|
||||
graph_ties = pynini.string_file(get_abs_path("data/numbers/ties.tsv"))
|
||||
graph_teen = pynini.string_file(get_abs_path("data/numbers/teen.tsv"))
|
||||
|
||||
graph_hundred = pynini.cross("hundred", "")
|
||||
|
||||
graph_hundred_component = pynini.union(graph_digit + delete_space + graph_hundred, pynutil.insert("0"))
|
||||
graph_hundred_component += delete_space
|
||||
graph_hundred_component += pynini.union(
|
||||
graph_teen | pynutil.insert("00"),
|
||||
(graph_ties | pynutil.insert("0")) + delete_space + (graph_digit | pynutil.insert("0")),
|
||||
)
|
||||
|
||||
graph_hundred_component_at_least_one_none_zero_digit = graph_hundred_component @ (
|
||||
pynini.closure(NEMO_DIGIT) + (NEMO_DIGIT - "0") + pynini.closure(NEMO_DIGIT)
|
||||
)
|
||||
self.graph_hundred_component_at_least_one_none_zero_digit = (
|
||||
graph_hundred_component_at_least_one_none_zero_digit
|
||||
)
|
||||
|
||||
graph_thousands = pynini.union(
|
||||
graph_hundred_component_at_least_one_none_zero_digit + delete_space + pynutil.delete("thousand"),
|
||||
pynutil.insert("000", weight=0.1),
|
||||
)
|
||||
|
||||
graph_million = pynini.union(
|
||||
graph_hundred_component_at_least_one_none_zero_digit + delete_space + pynutil.delete("million"),
|
||||
pynutil.insert("000", weight=0.1),
|
||||
)
|
||||
graph_billion = pynini.union(
|
||||
graph_hundred_component_at_least_one_none_zero_digit + delete_space + pynutil.delete("billion"),
|
||||
pynutil.insert("000", weight=0.1),
|
||||
)
|
||||
graph_trillion = pynini.union(
|
||||
graph_hundred_component_at_least_one_none_zero_digit + delete_space + pynutil.delete("trillion"),
|
||||
pynutil.insert("000", weight=0.1),
|
||||
)
|
||||
graph_quadrillion = pynini.union(
|
||||
graph_hundred_component_at_least_one_none_zero_digit + delete_space + pynutil.delete("quadrillion"),
|
||||
pynutil.insert("000", weight=0.1),
|
||||
)
|
||||
graph_quintillion = pynini.union(
|
||||
graph_hundred_component_at_least_one_none_zero_digit + delete_space + pynutil.delete("quintillion"),
|
||||
pynutil.insert("000", weight=0.1),
|
||||
)
|
||||
graph_sextillion = pynini.union(
|
||||
graph_hundred_component_at_least_one_none_zero_digit + delete_space + pynutil.delete("sextillion"),
|
||||
pynutil.insert("000", weight=0.1),
|
||||
)
|
||||
|
||||
graph = pynini.union(
|
||||
graph_sextillion
|
||||
+ delete_space
|
||||
+ graph_quintillion
|
||||
+ delete_space
|
||||
+ graph_quadrillion
|
||||
+ delete_space
|
||||
+ graph_trillion
|
||||
+ delete_space
|
||||
+ graph_billion
|
||||
+ delete_space
|
||||
+ graph_million
|
||||
+ delete_space
|
||||
+ graph_thousands
|
||||
+ delete_space
|
||||
+ graph_hundred_component,
|
||||
graph_zero,
|
||||
)
|
||||
|
||||
graph = graph @ pynini.union(
|
||||
pynutil.delete(pynini.closure("0")) + pynini.difference(NEMO_DIGIT, "0") + pynini.closure(NEMO_DIGIT), "0"
|
||||
)
|
||||
|
||||
labels_exception = [num_to_word(x) for x in range(0, 13)]
|
||||
graph_exception = pynini.union(*labels_exception)
|
||||
|
||||
graph = pynini.cdrewrite(pynutil.delete("and"), NEMO_SPACE, NEMO_SPACE, NEMO_SIGMA) @ graph
|
||||
|
||||
self.graph_no_exception = graph
|
||||
|
||||
self.graph = (pynini.project(graph, "input") - graph_exception.arcsort()) @ graph
|
||||
|
||||
optional_minus_graph = pynini.closure(
|
||||
pynutil.insert("negative: ") + pynini.cross("minus", "\"-\"") + NEMO_SPACE, 0, 1
|
||||
)
|
||||
|
||||
final_graph = optional_minus_graph + pynutil.insert("integer: \"") + self.graph + pynutil.insert("\"")
|
||||
|
||||
final_graph = self.add_tokens(final_graph)
|
||||
self.fst = final_graph.optimize()
|
||||
@@ -0,0 +1,163 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright 2015 and onwards Google, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from nemo_text_processing.inverse_text_normalization.utils import get_abs_path
|
||||
from nemo_text_processing.text_normalization.graph_utils import (
|
||||
NEMO_ALPHA,
|
||||
NEMO_DIGIT,
|
||||
GraphFst,
|
||||
delete_extra_space,
|
||||
delete_space,
|
||||
)
|
||||
|
||||
try:
|
||||
import pynini
|
||||
from pynini.lib import pynutil
|
||||
|
||||
graph_teen = pynini.string_file(get_abs_path("data/numbers/teen.tsv")).optimize()
|
||||
graph_digit = pynini.string_file(get_abs_path("data/numbers/digit.tsv")).optimize()
|
||||
ties_graph = pynini.string_file(get_abs_path("data/numbers/ties.tsv")).optimize()
|
||||
|
||||
PYNINI_AVAILABLE = True
|
||||
except (ModuleNotFoundError, ImportError):
|
||||
graph_teen = None
|
||||
graph_digit = None
|
||||
ties_graph = None
|
||||
|
||||
PYNINI_AVAILABLE = True
|
||||
|
||||
|
||||
def _get_month_graph():
|
||||
"""
|
||||
Transducer for month, e.g. march -> march
|
||||
"""
|
||||
month_graph = pynini.string_file(get_abs_path("data/months.tsv"))
|
||||
return month_graph
|
||||
|
||||
|
||||
def _get_ties_graph():
|
||||
"""
|
||||
Transducer for 20-99 e.g
|
||||
twenty three -> 23
|
||||
"""
|
||||
graph = ties_graph + (delete_space + graph_digit | pynutil.insert("0"))
|
||||
return graph
|
||||
|
||||
|
||||
def _get_range_graph():
|
||||
"""
|
||||
Transducer for decades (1**0s, 2**0s), centuries (2*00s, 1*00s), millennia (2000s)
|
||||
"""
|
||||
graph_ties = _get_ties_graph()
|
||||
graph = (graph_ties | graph_teen) + delete_space + pynini.cross("hundreds", "00s")
|
||||
graph |= pynini.cross("two", "2") + delete_space + pynini.cross("thousands", "000s")
|
||||
graph |= (
|
||||
(graph_ties | graph_teen)
|
||||
+ delete_space
|
||||
+ (pynini.closure(NEMO_ALPHA, 1) + (pynini.cross("ies", "y") | pynutil.delete("s")))
|
||||
@ (graph_ties | pynini.cross("ten", "10"))
|
||||
+ pynutil.insert("s")
|
||||
)
|
||||
graph @= pynini.union("1", "2") + NEMO_DIGIT + NEMO_DIGIT + NEMO_DIGIT + "s"
|
||||
return graph
|
||||
|
||||
|
||||
def _get_year_graph():
|
||||
"""
|
||||
Transducer for year, e.g. twenty twenty -> 2020
|
||||
"""
|
||||
|
||||
def _get_digits_graph():
|
||||
zero = pynini.cross((pynini.accep("oh") | pynini.accep("o")), "0")
|
||||
graph = zero + delete_space + graph_digit
|
||||
graph.optimize()
|
||||
return graph
|
||||
|
||||
def _get_thousands_graph():
|
||||
graph_ties = _get_ties_graph()
|
||||
graph_hundred_component = (graph_digit + delete_space + pynutil.delete("hundred")) | pynutil.insert("0")
|
||||
graph = (
|
||||
graph_digit
|
||||
+ delete_space
|
||||
+ pynutil.delete("thousand")
|
||||
+ delete_space
|
||||
+ graph_hundred_component
|
||||
+ delete_space
|
||||
+ (graph_teen | graph_ties)
|
||||
)
|
||||
return graph
|
||||
|
||||
graph_ties = _get_ties_graph()
|
||||
graph_digits = _get_digits_graph()
|
||||
graph_thousands = _get_thousands_graph()
|
||||
year_graph = (
|
||||
# 20 19, 40 12, 2012 - assuming no limit on the year
|
||||
(graph_teen + delete_space + (graph_ties | graph_digits | graph_teen))
|
||||
| (graph_ties + delete_space + (graph_ties | graph_digits | graph_teen))
|
||||
| graph_thousands
|
||||
)
|
||||
year_graph.optimize()
|
||||
return year_graph
|
||||
|
||||
|
||||
class DateFst(GraphFst):
|
||||
"""
|
||||
Finite state transducer for classifying date,
|
||||
e.g. january fifth twenty twelve -> date { month: "january" day: "5" year: "2012" preserve_order: true }
|
||||
e.g. the fifth of january twenty twelve -> date { day: "5" month: "january" year: "2012" preserve_order: true }
|
||||
e.g. twenty twenty -> date { year: "2012" preserve_order: true }
|
||||
|
||||
Args:
|
||||
ordinal: OrdinalFst
|
||||
"""
|
||||
|
||||
def __init__(self, ordinal: GraphFst):
|
||||
super().__init__(name="date", kind="classify")
|
||||
|
||||
ordinal_graph = ordinal.graph
|
||||
year_graph = _get_year_graph()
|
||||
YEAR_WEIGHT = 0.001
|
||||
year_graph = pynutil.add_weight(year_graph, YEAR_WEIGHT)
|
||||
month_graph = _get_month_graph()
|
||||
|
||||
month_graph = pynutil.insert("month: \"") + month_graph + pynutil.insert("\"")
|
||||
|
||||
day_graph = pynutil.insert("day: \"") + pynutil.add_weight(ordinal_graph, -0.7) + pynutil.insert("\"")
|
||||
optional_day_graph = pynini.closure(delete_extra_space + day_graph, 0, 1)
|
||||
optional_graph_year = pynini.closure(
|
||||
delete_extra_space
|
||||
+ pynutil.insert("year: \"")
|
||||
+ pynutil.add_weight(year_graph, -YEAR_WEIGHT)
|
||||
+ pynutil.insert("\""),
|
||||
0,
|
||||
1,
|
||||
)
|
||||
graph_mdy = month_graph + optional_day_graph + optional_graph_year
|
||||
graph_dmy = (
|
||||
pynutil.delete("the")
|
||||
+ delete_space
|
||||
+ day_graph
|
||||
+ delete_space
|
||||
+ pynutil.delete("of")
|
||||
+ delete_extra_space
|
||||
+ month_graph
|
||||
+ optional_graph_year
|
||||
)
|
||||
graph_year = pynutil.insert("year: \"") + (year_graph | _get_range_graph()) + pynutil.insert("\"")
|
||||
|
||||
final_graph = graph_mdy | graph_dmy | graph_year
|
||||
final_graph += pynutil.insert(" preserve_order: true")
|
||||
final_graph = self.add_tokens(final_graph)
|
||||
self.fst = final_graph.optimize()
|
||||
@@ -0,0 +1,95 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright 2015 and onwards Google, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from nemo_text_processing.inverse_text_normalization.utils import get_abs_path
|
||||
from nemo_text_processing.text_normalization.graph_utils import NEMO_DIGIT, GraphFst, delete_extra_space, delete_space
|
||||
|
||||
try:
|
||||
import pynini
|
||||
from pynini.lib import pynutil
|
||||
|
||||
PYNINI_AVAILABLE = True
|
||||
except (ModuleNotFoundError, ImportError):
|
||||
PYNINI_AVAILABLE = False
|
||||
|
||||
|
||||
def get_quantity(decimal: 'pynini.FstLike', cardinal_up_to_hundred: 'pynini.FstLike') -> 'pynini.FstLike':
|
||||
"""
|
||||
Returns FST that transforms either a cardinal or decimal followed by a quantity into a numeral,
|
||||
e.g. one million -> integer_part: "1" quantity: "million"
|
||||
e.g. one point five million -> integer_part: "1" fractional_part: "5" quantity: "million"
|
||||
|
||||
Args:
|
||||
decimal: decimal FST
|
||||
cardinal_up_to_hundred: cardinal FST
|
||||
"""
|
||||
numbers = cardinal_up_to_hundred @ (
|
||||
pynutil.delete(pynini.closure("0")) + pynini.difference(NEMO_DIGIT, "0") + pynini.closure(NEMO_DIGIT)
|
||||
)
|
||||
suffix = pynini.union("million", "billion", "trillion", "quadrillion", "quintillion", "sextillion")
|
||||
res = (
|
||||
pynutil.insert("integer_part: \"")
|
||||
+ numbers
|
||||
+ pynutil.insert("\"")
|
||||
+ delete_extra_space
|
||||
+ pynutil.insert("quantity: \"")
|
||||
+ suffix
|
||||
+ pynutil.insert("\"")
|
||||
)
|
||||
res |= decimal + delete_extra_space + pynutil.insert("quantity: \"") + (suffix | "thousand") + pynutil.insert("\"")
|
||||
return res
|
||||
|
||||
|
||||
class DecimalFst(GraphFst):
|
||||
"""
|
||||
Finite state transducer for classifying decimal
|
||||
e.g. minus twelve point five o o six billion -> decimal { negative: "true" integer_part: "12" fractional_part: "5006" quantity: "billion" }
|
||||
e.g. one billion -> decimal { integer_part: "1" quantity: "billion" }
|
||||
Args:
|
||||
cardinal: CardinalFst
|
||||
"""
|
||||
|
||||
def __init__(self, cardinal: GraphFst):
|
||||
super().__init__(name="decimal", kind="classify")
|
||||
|
||||
cardinal_graph = cardinal.graph_no_exception
|
||||
|
||||
graph_decimal = pynini.string_file(get_abs_path("data/numbers/digit.tsv"))
|
||||
graph_decimal |= pynini.string_file(get_abs_path("data/numbers/zero.tsv")) | pynini.cross("o", "0")
|
||||
|
||||
graph_decimal = pynini.closure(graph_decimal + delete_space) + graph_decimal
|
||||
self.graph = graph_decimal
|
||||
|
||||
point = pynutil.delete("point")
|
||||
|
||||
optional_graph_negative = pynini.closure(
|
||||
pynutil.insert("negative: ") + pynini.cross("minus", "\"true\"") + delete_extra_space, 0, 1
|
||||
)
|
||||
|
||||
graph_fractional = pynutil.insert("fractional_part: \"") + graph_decimal + pynutil.insert("\"")
|
||||
graph_integer = pynutil.insert("integer_part: \"") + cardinal_graph + pynutil.insert("\"")
|
||||
final_graph_wo_sign = (
|
||||
pynini.closure(graph_integer + delete_extra_space, 0, 1) + point + delete_extra_space + graph_fractional
|
||||
)
|
||||
final_graph = optional_graph_negative + final_graph_wo_sign
|
||||
|
||||
self.final_graph_wo_negative = final_graph_wo_sign | get_quantity(
|
||||
final_graph_wo_sign, cardinal.graph_hundred_component_at_least_one_none_zero_digit
|
||||
)
|
||||
final_graph |= optional_graph_negative + get_quantity(
|
||||
final_graph_wo_sign, cardinal.graph_hundred_component_at_least_one_none_zero_digit
|
||||
)
|
||||
final_graph = self.add_tokens(final_graph)
|
||||
self.fst = final_graph.optimize()
|
||||
@@ -0,0 +1,66 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright 2015 and onwards Google, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from nemo_text_processing.inverse_text_normalization.utils import get_abs_path
|
||||
from nemo_text_processing.text_normalization.graph_utils import NEMO_ALPHA, GraphFst, insert_space
|
||||
|
||||
try:
|
||||
import pynini
|
||||
from pynini.lib import pynutil
|
||||
|
||||
PYNINI_AVAILABLE = True
|
||||
except (ModuleNotFoundError, ImportError):
|
||||
PYNINI_AVAILABLE = False
|
||||
|
||||
|
||||
class ElectronicFst(GraphFst):
|
||||
"""
|
||||
Finite state transducer for classifying electronic: as URLs, email addresses, etc.
|
||||
e.g. c d f one at a b c dot e d u -> tokens { electronic { username: "cdf1" domain: "abc.edu" } }
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(name="electronic", kind="classify")
|
||||
|
||||
delete_extra_space = pynutil.delete(" ")
|
||||
alpha_num = (
|
||||
NEMO_ALPHA
|
||||
| pynini.string_file(get_abs_path("data/numbers/digit.tsv"))
|
||||
| pynini.string_file(get_abs_path("data/numbers/zero.tsv"))
|
||||
)
|
||||
username = (
|
||||
pynutil.insert("username: \"")
|
||||
+ pynini.closure(
|
||||
alpha_num + delete_extra_space + pynini.closure(pynini.cross("dot", '.') + delete_extra_space, 0, 1)
|
||||
)
|
||||
+ alpha_num
|
||||
+ pynutil.insert("\"")
|
||||
)
|
||||
single_alphanum = pynini.closure(alpha_num + delete_extra_space) + alpha_num
|
||||
server = single_alphanum | pynini.string_file(get_abs_path("data/electronic/server_name.tsv")).invert()
|
||||
domain = single_alphanum | pynini.string_file(get_abs_path("data/electronic/domain.tsv")).invert()
|
||||
domain_graph = (
|
||||
pynutil.insert("domain: \"")
|
||||
+ server
|
||||
+ delete_extra_space
|
||||
+ pynini.cross("dot", ".")
|
||||
+ delete_extra_space
|
||||
+ domain
|
||||
+ pynutil.insert("\"")
|
||||
)
|
||||
graph = username + delete_extra_space + pynutil.delete("at") + insert_space + delete_extra_space + domain_graph
|
||||
|
||||
final_graph = self.add_tokens(graph)
|
||||
self.fst = final_graph.optimize()
|
||||
@@ -0,0 +1,26 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright 2015 and onwards Google, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from nemo_text_processing.text_normalization.graph_utils import GraphFst
|
||||
|
||||
|
||||
class FractionFst(GraphFst):
|
||||
"""
|
||||
Finite state transducer for classifying fraction
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(name="fraction", kind="classify")
|
||||
# integer_part # numerator # denominator
|
||||
@@ -0,0 +1,103 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright 2015 and onwards Google, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from nemo_text_processing.inverse_text_normalization.utils import get_abs_path
|
||||
from nemo_text_processing.text_normalization.graph_utils import (
|
||||
NEMO_SIGMA,
|
||||
GraphFst,
|
||||
convert_space,
|
||||
delete_extra_space,
|
||||
delete_space,
|
||||
get_singulars,
|
||||
)
|
||||
|
||||
try:
|
||||
import pynini
|
||||
from pynini.lib import pynutil
|
||||
|
||||
PYNINI_AVAILABLE = True
|
||||
except (ModuleNotFoundError, ImportError):
|
||||
PYNINI_AVAILABLE = False
|
||||
|
||||
|
||||
class MeasureFst(GraphFst):
|
||||
"""
|
||||
Finite state transducer for classifying measure
|
||||
e.g. minus twelve kilograms -> measure { negative: "true" cardinal { integer: "12" } units: "kg" }
|
||||
|
||||
Args:
|
||||
cardinal: CardinalFst
|
||||
decimal: DecimalFst
|
||||
"""
|
||||
|
||||
def __init__(self, cardinal: GraphFst, decimal: GraphFst):
|
||||
super().__init__(name="measure", kind="classify")
|
||||
|
||||
cardinal_graph = cardinal.graph_no_exception
|
||||
|
||||
graph_unit = pynini.string_file(get_abs_path("data/measurements.tsv"))
|
||||
graph_unit_singular = pynini.invert(graph_unit) # singular -> abbr
|
||||
graph_unit_plural = get_singulars(graph_unit_singular) # plural -> abbr
|
||||
|
||||
optional_graph_negative = pynini.closure(
|
||||
pynutil.insert("negative: ") + pynini.cross("minus", "\"true\"") + delete_extra_space, 0, 1
|
||||
)
|
||||
|
||||
unit_singular = convert_space(graph_unit_singular)
|
||||
unit_plural = convert_space(graph_unit_plural)
|
||||
unit_misc = pynutil.insert("/") + pynutil.delete("per") + delete_space + convert_space(graph_unit_singular)
|
||||
|
||||
unit_singular = (
|
||||
pynutil.insert("units: \"")
|
||||
+ (unit_singular | unit_misc | pynutil.add_weight(unit_singular + delete_space + unit_misc, 0.01))
|
||||
+ pynutil.insert("\"")
|
||||
)
|
||||
unit_plural = (
|
||||
pynutil.insert("units: \"")
|
||||
+ (unit_plural | unit_misc | pynutil.add_weight(unit_plural + delete_space + unit_misc, 0.01))
|
||||
+ pynutil.insert("\"")
|
||||
)
|
||||
|
||||
subgraph_decimal = (
|
||||
pynutil.insert("decimal { ")
|
||||
+ optional_graph_negative
|
||||
+ decimal.final_graph_wo_negative
|
||||
+ pynutil.insert(" }")
|
||||
+ delete_extra_space
|
||||
+ unit_plural
|
||||
)
|
||||
subgraph_cardinal = (
|
||||
pynutil.insert("cardinal { ")
|
||||
+ optional_graph_negative
|
||||
+ pynutil.insert("integer: \"")
|
||||
+ ((NEMO_SIGMA - "one") @ cardinal_graph)
|
||||
+ pynutil.insert("\"")
|
||||
+ pynutil.insert(" }")
|
||||
+ delete_extra_space
|
||||
+ unit_plural
|
||||
)
|
||||
subgraph_cardinal |= (
|
||||
pynutil.insert("cardinal { ")
|
||||
+ optional_graph_negative
|
||||
+ pynutil.insert("integer: \"")
|
||||
+ pynini.cross("one", "1")
|
||||
+ pynutil.insert("\"")
|
||||
+ pynutil.insert(" }")
|
||||
+ delete_extra_space
|
||||
+ unit_singular
|
||||
)
|
||||
final_graph = subgraph_decimal | subgraph_cardinal
|
||||
final_graph = self.add_tokens(final_graph)
|
||||
self.fst = final_graph.optimize()
|
||||
@@ -0,0 +1,112 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright 2015 and onwards Google, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from nemo_text_processing.inverse_text_normalization.utils import get_abs_path
|
||||
from nemo_text_processing.text_normalization.graph_utils import (
|
||||
NEMO_DIGIT,
|
||||
NEMO_SIGMA,
|
||||
GraphFst,
|
||||
convert_space,
|
||||
delete_extra_space,
|
||||
delete_space,
|
||||
get_singulars,
|
||||
insert_space,
|
||||
)
|
||||
|
||||
try:
|
||||
import pynini
|
||||
from pynini.lib import pynutil
|
||||
|
||||
PYNINI_AVAILABLE = True
|
||||
except (ModuleNotFoundError, ImportError):
|
||||
PYNINI_AVAILABLE = False
|
||||
|
||||
|
||||
class MoneyFst(GraphFst):
|
||||
"""
|
||||
Finite state transducer for classifying money
|
||||
e.g. twelve dollars and five cents -> money { integer_part: "12" fractional_part: 05 currency: "$" }
|
||||
|
||||
Args:
|
||||
cardinal: CardinalFst
|
||||
decimal: DecimalFst
|
||||
"""
|
||||
|
||||
def __init__(self, cardinal: GraphFst, decimal: GraphFst):
|
||||
super().__init__(name="money", kind="classify")
|
||||
# quantity, integer_part, fractional_part, currency
|
||||
|
||||
cardinal_graph = cardinal.graph_no_exception
|
||||
graph_decimal_final = decimal.final_graph_wo_negative
|
||||
|
||||
unit = pynini.string_file(get_abs_path("data/currency.tsv"))
|
||||
unit_singular = pynini.invert(unit)
|
||||
unit_plural = get_singulars(unit_singular)
|
||||
|
||||
graph_unit_singular = pynutil.insert("currency: \"") + convert_space(unit_singular) + pynutil.insert("\"")
|
||||
graph_unit_plural = pynutil.insert("currency: \"") + convert_space(unit_plural) + pynutil.insert("\"")
|
||||
|
||||
add_leading_zero_to_double_digit = (NEMO_DIGIT + NEMO_DIGIT) | (pynutil.insert("0") + NEMO_DIGIT)
|
||||
# twelve dollars (and) fifty cents, zero cents
|
||||
cents_standalone = (
|
||||
pynutil.insert("fractional_part: \"")
|
||||
+ pynini.union(
|
||||
pynutil.add_weight(((NEMO_SIGMA - "one") @ cardinal_graph), -0.7) @ add_leading_zero_to_double_digit
|
||||
+ delete_space
|
||||
+ pynutil.delete("cents"),
|
||||
pynini.cross("one", "01") + delete_space + pynutil.delete("cent"),
|
||||
)
|
||||
+ pynutil.insert("\"")
|
||||
)
|
||||
|
||||
optional_cents_standalone = pynini.closure(
|
||||
delete_space
|
||||
+ pynini.closure(pynutil.delete("and") + delete_space, 0, 1)
|
||||
+ insert_space
|
||||
+ cents_standalone,
|
||||
0,
|
||||
1,
|
||||
)
|
||||
# twelve dollars fifty, only after integer
|
||||
optional_cents_suffix = pynini.closure(
|
||||
delete_extra_space
|
||||
+ pynutil.insert("fractional_part: \"")
|
||||
+ pynutil.add_weight(cardinal_graph @ add_leading_zero_to_double_digit, -0.7)
|
||||
+ pynutil.insert("\""),
|
||||
0,
|
||||
1,
|
||||
)
|
||||
|
||||
graph_integer = (
|
||||
pynutil.insert("integer_part: \"")
|
||||
+ ((NEMO_SIGMA - "one") @ cardinal_graph)
|
||||
+ pynutil.insert("\"")
|
||||
+ delete_extra_space
|
||||
+ graph_unit_plural
|
||||
+ (optional_cents_standalone | optional_cents_suffix)
|
||||
)
|
||||
graph_integer |= (
|
||||
pynutil.insert("integer_part: \"")
|
||||
+ pynini.cross("one", "1")
|
||||
+ pynutil.insert("\"")
|
||||
+ delete_extra_space
|
||||
+ graph_unit_singular
|
||||
+ (optional_cents_standalone | optional_cents_suffix)
|
||||
)
|
||||
graph_decimal = graph_decimal_final + delete_extra_space + graph_unit_plural
|
||||
graph_decimal |= pynutil.insert("currency: \"$\" integer_part: \"0\" ") + cents_standalone
|
||||
final_graph = graph_integer | graph_decimal
|
||||
final_graph = self.add_tokens(final_graph)
|
||||
self.fst = final_graph.optimize()
|
||||
@@ -0,0 +1,50 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright 2015 and onwards Google, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from nemo_text_processing.inverse_text_normalization.utils import get_abs_path
|
||||
from nemo_text_processing.text_normalization.graph_utils import NEMO_CHAR, GraphFst
|
||||
|
||||
try:
|
||||
import pynini
|
||||
from pynini.lib import pynutil
|
||||
|
||||
PYNINI_AVAILABLE = True
|
||||
except (ImportError, ModuleNotFoundError):
|
||||
PYNINI_AVAILABLE = False
|
||||
|
||||
|
||||
class OrdinalFst(GraphFst):
|
||||
"""
|
||||
Finite state transducer for classifying ordinal
|
||||
e.g. thirteenth -> ordinal { integer: "13" }
|
||||
|
||||
Args:
|
||||
cardinal: CardinalFst
|
||||
"""
|
||||
|
||||
def __init__(self, cardinal: GraphFst):
|
||||
super().__init__(name="ordinal", kind="classify")
|
||||
|
||||
cardinal_graph = cardinal.graph_no_exception
|
||||
graph_digit = pynini.string_file(get_abs_path("data/ordinals/digit.tsv"))
|
||||
graph_teens = pynini.string_file(get_abs_path("data/ordinals/teen.tsv"))
|
||||
graph = pynini.closure(NEMO_CHAR) + pynini.union(
|
||||
graph_digit, graph_teens, pynini.cross("tieth", "ty"), pynini.cross("th", "")
|
||||
)
|
||||
|
||||
self.graph = graph @ cardinal_graph
|
||||
final_graph = pynutil.insert("integer: \"") + self.graph + pynutil.insert("\"")
|
||||
final_graph = self.add_tokens(final_graph)
|
||||
self.fst = final_graph.optimize()
|
||||
@@ -0,0 +1,41 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright 2015 and onwards Google, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from nemo_text_processing.text_normalization.graph_utils import GraphFst
|
||||
|
||||
try:
|
||||
import pynini
|
||||
from pynini.lib import pynutil
|
||||
|
||||
PYNINI_AVAILABLE = False
|
||||
except (ModuleNotFoundError, ImportError):
|
||||
PYNINI_AVAILABLE = False
|
||||
|
||||
|
||||
class PunctuationFst(GraphFst):
|
||||
"""
|
||||
Finite state transducer for classifying punctuation
|
||||
e.g. a, -> tokens { name: "a" } tokens { name: "," }
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(name="punctuation", kind="classify")
|
||||
|
||||
s = "!#$%&\'()*+,-./:;<=>?@^_`{|}~"
|
||||
punct = pynini.union(*s)
|
||||
|
||||
graph = pynutil.insert("name: \"") + punct + pynutil.insert("\"")
|
||||
|
||||
self.fst = graph.optimize()
|
||||
@@ -0,0 +1,67 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright 2015 and onwards Google, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from nemo_text_processing.inverse_text_normalization.utils import get_abs_path
|
||||
from nemo_text_processing.text_normalization.graph_utils import GraphFst, delete_space, insert_space
|
||||
|
||||
try:
|
||||
import pynini
|
||||
from pynini.lib import pynutil
|
||||
|
||||
PYNINI_AVAILABLE = True
|
||||
except (ModuleNotFoundError, ImportError):
|
||||
PYNINI_AVAILABLE = False
|
||||
|
||||
|
||||
class TelephoneFst(GraphFst):
|
||||
"""
|
||||
Finite state transducer for classifying telephone numbers, e.g.
|
||||
one two three one two three five six seven eight -> { number_part: "123-123-5678" }
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(name="telephone", kind="classify")
|
||||
delete_space = pynutil.delete(' ')
|
||||
# country code, number_part, extension
|
||||
add_separator = pynutil.insert(" ") # between components
|
||||
digit = pynini.invert(pynini.string_file(get_abs_path("data/numbers/digit.tsv"))).optimize() | pynini.cross(
|
||||
"0", pynini.union("o", "oh", "zero")
|
||||
)
|
||||
|
||||
number_part = (
|
||||
(
|
||||
(pynini.closure(digit + insert_space, 2, 2) + digit + pynutil.delete("-"))
|
||||
| (
|
||||
pynutil.delete("(")
|
||||
+ pynini.closure(digit + insert_space, 2, 2)
|
||||
+ digit
|
||||
+ pynutil.delete(")")
|
||||
+ pynini.closure(pynutil.delete("-"), 0, 1)
|
||||
+ delete_space
|
||||
)
|
||||
)
|
||||
+ add_separator
|
||||
+ pynini.closure(digit + insert_space, 2, 2)
|
||||
+ digit
|
||||
+ pynutil.delete("-")
|
||||
+ add_separator
|
||||
+ pynini.closure(digit + insert_space, 3, 3)
|
||||
+ digit
|
||||
)
|
||||
number_part = pynutil.insert("number_part: \"") + pynini.invert(number_part) + pynutil.insert("\"")
|
||||
|
||||
graph = number_part
|
||||
final_graph = self.add_tokens(graph)
|
||||
self.fst = final_graph.optimize()
|
||||
@@ -0,0 +1,124 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright 2015 and onwards Google, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
from nemo_text_processing.inverse_text_normalization.taggers.cardinal import CardinalFst
|
||||
from nemo_text_processing.inverse_text_normalization.utils import get_abs_path, num_to_word
|
||||
from nemo_text_processing.text_normalization.graph_utils import (
|
||||
GraphFst,
|
||||
convert_space,
|
||||
delete_extra_space,
|
||||
delete_space,
|
||||
insert_space,
|
||||
)
|
||||
|
||||
try:
|
||||
import pynini
|
||||
from pynini.lib import pynutil
|
||||
|
||||
PYNINI_AVAILABLE = True
|
||||
except (ModuleNotFoundError, ImportError):
|
||||
PYNINI_AVAILABLE = False
|
||||
|
||||
|
||||
class TimeFst(GraphFst):
|
||||
"""
|
||||
Finite state transducer for classifying time
|
||||
e.g. twelve thirty -> time { hours: "12" minutes: "30" }
|
||||
e.g. twelve past one -> time { minutes: "12" hours: "1" }
|
||||
e.g. two o clock a m -> time { hours: "2" suffix: "a.m." }
|
||||
e.g. quarter to two -> time { hours: "1" minutes: "45" }
|
||||
e.g. quarter past two -> time { hours: "2" minutes: "15" }
|
||||
e.g. half past two -> time { hours: "2" minutes: "30" }
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(name="time", kind="classify")
|
||||
# hours, minutes, seconds, suffix, zone, style, speak_period
|
||||
|
||||
suffix_graph = pynini.string_file(get_abs_path("data/time/time_suffix.tsv"))
|
||||
time_zone_graph = pynini.invert(pynini.string_file(get_abs_path("data/time/time_zone.tsv")))
|
||||
time_to_graph = pynini.string_file(get_abs_path("data/time/time_to.tsv"))
|
||||
|
||||
# only used for < 1000 thousand -> 0 weight
|
||||
cardinal = pynutil.add_weight(CardinalFst().graph_no_exception, weight=-0.7)
|
||||
|
||||
labels_hour = [num_to_word(x) for x in range(0, 24)]
|
||||
labels_minute_single = [num_to_word(x) for x in range(1, 10)]
|
||||
labels_minute_double = [num_to_word(x) for x in range(10, 60)]
|
||||
|
||||
graph_hour = pynini.union(*labels_hour) @ cardinal
|
||||
|
||||
graph_minute_single = pynini.union(*labels_minute_single) @ cardinal
|
||||
graph_minute_double = pynini.union(*labels_minute_double) @ cardinal
|
||||
graph_minute_verbose = pynini.cross("half", "30") | pynini.cross("quarter", "15")
|
||||
oclock = pynini.cross(pynini.union("o' clock", "o clock", "o'clock", "oclock"), "")
|
||||
|
||||
final_graph_hour = pynutil.insert("hours: \"") + graph_hour + pynutil.insert("\"")
|
||||
final_graph_minute = (
|
||||
pynutil.insert("minutes: \"")
|
||||
+ (
|
||||
pynutil.insert("00")
|
||||
| oclock + pynutil.insert("00")
|
||||
| pynutil.delete("o") + delete_space + graph_minute_single
|
||||
| graph_minute_double
|
||||
)
|
||||
+ pynutil.insert("\"")
|
||||
)
|
||||
final_suffix = pynutil.insert("suffix: \"") + convert_space(suffix_graph) + pynutil.insert("\"")
|
||||
final_suffix_optional = pynini.closure(delete_space + insert_space + final_suffix, 0, 1)
|
||||
final_time_zone_optional = pynini.closure(
|
||||
delete_space
|
||||
+ insert_space
|
||||
+ pynutil.insert("zone: \"")
|
||||
+ convert_space(time_zone_graph)
|
||||
+ pynutil.insert("\""),
|
||||
0,
|
||||
1,
|
||||
)
|
||||
|
||||
# five o' clock
|
||||
# two o eight, two thiry five (am/pm)
|
||||
# two pm/am
|
||||
graph_hm = final_graph_hour + delete_extra_space + final_graph_minute
|
||||
# 10 past four, quarter past four, half past four
|
||||
graph_mh = (
|
||||
pynutil.insert("minutes: \"")
|
||||
+ pynini.union(graph_minute_single, graph_minute_double, graph_minute_verbose)
|
||||
+ pynutil.insert("\"")
|
||||
+ delete_space
|
||||
+ pynutil.delete("past")
|
||||
+ delete_extra_space
|
||||
+ final_graph_hour
|
||||
)
|
||||
|
||||
graph_quarter_time = (
|
||||
pynutil.insert("minutes: \"")
|
||||
+ pynini.cross("quarter", "45")
|
||||
+ pynutil.insert("\"")
|
||||
+ delete_space
|
||||
+ pynutil.delete(pynini.union("to", "till"))
|
||||
+ delete_extra_space
|
||||
+ pynutil.insert("hours: \"")
|
||||
+ time_to_graph
|
||||
+ pynutil.insert("\"")
|
||||
)
|
||||
final_graph = (
|
||||
(graph_hm | graph_mh | graph_quarter_time) + final_suffix_optional + final_time_zone_optional
|
||||
).optimize()
|
||||
|
||||
final_graph = self.add_tokens(final_graph)
|
||||
|
||||
self.fst = final_graph.optimize()
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright 2015 and onwards Google, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from nemo_text_processing.inverse_text_normalization.taggers.cardinal import CardinalFst
|
||||
from nemo_text_processing.inverse_text_normalization.taggers.date import DateFst
|
||||
from nemo_text_processing.inverse_text_normalization.taggers.decimal import DecimalFst
|
||||
from nemo_text_processing.inverse_text_normalization.taggers.electronic import ElectronicFst
|
||||
from nemo_text_processing.inverse_text_normalization.taggers.measure import MeasureFst
|
||||
from nemo_text_processing.inverse_text_normalization.taggers.money import MoneyFst
|
||||
from nemo_text_processing.inverse_text_normalization.taggers.ordinal import OrdinalFst
|
||||
from nemo_text_processing.inverse_text_normalization.taggers.punctuation import PunctuationFst
|
||||
from nemo_text_processing.inverse_text_normalization.taggers.telephone import TelephoneFst
|
||||
from nemo_text_processing.inverse_text_normalization.taggers.time import TimeFst
|
||||
from nemo_text_processing.inverse_text_normalization.taggers.whitelist import WhiteListFst
|
||||
from nemo_text_processing.inverse_text_normalization.taggers.word import WordFst
|
||||
from nemo_text_processing.text_normalization.graph_utils import GraphFst, delete_extra_space, delete_space
|
||||
|
||||
try:
|
||||
import pynini
|
||||
from pynini.lib import pynutil
|
||||
|
||||
PYNINI_AVAILABLE = True
|
||||
except (ModuleNotFoundError, ImportError):
|
||||
PYNINI_AVAILABLE = False
|
||||
|
||||
|
||||
class ClassifyFst(GraphFst):
|
||||
"""
|
||||
Final class that composes all other classification grammars. This class can process an entire sentence, that is lower cased.
|
||||
For deployment, this grammar will be compiled and exported to OpenFst Finate State Archiv (FAR) File.
|
||||
More details to deployment at NeMo/tools/text_processing_deployment.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(name="tokenize_and_classify", kind="classify")
|
||||
|
||||
cardinal = CardinalFst()
|
||||
cardinal_graph = cardinal.fst
|
||||
|
||||
ordinal = OrdinalFst(cardinal)
|
||||
ordinal_graph = ordinal.fst
|
||||
|
||||
decimal = DecimalFst(cardinal)
|
||||
decimal_graph = decimal.fst
|
||||
|
||||
measure_graph = MeasureFst(cardinal=cardinal, decimal=decimal).fst
|
||||
date_graph = DateFst(ordinal=ordinal).fst
|
||||
word_graph = WordFst().fst
|
||||
time_graph = TimeFst().fst
|
||||
money_graph = MoneyFst(cardinal=cardinal, decimal=decimal).fst
|
||||
whitelist_graph = WhiteListFst().fst
|
||||
punct_graph = PunctuationFst().fst
|
||||
electronic_graph = ElectronicFst().fst
|
||||
telephone_graph = TelephoneFst().fst
|
||||
|
||||
classify = (
|
||||
pynutil.add_weight(whitelist_graph, 1.01)
|
||||
| pynutil.add_weight(time_graph, 1.1)
|
||||
| pynutil.add_weight(date_graph, 1.09)
|
||||
| pynutil.add_weight(decimal_graph, 1.1)
|
||||
| pynutil.add_weight(measure_graph, 1.1)
|
||||
| pynutil.add_weight(cardinal_graph, 1.1)
|
||||
| pynutil.add_weight(ordinal_graph, 1.1)
|
||||
| pynutil.add_weight(money_graph, 1.1)
|
||||
| pynutil.add_weight(telephone_graph, 1.1)
|
||||
| pynutil.add_weight(electronic_graph, 1.1)
|
||||
| pynutil.add_weight(word_graph, 100)
|
||||
)
|
||||
|
||||
punct = pynutil.insert("tokens { ") + pynutil.add_weight(punct_graph, weight=1.1) + pynutil.insert(" }")
|
||||
token = pynutil.insert("tokens { ") + classify + pynutil.insert(" }")
|
||||
token_plus_punct = (
|
||||
pynini.closure(punct + pynutil.insert(" ")) + token + pynini.closure(pynutil.insert(" ") + punct)
|
||||
)
|
||||
|
||||
graph = token_plus_punct + pynini.closure(delete_extra_space + token_plus_punct)
|
||||
graph = delete_space + graph + delete_space
|
||||
|
||||
self.fst = graph.optimize()
|
||||
@@ -0,0 +1,40 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright 2015 and onwards Google, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from nemo_text_processing.inverse_text_normalization.utils import get_abs_path
|
||||
from nemo_text_processing.text_normalization.graph_utils import GraphFst, convert_space
|
||||
|
||||
try:
|
||||
import pynini
|
||||
from pynini.lib import pynutil
|
||||
|
||||
PYNINI_AVAILABLE = True
|
||||
except (ModuleNotFoundError, ImportError):
|
||||
PYNINI_AVAILABLE = False
|
||||
|
||||
|
||||
class WhiteListFst(GraphFst):
|
||||
"""
|
||||
Finite state transducer for classifying whitelisted tokens
|
||||
e.g. misses -> tokens { name: "mrs." }
|
||||
This class has highest priority among all classifier grammars. Whitelisted tokens are defined and loaded from "data/whitelist.tsv".
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(name="whitelist", kind="classify")
|
||||
|
||||
whitelist = pynini.string_file(get_abs_path("data/whitelist.tsv")).invert()
|
||||
graph = pynutil.insert("name: \"") + convert_space(whitelist) + pynutil.insert("\"")
|
||||
self.fst = graph.optimize()
|
||||
@@ -0,0 +1,36 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright 2015 and onwards Google, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from nemo_text_processing.text_normalization.graph_utils import NEMO_NOT_SPACE, GraphFst
|
||||
|
||||
try:
|
||||
import pynini
|
||||
from pynini.lib import pynutil
|
||||
|
||||
PYNINI_AVAILABLE = True
|
||||
except (ModuleNotFoundError, ImportError):
|
||||
PYNINI_AVAILABLE = False
|
||||
|
||||
|
||||
class WordFst(GraphFst):
|
||||
"""
|
||||
Finite state transducer for classifying plain tokens, that do not belong to any special class. This can be considered as the default class.
|
||||
e.g. sleep -> tokens { name: "sleep" }
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(name="word", kind="classify")
|
||||
word = pynutil.insert("name: \"") + pynini.closure(NEMO_NOT_SPACE, 1) + pynutil.insert("\"")
|
||||
self.fst = word.optimize()
|
||||
@@ -0,0 +1,47 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import os
|
||||
from typing import Union
|
||||
|
||||
import inflect
|
||||
|
||||
_inflect = inflect.engine()
|
||||
|
||||
|
||||
def num_to_word(x: Union[str, int]):
|
||||
"""
|
||||
converts integer to spoken representation
|
||||
|
||||
Args
|
||||
x: integer
|
||||
|
||||
Returns: spoken representation
|
||||
"""
|
||||
if isinstance(x, int):
|
||||
x = str(x)
|
||||
x = _inflect.number_to_words(str(x)).replace("-", " ").replace(",", "")
|
||||
return x
|
||||
|
||||
|
||||
def get_abs_path(rel_path):
|
||||
"""
|
||||
Get absolute path
|
||||
|
||||
Args:
|
||||
rel_path: relative path to this file
|
||||
|
||||
Returns absolute path
|
||||
"""
|
||||
return os.path.dirname(os.path.abspath(__file__)) + '/' + rel_path
|
||||
@@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
@@ -0,0 +1,55 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright 2015 and onwards Google, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from nemo_text_processing.text_normalization.graph_utils import NEMO_NOT_QUOTE, GraphFst, delete_space
|
||||
|
||||
try:
|
||||
import pynini
|
||||
from pynini.lib import pynutil
|
||||
|
||||
PYNINI_AVAILABLE = True
|
||||
except (ModuleNotFoundError, ImportError):
|
||||
PYNINI_AVAILABLE = False
|
||||
|
||||
|
||||
class CardinalFst(GraphFst):
|
||||
"""
|
||||
Finite state transducer for verbalizing cardinal
|
||||
e.g. cardinal { integer: "23" negative: "-" } -> -23
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(name="cardinal", kind="verbalize")
|
||||
optional_sign = pynini.closure(
|
||||
pynutil.delete("negative:")
|
||||
+ delete_space
|
||||
+ pynutil.delete("\"")
|
||||
+ NEMO_NOT_QUOTE
|
||||
+ pynutil.delete("\"")
|
||||
+ delete_space,
|
||||
0,
|
||||
1,
|
||||
)
|
||||
graph = (
|
||||
pynutil.delete("integer:")
|
||||
+ delete_space
|
||||
+ pynutil.delete("\"")
|
||||
+ pynini.closure(NEMO_NOT_QUOTE, 1)
|
||||
+ pynutil.delete("\"")
|
||||
)
|
||||
self.numbers = graph
|
||||
graph = optional_sign + graph
|
||||
delete_tokens = self.delete_tokens(graph)
|
||||
self.fst = delete_tokens.optimize()
|
||||
@@ -0,0 +1,87 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright 2015 and onwards Google, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from nemo_text_processing.text_normalization.graph_utils import (
|
||||
NEMO_NOT_QUOTE,
|
||||
GraphFst,
|
||||
delete_extra_space,
|
||||
delete_space,
|
||||
)
|
||||
|
||||
try:
|
||||
import pynini
|
||||
from pynini.lib import pynutil
|
||||
|
||||
PYNINI_AVAILABLE = True
|
||||
except (ModuleNotFoundError, ImportError):
|
||||
PYNINI_AVAILABLE = False
|
||||
|
||||
|
||||
class DateFst(GraphFst):
|
||||
"""
|
||||
Finite state transducer for verbalizing date, e.g.
|
||||
date { month: "january" day: "5" year: "2012" preserve_order: true } -> february 5 2012
|
||||
date { day: "5" month: "january" year: "2012" preserve_order: true } -> 5 february 2012
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(name="date", kind="verbalize")
|
||||
month = (
|
||||
pynutil.delete("month:")
|
||||
+ delete_space
|
||||
+ pynutil.delete("\"")
|
||||
+ pynini.closure(NEMO_NOT_QUOTE, 1)
|
||||
+ pynutil.delete("\"")
|
||||
)
|
||||
day = (
|
||||
pynutil.delete("day:")
|
||||
+ delete_space
|
||||
+ pynutil.delete("\"")
|
||||
+ pynini.closure(NEMO_NOT_QUOTE, 1)
|
||||
+ pynutil.delete("\"")
|
||||
)
|
||||
year = (
|
||||
pynutil.delete("year:")
|
||||
+ delete_space
|
||||
+ pynutil.delete("\"")
|
||||
+ pynini.closure(NEMO_NOT_QUOTE, 1)
|
||||
+ delete_space
|
||||
+ pynutil.delete("\"")
|
||||
)
|
||||
|
||||
# month (day) year
|
||||
graph_mdy = (
|
||||
month + pynini.closure(delete_extra_space + day, 0, 1) + pynini.closure(delete_extra_space + year, 0, 1)
|
||||
)
|
||||
|
||||
# (day) month year
|
||||
graph_dmy = (
|
||||
pynini.closure(day + delete_extra_space, 0, 1) + month + pynini.closure(delete_extra_space + year, 0, 1)
|
||||
)
|
||||
|
||||
optional_preserve_order = pynini.closure(
|
||||
pynutil.delete("preserve_order:") + delete_space + pynutil.delete("true") + delete_space
|
||||
| pynutil.delete("field_order:")
|
||||
+ delete_space
|
||||
+ pynutil.delete("\"")
|
||||
+ NEMO_NOT_QUOTE
|
||||
+ pynutil.delete("\"")
|
||||
+ delete_space
|
||||
)
|
||||
|
||||
final_graph = (graph_mdy | year | graph_dmy) + delete_space + optional_preserve_order
|
||||
|
||||
delete_tokens = self.delete_tokens(final_graph)
|
||||
self.fst = delete_tokens.optimize()
|
||||
@@ -0,0 +1,65 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright 2015 and onwards Google, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from nemo_text_processing.text_normalization.graph_utils import NEMO_NOT_QUOTE, GraphFst, delete_space
|
||||
|
||||
try:
|
||||
import pynini
|
||||
from pynini.lib import pynutil
|
||||
|
||||
PYNINI_AVAILABLE = True
|
||||
except (ModuleNotFoundError, ImportError):
|
||||
PYNINI_AVAILABLE = False
|
||||
|
||||
|
||||
class DecimalFst(GraphFst):
|
||||
"""
|
||||
Finite state transducer for verbalizing decimal, e.g.
|
||||
decimal { negative: "true" integer_part: "12" fractional_part: "5006" quantity: "billion" } -> -12.5006 billion
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(name="decimal", kind="verbalize")
|
||||
optionl_sign = pynini.closure(pynini.cross("negative: \"true\"", "-") + delete_space, 0, 1)
|
||||
integer = (
|
||||
pynutil.delete("integer_part:")
|
||||
+ delete_space
|
||||
+ pynutil.delete("\"")
|
||||
+ pynini.closure(NEMO_NOT_QUOTE, 1)
|
||||
+ pynutil.delete("\"")
|
||||
)
|
||||
optional_integer = pynini.closure(integer + delete_space, 0, 1)
|
||||
fractional = (
|
||||
pynutil.insert(".")
|
||||
+ pynutil.delete("fractional_part:")
|
||||
+ delete_space
|
||||
+ pynutil.delete("\"")
|
||||
+ pynini.closure(NEMO_NOT_QUOTE, 1)
|
||||
+ pynutil.delete("\"")
|
||||
)
|
||||
optional_fractional = pynini.closure(fractional + delete_space, 0, 1)
|
||||
quantity = (
|
||||
pynutil.delete("quantity:")
|
||||
+ delete_space
|
||||
+ pynutil.delete("\"")
|
||||
+ pynini.closure(NEMO_NOT_QUOTE, 1)
|
||||
+ pynutil.delete("\"")
|
||||
)
|
||||
optional_quantity = pynini.closure(pynutil.insert(" ") + quantity + delete_space, 0, 1)
|
||||
graph = optional_integer + optional_fractional + optional_quantity
|
||||
self.numbers = graph
|
||||
graph = optionl_sign + graph
|
||||
delete_tokens = self.delete_tokens(graph)
|
||||
self.fst = delete_tokens.optimize()
|
||||
@@ -0,0 +1,52 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright 2015 and onwards Google, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from nemo_text_processing.text_normalization.graph_utils import NEMO_NOT_QUOTE, GraphFst, delete_space
|
||||
|
||||
try:
|
||||
import pynini
|
||||
from pynini.lib import pynutil
|
||||
|
||||
PYNINI_AVAILABLE = True
|
||||
except (ModuleNotFoundError, ImportError):
|
||||
PYNINI_AVAILABLE = False
|
||||
|
||||
|
||||
class ElectronicFst(GraphFst):
|
||||
"""
|
||||
Finite state transducer for verbalizing electronic
|
||||
e.g. tokens { electronic { username: "cdf1" domain: "abc.edu" } } -> cdf1@abc.edu
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(name="electronic", kind="verbalize")
|
||||
user_name = (
|
||||
pynutil.delete("username:")
|
||||
+ delete_space
|
||||
+ pynutil.delete("\"")
|
||||
+ pynini.closure(NEMO_NOT_QUOTE, 1)
|
||||
+ pynutil.delete("\"")
|
||||
)
|
||||
domain = (
|
||||
pynutil.delete("domain:")
|
||||
+ delete_space
|
||||
+ pynutil.delete("\"")
|
||||
+ pynini.closure(NEMO_NOT_QUOTE, 1)
|
||||
+ pynutil.delete("\"")
|
||||
)
|
||||
|
||||
graph = user_name + delete_space + pynutil.insert("@") + domain
|
||||
delete_tokens = self.delete_tokens(graph)
|
||||
self.fst = delete_tokens.optimize()
|
||||
@@ -0,0 +1,25 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright 2015 and onwards Google, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from nemo_text_processing.text_normalization.graph_utils import GraphFst
|
||||
|
||||
|
||||
class FractionFst(GraphFst):
|
||||
"""
|
||||
Finite state transducer for verbalizing fraction,
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(name="fraction", kind="verbalize")
|
||||
@@ -0,0 +1,69 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright 2015 and onwards Google, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from nemo_text_processing.text_normalization.graph_utils import NEMO_CHAR, GraphFst, delete_space
|
||||
|
||||
try:
|
||||
import pynini
|
||||
from pynini.lib import pynutil
|
||||
|
||||
PYNINI_AVAILABLE = True
|
||||
except (ModuleNotFoundError, ImportError):
|
||||
|
||||
PYNINI_AVAILABLE = False
|
||||
|
||||
|
||||
class MeasureFst(GraphFst):
|
||||
"""
|
||||
Finite state transducer for verbalizing measure, e.g.
|
||||
measure { negative: "true" cardinal { integer: "12" } units: "kg" } -> -12 kg
|
||||
|
||||
Args:
|
||||
decimal: DecimalFst
|
||||
cardinal: CardinalFst
|
||||
"""
|
||||
|
||||
def __init__(self, decimal: GraphFst, cardinal: GraphFst):
|
||||
super().__init__(name="measure", kind="verbalize")
|
||||
optional_sign = pynini.closure(pynini.cross("negative: \"true\"", "-"), 0, 1)
|
||||
unit = (
|
||||
pynutil.delete("units:")
|
||||
+ delete_space
|
||||
+ pynutil.delete("\"")
|
||||
+ pynini.closure(NEMO_CHAR - " ", 1)
|
||||
+ pynutil.delete("\"")
|
||||
+ delete_space
|
||||
)
|
||||
graph_decimal = (
|
||||
pynutil.delete("decimal {")
|
||||
+ delete_space
|
||||
+ optional_sign
|
||||
+ delete_space
|
||||
+ decimal.numbers
|
||||
+ delete_space
|
||||
+ pynutil.delete("}")
|
||||
)
|
||||
graph_cardinal = (
|
||||
pynutil.delete("cardinal {")
|
||||
+ delete_space
|
||||
+ optional_sign
|
||||
+ delete_space
|
||||
+ cardinal.numbers
|
||||
+ delete_space
|
||||
+ pynutil.delete("}")
|
||||
)
|
||||
graph = (graph_cardinal | graph_decimal) + delete_space + pynutil.insert(" ") + unit
|
||||
delete_tokens = self.delete_tokens(graph)
|
||||
self.fst = delete_tokens.optimize()
|
||||
@@ -0,0 +1,48 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright 2015 and onwards Google, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from nemo_text_processing.text_normalization.graph_utils import NEMO_CHAR, GraphFst, delete_space
|
||||
|
||||
try:
|
||||
import pynini
|
||||
from pynini.lib import pynutil
|
||||
|
||||
PYNINI_AVAILABLE = True
|
||||
except (ModuleNotFoundError, ImportError):
|
||||
|
||||
PYNINI_AVAILABLE = False
|
||||
|
||||
|
||||
class MoneyFst(GraphFst):
|
||||
"""
|
||||
Finite state transducer for verbalizing money, e.g.
|
||||
money { integer_part: "12" fractional_part: "05" currency: "$" } -> $12.05
|
||||
|
||||
Args:
|
||||
decimal: DecimalFst
|
||||
"""
|
||||
|
||||
def __init__(self, decimal: GraphFst):
|
||||
super().__init__(name="money", kind="verbalize")
|
||||
unit = (
|
||||
pynutil.delete("currency:")
|
||||
+ delete_space
|
||||
+ pynutil.delete("\"")
|
||||
+ pynini.closure(NEMO_CHAR - " ", 1)
|
||||
+ pynutil.delete("\"")
|
||||
)
|
||||
graph = unit + delete_space + decimal.numbers
|
||||
delete_tokens = self.delete_tokens(graph)
|
||||
self.fst = delete_tokens.optimize()
|
||||
@@ -0,0 +1,64 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright 2015 and onwards Google, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from nemo_text_processing.text_normalization.graph_utils import NEMO_NOT_QUOTE, NEMO_SIGMA, GraphFst, delete_space
|
||||
|
||||
try:
|
||||
import pynini
|
||||
from pynini.lib import pynutil
|
||||
|
||||
PYNINI_AVAILABLE = True
|
||||
except (ModuleNotFoundError, ImportError):
|
||||
PYNINI_AVAILABLE = False
|
||||
|
||||
|
||||
class OrdinalFst(GraphFst):
|
||||
"""
|
||||
Finite state transducer for verbalizing ordinal, e.g.
|
||||
ordinal { integer: "13" } -> 13th
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(name="ordinal", kind="verbalize")
|
||||
graph = (
|
||||
pynutil.delete("integer:")
|
||||
+ delete_space
|
||||
+ pynutil.delete("\"")
|
||||
+ pynini.closure(NEMO_NOT_QUOTE, 1)
|
||||
+ pynutil.delete("\"")
|
||||
)
|
||||
convert_eleven = pynini.cross("11", "11th")
|
||||
convert_twelve = pynini.cross("12", "12th")
|
||||
convert_thirteen = pynini.cross("13", "13th")
|
||||
convert_one = pynini.cross("1", "1st")
|
||||
convert_two = pynini.cross("2", "2nd")
|
||||
convert_three = pynini.cross("3", "3rd")
|
||||
convert_rest = pynutil.insert("th", weight=0.01)
|
||||
|
||||
suffix = pynini.cdrewrite(
|
||||
convert_eleven
|
||||
| convert_twelve
|
||||
| convert_thirteen
|
||||
| convert_one
|
||||
| convert_two
|
||||
| convert_three
|
||||
| convert_rest,
|
||||
"",
|
||||
"[EOS]",
|
||||
NEMO_SIGMA,
|
||||
)
|
||||
graph = graph @ suffix
|
||||
delete_tokens = self.delete_tokens(graph)
|
||||
self.fst = delete_tokens.optimize()
|
||||
@@ -0,0 +1,39 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright 2015 and onwards Google, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from nemo_text_processing.text_normalization.graph_utils import NEMO_NOT_QUOTE, GraphFst
|
||||
|
||||
try:
|
||||
import pynini
|
||||
from pynini.lib import pynutil
|
||||
|
||||
PYNINI_AVAILABLE = True
|
||||
except (ModuleNotFoundError, ImportError):
|
||||
PYNINI_AVAILABLE = False
|
||||
|
||||
|
||||
class TelephoneFst(GraphFst):
|
||||
"""
|
||||
Finite state transducer for verbalizing telephone, e.g.
|
||||
telephone { number_part: "123-123-5678" }
|
||||
-> 123-123-5678
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(name="telephone", kind="verbalize")
|
||||
|
||||
number_part = pynutil.delete("number_part: \"") + pynini.closure(NEMO_NOT_QUOTE, 1) + pynutil.delete("\"")
|
||||
delete_tokens = self.delete_tokens(number_part)
|
||||
self.fst = delete_tokens.optimize()
|
||||
@@ -0,0 +1,87 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright 2015 and onwards Google, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from nemo_text_processing.text_normalization.graph_utils import (
|
||||
NEMO_CHAR,
|
||||
NEMO_DIGIT,
|
||||
GraphFst,
|
||||
delete_space,
|
||||
insert_space,
|
||||
)
|
||||
|
||||
try:
|
||||
import pynini
|
||||
from pynini.lib import pynutil
|
||||
|
||||
PYNINI_AVAILABLE = True
|
||||
except (ModuleNotFoundError, ImportError):
|
||||
PYNINI_AVAILABLE = False
|
||||
|
||||
|
||||
class TimeFst(GraphFst):
|
||||
"""
|
||||
Finite state transducer for verbalizing time, e.g.
|
||||
time { hours: "12" minutes: "30" } -> 12:30
|
||||
time { hours: "1" minutes: "12" } -> 01:12
|
||||
time { hours: "2" suffix: "a.m." } -> 02:00 a.m.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(name="time", kind="verbalize")
|
||||
add_leading_zero_to_double_digit = (NEMO_DIGIT + NEMO_DIGIT) | (pynutil.insert("0") + NEMO_DIGIT)
|
||||
hour = (
|
||||
pynutil.delete("hours:")
|
||||
+ delete_space
|
||||
+ pynutil.delete("\"")
|
||||
+ pynini.closure(NEMO_DIGIT, 1)
|
||||
+ pynutil.delete("\"")
|
||||
)
|
||||
minute = (
|
||||
pynutil.delete("minutes:")
|
||||
+ delete_space
|
||||
+ pynutil.delete("\"")
|
||||
+ pynini.closure(NEMO_DIGIT, 1)
|
||||
+ pynutil.delete("\"")
|
||||
)
|
||||
suffix = (
|
||||
delete_space
|
||||
+ insert_space
|
||||
+ pynutil.delete("suffix:")
|
||||
+ delete_space
|
||||
+ pynutil.delete("\"")
|
||||
+ pynini.closure(NEMO_CHAR - " ", 1)
|
||||
+ pynutil.delete("\"")
|
||||
)
|
||||
optional_suffix = pynini.closure(suffix, 0, 1)
|
||||
zone = (
|
||||
delete_space
|
||||
+ insert_space
|
||||
+ pynutil.delete("zone:")
|
||||
+ delete_space
|
||||
+ pynutil.delete("\"")
|
||||
+ pynini.closure(NEMO_CHAR - " ", 1)
|
||||
+ pynutil.delete("\"")
|
||||
)
|
||||
optional_zone = pynini.closure(zone, 0, 1)
|
||||
graph = (
|
||||
hour @ add_leading_zero_to_double_digit
|
||||
+ delete_space
|
||||
+ pynutil.insert(":")
|
||||
+ (minute @ add_leading_zero_to_double_digit)
|
||||
+ optional_suffix
|
||||
+ optional_zone
|
||||
)
|
||||
delete_tokens = self.delete_tokens(graph)
|
||||
self.fst = delete_tokens.optimize()
|
||||
@@ -0,0 +1,62 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright 2015 and onwards Google, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from nemo_text_processing.inverse_text_normalization.verbalizers.cardinal import CardinalFst
|
||||
from nemo_text_processing.inverse_text_normalization.verbalizers.date import DateFst
|
||||
from nemo_text_processing.inverse_text_normalization.verbalizers.decimal import DecimalFst
|
||||
from nemo_text_processing.inverse_text_normalization.verbalizers.electronic import ElectronicFst
|
||||
from nemo_text_processing.inverse_text_normalization.verbalizers.measure import MeasureFst
|
||||
from nemo_text_processing.inverse_text_normalization.verbalizers.money import MoneyFst
|
||||
from nemo_text_processing.inverse_text_normalization.verbalizers.ordinal import OrdinalFst
|
||||
from nemo_text_processing.inverse_text_normalization.verbalizers.telephone import TelephoneFst
|
||||
from nemo_text_processing.inverse_text_normalization.verbalizers.time import TimeFst
|
||||
from nemo_text_processing.inverse_text_normalization.verbalizers.whitelist import WhiteListFst
|
||||
from nemo_text_processing.text_normalization.graph_utils import GraphFst
|
||||
|
||||
|
||||
class VerbalizeFst(GraphFst):
|
||||
"""
|
||||
Composes other verbalizer grammars.
|
||||
For deployment, this grammar will be compiled and exported to OpenFst Finate State Archiv (FAR) File.
|
||||
More details to deployment at NeMo/tools/text_processing_deployment.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(name="verbalize", kind="verbalize")
|
||||
cardinal = CardinalFst()
|
||||
cardinal_graph = cardinal.fst
|
||||
ordinal_graph = OrdinalFst().fst
|
||||
decimal = DecimalFst()
|
||||
decimal_graph = decimal.fst
|
||||
measure_graph = MeasureFst(decimal=decimal, cardinal=cardinal).fst
|
||||
money_graph = MoneyFst(decimal=decimal).fst
|
||||
time_graph = TimeFst().fst
|
||||
date_graph = DateFst().fst
|
||||
whitelist_graph = WhiteListFst().fst
|
||||
telephone_graph = TelephoneFst().fst
|
||||
electronic_graph = ElectronicFst().fst
|
||||
graph = (
|
||||
time_graph
|
||||
| date_graph
|
||||
| money_graph
|
||||
| measure_graph
|
||||
| ordinal_graph
|
||||
| decimal_graph
|
||||
| cardinal_graph
|
||||
| whitelist_graph
|
||||
| telephone_graph
|
||||
| electronic_graph
|
||||
)
|
||||
self.fst = graph
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright 2015 and onwards Google, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from nemo_text_processing.inverse_text_normalization.verbalizers.verbalize import VerbalizeFst
|
||||
from nemo_text_processing.inverse_text_normalization.verbalizers.word import WordFst
|
||||
from nemo_text_processing.text_normalization.graph_utils import GraphFst, delete_extra_space, delete_space
|
||||
|
||||
try:
|
||||
import pynini
|
||||
from pynini.lib import pynutil
|
||||
|
||||
PYNINI_AVAILABLE = True
|
||||
except (ModuleNotFoundError, ImportError):
|
||||
PYNINI_AVAILABLE = False
|
||||
|
||||
|
||||
class VerbalizeFinalFst(GraphFst):
|
||||
"""
|
||||
Finite state transducer that verbalizes an entire sentence, e.g.
|
||||
tokens { name: "its" } tokens { time { hours: "12" minutes: "30" } } tokens { name: "now" } -> its 12:30 now
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(name="verbalize_final", kind="verbalize")
|
||||
verbalize = VerbalizeFst().fst
|
||||
word = WordFst().fst
|
||||
types = verbalize | word
|
||||
graph = (
|
||||
pynutil.delete("tokens")
|
||||
+ delete_space
|
||||
+ pynutil.delete("{")
|
||||
+ delete_space
|
||||
+ types
|
||||
+ delete_space
|
||||
+ pynutil.delete("}")
|
||||
)
|
||||
graph = delete_space + pynini.closure(graph + delete_extra_space) + graph + delete_space
|
||||
self.fst = graph
|
||||
@@ -0,0 +1,44 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright 2015 and onwards Google, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
from nemo_text_processing.text_normalization.graph_utils import NEMO_CHAR, NEMO_SIGMA, GraphFst, delete_space
|
||||
|
||||
try:
|
||||
import pynini
|
||||
from pynini.lib import pynutil
|
||||
|
||||
PYNINI_AVAILABLE = True
|
||||
except (ModuleNotFoundError, ImportError):
|
||||
PYNINI_AVAILABLE = False
|
||||
|
||||
|
||||
class WhiteListFst(GraphFst):
|
||||
"""
|
||||
Finite state transducer for verbalizing whitelist
|
||||
e.g. tokens { name: "mrs." } -> mrs.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(name="whitelist", kind="verbalize")
|
||||
graph = (
|
||||
pynutil.delete("name:")
|
||||
+ delete_space
|
||||
+ pynutil.delete("\"")
|
||||
+ pynini.closure(NEMO_CHAR - " ", 1)
|
||||
+ pynutil.delete("\"")
|
||||
)
|
||||
graph = graph @ pynini.cdrewrite(pynini.cross(u"\u00A0", " "), "", "", NEMO_SIGMA)
|
||||
self.fst = graph.optimize()
|
||||
@@ -0,0 +1,39 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright 2015 and onwards Google, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from nemo_text_processing.text_normalization.graph_utils import NEMO_CHAR, NEMO_SIGMA, GraphFst, delete_space
|
||||
|
||||
try:
|
||||
import pynini
|
||||
from pynini.lib import pynutil
|
||||
|
||||
PYNINI_AVAILABLE = True
|
||||
except (ModuleNotFoundError, ImportError):
|
||||
PYNINI_AVAILABLE = False
|
||||
|
||||
|
||||
class WordFst(GraphFst):
|
||||
"""
|
||||
Finite state transducer for verbalizing plain tokens
|
||||
e.g. tokens { name: "sleep" } -> sleep
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(name="word", kind="verbalize")
|
||||
chars = pynini.closure(NEMO_CHAR - " ", 1)
|
||||
char = pynutil.delete("name:") + delete_space + pynutil.delete("\"") + chars + pynutil.delete("\"")
|
||||
graph = char @ pynini.cdrewrite(pynini.cross(u"\u00A0", " "), "", "", NEMO_SIGMA)
|
||||
|
||||
self.fst = graph.optimize()
|
||||
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
conda install -c conda-forge -y pynini=2.1.3
|
||||
@@ -0,0 +1,11 @@
|
||||
Text Normalization system for english, e.g. `123 kg` -> `one hundred twenty three kilograms`
|
||||
Offers prediction and evaluation on text normalization data, e.g. [Google text normalization dataset](https://www.kaggle.com/richardwilliamsproat/text-normalization-for-english-russian-and-polish).
|
||||
|
||||
|
||||
Install dependencies:
|
||||
bash ../setup.sh
|
||||
|
||||
Example prediction run:
|
||||
python run_predict.py --input=`INPUT_FILE` --output=`OUTPUT_FILE` [--verbose]
|
||||
Example evaluation run:
|
||||
python run_evaluate.py --input=./en_with_types/output-00001-of-00100 [--cat CATEGORY]
|
||||
@@ -0,0 +1,33 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from nemo_text_processing.text_normalization.graph_utils import GraphFst
|
||||
from nemo_text_processing.text_normalization.taggers.tokenize_and_classify import ClassifyFst
|
||||
from nemo_text_processing.text_normalization.verbalizers.verbalize import VerbalizeFst
|
||||
from nemo_text_processing.text_normalization.verbalizers.verbalize_final import VerbalizeFinalFst
|
||||
|
||||
from nemo.utils import logging
|
||||
|
||||
try:
|
||||
import pynini
|
||||
|
||||
PYNINI_AVAILABLE = True
|
||||
except (ModuleNotFoundError, ImportError):
|
||||
logging.warning(
|
||||
"`pynini` is not installed ! \n"
|
||||
"Please run the `nemo_text_processing/setup.sh` script"
|
||||
"prior to usage of this toolkit."
|
||||
)
|
||||
|
||||
PYNINI_AVAILABLE = False
|
||||
@@ -0,0 +1,342 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from typing import List
|
||||
|
||||
import regex as re
|
||||
from nemo_text_processing.text_normalization.data_loader_utils import (
|
||||
EOS_TYPE,
|
||||
Instance,
|
||||
load_files,
|
||||
training_data_to_sentences,
|
||||
)
|
||||
|
||||
|
||||
"""
|
||||
This file is for evaluation purposes.
|
||||
filter_loaded_data() cleans data (list of instances) for text normalization. Filters and cleaners can be specified for each semiotic class individually.
|
||||
For example, normalized text should only include characters and whitespace characters but no punctuation.
|
||||
Cardinal unnormalized instances should contain at least one integer and all other characters are removed.
|
||||
"""
|
||||
|
||||
|
||||
class Filter:
|
||||
"""
|
||||
Filter class
|
||||
|
||||
Args:
|
||||
class_type: semiotic class used in dataset
|
||||
process_func: function to transform text
|
||||
filter_func: function to filter text
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, class_type: str, process_func: object, filter_func: object):
|
||||
self.class_type = class_type
|
||||
self.process_func = process_func
|
||||
self.filter_func = filter_func
|
||||
|
||||
def filter(self, instance: Instance) -> bool:
|
||||
"""
|
||||
filter function
|
||||
|
||||
Args:
|
||||
filters given instance with filter function
|
||||
|
||||
Returns: True if given instance fulfills criteria or does not belong to class type
|
||||
"""
|
||||
if instance.token_type != self.class_type:
|
||||
return True
|
||||
return self.filter_func(instance)
|
||||
|
||||
def process(self, instance: Instance) -> Instance:
|
||||
"""
|
||||
process function
|
||||
|
||||
Args:
|
||||
processes given instance with process function
|
||||
|
||||
Returns: processed instance if instance belongs to expected class type or original instance
|
||||
"""
|
||||
if instance.token_type != self.class_type:
|
||||
return instance
|
||||
return self.process_func(instance)
|
||||
|
||||
|
||||
def filter_cardinal_1(instance: Instance) -> bool:
|
||||
ok = re.search(r"[0-9]", instance.un_normalized)
|
||||
return ok
|
||||
|
||||
|
||||
def process_cardinal_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
normalized = instance.normalized
|
||||
un_normalized = re.sub(r"[^0-9]", "", un_normalized)
|
||||
normalized = re.sub(r"[^a-z ]", "", normalized)
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
def filter_ordinal_1(instance: Instance) -> bool:
|
||||
ok = re.search(r"(st|nd|rd|th)\s*$", instance.un_normalized)
|
||||
return ok
|
||||
|
||||
|
||||
def process_ordinal_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
normalized = instance.normalized
|
||||
un_normalized = re.sub(r"[,\s]", "", un_normalized)
|
||||
normalized = re.sub(r"[^a-z ]", "", normalized)
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
def filter_decimal_1(instance: Instance) -> bool:
|
||||
ok = re.search(r"[0-9]", instance.un_normalized)
|
||||
return ok
|
||||
|
||||
|
||||
def process_decimal_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
un_normalized = re.sub(r",", "", un_normalized)
|
||||
normalized = instance.normalized
|
||||
normalized = re.sub(r"[^a-z ]", "", normalized)
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
def filter_measure_1(instance: Instance) -> bool:
|
||||
ok = True
|
||||
return ok
|
||||
|
||||
|
||||
def process_measure_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
normalized = instance.normalized
|
||||
un_normalized = re.sub(r",", "", un_normalized)
|
||||
un_normalized = re.sub(r"m2", "m²", un_normalized)
|
||||
un_normalized = re.sub(r"(\d)([^\d.\s])", r"\1 \2", un_normalized)
|
||||
normalized = re.sub(r"[^a-z\s]", "", normalized)
|
||||
normalized = re.sub(r"per ([a-z\s]*)s$", r"per \1", normalized)
|
||||
normalized = re.sub(r"[^a-z ]", "", normalized)
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
def filter_money_1(instance: Instance) -> bool:
|
||||
ok = re.search(r"[0-9]", instance.un_normalized)
|
||||
return ok
|
||||
|
||||
|
||||
def process_money_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
normalized = instance.normalized
|
||||
un_normalized = re.sub(r",", "", un_normalized)
|
||||
un_normalized = re.sub(r"a\$", r"$", un_normalized)
|
||||
un_normalized = re.sub(r"us\$", r"$", un_normalized)
|
||||
un_normalized = re.sub(r"(\d)m\s*$", r"\1 million", un_normalized)
|
||||
un_normalized = re.sub(r"(\d)bn?\s*$", r"\1 billion", un_normalized)
|
||||
normalized = re.sub(r"[^a-z ]", "", normalized)
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
def filter_time_1(instance: Instance) -> bool:
|
||||
ok = re.search(r"[0-9]", instance.un_normalized)
|
||||
return ok
|
||||
|
||||
|
||||
def process_time_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
un_normalized = re.sub(r": ", ":", un_normalized)
|
||||
un_normalized = re.sub(r"(\d)\s?a\s?m\s?", r"\1 a.m.", un_normalized)
|
||||
un_normalized = re.sub(r"(\d)\s?p\s?m\s?", r"\1 p.m.", un_normalized)
|
||||
normalized = instance.normalized
|
||||
normalized = re.sub(r"[^a-z ]", "", normalized)
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
def filter_plain_1(instance: Instance) -> bool:
|
||||
ok = True
|
||||
return ok
|
||||
|
||||
|
||||
def process_plain_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
normalized = instance.normalized
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
def filter_punct_1(instance: Instance) -> bool:
|
||||
ok = True
|
||||
return ok
|
||||
|
||||
|
||||
def process_punct_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
normalized = instance.normalized
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
def filter_date_1(instance: Instance) -> bool:
|
||||
ok = True
|
||||
return ok
|
||||
|
||||
|
||||
def process_date_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
un_normalized = re.sub(r",", "", un_normalized)
|
||||
normalized = instance.normalized
|
||||
normalized = re.sub(r"[^a-z ]", "", normalized)
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
def filter_letters_1(instance: Instance) -> bool:
|
||||
ok = True
|
||||
return ok
|
||||
|
||||
|
||||
def process_letters_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
normalized = instance.normalized
|
||||
normalized = re.sub(r"[^a-z ]", "", normalized)
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
def filter_verbatim_1(instance: Instance) -> bool:
|
||||
ok = True
|
||||
return ok
|
||||
|
||||
|
||||
def process_verbatim_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
normalized = instance.normalized
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
def filter_digit_1(instance: Instance) -> bool:
|
||||
ok = re.search(r"[0-9]", instance.un_normalized)
|
||||
return ok
|
||||
|
||||
|
||||
def process_digit_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
normalized = instance.normalized
|
||||
normalized = re.sub(r"[^a-z ]", "", normalized)
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
def filter_telephone_1(instance: Instance) -> bool:
|
||||
ok = re.search(r"[0-9]", instance.un_normalized)
|
||||
return ok
|
||||
|
||||
|
||||
def process_telephone_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
normalized = instance.normalized
|
||||
normalized = re.sub(r"[^a-z ]", "", normalized)
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
def filter_electronic_1(instance: Instance) -> bool:
|
||||
ok = re.search(r"[0-9]", instance.un_normalized)
|
||||
return ok
|
||||
|
||||
|
||||
def process_electronic_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
normalized = instance.normalized
|
||||
normalized = re.sub(r"[^a-z ]", "", normalized)
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
def filter_fraction_1(instance: Instance) -> bool:
|
||||
ok = re.search(r"[0-9]", instance.un_normalized)
|
||||
return ok
|
||||
|
||||
|
||||
def process_fraction_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
normalized = instance.normalized
|
||||
normalized = re.sub(r"[^a-z ]", "", normalized)
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
def filter_address_1(instance: Instance) -> bool:
|
||||
ok = True
|
||||
return ok
|
||||
|
||||
|
||||
def process_address_1(instance: Instance) -> Instance:
|
||||
un_normalized = instance.un_normalized
|
||||
normalized = instance.normalized
|
||||
normalized = re.sub(r"[^a-z ]", "", normalized)
|
||||
return Instance(token_type=instance.token_type, un_normalized=un_normalized, normalized=normalized)
|
||||
|
||||
|
||||
filters = []
|
||||
filters.append(Filter(class_type="CARDINAL", process_func=process_cardinal_1, filter_func=filter_cardinal_1))
|
||||
filters.append(Filter(class_type="ORDINAL", process_func=process_ordinal_1, filter_func=filter_ordinal_1))
|
||||
filters.append(Filter(class_type="DECIMAL", process_func=process_decimal_1, filter_func=filter_decimal_1))
|
||||
filters.append(Filter(class_type="MEASURE", process_func=process_measure_1, filter_func=filter_measure_1))
|
||||
filters.append(Filter(class_type="MONEY", process_func=process_money_1, filter_func=filter_money_1))
|
||||
filters.append(Filter(class_type="TIME", process_func=process_time_1, filter_func=filter_time_1))
|
||||
|
||||
filters.append(Filter(class_type="DATE", process_func=process_date_1, filter_func=filter_date_1))
|
||||
filters.append(Filter(class_type="PLAIN", process_func=process_plain_1, filter_func=filter_plain_1))
|
||||
filters.append(Filter(class_type="PUNCT", process_func=process_punct_1, filter_func=filter_punct_1))
|
||||
filters.append(Filter(class_type="LETTERS", process_func=process_letters_1, filter_func=filter_letters_1))
|
||||
filters.append(Filter(class_type="VERBATIM", process_func=process_verbatim_1, filter_func=filter_verbatim_1))
|
||||
filters.append(Filter(class_type="DIGIT", process_func=process_digit_1, filter_func=filter_digit_1))
|
||||
filters.append(Filter(class_type="TELEPHONE", process_func=process_telephone_1, filter_func=filter_telephone_1))
|
||||
filters.append(Filter(class_type="ELECTRONIC", process_func=process_electronic_1, filter_func=filter_electronic_1))
|
||||
filters.append(Filter(class_type="FRACTION", process_func=process_fraction_1, filter_func=filter_fraction_1))
|
||||
filters.append(Filter(class_type="ADDRESS", process_func=process_address_1, filter_func=filter_address_1))
|
||||
filters.append(Filter(class_type=EOS_TYPE, process_func=lambda x: x, filter_func=lambda x: True))
|
||||
|
||||
|
||||
def filter_loaded_data(data: List[Instance], verbose: bool = False) -> List[Instance]:
|
||||
"""
|
||||
Filters list of instances
|
||||
|
||||
Args:
|
||||
data: list of instances
|
||||
|
||||
Returns: filtered and transformed list of instances
|
||||
"""
|
||||
updates_instances = []
|
||||
for instance in data:
|
||||
updated_instance = False
|
||||
for fil in filters:
|
||||
if fil.class_type == instance.token_type and fil.filter(instance):
|
||||
instance = fil.process(instance)
|
||||
updated_instance = True
|
||||
if updated_instance:
|
||||
if verbose:
|
||||
print(instance)
|
||||
updates_instances.append(instance)
|
||||
return updates_instances
|
||||
|
||||
|
||||
def parse_args():
|
||||
parser = ArgumentParser()
|
||||
parser.add_argument("--input", help="input file path", type=str, default='./en_with_types/output-00001-of-00100')
|
||||
parser.add_argument("--verbose", help="print filtered instances", action='store_true')
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
args = parse_args()
|
||||
file_path = args.input
|
||||
|
||||
print("Loading training data: " + file_path)
|
||||
instance_list = load_files([file_path]) # List of instances
|
||||
filtered_instance_list = filter_loaded_data(instance_list, args.verbose)
|
||||
training_data_to_sentences(filtered_instance_list)
|
||||
@@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
@@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
@@ -0,0 +1,35 @@
|
||||
$ dollar
|
||||
$ us dollar
|
||||
$ united states dollar
|
||||
£ pound
|
||||
€ euro
|
||||
₩ won
|
||||
nzd new zealand dollar
|
||||
rs rupee
|
||||
chf swiss franc
|
||||
dkk danish kroner
|
||||
fim finnish markka
|
||||
aed arab emirates dirham
|
||||
¥ yen
|
||||
czk czech koruna
|
||||
mro mauritanian ouguiya
|
||||
pkr pakistani rupee
|
||||
crc costa rican colon
|
||||
hk$ hong kong dollar
|
||||
npr nepalese rupee
|
||||
awg aruban florin
|
||||
nok norwegian kroner
|
||||
tzs tanzanian shilling
|
||||
sek swedish kronor
|
||||
cyp cypriot pound
|
||||
r real
|
||||
sar saudi riyal
|
||||
cve cape verde escudo
|
||||
rsd serbian dinar
|
||||
dm german mark
|
||||
shp saint helena pounds
|
||||
php philippine peso
|
||||
cad canadian dollar
|
||||
ssp south sudanese pound
|
||||
scr seychelles rupee
|
||||
mvr maldivian rufiyaa
|
||||
|
@@ -0,0 +1,2 @@
|
||||
cents
|
||||
pence
|
||||
|
@@ -0,0 +1,2 @@
|
||||
cent
|
||||
penny
|
||||
|
@@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
@@ -0,0 +1 @@
|
||||
com com
|
||||
|
@@ -0,0 +1,2 @@
|
||||
gmail g mail
|
||||
nvidia n vidia
|
||||
|
@@ -0,0 +1,20 @@
|
||||
. dot
|
||||
- dash
|
||||
_ underscore
|
||||
! exclamation mark
|
||||
# number sign
|
||||
$ dollar sign
|
||||
% percent sign
|
||||
& ampersand
|
||||
' quote
|
||||
* asterisk
|
||||
+ plus
|
||||
/ slash
|
||||
= equal sign
|
||||
? question mark
|
||||
^ circumflex
|
||||
` right single quote
|
||||
{ left brace
|
||||
| vertical bar
|
||||
} right brace
|
||||
~ tilde
|
||||
|
@@ -0,0 +1,2 @@
|
||||
k kay
|
||||
j jay
|
||||
|
@@ -0,0 +1,4 @@
|
||||
k thousand
|
||||
m million
|
||||
b billion
|
||||
t trillion
|
||||
|
@@ -0,0 +1,115 @@
|
||||
f fahrenheit
|
||||
c celsius
|
||||
km kilometer
|
||||
m meter
|
||||
cm centimeter
|
||||
mm millimeter
|
||||
ha hectare
|
||||
mi mile
|
||||
m² square meter
|
||||
m2 square meter
|
||||
km² square kilometer
|
||||
km2 square kilometer
|
||||
ft foot
|
||||
% percent
|
||||
hz hertz
|
||||
kw kilowatt
|
||||
hp horsepower
|
||||
mg milligram
|
||||
kg kilogram
|
||||
ghz gigahertz
|
||||
khz kilohertz
|
||||
mhz megahertz
|
||||
lb pound
|
||||
lbs pound
|
||||
lbs. pound
|
||||
v volt
|
||||
h hour
|
||||
mc mega coulomb
|
||||
s second
|
||||
nm nanometer
|
||||
rpm revolution per minute
|
||||
min minute
|
||||
mA milli ampere
|
||||
kwh kilo watt hour
|
||||
m³ cubic meter
|
||||
m3 cubic meter
|
||||
mph mile per hour
|
||||
tw tera watt
|
||||
mv milli volt
|
||||
mw megawatt
|
||||
μm micrometer
|
||||
" inch
|
||||
tb terabyte
|
||||
cc c c
|
||||
g gram
|
||||
da dalton
|
||||
atm atmosphere
|
||||
ω ohm
|
||||
db decibel
|
||||
ps peta second
|
||||
oz ounce
|
||||
hl hecto liter
|
||||
μg microgram
|
||||
pg petagram
|
||||
gb gigabyte
|
||||
kb kilobit
|
||||
ev electron volt
|
||||
mb megabyte
|
||||
kb kilobyte
|
||||
kbps kilobit per second
|
||||
mbps megabit per second
|
||||
kl kilo liter
|
||||
tj tera joule
|
||||
kv kilo volt
|
||||
mv mega volt
|
||||
kn kilonewton
|
||||
mm megameter
|
||||
au astronomical unit
|
||||
yd yard
|
||||
rad radian
|
||||
lm lumen
|
||||
hs hecto second
|
||||
mol mole
|
||||
gpa giga pascal
|
||||
ml milliliter
|
||||
gw gigawatt
|
||||
ma mega ampere
|
||||
kt knot
|
||||
kgf kilogram force
|
||||
ng nano gram
|
||||
ns nanosecond
|
||||
ms mega siemens
|
||||
bar bar
|
||||
gl giga liter
|
||||
μs microsecond
|
||||
da deci ampere
|
||||
pa pascal
|
||||
ds deci second
|
||||
ms milli second
|
||||
dm deci meter
|
||||
dm³ cubic deci meter
|
||||
dm3 cubic deci meter
|
||||
amu atomic mass unit
|
||||
mb megabit
|
||||
mf mega farad
|
||||
bq becquerel
|
||||
pb petabit
|
||||
mm² square millimeter
|
||||
mm2 square millimeter
|
||||
cm² square centimeter
|
||||
cm2 square centimeter
|
||||
sq mi square mile
|
||||
sq ft square foot
|
||||
kpa kilopascal
|
||||
cd candela
|
||||
tl tera liter
|
||||
ms mega second
|
||||
mpa megapascal
|
||||
pb peta byte
|
||||
gwh giga watt hour
|
||||
kcal kilo calory
|
||||
gy gray
|
||||
sv sievert
|
||||
cwt hundredweight
|
||||
cc c c
|
||||
|
Can't render this file because it contains an unexpected character in line 115 and column 8.
|
@@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
@@ -0,0 +1,12 @@
|
||||
jan january
|
||||
feb february
|
||||
mar march
|
||||
apr april
|
||||
jun june
|
||||
jul july
|
||||
aug august
|
||||
sep september
|
||||
sept september
|
||||
oct october
|
||||
nov november
|
||||
dec december
|
||||
|
@@ -0,0 +1,12 @@
|
||||
january
|
||||
february
|
||||
march
|
||||
april
|
||||
may
|
||||
june
|
||||
july
|
||||
august
|
||||
september
|
||||
october
|
||||
november
|
||||
december
|
||||
|
@@ -0,0 +1,24 @@
|
||||
1 january
|
||||
2 february
|
||||
3 march
|
||||
4 april
|
||||
5 may
|
||||
6 june
|
||||
7 july
|
||||
8 august
|
||||
9 september
|
||||
10 october
|
||||
11 november
|
||||
12 december
|
||||
01 january
|
||||
02 february
|
||||
03 march
|
||||
04 april
|
||||
05 may
|
||||
06 june
|
||||
07 july
|
||||
08 august
|
||||
09 september
|
||||
10 october
|
||||
11 november
|
||||
12 december
|
||||
|
@@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
BIN
Binary file not shown.
@@ -0,0 +1,9 @@
|
||||
one 1
|
||||
two 2
|
||||
three 3
|
||||
four 4
|
||||
five 5
|
||||
six 6
|
||||
seven 7
|
||||
eight 8
|
||||
nine 9
|
||||
|
@@ -0,0 +1 @@
|
||||
hundred
|
||||
|
@@ -0,0 +1,10 @@
|
||||
ten 10
|
||||
eleven 11
|
||||
twelve 12
|
||||
thirteen 13
|
||||
fourteen 14
|
||||
fifteen 15
|
||||
sixteen 16
|
||||
seventeen 17
|
||||
eighteen 18
|
||||
nineteen 19
|
||||
|
@@ -0,0 +1,22 @@
|
||||
thousand
|
||||
million
|
||||
billion
|
||||
trillion
|
||||
quadrillion
|
||||
quintillion
|
||||
sextillion
|
||||
septillion
|
||||
octillion
|
||||
nonillion
|
||||
decillion
|
||||
undecillion
|
||||
duodecillion
|
||||
tredecillion
|
||||
quattuordecillion
|
||||
quindecillion
|
||||
sexdecillion
|
||||
septendecillion
|
||||
octodecillion
|
||||
novemdecillion
|
||||
vigintillion
|
||||
centillion
|
||||
|
@@ -0,0 +1,8 @@
|
||||
twenty 2
|
||||
thirty 3
|
||||
forty 4
|
||||
fifty 5
|
||||
sixty 6
|
||||
seventy 7
|
||||
eighty 8
|
||||
ninety 9
|
||||
|
@@ -0,0 +1 @@
|
||||
zero 0
|
||||
|
@@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
@@ -0,0 +1,9 @@
|
||||
first one
|
||||
second two
|
||||
third three
|
||||
fourth four
|
||||
fifth five
|
||||
sixth sixth
|
||||
seventh seven
|
||||
eighth eight
|
||||
ninth nine
|
||||
|
@@ -0,0 +1 @@
|
||||
twelfth twelve
|
||||
|
@@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
@@ -0,0 +1,49 @@
|
||||
i 1
|
||||
ii 2
|
||||
iii 3
|
||||
iv 4
|
||||
v 5
|
||||
vi 6
|
||||
vii 7
|
||||
viii 8
|
||||
ix 9
|
||||
x 10
|
||||
xi 11
|
||||
xii 12
|
||||
xiii 13
|
||||
xiv 14
|
||||
xv 15
|
||||
xvi 16
|
||||
xvii 17
|
||||
xviii 18
|
||||
xix 19
|
||||
xx 20
|
||||
xxi 21
|
||||
xxii 22
|
||||
xxiii 23
|
||||
xxiv 24
|
||||
xxv 25
|
||||
xxvi 26
|
||||
xxvii 27
|
||||
xxviii 28
|
||||
xxix 29
|
||||
xxx 30
|
||||
xxxi 31
|
||||
xxxii 32
|
||||
xxxiii 33
|
||||
xxxiv 34
|
||||
xxxv 35
|
||||
xxxvi 36
|
||||
xxxvii 37
|
||||
xxxviii 38
|
||||
xxxix 39
|
||||
xl 40
|
||||
xli 41
|
||||
xlii 42
|
||||
xliii 43
|
||||
xliv 44
|
||||
xlv 45
|
||||
xlvi 46
|
||||
xlvii 47
|
||||
xlviii 48
|
||||
xlix 49
|
||||
|
@@ -0,0 +1,9 @@
|
||||
c 100
|
||||
cc 200
|
||||
ccc 300
|
||||
cd 400
|
||||
d 500
|
||||
dc 600
|
||||
dcc 700
|
||||
dccc 800
|
||||
cm 900
|
||||
|
@@ -0,0 +1,5 @@
|
||||
l 50
|
||||
lx 60
|
||||
lxx 70
|
||||
lxxx 80
|
||||
xc 90
|
||||
|
@@ -0,0 +1,37 @@
|
||||
deer
|
||||
fish
|
||||
sheep
|
||||
foot feet
|
||||
goose geese
|
||||
man men
|
||||
mouse mice
|
||||
tooth teeth
|
||||
woman women
|
||||
won
|
||||
child children
|
||||
ox oxen
|
||||
wife wives
|
||||
wolf wolves
|
||||
analysis analyses
|
||||
criterion criteria
|
||||
focus foci
|
||||
percent
|
||||
hertz
|
||||
kroner krone
|
||||
inch inches
|
||||
calory calories
|
||||
yen
|
||||
megahertz
|
||||
gigahertz
|
||||
kilohertz
|
||||
hertz
|
||||
c c
|
||||
horsepower
|
||||
hundredweight
|
||||
kilogram force kilograms force
|
||||
mega siemens
|
||||
revolution per minute revolutions per minute
|
||||
mile per hour miles per hour
|
||||
megabit per second megabits per second
|
||||
square foot square feet
|
||||
kilobit per second kilobits per second
|
||||
|
@@ -0,0 +1,6 @@
|
||||
p.m. p m
|
||||
p.m. p m
|
||||
pm p m
|
||||
a.m. a m
|
||||
a.m a m
|
||||
am a m
|
||||
|
@@ -0,0 +1,14 @@
|
||||
cst c s t
|
||||
c.s.t c s t
|
||||
cet c e t
|
||||
c.e.t c e t
|
||||
pst p s t
|
||||
p.s.t p s t
|
||||
est e s t
|
||||
e.s.t e s t
|
||||
pt p t
|
||||
p.t p t
|
||||
et e t
|
||||
e.t e t
|
||||
gmt g m t
|
||||
g.m.t g m t
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user