-
Notifications
You must be signed in to change notification settings - Fork 47
Replace direct matrix inverse with Tikhonov-regularized solve for MVAR Fourier #72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…R Fourier - Replace xp.linalg.inv(H) with xp.linalg.solve(H + λI, I) in _MVAR_Fourier_coefficients - Replace xp.linalg.inv(H_0) with regularized solve in _estimate_transfer_function - Use scale-aware regularization: λ = 1e-12 * mean(||H||²) for stability - Add stress test for near-singular frequency bins to verify no LinAlgError This prevents numerical instability from singular or near-singular transfer function matrices that can occur with highly correlated signals. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR replaces direct matrix inversion operations in MVAR Fourier coefficient computations with Tikhonov-regularized linear solves to prevent numerical instability when dealing with near-singular frequency bins.
- Replaces
inv(H)withsolve(H + λI, I)using scale-aware regularization - Adds comprehensive stress test for near-singular cross-spectral matrices
- Applies regularization to both transfer function estimation and MVAR coefficient computation
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| spectral_connectivity/connectivity.py | Implements Tikhonov regularization in _MVAR_Fourier_coefficients property and _estimate_transfer_function function |
| tests/test_connectivity.py | Adds stress test test_mvar_regularized_inverse_near_singular for near-singular frequency bins |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| H = self._transfer_function | ||
| # Tikhonov regularization: solve(H + λI, I) instead of inv(H) | ||
| lam = 1e-12 * xp.mean(xp.real(xp.conj(H) * H)) # Scale-aware regularization |
Copilot
AI
Sep 25, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The regularization parameter lam uses a magic number 1e-12. Consider defining this as a named constant (e.g., TIKHONOV_REGULARIZATION_FACTOR = 1e-12) to improve maintainability and make it easier to adjust if needed.
| ) | ||
| H_0 = inverse_fourier_coefficients[..., 0:1, :, :] | ||
| # Tikhonov regularization: solve(H_0 + λI, I) instead of inv(H_0) | ||
| lam = 1e-12 * xp.mean(H_0 * H_0) # Scale-aware regularization for real matrix |
Copilot
AI
Sep 25, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The regularization parameter uses the same magic number 1e-12 as in the other function. Consider extracting this to a shared constant to ensure consistency and easier maintenance.
tests/test_connectivity.py
Outdated
| base_signal = np.random.randn(n_time_samples, n_trials, n_tapers, n_fft_samples) + \ | ||
| 1j * np.random.randn(n_time_samples, n_trials, n_tapers, n_fft_samples) |
Copilot
AI
Sep 25, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The complex signal generation spans multiple lines with backslash continuation. Consider using parentheses for line continuation instead: base_signal = (np.random.randn(...) + 1j * np.random.randn(...))
| base_signal = np.random.randn(n_time_samples, n_trials, n_tapers, n_fft_samples) + \ | |
| 1j * np.random.randn(n_time_samples, n_trials, n_tapers, n_fft_samples) | |
| base_signal = ( | |
| np.random.randn(n_time_samples, n_trials, n_tapers, n_fft_samples) | |
| + 1j * np.random.randn(n_time_samples, n_trials, n_tapers, n_fft_samples) | |
| ) |
- Break long lines in regularized inverse implementation - Fix line length issues in new stress test - Apply black formatting to ensure consistent style 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
Address copilot review comments: - Define TIKHONOV_REGULARIZATION_FACTOR = 1e-12 as module-level constant - Use constant in both _MVAR_Fourier_coefficients and _estimate_transfer_function - Improves maintainability and ensures consistency 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Merged latest master branch changes including new validation tests. All tests from both branches are preserved. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Document Tikhonov regularization changes in PR #72 for numerical stability. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Summary
Test plan
test_mvar_regularized_inverse_near_singularpasses🤖 Generated with Claude Code