Commit Graph

5 Commits

Author SHA1 Message Date
Leo Camus
716c594eab Fix symeig3x3 for inputs that are not of order 1 (#2045)
Summary:
## Motivation

`symeig3x3` uses a fixed absolute epsilon (`torch.finfo(torch.float).eps`) in several places where the magnitude of the input actually matters:

- `p1.clamp(self._eps)`
- the `diag_soft_cond` test, which decides whether a matrix is treated as diagonal
- the `+= eps * sign(...)` regularizers in `_get_ev0` and `_get_ev1`

Since those thresholds are absolute, the routine only behaves as intended for matrices whose entries are of order 1. Once the entries drop below roughly `1e-3` the regularizers dominate the data and the output stops being an eigendecomposition at all. At the other end, `1e10` is already wrong and `1e30` returns NaN.

This is not an exotic corner. `estimate_pointcloud_normals` and `estimate_pointcloud_local_coord_frames` call `symeig3x3` by default (`use_symeig_workaround=True`) on per-point covariance matrices, and those scale with the square of the local neighbourhood size. The denser the point cloud, the smaller the covariances, and the worse the normals get, silently.

Points sampled on a sphere, `neighborhood_size=50`, median angle between the estimated normal and the true radial normal:

| points | radius | mean abs cov entry | main | this PR | `torch.linalg.eigh` |
|--------|--------|--------------------|------|---------|---------------------|
| 4 000 | 1.0 | 4.5e-03 | 1.60° | 1.61° | 1.61° |
| 20 000 | 1.0 | 9.1e-04 | 1.55° | 0.68° | 0.68° |
| 100 000 | 1.0 | 1.8e-04 | 31.86° | 0.31° | 0.31° |
| 4 000 | 0.1 | 4.5e-05 | 50.24° | 1.54° | 1.54° |

This looks like the cause of https://github.com/facebookresearch/pytorch3d/issues/1577, where the reporter narrowed bad normals down to `symeig3x3` and found that passing `use_symeig_workaround=False` fixed them.

## Fix

The decomposition is homogeneous: `eig(s * A) == s * eig(A)` and the eigenvectors do not change. So preconditioning each matrix to unit maximum magnitude and undoing the scaling on the eigenvalues afterwards is exact, and it puts the absolute thresholds back in the regime they were written for.

The scale is detached. For any fixed scale the expression is exactly the eigendecomposition of the input, so gradients are unaffected, and this avoids differentiating through `amax`.

Max relative reconstruction error `max|V diag(w) Vᵀ - A| / max|A|` over 2 000 random symmetric matrices:

| input scale | main | this PR |
|-------------|---------|---------|
| 1e30 | nan | 9.9e-07 |
| 1e10 | 1.00 | 1.0e-06 |
| 1e0 | 1.6e-06 | 1.0e-06 |
| 1e-10 | 1.74 | 9.7e-07 |
| 1e-30 | 1.73 | 9.7e-07 |

float64 inputs break on main below about `1e-8` and are accurate here down to `1e-60`. Exactly-zero, identity, diagonal and rank-1 inputs, and batches mixing magnitudes within one call, all behave.

## Tests

Added `test_is_eigen_small_magnitude`, which runs the existing eigen check on the same random matrices scaled by `1e-2`, `1e-4` and `1e-6` with a correspondingly scaled `atol`. On main it fails with a max relative difference of 101.6; with the fix it passes.

The 13 existing tests in `tests/test_symeig3x3.py` pass unchanged both before and after, on CPU and on GPU, `gradcheck` included.

Cost is one `amax` and one division: no measurable change on GPU, around 2% on CPU at 1e6 matrices.

Pull Request resolved: https://github.com/facebookresearch/pytorch3d/pull/2045

Reviewed By: MichaelRamamonjisoa

Differential Revision: D119970731

Pulled By: bottler

fbshipit-source-id: 35d85a342513c11faca4e6d8ee98052be90172a6
2026-09-15 03:54:46 -07:00
Jeremy Reizenstein
34f648ede0 move targets
Summary: Move testing targets from pytorch3d/tests/TARGETS to pytorch3d/TARGETS.

Reviewed By: shapovalov

Differential Revision: D36186940

fbshipit-source-id: a4c52c4d99351f885e2b0bf870532d530324039b
2022-05-25 06:16:03 -07:00
Tim Hatch
34bbb3ad32 apply import merging for fbcode/vision/fair (2 of 2)
Summary:
Applies new import merging and sorting from µsort v1.0.

When merging imports, µsort will make a best-effort to move associated
comments to match merged elements, but there are known limitations due to
the diynamic nature of Python and developer tooling. These changes should
not produce any dangerous runtime changes, but may require touch-ups to
satisfy linters and other tooling.

Note that µsort uses case-insensitive, lexicographical sorting, which
results in a different ordering compared to isort. This provides a more
consistent sorting order, matching the case-insensitive order used when
sorting import statements by module name, and ensures that "frog", "FROG",
and "Frog" always sort next to each other.

For details on µsort's sorting and merging semantics, see the user guide:
https://usort.readthedocs.io/en/stable/guide.html#sorting

Reviewed By: bottler

Differential Revision: D35553814

fbshipit-source-id: be49bdb6a4c25264ff8d4db3a601f18736d17be1
2022-04-13 06:51:33 -07:00
Jeremy Reizenstein
9eeb456e82 Update license for company name
Summary: Update all FB license strings to the new format.

Reviewed By: patricklabatut

Differential Revision: D33403538

fbshipit-source-id: 97a4596c5c888f3c54f44456dc07e718a387a02c
2022-01-04 11:43:38 -08:00
Nikita Smetanin
d7d740abe9 Symmetric eigen 3x3 implementation + benchmark & tests
Summary:
Symmetric eigenvalues 3x3 implementation from https://github.com/fairinternal/denseposeslim/blob/roman_c3dpo/tools/functions.py#L612

based on https://en.wikipedia.org/wiki/Eigenvalue_algorithm#3.C3.973_matrices and https://www.geometrictools.com/Documentation/RobustEigenSymmetric3x3.pdf

Benchmarks show significant outperformance of symeig3x3 in comparison with torch implementations (torch.symeig and torch.linalg.eigh) on GPU (P100), especially for large batches: 70-280ns per sample vs 3400ns per sample for torch_linalg_eigh_1048576_cpu

It's worth mentioning that torch.linalg.eigh is still comparably fast for batches up to 8192 on CPU.

Some tests are still failing as the error thresholds need to be adjusted appropriately.

Reviewed By: patricklabatut

Differential Revision: D29915453

fbshipit-source-id: 7c1b062da631c57c4e22a42dd0027ea5e205f1b5
2021-10-06 10:57:07 -07:00