Browse Source

[to #42322933] Fix some bugs when downgrade the version of some dependencies

1. Fix bug in model exporting
2. Skip some long trainings in test level 2
3. Refine some comments
4. Fix a bug that mode is not correct when saving checkpoints
        Link: https://code.alibaba-inc.com/Ali-MaaS/MaaS-lib/codereview/10564716
master
yuze.zyz yingda.chen 2 years ago
parent
commit
4b7e8e89aa
8 changed files with 92 additions and 13 deletions
  1. +78
    -8
      modelscope/exporters/torch_model_exporter.py
  2. +7
    -0
      modelscope/models/base/base_model.py
  3. +1
    -0
      modelscope/models/nlp/bert/text_ranking.py
  4. +1
    -0
      modelscope/models/nlp/structbert/text_classification.py
  5. +2
    -2
      modelscope/trainers/trainer.py
  6. +1
    -1
      tests/export/test_export_sbert_sequence_classification.py
  7. +1
    -1
      tests/trainers/test_finetune_sequence_classification.py
  8. +1
    -1
      tests/trainers/test_trainer_with_nlp.py

+ 78
- 8
modelscope/exporters/torch_model_exporter.py View File

@@ -7,9 +7,9 @@ from typing import Any, Dict, Mapping
import torch import torch
from torch import nn from torch import nn
from torch.onnx import export as onnx_export from torch.onnx import export as onnx_export
from torch.onnx.utils import _decide_input_format


from modelscope.models import TorchModel from modelscope.models import TorchModel
from modelscope.outputs import ModelOutputBase
from modelscope.pipelines.base import collate_fn from modelscope.pipelines.base import collate_fn
from modelscope.utils.constant import ModelFile from modelscope.utils.constant import ModelFile
from modelscope.utils.logger import get_logger from modelscope.utils.logger import get_logger
@@ -102,6 +102,53 @@ class TorchModelExporter(Exporter):
""" """
return None return None


@staticmethod
def _decide_input_format(model, args):
import inspect

def _signature(model) -> inspect.Signature:
should_be_callable = getattr(model, 'forward', model)
if callable(should_be_callable):
return inspect.signature(should_be_callable)
raise ValueError('model has no forward method and is not callable')

try:
sig = _signature(model)
except ValueError as e:
logger.warn('%s, skipping _decide_input_format' % e)
return args
try:
ordered_list_keys = list(sig.parameters.keys())
if ordered_list_keys[0] == 'self':
ordered_list_keys = ordered_list_keys[1:]
args_dict: Dict = {}
if isinstance(args, list):
args_list = args
elif isinstance(args, tuple):
args_list = list(args)
else:
args_list = [args]
if isinstance(args_list[-1], dict):
args_dict = args_list[-1]
args_list = args_list[:-1]
n_nonkeyword = len(args_list)
for optional_arg in ordered_list_keys[n_nonkeyword:]:
if optional_arg in args_dict:
args_list.append(args_dict[optional_arg])
# Check if this arg has a default value
else:
param = sig.parameters[optional_arg]
if param.default != param.empty:
args_list.append(param.default)
args = args_list if isinstance(args, list) else tuple(args_list)
# Cases of models with no input args
except IndexError:
logger.warn('No input args, skipping _decide_input_format')
except Exception as e:
logger.warn('Skipping _decide_input_format\n {}'.format(e.args[0]))

return args

def _torch_export_onnx(self, def _torch_export_onnx(self,
model: nn.Module, model: nn.Module,
output: str, output: str,
@@ -179,16 +226,21 @@ class TorchModelExporter(Exporter):
with torch.no_grad(): with torch.no_grad():
model.eval() model.eval()
outputs_origin = model.forward( outputs_origin = model.forward(
*_decide_input_format(model, dummy_inputs))
if isinstance(outputs_origin, Mapping):
outputs_origin = numpify_tensor_nested(
list(outputs_origin.values()))
*self._decide_input_format(model, dummy_inputs))
if isinstance(outputs_origin, (Mapping, ModelOutputBase)):
outputs_origin = list(
numpify_tensor_nested(outputs_origin).values())
elif isinstance(outputs_origin, (tuple, list)): elif isinstance(outputs_origin, (tuple, list)):
outputs_origin = numpify_tensor_nested(outputs_origin)
outputs_origin = list(numpify_tensor_nested(outputs_origin))
outputs = ort_session.run( outputs = ort_session.run(
onnx_outputs, onnx_outputs,
numpify_tensor_nested(dummy_inputs), numpify_tensor_nested(dummy_inputs),
) )
outputs = numpify_tensor_nested(outputs)
if isinstance(outputs, dict):
outputs = list(outputs.values())
elif isinstance(outputs, tuple):
outputs = list(outputs)


tols = {} tols = {}
if rtol is not None: if rtol is not None:
@@ -232,12 +284,26 @@ class TorchModelExporter(Exporter):
'Model property dummy_inputs must be set.') 'Model property dummy_inputs must be set.')
dummy_inputs = collate_fn(dummy_inputs, device) dummy_inputs = collate_fn(dummy_inputs, device)
if isinstance(dummy_inputs, Mapping): if isinstance(dummy_inputs, Mapping):
dummy_inputs = tuple(dummy_inputs.values())
dummy_inputs = self._decide_input_format(model, dummy_inputs)
dummy_inputs_filter = []
for _input in dummy_inputs:
if _input is not None:
dummy_inputs_filter.append(_input)
else:
break

if len(dummy_inputs) != len(dummy_inputs_filter):
logger.warn(
f'Dummy inputs is not continuous in the forward method, '
f'origin length: {len(dummy_inputs)}, '
f'the length after filtering: {len(dummy_inputs_filter)}')
dummy_inputs = dummy_inputs_filter

with torch.no_grad(): with torch.no_grad():
model.eval() model.eval()
with replace_call(): with replace_call():
traced_model = torch.jit.trace( traced_model = torch.jit.trace(
model, dummy_inputs, strict=strict)
model, tuple(dummy_inputs), strict=strict)
torch.jit.save(traced_model, output) torch.jit.save(traced_model, output)


if validation: if validation:
@@ -249,6 +315,10 @@ class TorchModelExporter(Exporter):
outputs = numpify_tensor_nested(outputs) outputs = numpify_tensor_nested(outputs)
outputs_origin = model.forward(*dummy_inputs) outputs_origin = model.forward(*dummy_inputs)
outputs_origin = numpify_tensor_nested(outputs_origin) outputs_origin = numpify_tensor_nested(outputs_origin)
if isinstance(outputs, dict):
outputs = list(outputs.values())
if isinstance(outputs_origin, dict):
outputs_origin = list(outputs_origin.values())
tols = {} tols = {}
if rtol is not None: if rtol is not None:
tols['rtol'] = rtol tols['rtol'] = rtol


+ 7
- 0
modelscope/models/base/base_model.py View File

@@ -161,5 +161,12 @@ class Model(ABC):
assert config is not None, 'Cannot save the model because the model config is empty.' assert config is not None, 'Cannot save the model because the model config is empty.'
if isinstance(config, Config): if isinstance(config, Config):
config = config.to_dict() config = config.to_dict()
if 'preprocessor' in config and config['preprocessor'] is not None:
if 'mode' in config['preprocessor']:
config['preprocessor']['mode'] = 'inference'
elif 'val' in config['preprocessor'] and 'mode' in config[
'preprocessor']['val']:
config['preprocessor']['val']['mode'] = 'inference'

save_pretrained(self, target_folder, save_checkpoint_names, save_pretrained(self, target_folder, save_checkpoint_names,
save_function, config, **kwargs) save_function, config, **kwargs)

+ 1
- 0
modelscope/models/nlp/bert/text_ranking.py View File

@@ -36,6 +36,7 @@ class BertForTextRanking(BertForSequenceClassification):
output_attentions=None, output_attentions=None,
output_hidden_states=None, output_hidden_states=None,
return_dict=None, return_dict=None,
*args,
**kwargs) -> AttentionTextClassificationModelOutput: **kwargs) -> AttentionTextClassificationModelOutput:
outputs = self.base_model.forward( outputs = self.base_model.forward(
input_ids=input_ids, input_ids=input_ids,


+ 1
- 0
modelscope/models/nlp/structbert/text_classification.py View File

@@ -109,6 +109,7 @@ class SbertForSequenceClassification(SbertPreTrainedModel):
output_attentions=None, output_attentions=None,
output_hidden_states=None, output_hidden_states=None,
return_dict=None, return_dict=None,
*args,
**kwargs): **kwargs):
r""" r"""
Args: Args:


