File size: 3,830 Bytes
119802d
 
a00fee9
 
 
 
119802d
 
a00fee9
 
6c2294e
119802d
 
547bc5b
6c2294e
119802d
 
 
6c2294e
119802d
 
 
 
 
6c2294e
119802d
 
6c2294e
119802d
 
 
6c2294e
119802d
a00fee9
119802d
6c2294e
119802d
 
6c2294e
a00fee9
 
6c2294e
119802d
6c2294e
6bf2e25
6c2294e
 
 
 
 
 
 
119802d
 
 
6c2294e
119802d
6c2294e
119802d
6c2294e
119802d
 
6c2294e
119802d
 
 
6c2294e
119802d
 
 
 
 
6c2294e
119802d
6c2294e
119802d
a00fee9
119802d
 
 
6c2294e
119802d
 
 
6c2294e
119802d
6c2294e
a00fee9
119802d
6c2294e
119802d
 
 
 
6c2294e
119802d
 
 
 
 
 
6c2294e
119802d
 
 
6c2294e
119802d
 
 
6c2294e
119802d
6c2294e
 
 
 
 
 
 
 
119802d
 
 
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import json
from pathlib import Path

import mlflow
import torch
from sklearn.metrics import f1_score
from transformers import (
    AutoModelForSequenceClassification,
    AutoModelForTokenClassification,
    AutoTokenizer,
    pipeline,
)

from absa.training.mlflow_utils import setup_mlflow


def load_data(file_path: Path):
    data = []
    with open(file_path, "r", encoding="utf-8") as f:
        for line in f:
            if line.strip():
                data.append(json.loads(line))
    return data


def main():
    setup_mlflow()

    # Check if models exist (might not if trained on Colab)
    aspect_model_path = Path("models/aspect_extraction/best")
    sentiment_model_path = Path("models/sentiment/best")

    if not aspect_model_path.exists() or not sentiment_model_path.exists():
        print("Models not found locally. Skipping cross-lingual evaluation until models are trained.")
        return

    print("Loading models...")
    tokenizer = AutoTokenizer.from_pretrained("xlm-roberta-base")

    aspect_model = AutoModelForTokenClassification.from_pretrained(str(aspect_model_path))
    sentiment_model = AutoModelForSequenceClassification.from_pretrained(str(sentiment_model_path))

    device = 0 if torch.cuda.is_available() else -1

    pipeline(
        "token-classification",
        model=aspect_model,
        tokenizer=tokenizer,
        device=device,
        aggregation_strategy="simple",
    )

    # Load Hindi Data
    hindi_path = Path("data/processed/amazon_hindi.jsonl")
    hindi_data = load_data(hindi_path)

    print(f"Evaluating zero-shot on {len(hindi_data)} Hindi samples...")

    sentiment_map = {"positive": 0, "negative": 1, "neutral": 2, "conflict": 3}

    true_labels = []
    pred_labels = []

    for item in hindi_data:
        text = item["text"]
        aspects = item.get("aspect_terms", [])

        for aspect in aspects:
            term = aspect["term"]
            true_polarity = aspect["polarity"]
            if true_polarity not in sentiment_map:
                continue

            true_labels.append(sentiment_map[true_polarity])

            # Inference Sentiment
            inputs = tokenizer(text, term, return_tensors="pt", truncation=True, max_length=128)
            if device == 0:
                inputs = {k: v.to("cuda") for k, v in inputs.items()}
                sentiment_model.to("cuda")

            with torch.no_grad():
                logits = sentiment_model(**inputs).logits
                pred_idx = torch.argmax(logits, dim=1).item()

            pred_labels.append(pred_idx)

    hindi_macro_f1 = f1_score(true_labels, pred_labels, average="macro") if len(true_labels) > 0 else 0.0
    print(f"Hindi Zero-Shot Macro-F1: {hindi_macro_f1}")

    # We retrieve the best English test score from MLflow
    # For now, let's just log the cross lingual gap if we know English F1
    client = mlflow.tracking.MlflowClient()
    experiment = client.get_experiment_by_name("multilingual-absa")

    en_macro_f1 = 0.0
    if experiment:
        runs = client.search_runs(
            experiment_ids=[experiment.experiment_id],
            filter_string="metrics.test_macro_f1 > 0",
            max_results=1,
            order_by=["metrics.test_macro_f1 DESC"],
        )
        if runs:
            en_macro_f1 = runs[0].data.metrics.get("test_macro_f1", 0.0)

    print(f"Best English Test Macro-F1: {en_macro_f1}")
    gap = en_macro_f1 - hindi_macro_f1
    print(f"Cross-Lingual Gap: {gap}")

    with mlflow.start_run(run_name="cross_lingual_eval"):
        mlflow.log_metrics(
            {
                "hindi_zero_shot_macro_f1": float(hindi_macro_f1),
                "english_test_macro_f1": float(en_macro_f1),
                "cross_lingual_gap": float(gap),
            }
        )


if __name__ == "__main__":
    main()