docker_images/mindspore/app/pipelines/image_classification.py (70 lines of code) (raw):

import json import os from typing import TYPE_CHECKING, Any, Dict, List import tinyms as ts from app.pipelines import Pipeline from huggingface_hub import snapshot_download from tinyms import Tensor, model, vision from tinyms.primitives import Softmax if TYPE_CHECKING: from PIL import Image ALLOWED_MODEL = { "LeNet5": model.lenet5, "ResNet50": model.resnet50, "MobileNetV2": model.mobilenetv2, } ALLOWED_TRANSFORM = { "mnist": vision.mnist_transform, "cifar10": vision.cifar10_transform, "imagenet2012": vision.imagefolder_transform, } def load_tranform_func(config): dataset = config.get("dataset_transform") if dataset not in ALLOWED_TRANSFORM: raise EnvironmentError( f"Currently doesn't supports dataset {dataset} transform!" ) return ALLOWED_TRANSFORM.get(dataset) def load_config(config_json_file): with open(config_json_file, "r", encoding="utf-8") as reader: config = reader.read() return json.loads(config) def load_model_config_from_hf(model_id): repo_path = snapshot_download(model_id) config_json_file = os.path.join(repo_path, "config.json") if not os.path.exists(config_json_file): raise EnvironmentError( f"The path of the config.json file {config_json_file} doesn't exist!" ) config = load_config(config_json_file) architecture = config.get("architecture") if architecture not in ALLOWED_MODEL: raise EnvironmentError(f"Currently doesn't supports {model} model!") net_func = ALLOWED_MODEL.get(architecture) class_num = config.get("num_classes") net = net_func(class_num=class_num, is_training=False) ms_model = model.Model(net) model_file = os.path.join(repo_path, "mindspore_model.ckpt") if not os.path.exists(model_file): raise EnvironmentError( f"The path of the model file {model_file} doesn't exist!" ) ms_model.load_checkpoint(model_file) return ms_model, config class ImageClassificationPipeline(Pipeline): def __init__(self, model_id: str): self.model, self.config = load_model_config_from_hf(model_id) # Obtain labels self.id2label = self.config.get("id2label") # Get dataset transform function self.tranform_func = load_tranform_func(self.config) # Return at most the top 5 predicted classes self.top_k = 5 def __call__(self, inputs: "Image.Image") -> List[Dict[str, Any]]: """ Args: inputs (:obj:`PIL.Image`): The raw image representation as PIL. No transformation made whatsoever from the input. Make all necessary transformations here. Return: A :obj:`list`:. The list contains items that are dicts should be liked {"label": "XXX", "score": 0.82} It is preferred if the returned list is in decreasing `score` order """ # Preprocess data img_data = self.tranform_func(inputs) input_data = ts.array(img_data.tolist(), dtype=img_data.dtype.name) # Execute model prediction preds = self.model.predict(ts.expand_dims(input_data, 0)) # Postprocess data softmax = Softmax() pred_outputs = softmax(Tensor(preds, dtype=ts.float32)).asnumpy() labels = [ {"label": str(self.id2label[str(i)]), "score": float(pred_outputs[0][i])} for i in range(len(pred_outputs[0])) ] return sorted(labels, key=lambda tup: tup["score"], reverse=True)[: self.top_k]