+ 2
- 2
modelscope/trainers/trainer.py View File

@@ -672,7 +672,7 @@ class EpochBasedTrainer(BaseTrainer):
self.model, cfg=cfg, default_args=default_args) self.model, cfg=cfg, default_args=default_args)
except KeyError as e: except KeyError as e:
self.logger.error( self.logger.error(
f'Build optimizer error, the optimizer {cfg} is native torch optimizer, '
f'Build optimizer error, the optimizer {cfg} is a torch native component, '
f'please check if your torch with version: {torch.__version__} matches the config.' f'please check if your torch with version: {torch.__version__} matches the config.'
) )
raise e raise e
@@ -682,7 +682,7 @@ class EpochBasedTrainer(BaseTrainer):
return build_lr_scheduler(cfg=cfg, default_args=default_args) return build_lr_scheduler(cfg=cfg, default_args=default_args)
except KeyError as e: except KeyError as e:
self.logger.error( self.logger.error(
f'Build lr_scheduler error, the lr_scheduler {cfg} is native torch lr_scheduler, '
f'Build lr_scheduler error, the lr_scheduler {cfg} is a torch native component, '
f'please check if your torch with version: {torch.__version__} matches the config.' f'please check if your torch with version: {torch.__version__} matches the config.'
) )
raise e raise e


