Browse Source

[Fix] Fix classification deploy code (#105)

Lin Manhui 2 years ago
parent
commit
18c29f1ea2

+ 16 - 1
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,

+ 1 - 1
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)

+ 28 - 17
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
 

+ 4 - 7
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