diff --git a/paddlers/deploy/predictor.py b/paddlers/deploy/predictor.py index a556012..96fdb97 100644 --- a/paddlers/deploy/predictor.py +++ b/paddlers/deploy/predictor.py @@ -13,8 +13,10 @@ # limitations under the License. import os.path as osp +from operator import itemgetter import numpy as np +import paddle from paddle.inference import Config from paddle.inference import create_predictor from paddle.inference import PrecisionType @@ -170,7 +172,20 @@ class Predictor(object): def postprocess(self, net_outputs, topk=1, ori_shape=None, transforms=None): if self._model.model_type == 'classifier': true_topk = min(self._model.num_classes, topk) - preds = self._model._postprocess(net_outputs[0], true_topk) + if self._model._postprocess is None: + self._model.build_postprocess_from_labels(topk) + # XXX: Convert ndarray to tensor as self._model._postprocess requires + net_outputs = paddle.to_tensor(net_outputs) + assert net_outputs.shape[1] == 1 + outputs = self._model._postprocess(net_outputs.squeeze(1)) + class_ids = map(itemgetter('class_ids'), outputs) + scores = map(itemgetter('scores'), outputs) + label_names = map(itemgetter('label_names'), outputs) + preds = [{ + 'class_ids_map': l, + 'scores_map': s, + 'label_names_map': n, + } for l, s, n in zip(class_ids, scores, label_names)] elif self._model.model_type in ('segmenter', 'changedetector'): label_map, score_map = self._model._postprocess( net_outputs, diff --git a/paddlers/tasks/base.py b/paddlers/tasks/base.py index 2fc63d3..edd1fb1 100644 --- a/paddlers/tasks/base.py +++ b/paddlers/tasks/base.py @@ -614,7 +614,7 @@ class BaseModel(metaclass=ModelMeta): return pipeline_info def _build_inference_net(self): - if self.model_type == 'detector': + if self.model_type in ('classifier', 'detector'): infer_net = self.net elif self.model_type == 'changedetector': infer_net = InferCDNet(self.net) diff --git a/paddlers/tasks/classifier.py b/paddlers/tasks/classifier.py index 6fa083b..84564b6 100644 --- a/paddlers/tasks/classifier.py +++ b/paddlers/tasks/classifier.py @@ -15,6 +15,7 @@ import math import os.path as osp from collections import OrderedDict +from operator import itemgetter import numpy as np import paddle @@ -119,11 +120,12 @@ class BaseClassifier(BaseModel): def run(self, net, inputs, mode): net_out = net(inputs[0]) - label = paddle.to_tensor(inputs[1], dtype="int64") - outputs = OrderedDict() + if mode == 'test': - result = self._postprocess(net_out) - outputs = result[0] + return self._postprocess(net_out) + + outputs = OrderedDict() + label = paddle.to_tensor(inputs[1], dtype="int64") if mode == 'eval': # print(self._postprocess(net_out)[0]) # for test @@ -171,6 +173,18 @@ class BaseClassifier(BaseModel): } return build_postprocess(default_config) + def build_postprocess_from_labels(self, topk=1): + label_dict = dict() + for i, label in enumerate(self.labels): + label_dict[i] = label + self._postprocess = build_postprocess({ + "name": "Topk", + "topk": topk, + "class_id_map_file": None + }) + # Add class_id_map from model.yml + self._postprocess.class_id_map = label_dict + def train(self, num_epochs, train_dataset, @@ -423,28 +437,25 @@ class BaseClassifier(BaseModel): self.model_type) self.net.eval() data = (batch_im, batch_origin_shape, transforms.transforms) - # add class_id_map from model.yml + if self._postprocess is None: - label_dict = dict() - for i, label in enumerate(self.labels): - label_dict[i] = label - self._postprocess = self.default_postprocess(None) - self._postprocess.class_id_map = label_dict + self.build_postprocess_from_labels() + outputs = self.run(self.net, data, 'test') - label_list = outputs['class_ids'] - score_list = outputs['scores'] - name_list = outputs['label_names'] + class_ids = map(itemgetter('class_ids'), outputs) + scores = map(itemgetter('scores'), outputs) + label_names = map(itemgetter('label_names'), outputs) if isinstance(img_file, list): prediction = [{ 'class_ids_map': l, 'scores_map': s, 'label_names_map': n, - } for l, s, n in zip(label_list, score_list, name_list)] + } for l, s, n in zip(class_ids, scores, label_names)] else: prediction = { - 'class_ids': label_list[0], - 'scores': score_list[0], - 'label_names': name_list[0] + 'class_ids_map': next(class_ids), + 'scores_map': next(scores), + 'label_names_map': next(label_names) } return prediction diff --git a/paddlers/tasks/utils/infer_nets.py b/paddlers/tasks/utils/infer_nets.py index 8ac71e8..d3ecede 100644 --- a/paddlers/tasks/utils/infer_nets.py +++ b/paddlers/tasks/utils/infer_nets.py @@ -21,13 +21,10 @@ class PostProcessor(paddle.nn.Layer): self.model_type = model_type def forward(self, net_outputs): - if self.model_type == 'classifier': - outputs = paddle.nn.functional.softmax(net_outputs, axis=1) - else: - # label_map [NHW], score_map [NHWC] - logit = net_outputs[0] - outputs = paddle.argmax(logit, axis=1, keepdim=False, dtype='int32'), \ - paddle.transpose(paddle.nn.functional.softmax(logit, axis=1), perm=[0, 2, 3, 1]) + # label_map [NHW], score_map [NHWC] + logit = net_outputs[0] + outputs = paddle.argmax(logit, axis=1, keepdim=False, dtype='int32'), \ + paddle.transpose(paddle.nn.functional.softmax(logit, axis=1), perm=[0, 2, 3, 1]) return outputs