Spaces:
Runtime error
Runtime error
| # copyright (c) 2022 PaddlePaddle Authors. All Rights Reserve. | |
| # | |
| # Licensed under the Apache License, Version 2.0 (the "License"); | |
| # you may not use this file except in compliance with the License. | |
| # You may obtain a copy of the License at | |
| # | |
| # http://www.apache.org/licenses/LICENSE-2.0 | |
| # | |
| # Unless required by applicable law or agreed to in writing, software | |
| # distributed under the License is distributed on an "AS IS" BASIS, | |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| # See the License for the specific language governing permissions and | |
| # limitations under the License. | |
| # reference from : https://github.com/open-mmlab/mmocr/blob/main/mmocr/models/kie/losses/sdmgr_loss.py | |
| from __future__ import absolute_import | |
| from __future__ import division | |
| from __future__ import print_function | |
| from paddle import nn | |
| import paddle | |
| class SDMGRLoss(nn.Layer): | |
| def __init__(self, node_weight=1.0, edge_weight=1.0, ignore=0): | |
| super().__init__() | |
| self.loss_node = nn.CrossEntropyLoss(ignore_index=ignore) | |
| self.loss_edge = nn.CrossEntropyLoss(ignore_index=-1) | |
| self.node_weight = node_weight | |
| self.edge_weight = edge_weight | |
| self.ignore = ignore | |
| def pre_process(self, gts, tag): | |
| gts, tag = gts.numpy(), tag.numpy().tolist() | |
| temp_gts = [] | |
| batch = len(tag) | |
| for i in range(batch): | |
| num, recoder_len = tag[i][0], tag[i][1] | |
| temp_gts.append( | |
| paddle.to_tensor( | |
| gts[i, :num, :num + 1], dtype='int64')) | |
| return temp_gts | |
| def accuracy(self, pred, target, topk=1, thresh=None): | |
| """Calculate accuracy according to the prediction and target. | |
| Args: | |
| pred (torch.Tensor): The model prediction, shape (N, num_class) | |
| target (torch.Tensor): The target of each prediction, shape (N, ) | |
| topk (int | tuple[int], optional): If the predictions in ``topk`` | |
| matches the target, the predictions will be regarded as | |
| correct ones. Defaults to 1. | |
| thresh (float, optional): If not None, predictions with scores under | |
| this threshold are considered incorrect. Default to None. | |
| Returns: | |
| float | tuple[float]: If the input ``topk`` is a single integer, | |
| the function will return a single float as accuracy. If | |
| ``topk`` is a tuple containing multiple integers, the | |
| function will return a tuple containing accuracies of | |
| each ``topk`` number. | |
| """ | |
| assert isinstance(topk, (int, tuple)) | |
| if isinstance(topk, int): | |
| topk = (topk, ) | |
| return_single = True | |
| else: | |
| return_single = False | |
| maxk = max(topk) | |
| if pred.shape[0] == 0: | |
| accu = [pred.new_tensor(0.) for i in range(len(topk))] | |
| return accu[0] if return_single else accu | |
| pred_value, pred_label = paddle.topk(pred, maxk, axis=1) | |
| pred_label = pred_label.transpose( | |
| [1, 0]) # transpose to shape (maxk, N) | |
| correct = paddle.equal(pred_label, | |
| (target.reshape([1, -1]).expand_as(pred_label))) | |
| res = [] | |
| for k in topk: | |
| correct_k = paddle.sum(correct[:k].reshape([-1]).astype('float32'), | |
| axis=0, | |
| keepdim=True) | |
| res.append( | |
| paddle.multiply(correct_k, | |
| paddle.to_tensor(100.0 / pred.shape[0]))) | |
| return res[0] if return_single else res | |
| def forward(self, pred, batch): | |
| node_preds, edge_preds = pred | |
| gts, tag = batch[4], batch[5] | |
| gts = self.pre_process(gts, tag) | |
| node_gts, edge_gts = [], [] | |
| for gt in gts: | |
| node_gts.append(gt[:, 0]) | |
| edge_gts.append(gt[:, 1:].reshape([-1])) | |
| node_gts = paddle.concat(node_gts) | |
| edge_gts = paddle.concat(edge_gts) | |
| node_valids = paddle.nonzero(node_gts != self.ignore).reshape([-1]) | |
| edge_valids = paddle.nonzero(edge_gts != -1).reshape([-1]) | |
| loss_node = self.loss_node(node_preds, node_gts) | |
| loss_edge = self.loss_edge(edge_preds, edge_gts) | |
| loss = self.node_weight * loss_node + self.edge_weight * loss_edge | |
| return dict( | |
| loss=loss, | |
| loss_node=loss_node, | |
| loss_edge=loss_edge, | |
| acc_node=self.accuracy( | |
| paddle.gather(node_preds, node_valids), | |
| paddle.gather(node_gts, node_valids)), | |
| acc_edge=self.accuracy( | |
| paddle.gather(edge_preds, edge_valids), | |
| paddle.gather(edge_gts, edge_valids))) | |