77
88import funcy
99import jax
10+ import jax .numpy as jnp
1011import numpy as np
1112import optax
1213import quimb as qu
1314import quimb .tensor as qtn
14- from scipy .special import softmax
1515from tqdm import tqdm
1616
1717from ..embeddings import *
2121logger = logging .getLogger (__name__ )
2222
2323
24+ def _as_class_labels (values : jnp .ndarray ) -> jnp .ndarray :
25+ """Convert class scores, one-hot labels, or class labels to label indices.
26+
27+ If values are class scores, the predicted class is selected with argmax.
28+ If values are one-hot labels, the class label is extracted with argmax.
29+ If values are already class labels, they are returned as is.
30+
31+ Parameters
32+ ----------
33+ values : jnp.ndarray
34+ Array of class scores, one-hot labels, or class labels.
35+
36+ Returns
37+ -------
38+ jnp.ndarray
39+ Array of class label indices.
40+ """
41+ values = jnp .asarray (values )
42+ if values .ndim == 0 :
43+ return values .reshape ((1 ,)).astype (jnp .int32 )
44+ if values .ndim == 1 :
45+ return values .astype (jnp .int32 )
46+ if values .shape [- 1 ] == 1 :
47+ return jnp .squeeze (values , axis = - 1 ).astype (jnp .int32 )
48+ return jnp .argmax (values , axis = - 1 )
49+
50+
2451def _enable_cpu_multithreading () -> None :
2552 """Enable XLA multi-threading for CPU backend.
2653
@@ -356,12 +383,13 @@ def forward(
356383
357384 def accuracy (
358385 self ,
359- data : jnp .ndarray ,
360- y_true : jnp .ndarray | None = None ,
386+ data : jnp .ndarray | np . ndarray ,
387+ y_true : jnp .ndarray | np . ndarray | None = None ,
361388 embedding : Embedding | None = None ,
362389 batch_size : int = 64 ,
363390 shuffle : bool = False ,
364391 normalize : bool = False ,
392+ accuracy_fn : Callable [[jnp .ndarray ], jnp .ndarray ] | None = None ,
365393 dtype : Any = jnp .float_ ,
366394 seed : int = 42 ,
367395 alternate_flip : bool = False ,
@@ -382,6 +410,10 @@ def accuracy(
382410 Batch size for data processing.
383411 normalize: bool
384412 If True, the model output is normalized in predict function.
413+ accuracy_fn: Callable
414+ Function applied to raw model outputs before class labels are extracted.
415+ If it returns class scores, the predicted class is selected with argmax;
416+ if it returns class labels, those labels are compared directly.
385417 dtype: Any
386418 Data type of input data.
387419 seed: int
@@ -421,14 +453,14 @@ def accuracy(
421453 x = jax .device_put (jnp .array (x , dtype = dtype ), _target_device )
422454 y = jax .device_put (jnp .array (y ), _target_device )
423455
424- y_pred = softmax (
425- jnp . squeeze ( _predict_batch ( x , embedding , False , normalize )), axis = - 1
426- )
456+ y_pred = _predict_batch ( x , embedding , False , normalize )
457+ if accuracy_fn is not None :
458+ y_pred = accuracy_fn ( y_pred )
427459
428460 correct_predictions += jnp .sum (
429- jnp . argmax (y_pred , axis = - 1 ) == jnp . argmax ( y , axis = - 1 )
461+ _as_class_labels (y_pred ) == _as_class_labels ( y )
430462 )
431- num_samples += y_pred .shape [0 ]
463+ num_samples += x .shape [0 ]
432464
433465 return float (jax .block_until_ready (correct_predictions )) / num_samples
434466
@@ -603,6 +635,7 @@ def train(
603635 val_batch_size : int | None = None ,
604636 eval_metric : Callable | None = None ,
605637 display_val_acc : bool | None = False ,
638+ accuracy_fn : Callable [[jnp .ndarray ], jnp .ndarray ] | None = None ,
606639 dtype : Any = jnp .float_ ,
607640 shuffle : bool | None = False ,
608641 seed : int | None = 42 ,
@@ -642,6 +675,9 @@ def train(
642675 Number of samples per validation batch.
643676 display_val_acc : bool
644677 If True, displays validation accuracy.
678+ accuracy_fn : Callable
679+ Function applied to raw model outputs before validation accuracy labels
680+ are extracted. Passed to :meth:`accuracy`.
645681 alternate_flip : bool
646682 If True, flips every other batch along axis=1.
647683
@@ -888,6 +924,7 @@ def single_loss(x, y=None):
888924 batch_size = val_batch_size ,
889925 embedding = embedding ,
890926 shuffle = shuffle ,
927+ accuracy_fn = accuracy_fn ,
891928 dtype = dtype ,
892929 seed = seed ,
893930 alternate_flip = alternate_flip ,
0 commit comments