Views
No views yet
vinai/phobert-base on visolex/VLSP2018-ABSA-Hotel for joint aspect detection + sentiment classification (shared heads).vinai/phobert-basevisolex/VLSP2018-ABSA-HotelFACILITIES#CLEANLINESSFACILITIES#COMFORTFACILITIES#DESIGN&FEATURESFACILITIES#GENERALFACILITIES#MISCELLANEOUSFACILITIES#PRICESFACILITIES#QUALITYFOOD&DRINKS#MISCELLANEOUSFOOD&DRINKS#PRICESFOOD&DRINKS#QUALITYFOOD&DRINKS#STYLE&OPTIONSHOTEL#CLEANLINESSHOTEL#COMFORTHOTEL#DESIGN&FEATURESHOTEL#GENERALHOTEL#MISCELLANEOUSHOTEL#PRICESHOTEL#QUALITYLOCATION#GENERALROOMS#CLEANLINESSROOMS#COMFORTROOMS#DESIGN&FEATURESROOMS#GENERALROOMS#MISCELLANEOUSROOMS#PRICESROOMS#QUALITYROOM_AMENITIES#CLEANLINESSROOM_AMENITIES#COMFORTROOM_AMENITIES#DESIGN&FEATURESROOM_AMENITIES#GENERALROOM_AMENITIES#MISCELLANEOUSROOM_AMENITIES#PRICESROOM_AMENITIES#QUALITYSERVICE#GENERALPOSITIVENEGATIVENEUTRAL1import torch
2from transformers import AutoTokenizer, AutoModel
3
4# Danh sách aspect và sentiment labels
5aspect_labels = [
6 "FACILITIES#CLEANLINESS", "FACILITIES#COMFORT", "FACILITIES#DESIGN&FEATURES",
7 "FACILITIES#GENERAL", "FACILITIES#MISCELLANEOUS", "FACILITIES#PRICES",
8 "FACILITIES#QUALITY", "FOOD&DRINKS#MISCELLANEOUS", "FOOD&DRINKS#PRICES",
9 "FOOD&DRINKS#QUALITY", "FOOD&DRINKS#STYLE&OPTIONS", "HOTEL#CLEANLINESS",
10 "HOTEL#COMFORT", "HOTEL#DESIGN&FEATURES", "HOTEL#GENERAL",
11 "HOTEL#MISCELLANEOUS", "HOTEL#PRICES", "HOTEL#QUALITY", "LOCATION#GENERAL",
12 "ROOMS#CLEANLINESS", "ROOMS#COMFORT", "ROOMS#DESIGN&FEATURES",
13 "ROOMS#GENERAL", "ROOMS#MISCELLANEOUS", "ROOMS#PRICES", "ROOMS#QUALITY",
14 "ROOM_AMENITIES#CLEANLINESS", "ROOM_AMENITIES#COMFORT",
15 "ROOM_AMENITIES#DESIGN&FEATURES", "ROOM_AMENITIES#GENERAL",
16 "ROOM_AMENITIES#MISCELLANEOUS", "ROOM_AMENITIES#PRICES",
17 "ROOM_AMENITIES#QUALITY", "SERVICE#GENERAL"
18]
19sentiment_labels = ["POSITIVE", "NEGATIVE", "NEUTRAL"]
20
21# Load tokenizer và model (phải về đúng class TransformerForABSA)
22repo = "visolex/phobert-absa-hotel"
23tokenizer = AutoTokenizer.from_pretrained(repo, trust_remote_code=True)
24model = AutoModel.from_pretrained(repo, trust_remote_code=True)
25model.eval()
26
27def predict_absa_multi(
28 text: str,
29 aspect_labels: list[str],
30 sentiment_labels: list[str],
31 threshold: float = 0.5
32) -> list[tuple[str,str]]:
33 inputs = tokenizer(
34 text,
35 return_tensors="pt",
36 padding=True,
37 truncation=True,
38 max_length=256
39 )
40 inputs.pop("token_type_ids", None)
41
42 with torch.no_grad():
43 out = model(**inputs)
44
45 # out.logits có shape [1, A, S+1]
46 logits = out.logits.squeeze(0)
47 probs = torch.softmax(logits, dim=-1)
48
49 num_s = len(sentiment_labels)
50 none_id = probs.size(-1) - 1
51 results = []
52
53 for i, asp in enumerate(aspect_labels):
54 prob_i = probs[i]
55 pred_id = int(prob_i.argmax().item())
56
57 if pred_id != none_id and pred_id < num_s:
58 score = prob_i[pred_id].item()
59 if score >= threshold:
60 results.append((asp, sentiment_labels[pred_id].lower()))
61
62 return results
63
64# Example usage
65text = "Khách sạn này sạch sẽ nhưng phòng lại hơi nhỏ và dịch vụ chưa tốt lắm."
66preds = predict_absa_multi(text, aspect_labels, sentiment_labels, threshold=0.2)
67print(preds)
68# Expected output similar to: [('HOTEL#CLEANLINESS', 'positive'), ('ROOMS#COMFORT', 'negative'), ('SERVICE#GENERAL', 'negative')]