Skip to content

Commit 6e2f466

Browse files
committed
feat: allow resuming wandb runs for evaluation and log evaluation metrics
1 parent 763b225 commit 6e2f466

2 files changed

Lines changed: 75 additions & 18 deletions

File tree

delft/applications/grobidTagger.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,7 @@ def eval_(
467467
input_path=None,
468468
architecture="BidLSTM_CRF",
469469
report_to_wandb=False,
470+
wandb_run_id=None,
470471
):
471472
print("Loading data...")
472473
if input_path is None:
@@ -488,8 +489,12 @@ def eval_(
488489
start_time = time.time()
489490

490491
# load the model
491-
model = Sequence(model_name, report_to_wandb=report_to_wandb)
492+
model = Sequence(model_name)
492493
model.load()
494+
495+
# Initialize wandb for eval if requested
496+
if report_to_wandb:
497+
model.init_wandb_for_eval(run_id=wandb_run_id)
493498

494499
# evaluation
495500
print("\nEvaluation:")
@@ -678,6 +683,12 @@ class Tasks:
678683
action="store_true",
679684
)
680685

686+
parser.add_argument(
687+
"--wandb-run-id",
688+
default=None,
689+
help="Wandb run ID to resume for eval (only valid with eval action)",
690+
)
691+
681692
args = parser.parse_args()
682693

683694
model = args.model
@@ -697,6 +708,7 @@ class Tasks:
697708
early_stop = args.early_stop
698709
multi_gpu = args.multi_gpu
699710
wandb = args.wandb
711+
wandb_run_id = args.wandb_run_id
700712

701713
if architecture is None:
702714
raise ValueError(
@@ -738,7 +750,11 @@ class Tasks:
738750
"A Grobid evaluation data file must be specified to evaluate a grobid model with the parameter --input"
739751
)
740752
eval_(
741-
model, input_path=input_path, architecture=architecture
753+
model,
754+
input_path=input_path,
755+
architecture=architecture,
756+
report_to_wandb=wandb,
757+
wandb_run_id=wandb_run_id,
742758
)
743759

744760
if action == Tasks.TRAIN_EVAL:

delft/sequenceLabelling/wrapper.py

Lines changed: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,13 @@ def __init__(
164164
if report_to_wandb:
165165
self._init_wandb(model_name)
166166

167-
def _init_wandb(self, model_name):
168-
"""Initialize Weights & Biases logging."""
167+
def _init_wandb(self, model_name, run_id=None):
168+
"""Initialize Weights & Biases logging.
169+
170+
Args:
171+
model_name: Name for the wandb run
172+
run_id: Optional run ID to resume an existing run
173+
"""
169174
try:
170175
import wandb
171176
from dotenv import load_dotenv
@@ -175,24 +180,44 @@ def _init_wandb(self, model_name):
175180
print("Warning: WANDB_API_KEY not set, wandb disabled")
176181
self.report_to_wandb = False
177182
return
178-
wandb.init(
179-
name=model_name,
180-
config={
181-
"model_name": self.model_config.model_name,
182-
"architecture": self.model_config.architecture,
183-
"transformer_name": self.model_config.transformer_name,
184-
"embeddings_name": self.model_config.embeddings_name,
185-
"embedding_size": self.model_config.word_embedding_size,
186-
"batch_size": self.training_config.batch_size,
187-
"learning_rate": self.training_config.learning_rate,
188-
"max_epoch": self.training_config.max_epoch,
189-
},
190-
)
183+
184+
# Resume existing run or start new one
185+
if run_id:
186+
wandb.init(id=run_id, resume="must")
187+
print(f"Resumed wandb run: {run_id}")
188+
else:
189+
wandb.init(
190+
name=model_name,
191+
config={
192+
"model_name": self.model_config.model_name,
193+
"architecture": self.model_config.architecture,
194+
"transformer_name": self.model_config.transformer_name,
195+
"embeddings_name": self.model_config.embeddings_name,
196+
"embedding_size": self.model_config.word_embedding_size,
197+
"batch_size": self.training_config.batch_size,
198+
"learning_rate": self.training_config.learning_rate,
199+
"max_epoch": self.training_config.max_epoch,
200+
},
201+
)
202+
self.wandb = wandb
191203
wandb.define_metric("f1", summary="max")
204+
wandb.define_metric("eval_f1", summary="max")
192205
except ImportError:
193206
print("Warning: wandb not available")
194207
self.report_to_wandb = False
195208

209+
def init_wandb_for_eval(self, run_id=None):
210+
"""Initialize wandb for evaluation logging.
211+
212+
Call this after model.load() to enable logging eval results to wandb.
213+
214+
Args:
215+
run_id: Optional wandb run ID to resume an existing run.
216+
If None, starts a new run.
217+
"""
218+
self.report_to_wandb = True
219+
self._init_wandb(self.model_config.model_name, run_id=run_id)
220+
196221
def train(
197222
self,
198223
x_train,
@@ -479,8 +504,24 @@ def eval_single(self, x_test, y_test, features=None):
479504
[idx_to_label.get(l, "O") for l in label] for label in all_labels
480505
]
481506

482-
report, _ = classification_report(true_labels, pred_labels, digits=4)
507+
report, evaluation = classification_report(true_labels, pred_labels, digits=4)
483508
print(report)
509+
510+
# Extract metrics for return and wandb logging
511+
metrics = {}
512+
if "micro" in evaluation:
513+
metrics = {
514+
"eval_f1": evaluation["micro"]["f1"],
515+
"eval_precision": evaluation["micro"]["precision"],
516+
"eval_recall": evaluation["micro"]["recall"],
517+
}
518+
519+
# Log to wandb if enabled
520+
if self.report_to_wandb and hasattr(self, 'wandb'):
521+
self.wandb.log(metrics)
522+
print(f"Logged evaluation metrics to wandb: f1={metrics.get('eval_f1', 0):.4f}")
523+
524+
return metrics
484525

485526
def eval_nfold(self, x_test, y_test, features=None):
486527
"""Evaluate n-fold models."""

0 commit comments

Comments
 (0)