Sign correction to ensure deterministic output from SVD. This function is useful for orienting eigenvectors such that they all lie in a shared but arbitrary half-space. This makes it possible to ensure that results are equivalent across SVD implementations and random number generato
(u, v, u_based_decision=False)
| 529 | |
| 530 | |
| 531 | def svd_flip(u, v, u_based_decision=False): |
| 532 | """Sign correction to ensure deterministic output from SVD. |
| 533 | |
| 534 | This function is useful for orienting eigenvectors such that |
| 535 | they all lie in a shared but arbitrary half-space. This makes |
| 536 | it possible to ensure that results are equivalent across SVD |
| 537 | implementations and random number generator states. |
| 538 | |
| 539 | Parameters |
| 540 | ---------- |
| 541 | |
| 542 | u : (M, K) array_like |
| 543 | Left singular vectors (in columns) |
| 544 | v : (K, N) array_like |
| 545 | Right singular vectors (in rows) |
| 546 | u_based_decision: bool |
| 547 | Whether or not to choose signs based |
| 548 | on `u` rather than `v`, by default False |
| 549 | |
| 550 | Returns |
| 551 | ------- |
| 552 | |
| 553 | u : (M, K) array_like |
| 554 | Left singular vectors with corrected sign |
| 555 | v: (K, N) array_like |
| 556 | Right singular vectors with corrected sign |
| 557 | """ |
| 558 | # Determine half-space in which all singular vectors |
| 559 | # lie relative to an arbitrary vector; summation |
| 560 | # equivalent to dot product with row vector of ones |
| 561 | if u_based_decision: |
| 562 | dtype = u.dtype |
| 563 | signs = np.sum(u, axis=0, keepdims=True) |
| 564 | else: |
| 565 | dtype = v.dtype |
| 566 | signs = np.sum(v, axis=1, keepdims=True).T |
| 567 | signs = 2.0 * ((signs >= 0) - 0.5).astype(dtype) |
| 568 | # Force all singular vectors into same half-space |
| 569 | u, v = u * signs, v * signs.T |
| 570 | return u, v |
| 571 | |
| 572 | |
| 573 | def scipy_linalg_safe(func_name, *args, **kwargs): |