File size: 2,264 Bytes
6074409
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
from transformers import PreTrainedModel
from modules import SmartphoneBERT
import torch

from .configuration_vnsabsa import VnSmartphoneBERTConfig

from typing import Tuple


class VnSmartphoneBERTModel(PreTrainedModel):
    config_class = VnSmartphoneBERTConfig
    
    def __init__(
        self,
        config: VnSmartphoneBERTConfig
    ):
        super().__init__(config)
        self.model = SmartphoneBERT(
            vocab_size=config.vocab_size,
            embed_dim=config.embed_dim,
            num_heads=config.num_heads,
            num_encoders=config.num_encoders,
            encoder_dropout=config.encoder_dropout,
            fc_dropout=config.fc_dropout,
            fc_hidden_size=config.fc_hidden_size
        )
        self.ASPECT_LOOKUP = {
            i: a
            for i, a in enumerate(["CAMERA", "FEATURES", "BATTERY", "PRICE", "GENERAL", "SER&ACC", "PERFORMANCE", "SCREEN", "DESIGN", "STORAGE", "OTHERS"])
        }
        self.POLARITY_LOOKUP = {
            i: p
            for i, p in enumerate(["Negative", "Neutral", "Positive"])
        }
    
    def forward(
        self,
        input_ids: torch.Tensor,
        attention_mask: torch.Tensor,
        aspect_thresholds: float | torch.Tensor = 0.5
    ):
        pred = self.model(input_ids, attention_mask)
        result = self.decode_absa(
            pred, 
            aspect_thresholds=aspect_thresholds
        )
        return result

    def decode_absa(
        self, 
        pred: Tuple[torch.Tensor, torch.Tensor],
        aspect_thresholds: float | torch.Tensor = 0.5
    ):
        if isinstance(aspect_thresholds, float):
            aspect_thresholds = torch.full((11,), aspect_thresholds)
        
        a, p = pred
        a = a.sigmoid().cpu()
        p = p.argmax(dim=-1).cpu()

        results = []
        for a_i, p_i in zip(a, p):
            res_i = {}
            for i in range(10):
                a = self.ASPECT_LOOKUP[i]
                p = self.POLARITY_LOOKUP[p_i[i].item()]
                if a_i[i] >= aspect_thresholds[i]:
                    res_i[a] = p
            results.append(res_i)

            # OTHERS
            if a_i[-1] >= aspect_thresholds[-1]:
                res_i["OTHERS"] = ""
        
        return results