Views
No views yet
vinai/phobert-base on visolex/phobert-absa-smartphone for joint aspect detection + sentiment classification (shared heads).1import torch
2from transformers import AutoTokenizer, AutoModel
3
4# Danh sách aspect và sentiment labels
5aspect_labels = [
6 "BATTERY", "CAMERA", "DESIGN", "FEATURES", "GENERAL",
7 "PERFORMANCE", "PRICE", "SCREEN", "SERandACC", "STORAGE"
8]
9sentiment_labels = ["POSITIVE", "NEGATIVE", "NEUTRAL"]
10
11# 1) Load tokenizer và model (phải về đúng class TransformerForABSA)
12repo = "visolex/phobert-absa-smartphone"
13tokenizer = AutoTokenizer.from_pretrained(repo, trust_remote_code=True)
14model = AutoModel.from_pretrained(repo, trust_remote_code=True)
15model.eval()
16
17def predict_absa_multi(
18 text: str,
19 aspect_labels: list[str],
20 sentiment_labels: list[str],
21 threshold: float = 0.5
22) -> list[tuple[str,str]]:
23 inputs = tokenizer(
24 text,
25 return_tensors="pt",
26 padding=True,
27 truncation=True,
28 max_length=256
29 )
30 inputs.pop("token_type_ids", None)
31
32 with torch.no_grad():
33 out = model(**inputs)
34
35 # out.logits có shape [1, A, S+1]
36 logits = out.logits.squeeze(0) # [A, S+1]
37 probs = torch.softmax(logits, dim=-1) # [A, S+1]
38
39 num_s = len(sentiment_labels)
40 none_id = probs.size(-1) - 1 # chỉ số của lớp "none"
41 results = []
42
43 for i, asp in enumerate(aspect_labels):
44 prob_i = probs[i]
45 pred_id = int(prob_i.argmax().item())
46
47 if pred_id != none_id and pred_id < num_s:
48 score = prob_i[pred_id].item()
49 if score >= threshold:
50 results.append((asp, sentiment_labels[pred_id].lower()))
51
52 return results
53
54
55text = "mới mua được một tuần pin bốn nghìn mà quá tệ cảm ứng hơi đơ nhận sim bị lỗi."
56preds = predict_absa_multi(text, aspect_labels, sentiment_labels, threshold=0.2)
57print(preds)
58# ➔ [('BATTERY','negative'), ('PERFORMANCE','negative'), ...]