1import torch
2from torch.utils.data import Dataset, DataLoader
3from transformers import AutoTokenizer, AutoModelForSequenceClassification
4from datasets import load_dataset
5from sklearn.metrics import accuracy_score, f1_score, classification_report
6import pandas as pd
7from collections import defaultdict
8
9# ------------------- Sabitler -------------------
10MODEL_ID = "ebrukilic/bert-absa-tr-v4"
11DATASET_ID = "ebrukilic/tubitak_clothing_absa_v3"
12SPLIT = "test"
13TEXT_COL = "normalized_yorum"
14LABEL_COL = "polarity"
15ASPECT_COL = "aspects"
16BATCH_SIZE = 16
17MAX_LEN = 128
18
19device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
20print("Device:", device)
21
22# ---------- Dataset yükleme işlemi ----------------
23ds_raw = load_dataset(DATASET_ID, split=SPLIT)
24df = ds_raw.to_pandas()
25
26# Aspect listelerini temizle
27def to_list(x):
28 if x is None: return []
29 if isinstance(x, list): return x
30 return [x]
31
32def clean_list(lst):
33 return [str(a) for a in lst if str(a).lower() not in {"unknown", "unk", ""}]
34
35df["_aspect_list"] = df[ASPECT_COL].apply(to_list).apply(clean_list)
36df = df[df["_aspect_list"].map(len) > 0].copy()
37
38# Label encode
39label_space = sorted(list(set(map(str, df[LABEL_COL]))))
40label2id = {label:i for i,label in enumerate(label_space)}
41id2label = {i:label for label,i in label2id.items()}
42print("Label mapping:", label2id, "\n")
43
44# ------------------- Model yükle -------------------
45tokenizer = AutoTokenizer.from_pretrained(MODEL_ID, use_fast=True)
46model = AutoModelForSequenceClassification.from_pretrained(
47 MODEL_ID, num_labels=len(label_space), id2label=id2label, label2id=label2id
48).to(device)
49model.eval()
50
51# Aspect-aware dataset
52class AspectAwareDataset(Dataset):
53 def __init__(self, dataframe, tokenizer, label2id, max_length=128):
54 self.data = dataframe.explode("_aspect_list").rename(columns={"_aspect_list":"aspect"}).reset_index(drop=True)
55 self.tokenizer = tokenizer
56 self.label2id = label2id
57 self.max_length = max_length
58
59 def __len__(self):
60 return len(self.data)
61
62 def __getitem__(self, idx):
63 row = self.data.iloc[idx]
64 text, aspect = row[TEXT_COL], row["aspect"] #hem text hem aspect verildi
65 label = self.label2id[str(row[LABEL_COL])]
66 inputs = self.tokenizer(
67 aspect, text,
68 truncation=True,
69 padding='max_length',
70 max_length=self.max_length,
71 return_tensors="pt"
72 )
73 return {
74 'input_ids': inputs['input_ids'].squeeze(0),
75 'attention_mask': inputs['attention_mask'].squeeze(0),
76 'labels': torch.tensor(label)
77 }
78
79# ------------------- DataLoader -------------------
80dataloader_aspect = DataLoader(AspectAwareDataset(df, tokenizer, label2id, MAX_LEN),
81 batch_size=BATCH_SIZE, shuffle=False)
82
83# ------------------- Değerlendirme Fonksiyonu -------------------
84def evaluate_model(dataloader, device, df):
85 y_true, y_pred = [], []
86 aspect_perf = defaultdict(list)
87
88 with torch.no_grad():
89 for idx, batch in enumerate(dataloader):
90 input_ids = batch['input_ids'].to(device)
91 attention_mask = batch['attention_mask'].to(device)
92 labels = batch['labels'].to(device)
93
94 outputs = model(input_ids=input_ids, attention_mask=attention_mask)
95 predictions = torch.argmax(outputs.logits, dim=1)
96
97 y_true.extend(labels.cpu().tolist())
98 y_pred.extend(predictions.cpu().tolist())
99
100 batch_start = idx * BATCH_SIZE
101 for i in range(len(labels)):
102 data_idx = batch_start + i
103 if data_idx < len(df):
104 true_label = labels[i].cpu().item()
105 pred_label = predictions[i].cpu().item()
106 aspects = df.iloc[data_idx]["_aspect_list"]
107 for aspect in aspects:
108 aspect_perf[aspect].append((true_label, pred_label))
109 return y_true, y_pred, aspect_perf
110
111# ------------------- Modeli Değerlendir -------------------
112print("=== Aspect-aware Evaluation ===")
113y_true, y_pred, aspect_perf = evaluate_model(dataloader_aspect, device, df)
114print(f"Accuracy: {accuracy_score(y_true, y_pred):.4f} Macro-F1: {f1_score(y_true, y_pred, average='macro'):.4f}")
115print(classification_report(y_true, y_pred, target_names=label_space))