Exemplo n.º 1
0
def convert(
        id: str = typer.Option(None, '-i', '--id', help='ID of model.'),
        yaml_file: Optional[Path] = typer.Option(
            None, '-f', '--yaml-file', exists=True, file_okay=True,
            help='Path to configuration YAML file. You should either set the `yaml_file` field or fields '
                 '(`FILE_OR_DIR`, `--name`, `--framework`, `--engine`, `--version`, `--task`, `--dataset`,'
                 '`--metric`, `--input`, `--output`).'
        ),
        register: bool = typer.Option(False, '-r', '--register', is_flag=True, help='register the converted models to modelhub, default false')
):
    model = None
    if id is None and yaml_file is None:
        raise ValueError('WARNING: Please assign a way to find the target model! details refer to --help')
    if id is not None and yaml_file is not None:
        raise ValueError('WARNING: Do not use -id and -path at the same time!')
    elif id is not None and yaml_file is None:
        if ModelDB.exists_by_id(id):
            model = ModelDB.get_by_id(id)
        else:
            typer.echo(f"model id: {id} does not exist in modelhub")
    elif id is None and yaml_file is not None:
        # get MLModel from yaml file
        with open(yaml_file) as f:
            model_config = yaml.safe_load(f)
        model_yaml = MLModelFromYaml.parse_obj(model_config)
        model_in_saved_path = model_yaml.saved_path
        if model_in_saved_path != model_yaml.weight:
            copy2(model_yaml.weight, model_in_saved_path)
        if model_yaml.engine == Engine.TFS:
            weight_dir = model_yaml.weight
            make_archive(weight_dir.with_suffix('.zip'), 'zip', weight_dir)

        model_data = model_yaml.dict(exclude_none=True, exclude={'convert', 'profile'})
        model = MLModel.parse_obj(model_data)

    # auto execute all possible convert and return a list of save paths of every converted model
    generated_dir_list = generate_model_family(model)
    typer.echo(f"Converted models are save in: {generated_dir_list}")
    if register:
        model_data = model.dict(exclude={'weight', 'id', 'model_status', 'engine'})
        for model_dir in generated_dir_list:
            parse_result = parse_path_plain(model_dir)
            engine = parse_result['engine']
            model_cvt = MLModel(**model_data, weight=model_dir, engine=engine, model_status=[ModelStatus.CONVERTED])
            ModelDB.save(model_cvt)
            typer.echo(f"converted {engine} are successfully registered in Modelhub")
Exemplo n.º 2
0
def load(model_weight_path: os.PathLike, *args, **kwargs):
    """A unify API to load model weight files in various format.

    Args:
        model_weight_path: Path to the model weight file. The model is saved in ModelCI standard directory.
    """

    model_weight_path = Path(model_weight_path)
    try:
        model_info = parse_path_plain(model_weight_path)
    except ValueError as e:
        # TODO: handle other path format, e.g. torch hub
        raise e

    if model_info['framework'] == 'PYTORCH' and model_info['engine'] in (
            'NONE', 'PYTORCH'):  # PyTorch
        return pytorch_loader(model_weight_path)
    elif model_info['framework'] == 'TENSORFLOW' and model_info['engine'] in (
            'None', 'TENSORFLOW'):  # TensorFlow
        return savedmodel_loader(model_weight_path)
Exemplo n.º 3
0
def register_model(
    model: MLModel,
    convert: bool = True,
    profile: bool = True,
) -> List[MLModel]:
    """Upload a model to ModelDB.
    This function will upload the given model into the database with some variation. It may optionally generate a
        branch of models (i.e. model family) with different optimization techniques. Besides, a benchmark will be
        scheduled for each generated model, in order to gain profiling results for model selection strategies.
        In the `no_generate` model(i.e. `no_generate` flag is set to be `True`), `architecture`, `framework`, `engine`
        and `version` could be None. If any of the above arguments is `None`, all of them will be auto induced
        from the origin_model path. An `ValueError` will be raised if the mata info cannot be induced.

    TODO:
        This function has a super comprehensive logic, need to be simplified.

    Arguments:
        model: Required inputs for register a model. All information is wrapped in such model.
        convert (bool): Flag for generation of model family. Default to True.
        profile (bool): Flag for profiling uploaded (including converted) models. Default to True.
    """
    models = list()

    model_dir_list = list()
    model.model_status = [ModelStatus.PUBLISHED]
    models.append(save(model))

    # generate model family
    if convert:
        model_dir_list.extend(converter.generate_model_family(model))

    # register
    model_data = model.dict(exclude={'weight', 'id', 'model_status', 'engine'})
    for model_dir in model_dir_list:
        parse_result = parse_path_plain(model_dir)
        engine = parse_result['engine']

        model_cvt = MLModel(**model_data,
                            weight=model_dir,
                            engine=engine,
                            model_status=[ModelStatus.CONVERTED])
        models.append(save(model_cvt))

    # profile registered model
    if profile:
        from modelci.controller import job_executor
        from modelci.controller.executor import Job

        file = tf.keras.utils.get_file(
            "grace_hopper.jpg",
            "https://storage.googleapis.com/download.tensorflow.org/example_images/grace_hopper.jpg"
        )
        test_img_bytes = cv2.imread(file)

        kwargs = {
            'repeat_data': test_img_bytes,
            'batch_size': 32,
            'batch_num': 100,
            'asynchronous': False,
        }

        for model in models:
            model.model_status = [ModelStatus.PROFILING]
            ModelService.update_model(model)
            kwargs['model_info'] = model
            engine = model.engine

            if engine == Engine.TORCHSCRIPT:
                client = CVTorchClient(**kwargs)
            elif engine == Engine.TFS:
                client = CVTFSClient(**kwargs)
            elif engine == Engine.ONNX:
                client = CVONNXClient(**kwargs)
            elif engine == Engine.TRT:
                client = CVTRTClient(**kwargs)
            else:
                raise ValueError(f'No such serving engine: {engine}')

            job_cuda = Job(client=client, device='cuda:0', model_info=model)
            # job_cpu = Job(client=client, device='cpu', model_info=model)
            job_executor.submit(job_cuda)
            # job_executor.submit(job_cpu)

    return models