+ 1
- 1
tests/export/test_export_sbert_sequence_classification.py View File

@@ -23,7 +23,7 @@ class TestExportSbertSequenceClassification(unittest.TestCase):
shutil.rmtree(self.tmp_dir) shutil.rmtree(self.tmp_dir)
super().tearDown() super().tearDown()


@unittest.skip
@unittest.skipUnless(test_level() >= 0, 'skip test in current test level')
def test_export_sbert_sequence_classification(self): def test_export_sbert_sequence_classification(self):
model = Model.from_pretrained(self.model_id) model = Model.from_pretrained(self.model_id)
print( print(


+ 1
- 1
tests/trainers/test_finetune_sequence_classification.py View File

@@ -38,7 +38,7 @@ class TestFinetuneSequenceClassification(unittest.TestCase):
shutil.rmtree(self.tmp_dir) shutil.rmtree(self.tmp_dir)
super().tearDown() super().tearDown()


@unittest.skipUnless(test_level() >= 2, 'skip test in current test level')
@unittest.skip
def test_trainer_cfg_class(self): def test_trainer_cfg_class(self):
dataset = MsDataset.load('clue', subset_name='tnews') dataset = MsDataset.load('clue', subset_name='tnews')
train_dataset = dataset['train'] train_dataset = dataset['train']


+ 1
- 1
tests/trainers/test_trainer_with_nlp.py View File

@@ -72,7 +72,7 @@ class TestTrainerWithNlp(unittest.TestCase):
output_dir = os.path.join(self.tmp_dir, ModelFile.TRAIN_OUTPUT_DIR) output_dir = os.path.join(self.tmp_dir, ModelFile.TRAIN_OUTPUT_DIR)
pipeline_sentence_similarity(output_dir) pipeline_sentence_similarity(output_dir)


@unittest.skipUnless(test_level() >= 3, 'skip test in current test level')
@unittest.skip
def test_trainer_with_backbone_head(self): def test_trainer_with_backbone_head(self):
model_id = 'damo/nlp_structbert_sentiment-classification_chinese-base' model_id = 'damo/nlp_structbert_sentiment-classification_chinese-base'
kwargs = dict( kwargs = dict(


Loading…
Cancel
Save