AnkitAI commited on
Commit
4540fc1
·
verified ·
1 Parent(s): 9667a80

Upload eval/train_and_eval.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. eval/train_and_eval.py +82 -0
eval/train_and_eval.py ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """General-sentiment trainer — SST-2, targeting the 3.9M-dl/mo distilbert-sst2 incumbent.
2
+
3
+ Same discipline as finsense_train.py: fp32, best-ckpt by val metric, held-out
4
+ reporting. SST-2 official: train 67,349 / validation 872 (the reported split —
5
+ incumbent's 91.3 is on validation; test is unlabeled). We carve 5% of train as
6
+ our early-stop val and report on the official validation set, untouched.
7
+
8
+ Usage: python sst2_train.py [--seed 42] [--base answerdotai/ModernBERT-base]
9
+ """
10
+ import argparse
11
+ import json
12
+ import os
13
+
14
+ import torch
15
+ from datasets import load_dataset
16
+ from sklearn.metrics import accuracy_score, f1_score
17
+ from transformers import (AutoModelForSequenceClassification, AutoTokenizer,
18
+ Trainer, TrainingArguments)
19
+
20
+ p = argparse.ArgumentParser()
21
+ p.add_argument("--seed", type=int, default=42)
22
+ p.add_argument("--base", default="answerdotai/ModernBERT-base")
23
+ p.add_argument("--epochs", type=int, default=2)
24
+ args = p.parse_args()
25
+
26
+ OUT = os.path.expanduser(f"~/finsense_runs/sst2-{args.base.split('/')[-1]}-s{args.seed}")
27
+ os.makedirs(OUT, exist_ok=True)
28
+ LABELS = ["negative", "positive"]
29
+
30
+ ds = load_dataset("nyu-mll/glue", "sst2")
31
+ full_train = ds["train"].shuffle(seed=42)
32
+ n_val = int(len(full_train) * 0.05)
33
+ early_val = full_train.select(range(n_val))
34
+ train = full_train.select(range(n_val, len(full_train)))
35
+ report_val = ds["validation"] # incumbent's benchmark split — never used for selection
36
+ print(f"train={len(train)} early_val={len(early_val)} report_val={len(report_val)}", flush=True)
37
+
38
+ tok = AutoTokenizer.from_pretrained(args.base)
39
+
40
+ def enc(d):
41
+ return d.map(lambda b: tok(b["sentence"], truncation=True, max_length=128),
42
+ batched=True, remove_columns=[c for c in d.column_names if c not in ("label",)])
43
+
44
+ torch.manual_seed(args.seed)
45
+ model = AutoModelForSequenceClassification.from_pretrained(
46
+ args.base, num_labels=2,
47
+ id2label=dict(enumerate(LABELS)), label2id={l: i for i, l in enumerate(LABELS)})
48
+
49
+ def metrics(pred):
50
+ y, yhat = pred.label_ids, pred.predictions.argmax(-1)
51
+ return {"accuracy": accuracy_score(y, yhat)}
52
+
53
+ import transformers as _tf
54
+ _tok_kw = {"processing_class": tok} if int(_tf.__version__.split(".")[0]) >= 5 else {"tokenizer": tok}
55
+ trainer = Trainer(
56
+ model=model, **_tok_kw,
57
+ train_dataset=enc(train), eval_dataset=enc(early_val),
58
+ compute_metrics=metrics,
59
+ args=TrainingArguments(
60
+ output_dir=f"{OUT}/ckpt",
61
+ num_train_epochs=args.epochs,
62
+ per_device_train_batch_size=32, per_device_eval_batch_size=64,
63
+ learning_rate=2e-5, warmup_ratio=0.06, weight_decay=0.01,
64
+ eval_strategy="steps", eval_steps=500,
65
+ save_strategy="steps", save_steps=500, save_total_limit=1,
66
+ load_best_model_at_end=True, metric_for_best_model="accuracy",
67
+ logging_steps=100, seed=args.seed, report_to=[],
68
+ fp16=False, bf16=False,
69
+ ),
70
+ )
71
+ trainer.train()
72
+
73
+ pred = trainer.predict(enc(report_val))
74
+ y, yhat = pred.label_ids, pred.predictions.argmax(-1)
75
+ res = {"base": args.base, "seed": args.seed, "task": "sst2",
76
+ "val_accuracy": float(accuracy_score(y, yhat)),
77
+ "val_f1": float(f1_score(y, yhat)),
78
+ "incumbent": "distilbert-sst2 = 0.913 on this same validation split"}
79
+ json.dump(res, open(f"{OUT}/result.json", "w"), indent=1)
80
+ print("SST2_RESULT", json.dumps(res), flush=True)
81
+ model.save_pretrained(f"{OUT}/model")
82
+ tok.save_pretrained(f"{OUT}/model")