Build zero-shot classifier weights. Args: model: VTPModel instance with get_clip_text_feature method. tokenizer: Text tokenizer. classnames: Sequence of class names. templates: Sequence of template functions. num_classes_per_batch: Number of classes to pr
(
model: VTPModel,
tokenizer,
classnames: Sequence[str],
templates: Sequence[Callable],
num_classes_per_batch: int = 10,
device: torch.device = None,
use_tqdm: bool = True,
)
| 340 | # ============================================================================ |
| 341 | |
| 342 | def build_zero_shot_classifier( |
| 343 | model: VTPModel, |
| 344 | tokenizer, |
| 345 | classnames: Sequence[str], |
| 346 | templates: Sequence[Callable], |
| 347 | num_classes_per_batch: int = 10, |
| 348 | device: torch.device = None, |
| 349 | use_tqdm: bool = True, |
| 350 | ) -> torch.Tensor: |
| 351 | """Build zero-shot classifier weights. |
| 352 | |
| 353 | Args: |
| 354 | model: VTPModel instance with get_clip_text_feature method. |
| 355 | tokenizer: Text tokenizer. |
| 356 | classnames: Sequence of class names. |
| 357 | templates: Sequence of template functions. |
| 358 | num_classes_per_batch: Number of classes to process per batch. |
| 359 | device: Device to use. |
| 360 | use_tqdm: Whether to show progress bar. |
| 361 | |
| 362 | Returns: |
| 363 | Zero-shot classifier weights, shape (embed_dim, num_classes). |
| 364 | """ |
| 365 | num_templates = len(templates) |
| 366 | num_classes = len(classnames) |
| 367 | |
| 368 | if use_tqdm: |
| 369 | num_iter = (num_classes - 1) // num_classes_per_batch + 1 |
| 370 | iter_wrap = partial(tqdm, total=num_iter, desc="Building classifier", unit_scale=num_classes_per_batch) |
| 371 | else: |
| 372 | iter_wrap = iter |
| 373 | |
| 374 | def _process_batch(batch_classnames: List[str]) -> torch.Tensor: |
| 375 | num_batch_classes = len(batch_classnames) |
| 376 | texts = [template(c) for c in batch_classnames for template in templates] |
| 377 | tokens = tokenizer(texts).to(device) |
| 378 | |
| 379 | # Use VTPModel's get_clip_text_feature method |
| 380 | text_features = model.get_clip_text_feature(tokens, normalize=True) |
| 381 | |
| 382 | # Reshape and average over templates |
| 383 | text_features = text_features.reshape(num_batch_classes, num_templates, -1).mean(dim=1) |
| 384 | text_features = F.normalize(text_features, dim=1) |
| 385 | return text_features.T # (embed_dim, num_batch_classes) |
| 386 | |
| 387 | with torch.no_grad(): |
| 388 | batched_embeds = [ |
| 389 | _process_batch(batch) |
| 390 | for batch in iter_wrap(batched(classnames, num_classes_per_batch)) |
| 391 | ] |
| 392 | zeroshot_weights = torch.cat(batched_embeds, dim=1) |
| 393 | |
| 394 | return zeroshot_weights |
| 395 | |
| 396 | |
| 397 | # ============================================================================ |
no test coverage detected