test_eigh is silently skipped on the OpenVINO backend, and it fails when it runs
conftest.py decides whether to skip a test on the OpenVINO backend with a substring check:
for skipped_test in openvino_skipped_tests:
if skipped_test in item.nodeid:
excluded_concrete_tests.txt contains LinalgOpsCorrectnessTest::test_eig, which is a prefix of LinalgOpsCorrectnessTest::test_eigh, so listing the first also skips the second.
#22363 added eigh for OpenVINO and removed LinalgOpsCorrectnessTest::test_eigh from the exclusion file to turn that test on. LinalgOpsCorrectnessTest::test_eig was already in the file then and still is, so the removal had no effect and test_eigh has never run on this backend.
$ KERAS_BACKEND=openvino pytest "keras/src/ops/linalg_test.py::LinalgOpsCorrectnessTest::test_eigh" -q
1 skipped
Remove only the LinalgOpsCorrectnessTest::test_eig line and the test runs, and fails:
Mismatched elements: 18 / 18 (100%)
[0, 0, 0]: 2.833422635283655 (ACTUAL), 0.39117862568583617 (DESIRED)
[0, 0, 1]: 4.5470004435077795 (ACTUAL), 0.41911281144718415 (DESIRED)
Max relative difference among violations: 10.16354715
eigh
Reconstructing a symmetric matrix from the returned eigenvalues and eigenvectors does not return the original for n >= 3. Checking (v * w[..., None, :]) @ v.transpose(0, 2, 1) against the input on random symmetric positive definite matrices:
| size | max abs error |
|---|---|
| 2x2 | 4.8e-07 |
| 3x3 | 3.0 |
| 4x4 | 5.9 |
| 5x5 | nan |
| 6x6 | nan |
Indefinite matrices behave the same. Already diagonal inputs are correct at every size and 2x2 is correct, so this looks like the rotation not converging rather than a wrapper problem. Outputs at n >= 5 include nan and values around 1.2e20.
keras.ops.eigh is documented and dispatches here on the OpenVINO backend, so it currently returns wrong eigendecompositions with no error.
the matching
Worth noting the substring behavior is load bearing, so exact matching would be the wrong fix. Entries like LinalgOpsCorrectnessTest::test_norm_2_2 and NNOpsDtypeTest::test_ctc_decode intentionally cover their parameterized variants (..._none_true, ..._float16, and so on) by prefix.
What separates those from the eig case is that a parameterized variant appends _ to the base name, and eigh does not. Requiring the remainder after the match to be empty or start with _ covers it. Across the 8366 tests collected under keras/src/ops and keras/src/backend with the OpenVINO backend, that rule changes exactly one outcome: test_eigh stops being skipped. Every other entry keeps the same match set.
Environment: openvino 2026.3.0, keras at 993e8a5.
I would like to work on this. I would send the conftest.py change and the eigh fix as two PRs, since the first turns the failure on in CI and the second is a separate piece of work. Could this be assigned to me?
Source: keras-team/keras