Files
VideoDetect/tests/test_story_05.py
T
2026-08-10 15:51:25 -04:00

84 lines
3.2 KiB
Python

import sys
import unittest
from pathlib import Path
import numpy as np
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
import aggregator
import router
from classifier import FaceClassifier, calibrated_softmax
class Story05ClassifierTests(unittest.TestCase):
def test_calibrated_softmax_sums_to_one(self):
logits = np.array([[2.0, 1.0], [-1.0, 3.0]], dtype=np.float32)
probs = calibrated_softmax(logits, temperature=1.0)
np.testing.assert_allclose(probs.sum(axis=1), [1.0, 1.0], atol=1e-6)
def test_temperature_scaling_raises_lower_confidence_entropy(self):
logits = np.array([[2.0, 0.5]], dtype=np.float32)
sharp = calibrated_softmax(logits, temperature=0.5)
soft = calibrated_softmax(logits, temperature=2.0)
# higher temperature → softer distribution (target class prob moves toward 0.5)
self.assertGreater(sharp[0, 0], soft[0, 0])
def test_classifier_placeholder_returns_neutral_probability(self):
clf = FaceClassifier(engine_path="/nonexistent/model.trt", temperature=1.0)
probs = clf.classify([])
self.assertEqual(probs, [])
def test_classifier_placeholder_single_crop_returns_half(self):
import tempfile
from PIL import Image
clf = FaceClassifier(engine_path="/nonexistent/model.trt", temperature=1.0)
with tempfile.TemporaryDirectory() as tmpdir:
crop = Path(tmpdir) / "crop.jpg"
Image.new("RGB", (224, 224)).save(crop)
probs = clf.classify([str(crop)])
# placeholder logits are all zeros → softmax → 0.5 for each class
self.assertAlmostEqual(probs[0], 0.5, places=5)
class Story05AggregatorTests(unittest.TestCase):
def test_max_strategy(self):
self.assertAlmostEqual(aggregator.aggregate([0.3, 0.8, 0.6], strategy="max"), 0.8)
def test_empty_confidences_returns_zero(self):
self.assertEqual(aggregator.aggregate([], strategy="max"), 0.0)
def test_top_k_mean(self):
result = aggregator.aggregate([0.1, 0.9, 0.5, 0.8], strategy="top_k_mean", top_k=2)
self.assertAlmostEqual(result, (0.9 + 0.8) / 2, places=5)
def test_weighted_mean_clamps_to_unit_interval(self):
result = aggregator.aggregate([1.0, 1.0], strategy="weighted_mean", alpha=100.0, beta=0.0)
self.assertLessEqual(result, 1.0)
self.assertGreaterEqual(result, 0.0)
class Story05RouterTests(unittest.TestCase):
def test_match_at_high_threshold(self):
self.assertEqual(router.route(0.75), router.MATCH)
def test_review_between_thresholds(self):
self.assertEqual(router.route(0.60), router.REVIEW)
def test_skip_below_low_threshold(self):
self.assertEqual(router.route(0.44), router.SKIP)
def test_inclusive_high_threshold_boundary(self):
self.assertEqual(router.route(0.75, t_high=0.75, t_low=0.45), router.MATCH)
def test_inclusive_low_threshold_boundary(self):
self.assertEqual(router.route(0.45, t_high=0.75, t_low=0.45), router.REVIEW)
def test_no_faces_zero_confidence_routes_skip(self):
self.assertEqual(router.route(0.0), router.SKIP)
if __name__ == "__main__":
unittest.main()