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