Introduce code from Rust monorepo. This is a mess

This commit is contained in:
Brandon Thomas
2022-02-28 05:43:54 -05:00
parent 921fb49f9a
commit ba326bfcfd
1058 changed files with 192192 additions and 0 deletions
@@ -0,0 +1,48 @@
# Copyright (c) 2020, 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 pytest
import torch
from sklearn.metrics import precision_recall_fscore_support
from nemo.collections.nlp.metrics.classification_report import ClassificationReport
class ClassificationReportTests:
num_classes = 3
label_ids = {'a': 0, 'b': 1, 'c': 2}
@pytest.mark.unit
def test_classification_report(self):
preds = torch.Tensor([0, 1, 1, 1, 2, 2, 0])
labels = torch.Tensor([1, 0, 0, 1, 2, 1, 0])
def __convert_to_tensor(sklearn_metric):
return torch.Tensor([round(sklearn_metric * 100)])[0]
for mode in ['macro', 'micro', 'weighted']:
classification_report_nemo = ClassificationReport(
num_classes=self.num_classes, label_ids=self.label_ids, mode=mode
)
# pytest.set_trace()
precision, recall, f1, _ = classification_report_nemo(preds, labels)
tp, fp, fn = classification_report_nemo.tp, classification_report_nemo.fp, classification_report_nemo.fn
pr_sklearn, recall_sklearn, f1_sklearn, _ = precision_recall_fscore_support(labels, preds, average=mode)
self.assertEqual(torch.round(precision), __convert_to_tensor(pr_sklearn), f'wrong precision for {mode}')
self.assertEqual(torch.round(recall), __convert_to_tensor(recall_sklearn), f'wrong recall for {mode}')
self.assertEqual(torch.round(f1), __convert_to_tensor(f1_sklearn), f'wrong f1 for {mode}')
@@ -0,0 +1,83 @@
# 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
import shutil
import tempfile
import pytest
import wget
from omegaconf import OmegaConf
from nemo.collections.nlp.models import EntityLinkingModel
def get_cfg():
language_model = OmegaConf.create(
{"pretrained_model_name": "bert-base-uncased", "config_file": None, "config": None, "lm_checkpoint": None}
)
tokenizer = OmegaConf.create(
{"tokenizer_name": "bert-base-uncased", "vocab_file": None, "tokenizer_model": None, "do_lower_case": True}
)
model = OmegaConf.create(
{
"nemo_path": "sap_entity_linking.nemo",
"max_seq_length": 128,
"language_model": language_model,
"tokenizer": tokenizer,
"train_ds": None,
"validation_ds": None,
}
)
cfg = OmegaConf.create({"model": model})
return cfg
class TestEntityLinkingModel:
@pytest.mark.unit
def test_creation_saving_restoring(self):
# Create a new temporary directory
with tempfile.TemporaryDirectory() as restore_dir:
with tempfile.TemporaryDirectory() as save_dir:
model = EntityLinkingModel(cfg=get_cfg().model)
assert isinstance(model, EntityLinkingModel)
save_dir_path = save_dir
# Where model will be saved
model_save_path = os.path.join(save_dir, f"{model.__class__.__name__}.nemo")
model.save_to(save_path=model_save_path)
# Where model will be restored from
model_restore_path = os.path.join(restore_dir, f"{model.__class__.__name__}.nemo")
shutil.copy(model_save_path, model_restore_path)
# at this point save_dir should not exist
assert save_dir_path is not None and not os.path.exists(save_dir_path)
assert not os.path.exists(model_save_path)
assert os.path.exists(model_restore_path)
# attempt to restore
model_copy = model.__class__.restore_from(restore_path=model_restore_path)
assert model.num_weights == model_copy.num_weights
if __name__ == "__main__":
t = TestEntityLinkingModel()
t.test_creation_saving_restoring()
@@ -0,0 +1,86 @@
# Copyright (c) 2020, 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
import tempfile
import pytest
import torch
import nemo.collections.nlp as nemo_nlp
from nemo.collections.common.tokenizers.huggingface.auto_tokenizer import AutoTokenizer
from nemo.collections.nlp.modules.common.tokenizer_utils import get_tokenizer
def do_export(model, name: str):
with tempfile.TemporaryDirectory() as tmpdir:
# Generate filename in the temporary directory.
tmp_file_name = os.path.join(tmpdir, name + '.onnx')
# Test export.
if torch.cuda.is_available():
model = model.cuda()
model.export(tmp_file_name)
class TestHuggingFace:
@pytest.mark.unit
def test_list_pretrained_models(self):
pretrained_lm_models = nemo_nlp.modules.get_pretrained_lm_models_list()
assert len(pretrained_lm_models) > 0
@pytest.mark.with_downloads()
@pytest.mark.unit
def test_get_pretrained_bert_model(self):
model = nemo_nlp.modules.get_lm_model(pretrained_model_name='bert-base-uncased')
assert isinstance(model, nemo_nlp.modules.BertEncoder)
do_export(model, "bert-base-uncased")
@pytest.mark.with_downloads()
@pytest.mark.unit
def test_get_pretrained_distilbert_model(self):
model = nemo_nlp.modules.get_lm_model(pretrained_model_name='distilbert-base-uncased')
assert isinstance(model, nemo_nlp.modules.DistilBertEncoder)
do_export(model, "distilbert-base-uncased")
@pytest.mark.with_downloads()
@pytest.mark.unit
def test_get_pretrained_roberta_model(self):
model = nemo_nlp.modules.get_lm_model(pretrained_model_name='roberta-base')
assert isinstance(model, nemo_nlp.modules.RobertaEncoder)
do_export(model, "roberta-base-uncased")
@pytest.mark.with_downloads()
@pytest.mark.unit
def test_get_pretrained_albert_model(self):
model = nemo_nlp.modules.get_lm_model(pretrained_model_name='albert-base-v1')
assert isinstance(model, nemo_nlp.modules.AlbertEncoder)
do_export(model, "albert-base-v1")
@pytest.mark.with_downloads()
@pytest.mark.unit
def test_get_pretrained_chinese_bert_wwm_model(self):
model_name = 'hfl/chinese-bert-wwm'
model = nemo_nlp.modules.get_lm_model(pretrained_model_name=model_name)
assert isinstance(model, nemo_nlp.modules.BertModule)
tokenizer = get_tokenizer(tokenizer_name=model_name)
assert isinstance(tokenizer, AutoTokenizer)
@pytest.mark.with_downloads()
@pytest.mark.unit
def test_get_pretrained_arabic_model(self):
model_name = 'asafaya/bert-base-arabic'
model = nemo_nlp.modules.get_lm_model(pretrained_model_name=model_name)
assert isinstance(model, nemo_nlp.modules.BertModule)
tokenizer = get_tokenizer(tokenizer_name=model_name)
assert isinstance(tokenizer, AutoTokenizer)
@@ -0,0 +1,76 @@
# Copyright (c) 2020, 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.
try:
import apex
apex_available = True
except Exception:
apex_available = False
import os
import tempfile
import onnx
import pytest
import torch
import nemo.collections.nlp as nemo_nlp
from nemo.core.classes import typecheck
def get_pretrained_bert_345m_uncased_model():
model_name = "megatron-bert-345m-uncased"
model = nemo_nlp.modules.get_lm_model(pretrained_model_name=model_name)
if torch.cuda.is_available():
model = model.cuda()
return model
class TestMegatron:
@pytest.mark.run_only_on('GPU')
@pytest.mark.unit
def test_list_pretrained_models(self):
pretrained_lm_models = nemo_nlp.modules.get_pretrained_lm_models_list()
assert len(pretrained_lm_models) > 0
@pytest.mark.with_downloads()
@pytest.mark.run_only_on('GPU')
@pytest.mark.unit
@pytest.mark.skip("Only one Megatron model is allowed")
def test_get_model(self):
model = get_pretrained_bert_345m_uncased_model()
assert isinstance(model, nemo_nlp.modules.MegatronBertEncoder)
typecheck.set_typecheck_enabled(enabled=False)
inp = model.input_example()
out = model.forward(*inp)
typecheck.set_typecheck_enabled(enabled=True)
@pytest.mark.skipif(not os.path.exists('/home/TestData/nlp'), reason='Not a Jenkins machine')
@pytest.mark.with_downloads()
@pytest.mark.run_only_on('GPU')
@pytest.mark.unit
def test_onnx_export(self):
model = get_pretrained_bert_345m_uncased_model()
assert model
with tempfile.TemporaryDirectory() as tmpdir:
# Generate filename in the temporary directory.
# Test export.
model.export(os.path.join(".", "megatron.onnx"))
if __name__ == "__main__":
t = TestMegatron()
t.test_onnx_export()
@@ -0,0 +1,176 @@
# Copyright (c) 2020, 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
import tempfile
import onnx
import pytest
import pytorch_lightning as pl
import torch
import wget
from omegaconf import OmegaConf
from nemo.collections import nlp as nemo_nlp
from nemo.collections.nlp.models import IntentSlotClassificationModel
from nemo.collections.nlp.modules.common import (
SequenceClassifier,
SequenceRegression,
SequenceTokenClassifier,
TokenClassifier,
)
def classifier_export(obj):
with tempfile.TemporaryDirectory() as tmpdir:
filename = os.path.join(tmpdir, obj.__class__.__name__ + '.onnx')
obj = obj.cuda()
obj.export(output=filename)
class TestExportableClassifiers:
@pytest.mark.run_only_on('GPU')
@pytest.mark.unit
def test_token_classifier_export_to_onnx(self):
for num_layers in [1, 2, 4]:
classifier_export(TokenClassifier(hidden_size=256, num_layers=num_layers, num_classes=16))
@pytest.mark.run_only_on('GPU')
@pytest.mark.unit
def test_bert_pretraining_export_to_onnx(self):
for num_layers in [1, 2, 4]:
classifier_export(TokenClassifier(hidden_size=256, num_layers=num_layers, num_classes=16))
@pytest.mark.run_only_on('GPU')
@pytest.mark.unit
def test_sequence_token_classifier_export_to_onnx(self):
for num_layers in [1, 2, 4]:
classifier_export(
SequenceTokenClassifier(hidden_size=256, num_slots=8, num_intents=8, num_layers=num_layers)
)
@pytest.mark.run_only_on('GPU')
@pytest.mark.unit
def test_sequence_classifier_export_to_onnx(self):
for num_layers in [1, 2, 4]:
classifier_export(SequenceClassifier(hidden_size=256, num_classes=16, num_layers=num_layers))
@pytest.mark.run_only_on('GPU')
@pytest.mark.unit
def test_sequence_regression_export_to_onnx(self):
for num_layers in [1, 2, 4]:
classifier_export(SequenceRegression(hidden_size=256, num_layers=num_layers))
@pytest.mark.run_only_on('GPU')
@pytest.mark.unit
def test_IntentSlotClassificationModel_export_to_onnx(self, dummy_data):
with tempfile.TemporaryDirectory() as tmpdir:
wget.download(
'https://raw.githubusercontent.com/NVIDIA/NeMo/main/examples/'
'nlp/intent_slot_classification/conf/intent_slot_classification_config.yaml',
tmpdir,
)
config_file = os.path.join(tmpdir, 'intent_slot_classification_config.yaml')
config = OmegaConf.load(config_file)
config = OmegaConf.create(OmegaConf.to_container(config, resolve=True))
config.model.data_dir = dummy_data
config.trainer.gpus = 1
config.trainer.precision = 32
config.trainer.accelerator = None
trainer = pl.Trainer(**config.trainer)
model = IntentSlotClassificationModel(config.model, trainer=trainer)
filename = os.path.join(tmpdir, 'isc.onnx')
model.export(output=filename)
onnx_model = onnx.load(filename)
onnx.checker.check_model(onnx_model, full_check=True) # throws when failed
assert onnx_model.graph.input[0].name == 'input_ids'
assert onnx_model.graph.input[1].name == 'attention_mask'
assert onnx_model.graph.input[2].name == 'token_type_ids'
assert onnx_model.graph.output[0].name == 'intent_logits'
assert onnx_model.graph.output[1].name == 'slot_logits'
@pytest.mark.run_only_on('GPU')
@pytest.mark.unit
@pytest.mark.skip('Are we exporting to torchscript?')
def test_IntentSlotClassificationModel_export_to_torchscript(self, dummy_data):
with tempfile.TemporaryDirectory() as tmpdir:
wget.download(
'https://raw.githubusercontent.com/NVIDIA/NeMo/main/examples/'
'nlp/intent_slot_classification/conf/intent_slot_classification_config.yaml',
tmpdir,
)
config_file = os.path.join(tmpdir, 'intent_slot_classification_config.yaml')
config = OmegaConf.load(config_file)
config = OmegaConf.create(OmegaConf.to_container(config, resolve=True))
config.model.data_dir = dummy_data
config.trainer.gpus = 1
config.trainer.precision = 32
config.trainer.accelerator = None
trainer = pl.Trainer(**config.trainer)
model = IntentSlotClassificationModel(config.model, trainer=trainer)
filename = os.path.join(tmpdir, 'isc.pt')
model.export(output=filename, check_trace=True)
torchscript_model = torch.jit.load(filename)
inputs = list(torchscript_model.graph.inputs())
assert inputs[1].debugName() == 'input_ids.1'
assert inputs[2].debugName() == 'input.1'
assert inputs[3].debugName() == 'attention_mask.1'
modules = list(torchscript_model.modules())
assert modules[2].original_name == 'BertEmbeddings'
assert modules[46].original_name == 'BertSelfAttention'
assert modules[217].original_name == 'SequenceTokenClassifier'
assert modules[219].original_name == 'MultiLayerPerceptron'
@pytest.mark.run_only_on('GPU')
@pytest.mark.unit
def test_TokenClassificationModel_export_to_onnx(self):
model = nemo_nlp.models.TokenClassificationModel.from_pretrained(model_name="ner_en_bert")
with tempfile.TemporaryDirectory() as tmpdir:
filename = os.path.join(tmpdir, 'ner.onnx')
model.export(output=filename)
onnx_model = onnx.load(filename)
onnx.checker.check_model(onnx_model, full_check=True) # throws when failed
assert onnx_model.graph.input[0].name == 'input_ids'
assert onnx_model.graph.output[0].name == 'logits'
@pytest.mark.run_only_on('GPU')
@pytest.mark.unit
def test_PunctuationCapitalizationModel_export_to_onnx(self):
model = nemo_nlp.models.PunctuationCapitalizationModel.from_pretrained(model_name="punctuation_en_distilbert")
with tempfile.TemporaryDirectory() as tmpdir:
filename = os.path.join(tmpdir, 'puncap.onnx')
model.export(output=filename)
onnx_model = onnx.load(filename)
onnx.checker.check_model(onnx_model, full_check=True) # throws when failed
assert onnx_model.graph.input[0].name == 'input_ids'
# assert onnx_model.graph.input[2].name == 'token_type_ids'
assert onnx_model.graph.output[0].name == 'punct_logits'
assert onnx_model.graph.output[1].name == 'capit_logits'
@pytest.mark.run_only_on('GPU')
@pytest.mark.unit
def test_QAModel_export_to_onnx(self):
model = nemo_nlp.models.QAModel.from_pretrained(model_name="qa_squadv2.0_bertbase")
with tempfile.TemporaryDirectory() as tmpdir:
filename = os.path.join(tmpdir, 'qa.onnx')
model.export(output=filename)
onnx_model = onnx.load(filename)
onnx.checker.check_model(onnx_model, full_check=True) # throws when failed
assert onnx_model.graph.input[0].name == 'input_ids'
assert onnx_model.graph.input[2].name == 'token_type_ids'
assert onnx_model.graph.output[0].name == 'logits'
@pytest.fixture()
def dummy_data(test_data_dir):
return os.path.join(test_data_dir, 'nlp', 'dummy_data')
@@ -0,0 +1,144 @@
# Copyright (c) 2020, 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
import shutil
import tempfile
import pytest
import torch
from omegaconf import DictConfig, OmegaConf
from nemo.collections.nlp.models import MTEncDecModel
from nemo.collections.nlp.models.machine_translation.mt_enc_dec_config import AAYNBaseConfig
def export_test(model, suffix, try_script=False):
with tempfile.TemporaryDirectory() as restore_folder:
enc_filename = os.path.join(restore_folder, 'nmt_e' + suffix)
dec_filename = os.path.join(restore_folder, 'nmt_d' + suffix)
model.encoder.export(output=enc_filename, try_script=try_script)
model.decoder.export(output=dec_filename, try_script=try_script)
assert os.path.exists(enc_filename)
assert os.path.exists(dec_filename)
def get_cfg():
cfg = AAYNBaseConfig()
cfg.encoder_tokenizer.tokenizer_name = 'yttm'
cfg.encoder_tokenizer.tokenizer_model = 'tests/.data/yttm.4096.en-de.model'
cfg.decoder_tokenizer.tokenizer_name = 'yttm'
cfg.decoder_tokenizer.tokenizer_model = 'tests/.data/yttm.4096.en-de.model'
cfg.train_ds = None
cfg.validation_ds = None
cfg.test_ds = None
return cfg
class TestMTEncDecModel:
@pytest.mark.unit
def test_creation_saving_restoring(self):
model = MTEncDecModel(cfg=get_cfg())
assert isinstance(model, MTEncDecModel)
# Create a new temporary directory
with tempfile.TemporaryDirectory() as restore_folder:
with tempfile.TemporaryDirectory() as save_folder:
save_folder_path = save_folder
# Where model will be saved
model_save_path = os.path.join(save_folder, f"{model.__class__.__name__}.nemo")
model.save_to(save_path=model_save_path)
# Where model will be restored from
model_restore_path = os.path.join(restore_folder, f"{model.__class__.__name__}.nemo")
shutil.copy(model_save_path, model_restore_path)
# at this point save_folder should not exist
assert save_folder_path is not None and not os.path.exists(save_folder_path)
assert not os.path.exists(model_save_path)
assert os.path.exists(model_restore_path)
# attempt to restore
model_copy = model.__class__.restore_from(restore_path=model_restore_path)
assert model.num_weights == model_copy.num_weights
@pytest.mark.unit
def test_no_artifact_name_collision(self):
model = MTEncDecModel(cfg=get_cfg())
assert isinstance(model, MTEncDecModel)
with tempfile.TemporaryDirectory() as tmpdir1:
model.save_to("nmt_model.nemo")
with tempfile.TemporaryDirectory() as tmpdir:
model._unpack_nemo_file(path2file="nmt_model.nemo", out_folder=tmpdir)
conf = OmegaConf.load(os.path.join(tmpdir, "model_config.yaml"))
# Make sure names now differ in saved config
assert conf.encoder_tokenizer.tokenizer_model != conf.decoder_tokenizer.tokenizer_model
# Make sure names in config start with "nemo:" prefix
assert conf.encoder_tokenizer.tokenizer_model.startswith("nemo:")
assert conf.decoder_tokenizer.tokenizer_model.startswith("nemo:")
# Check if both tokenizers were included
assert os.path.exists(os.path.join(tmpdir, conf.encoder_tokenizer.tokenizer_model[5:]))
assert os.path.exists(os.path.join(tmpdir, conf.decoder_tokenizer.tokenizer_model[5:]))
@pytest.mark.unit
def test_train_eval_loss(self):
cfg = get_cfg()
cfg.label_smoothing = 0.5
model = MTEncDecModel(cfg=cfg)
assert isinstance(model, MTEncDecModel)
batch_size = 10
time = 32
vocab_size = 32000
torch.manual_seed(42)
tgt_ids = torch.LongTensor(batch_size, time).random_(1, model.decoder_tokenizer.vocab_size)
logits = torch.FloatTensor(batch_size, time, vocab_size).random_(-1, 1)
log_probs = torch.nn.functional.log_softmax(logits, dim=-1)
train_loss = model.loss_fn(log_probs=log_probs, labels=tgt_ids)
eval_loss = model.eval_loss_fn(log_probs=log_probs, labels=tgt_ids)
assert not torch.allclose(train_loss, eval_loss) # , (train_loss, eval_loss)
cfg.label_smoothing = 0
model = MTEncDecModel(cfg=cfg)
# Train loss == val loss when label smoothing = 0
train_loss = model.loss_fn(log_probs=log_probs, labels=tgt_ids)
eval_loss = model.eval_loss_fn(log_probs=log_probs, labels=tgt_ids)
assert torch.allclose(train_loss, eval_loss)
@pytest.mark.unit
def test_cpu_export_onnx(self):
model = MTEncDecModel(cfg=get_cfg())
assert isinstance(model, MTEncDecModel)
export_test(model, ".ts")
@pytest.mark.unit
def test_cpu_export_ts(self):
model = MTEncDecModel(cfg=get_cfg())
assert isinstance(model, MTEncDecModel)
export_test(model, ".onnx")
@pytest.mark.skipif(not os.path.exists('/home/TestData/nlp'), reason='Not a Jenkins machine')
@pytest.mark.run_only_on('GPU')
@pytest.mark.unit
def test_gpu_export_ts(self):
model = MTEncDecModel(cfg=get_cfg()).cuda()
assert isinstance(model, MTEncDecModel)
export_test(model, ".ts")
@pytest.mark.run_only_on('GPU')
@pytest.mark.unit
def test_gpu_export_onnx(self):
model = MTEncDecModel(cfg=get_cfg()).cuda()
assert isinstance(model, MTEncDecModel)
export_test(model, ".onnx")
if __name__ == "__main__":
t = TestMTEncDecModel()
# t.test_gpu_export_ts()
t.test_train_eval_loss()
@@ -0,0 +1,110 @@
# Copyright (c) 2020, 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 pathlib import Path
from shutil import rmtree
from unittest import TestCase
import pytest
import pytorch_lightning as pl
from omegaconf import OmegaConf
import nemo.collections.nlp.models as models
def get_metrics(data_dir, model):
trainer = pl.Trainer(gpus=[0])
model.set_trainer(trainer)
model.update_data_dir(data_dir)
test_ds = OmegaConf.create(
{
'text_file': 'text_dev.txt',
'labels_file': 'labels_dev.txt',
'shuffle': False,
'num_samples': -1,
'batch_size': 8,
}
)
model._cfg.dataset.use_cache = False
trainer.test(model)
model.setup_test_data(test_data_config=test_ds)
metrics = trainer.test(model)[0]
return metrics
def data_exists(data_dir):
return os.path.exists(data_dir)
class TestPretrainedModelPerformance:
@pytest.mark.with_downloads()
@pytest.mark.unit
@pytest.mark.run_only_on('GPU')
@pytest.mark.skipif(
not data_exists('/home/TestData/nlp/token_classification_punctuation/fisher'), reason='Not a Jenkins machine'
)
def test_punct_capit_with_bert(self):
data_dir = '/home/TestData/nlp/token_classification_punctuation/fisher'
model = models.PunctuationCapitalizationModel.from_pretrained("punctuation_en_bert")
metrics = get_metrics(data_dir, model)
assert abs(metrics['punct_precision'] - 52.3024) < 0.001
assert abs(metrics['punct_recall'] - 58.9220) < 0.001
assert abs(metrics['punct_f1'] - 53.2976) < 0.001
assert abs(metrics['capit_precision'] - 87.0707) < 0.001
assert abs(metrics['capit_recall'] - 87.0707) < 0.001
assert abs(metrics['capit_f1'] - 87.0707) < 0.001
assert int(model.punct_class_report.total_examples) == 128
preds_512 = model.add_punctuation_capitalization(['what can i do for you today'], max_seq_length=512)[0]
assert preds_512 == 'What can I do for you today?'
preds_5 = model.add_punctuation_capitalization(['what can i do for you today'], max_seq_length=5)[0]
assert preds_5 == 'What can i'
@pytest.mark.with_downloads()
@pytest.mark.unit
@pytest.mark.run_only_on('GPU')
@pytest.mark.skipif(
not data_exists('/home/TestData/nlp/token_classification_punctuation/fisher'), reason='Not a Jenkins machine'
)
def test_punct_capit_with_distilbert(self):
data_dir = '/home/TestData/nlp/token_classification_punctuation/fisher'
model = models.PunctuationCapitalizationModel.from_pretrained("punctuation_en_distilbert")
metrics = get_metrics(data_dir, model)
assert abs(metrics['punct_precision'] - 53.0826) < 0.001
assert abs(metrics['punct_recall'] - 56.2905) < 0.001
assert abs(metrics['punct_f1'] - 52.4225) < 0.001
assert int(model.punct_class_report.total_examples) == 128
@pytest.mark.with_downloads()
@pytest.mark.unit
@pytest.mark.run_only_on('GPU')
@pytest.mark.skipif(
not data_exists('/home/TestData/nlp/token_classification_punctuation/gmb'), reason='Not a Jenkins machine'
)
def test_ner_model(self):
data_dir = '/home/TestData/nlp/token_classification_punctuation/gmb'
model = models.TokenClassificationModel.from_pretrained("ner_en_bert")
metrics = get_metrics(data_dir, model)
assert abs(metrics['precision'] - 96.0937) < 0.001
assert abs(metrics['recall'] - 96.0146) < 0.001
assert abs(metrics['f1'] - 95.6076) < 0.001
assert int(model.classification_report.total_examples) == 202