dimensionality 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dimensionality-0.1.0/CLAUDE.md +142 -0
- dimensionality-0.1.0/PKG-INFO +21 -0
- dimensionality-0.1.0/README.md +237 -0
- dimensionality-0.1.0/examples/demo.ipynb +568 -0
- dimensionality-0.1.0/examples/synthetic.py +147 -0
- dimensionality-0.1.0/legacy/biology/.ipynb_checkpoints/on_Stringer-checkpoint.ipynb +565 -0
- dimensionality-0.1.0/legacy/biology/.ipynb_checkpoints/on_TVSD-checkpoint.ipynb +1112 -0
- dimensionality-0.1.0/legacy/biology/.ipynb_checkpoints/tvsd_all_cat_dim-checkpoint.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/BrainScore/.ipynb_checkpoints/Compare_all_DiCarlo-checkpoint.ipynb +1380 -0
- dimensionality-0.1.0/legacy/biology/BrainScore/.ipynb_checkpoints/Get_DiCarlo_Data_and_Save-checkpoint.ipynb +932 -0
- dimensionality-0.1.0/legacy/biology/BrainScore/.ipynb_checkpoints/on_Majaj-checkpoint.ipynb +2049 -0
- dimensionality-0.1.0/legacy/biology/BrainScore/Compare_all_DiCarlo.ipynb +1380 -0
- dimensionality-0.1.0/legacy/biology/BrainScore/Get_DiCarlo_Data_and_Save.ipynb +975 -0
- dimensionality-0.1.0/legacy/biology/BrainScore/IT_Chabo.npz +0 -0
- dimensionality-0.1.0/legacy/biology/BrainScore/IT_Tito.npz +0 -0
- dimensionality-0.1.0/legacy/biology/BrainScore/V4_Chabo.npz +0 -0
- dimensionality-0.1.0/legacy/biology/BrainScore/V4_Tito.npz +0 -0
- dimensionality-0.1.0/legacy/biology/BrainScore/dicarlo_data.npz +0 -0
- dimensionality-0.1.0/legacy/biology/BrainScore/dicarlo_data2.npz +0 -0
- dimensionality-0.1.0/legacy/biology/BrainScore/majaj_dim_Ps_Chabo_IT.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/BrainScore/majaj_dim_Ps_Chabo_V4.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/BrainScore/majaj_dim_Ps_Tito_IT.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/BrainScore/majaj_dim_Ps_Tito_V4.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/BrainScore/majaj_dim_Qs_Chabo_IT.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/BrainScore/majaj_dim_Qs_Chabo_V4.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/BrainScore/majaj_dim_Qs_Tito_IT.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/BrainScore/majaj_dim_Qs_Tito_V4.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/BrainScore/majaj_dim_mse_Ps_Chabo_IT.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/BrainScore/majaj_dim_mse_Ps_Chabo_V4.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/BrainScore/majaj_dim_mse_Ps_Tito_IT.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/BrainScore/majaj_dim_mse_Ps_Tito_V4.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/BrainScore/majaj_dim_mse_Qs_Chabo_IT.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/BrainScore/majaj_dim_mse_Qs_Chabo_V4.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/BrainScore/majaj_dim_mse_Qs_Tito_IT.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/BrainScore/majaj_dim_mse_Qs_Tito_V4.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/BrainScore/on_Majaj.ipynb +2069 -0
- dimensionality-0.1.0/legacy/biology/on_Stringer.ipynb +572 -0
- dimensionality-0.1.0/legacy/biology/on_TVSD.ipynb +1256 -0
- dimensionality-0.1.0/legacy/biology/stinger_dim_Ps.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/stringer_dim_Ps.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/stringer_dim_Qs.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/stringer_dim_mse_Ps.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/stringer_dim_mse_Qs.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/tvsd_all_cat_dim.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/tvsd_all_cat_dim_diff_mid0.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/tvsd_all_cat_dim_diff_mid1.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/tvsd_all_cat_dim_diff_mid2.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/tvsd_all_cat_dim_roi0.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/tvsd_all_cat_dim_roi0_mid0.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/tvsd_all_cat_dim_roi0_mid1.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/tvsd_all_cat_dim_roi1.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/tvsd_all_cat_dim_roi1_mid0.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/tvsd_all_cat_dim_roi1_mid1.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/tvsd_all_cat_dim_roi2.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/tvsd_all_cat_dim_roi2_mid0.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/tvsd_all_cat_dim_roi2_mid1.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/tvsd_cat_dim.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/tvsd_dim.pdf +0 -0
- dimensionality-0.1.0/legacy/biology/tvsd_dim_mse.pdf +0 -0
- dimensionality-0.1.0/legacy/intrinsic/.ipynb_checkpoints/Final_dim-checkpoint.ipynb +116 -0
- dimensionality-0.1.0/legacy/intrinsic/.ipynb_checkpoints/nonlin_manifold-checkpoint.ipynb +830 -0
- dimensionality-0.1.0/legacy/intrinsic/Final_dim.ipynb +176 -0
- dimensionality-0.1.0/legacy/intrinsic/nonlin_manifold.ipynb +943 -0
- dimensionality-0.1.0/legacy/synthetic/.ipynb_checkpoints/Linear_example-checkpoint.ipynb +146 -0
- dimensionality-0.1.0/legacy/synthetic/.ipynb_checkpoints/linear_dim-checkpoint.pdf +0 -0
- dimensionality-0.1.0/legacy/synthetic/Linear_example.ipynb +303 -0
- dimensionality-0.1.0/legacy/synthetic/linear_dim.pdf +0 -0
- dimensionality-0.1.0/legacy/synthetic/linear_dim.png +0 -0
- dimensionality-0.1.0/legacy/synthetic/linear_dim_mse.pdf +0 -0
- dimensionality-0.1.0/pyproject.toml +51 -0
- dimensionality-0.1.0/src/dimensionality/__init__.py +56 -0
- dimensionality-0.1.0/src/dimensionality/_core.py +44 -0
- dimensionality-0.1.0/src/dimensionality/estimators.py +206 -0
- dimensionality-0.1.0/src/dimensionality/finite.py +224 -0
- dimensionality-0.1.0/src/dimensionality/plot.py +95 -0
- dimensionality-0.1.0/src/dimensionality/sweep.py +200 -0
- dimensionality-0.1.0/tests/__init__.py +0 -0
- dimensionality-0.1.0/tests/test_estimators.py +268 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# Dimensionality Estimator
|
|
2
|
+
|
|
3
|
+
Python research repository implementing a bias-corrected participation ratio (PR) estimator for measuring global (and local) dimensionality of neural representation manifolds. Based on the ICLR 2026 paper:
|
|
4
|
+
|
|
5
|
+
> **Estimating Dimensionality of Neural Representations from Finite Samples**
|
|
6
|
+
> Chanwoo Chun\*, Abdulkadir Canatar\*, SueYeon Chung, Daniel Lee
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Background
|
|
11
|
+
|
|
12
|
+
The **participation ratio (PR)** γ is a soft count of nonzero eigenvalues of a covariance matrix K = (1/Q) ΦΦᵀ, where Φ ∈ ℝ^{P×Q} is the neural activation matrix (P stimuli × Q neurons):
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
γ = (Σᵢ λᵢ)² / Σᵢ λᵢ² = A / B
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The naive estimator γ_naive is heavily biased when P or Q is small. The key insight: bias arises from **overlapping indices** in the sums for A and B. The fix is to average over **disjoint/unequal indices** only.
|
|
19
|
+
|
|
20
|
+
### Estimators
|
|
21
|
+
|
|
22
|
+
| Estimator | Corrects | Use when |
|
|
23
|
+
|--------------|------------------|-----------------------------------------------|
|
|
24
|
+
| `γ_naive` | nothing | baseline comparison |
|
|
25
|
+
| `γ_row` | row (stimulus) sampling bias | full neuron access, sampled stimuli |
|
|
26
|
+
| `γ_col` | column (neuron) sampling bias | full stimulus access, sampled neurons |
|
|
27
|
+
| `γ_both` | both row and column bias | general case (recommended) |
|
|
28
|
+
|
|
29
|
+
### Extensions
|
|
30
|
+
|
|
31
|
+
- **Noise correction**: pass two trial matrices Φ⁽¹⁾, Φ⁽²⁾; redefine v^{αβ}_{ijkl} ← Φ⁽¹⁾_{iα} Φ⁽²⁾_{jα} Φ⁽¹⁾_{kβ} Φ⁽²⁾_{lβ}. Eliminates additive/multiplicative noise bias.
|
|
32
|
+
- **Importance sampling**: weight samples by r(x) = ρ_X(x)/ρ_X^obs(x) and c(w) = ρ_W(w)/ρ_W^obs(w) to correct for biased sampling distributions.
|
|
33
|
+
- **Sparse matrices**: skip summands that include any missing entry.
|
|
34
|
+
- **Finite underlying matrix**: when sampling P rows/cols from a finite R×C matrix (without replacement), use the corrected estimators that require knowledge of R and C.
|
|
35
|
+
- **Local dimensionality**: weight samples by proximity (Mahalanobis distance with local metric), take average over all center points. Noise-resistant unlike TwoNN.
|
|
36
|
+
|
|
37
|
+
### Scaling law of γ_naive
|
|
38
|
+
|
|
39
|
+
Under uniform row/column norms:
|
|
40
|
+
```
|
|
41
|
+
E[1/γ_naive] ≈ 1/P + 1/Q + 1/γ
|
|
42
|
+
```
|
|
43
|
+
γ_naive is approximately a harmonic mean of P, Q, and γ — like parallel resistance.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Implementation Notes
|
|
48
|
+
|
|
49
|
+
- Core computation uses `opt_einsum` (no JAX). Disjoint-index sums are re-expressed as linear combinations of regular sums to enable vectorization. See Sec. A.3 of the paper for the full expansions.
|
|
50
|
+
- **Centering is algebraic**: the three-term formula structure encodes centering (e.g. A = ⟨v_iijj⟩ − 2⟨v_iijl⟩ + ⟨v_ijlr⟩). Do **not** pre-subtract column means before calling the estimators — doing so introduces statistical dependencies that break the bias correction.
|
|
51
|
+
- Task dimensionality (default): pass Φ directly (rows = stimuli, columns = neurons).
|
|
52
|
+
- Neuron dimensionality: pass Φ.T instead.
|
|
53
|
+
- The ratio A/B introduces a small, unavoidable O((1/P + 1/Q)²) bias even when A and B are individually unbiased — this is negligible in practice.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Package API
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from dimensionality import participation_ratio, participation_ratio_finite
|
|
61
|
+
|
|
62
|
+
# Single-trial, default output (γ_both, bias-corrected for both axes)
|
|
63
|
+
gamma = participation_ratio(Phi) # float
|
|
64
|
+
|
|
65
|
+
# Two-trial noise correction
|
|
66
|
+
gamma = participation_ratio(Phi1, Phi2) # float
|
|
67
|
+
|
|
68
|
+
# Return all four estimators
|
|
69
|
+
result = participation_ratio(Phi, return_all=True)
|
|
70
|
+
# result['naive'], result['row'], result['col'], result['both']
|
|
71
|
+
|
|
72
|
+
# Return numerator A and denominator B
|
|
73
|
+
result = participation_ratio(Phi, return_parts=True)
|
|
74
|
+
# result['both'], result['A'], result['B']
|
|
75
|
+
|
|
76
|
+
# Both options at once — adds A_naive/B_naive, A_row/B_row, etc.
|
|
77
|
+
result = participation_ratio(Phi, return_all=True, return_parts=True)
|
|
78
|
+
|
|
79
|
+
# Finite underlying matrix (R×C), submatrix Φ is P×Q
|
|
80
|
+
gamma = participation_ratio_finite(Phi, R=5000, C=2000) # float
|
|
81
|
+
gamma = participation_ratio_finite(Phi1, R=5000, C=2000, Phi2=Phi2) # two-trial
|
|
82
|
+
result = participation_ratio_finite(Phi, R=5000, C=2000, return_parts=True)
|
|
83
|
+
# result['gamma'], result['A'], result['B']
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Minimum sizes: `participation_ratio` requires P ≥ 4, Q ≥ 2. `participation_ratio_finite` requires the same plus R ≥ P, C ≥ Q.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Repository Structure
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
src/
|
|
94
|
+
dimensionality/
|
|
95
|
+
__init__.py # exports participation_ratio, participation_ratio_finite
|
|
96
|
+
_core.py # _gett_all(pattern, A, B) — quartic einsum helper
|
|
97
|
+
estimators.py # participation_ratio (infinite underlying matrix)
|
|
98
|
+
finite.py # participation_ratio_finite (finite R×C underlying matrix)
|
|
99
|
+
tests/
|
|
100
|
+
test_estimators.py # API tests, bias ordering, noise correction, finite estimator
|
|
101
|
+
examples/
|
|
102
|
+
synthetic.py # Figure 1 reproduction (vary P or Q, all four estimators)
|
|
103
|
+
legacy/ # Old exploratory notebooks — ignore unless explicitly referenced
|
|
104
|
+
biology/ # Brain data experiments (Stringer, MajajHong, TVSD)
|
|
105
|
+
intrinsic/ # Local dimensionality experiments
|
|
106
|
+
synthetic/ # Synthetic data experiments
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
The `legacy/` folder contains the original research notebooks used to produce figures in the paper. **Do not modify or base new code on legacy/ unless explicitly asked.**
|
|
110
|
+
|
|
111
|
+
To run examples:
|
|
112
|
+
```bash
|
|
113
|
+
python examples/synthetic.py # saves examples/figure1.png
|
|
114
|
+
python examples/synthetic.py --show # also opens interactive window
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
To run tests:
|
|
118
|
+
```bash
|
|
119
|
+
pytest tests/
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Key Symbols
|
|
125
|
+
|
|
126
|
+
| Symbol | Meaning |
|
|
127
|
+
|--------|---------|
|
|
128
|
+
| Φ ∈ ℝ^{P×Q} | Sample activation matrix (P stimuli, Q neurons) |
|
|
129
|
+
| Φ^{(∞)} | True infinite underlying matrix |
|
|
130
|
+
| K = (1/Q)ΦΦᵀ | Sample covariance matrix |
|
|
131
|
+
| γ | True participation ratio (dimensionality) |
|
|
132
|
+
| γ_naive | Naive estimator (biased) |
|
|
133
|
+
| γ_both | Bias-corrected estimator (both row and column) |
|
|
134
|
+
| A, B | Numerator and denominator of γ (centered) |
|
|
135
|
+
| v^{αβ}_{ijlr} = Φ_{iα}Φ_{jα}Φ_{lβ}Φ_{rβ} | Elementary quartic tensor |
|
|
136
|
+
| r_{ijlr} | Column-marginalized tensor (sum over α≠β) |
|
|
137
|
+
| t¹–t⁵ | Five unique terms in A and B |
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
## Environment
|
|
141
|
+
- Conda environment: `dimensionality`
|
|
142
|
+
- Activate before running any Python: `conda activate dimensionality`
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dimensionality
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Bias-corrected participation ratio estimator for measuring dimensionality of neural representations
|
|
5
|
+
Project-URL: Homepage, https://github.com/badooki/dimensionality
|
|
6
|
+
Project-URL: Paper, https://arxiv.org/abs/2509.26560
|
|
7
|
+
Author: Chanwoo Chun, Abdulkadir Canatar, SueYeon Chung, Daniel Lee
|
|
8
|
+
License: MIT
|
|
9
|
+
Keywords: dimensionality,neural manifold,neuroscience,participation ratio,representation geometry
|
|
10
|
+
Classifier: Intended Audience :: Science/Research
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
13
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
14
|
+
Requires-Python: >=3.9
|
|
15
|
+
Requires-Dist: numpy>=1.24
|
|
16
|
+
Requires-Dist: opt-einsum>=3.3
|
|
17
|
+
Provides-Extra: dev
|
|
18
|
+
Requires-Dist: jupyter; extra == 'dev'
|
|
19
|
+
Requires-Dist: matplotlib>=3.6; extra == 'dev'
|
|
20
|
+
Requires-Dist: pytest>=7; extra == 'dev'
|
|
21
|
+
Requires-Dist: scipy>=1.10; extra == 'dev'
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# Sample-size invariant measure of dimensionality
|
|
2
|
+
|
|
3
|
+
Bias-corrected **participation ratio (PR)** estimators for measuring the dimensionality of neural representation manifolds, as introduced in:
|
|
4
|
+
|
|
5
|
+
> **Estimating Dimensionality of Neural Representations from Finite Samples**
|
|
6
|
+
> Chanwoo Chun\*, Abdulkadir Canatar\*, SueYeon Chung, Daniel Lee
|
|
7
|
+
> *ICLR 2026*
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 📐 Background
|
|
12
|
+
|
|
13
|
+
Given a neural activation matrix $\Phi \in \mathbb{R}^{P\times Q}$ (P stimuli × Q neurons), the participation ratio
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
$$ \gamma =\frac{\left(\sum_i \lambda_i \right)^2}{\sum_i \lambda_i^2} $$
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
is a soft count of the number of nonzero eigenvalues of the stimulus covariance $K=\frac{1}{Q}\Phi\Phi^\top$. The naive estimator is severely biased downward when P or Q is small — it behaves approximately as a harmonic mean of P, Q, and the true $\gamma$:
|
|
20
|
+
|
|
21
|
+
$$ \mathbb{E}\left[ \frac{1}{\gamma_{\text{naive}}}\right] \approx \frac{1}{P}+ \frac{1}{Q} +\frac{1}{\gamma} $$
|
|
22
|
+
|
|
23
|
+
This package provides unbiased estimators that correct for finite P and/or Q by averaging over disjoint index sets.
|
|
24
|
+
|
|
25
|
+
| Estimator | Corrects | Use when |
|
|
26
|
+
|-----------|----------|----------|
|
|
27
|
+
| `γ_naive` | nothing | baseline reference |
|
|
28
|
+
| `γ_row` | row (stimulus) sampling bias | full neuron access, subsampled stimuli |
|
|
29
|
+
| `γ_col` | column (neuron) sampling bias | full stimulus access, subsampled neurons |
|
|
30
|
+
| `γ_both` | both row and column bias | subsampled neurons, subsampled stimuli|
|
|
31
|
+
|
|
32
|
+
An additional `participation_ratio_finite` estimator handles the case where Φ is a submatrix sampled without replacement from a large-but-finite R×C matrix (Appendix A.6 of the paper).
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 📦 Installation
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pip install git+https://github.com/badooki/dimensionality.git
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Or, for development:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
git clone https://github.com/badooki/dimensionality.git
|
|
46
|
+
cd dimensionality
|
|
47
|
+
pip install -e ".[dev]"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Dependencies:** `numpy >= 1.24`, `opt_einsum >= 3.3`. Python ≥ 3.9.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## 🚀 Quick start
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
import numpy as np
|
|
58
|
+
from dimensionality import participation_ratio
|
|
59
|
+
|
|
60
|
+
# Phi: P stimuli × Q neurons (do NOT pre-center)
|
|
61
|
+
Phi = np.random.randn(200, 100)
|
|
62
|
+
|
|
63
|
+
# Default: γ_both (bias-corrected for both row and column subsampling)
|
|
64
|
+
gamma = participation_ratio(Phi)
|
|
65
|
+
print(gamma)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### All four estimators
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
result = participation_ratio(Phi, return_all=True)
|
|
72
|
+
# result['naive'], result['row'], result['col'], result['both']
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Two-trial noise correction
|
|
76
|
+
|
|
77
|
+
When two independent repeat trials are available for the same stimuli and neurons, the cross-trial construction removes additive and multiplicative noise bias:
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
gamma = participation_ratio(Phi1, Phi2)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Return numerator and denominator separately
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
result = participation_ratio(Phi, return_parts=True)
|
|
87
|
+
# result['both'], result['A'], result['B']
|
|
88
|
+
|
|
89
|
+
# Combined with return_all:
|
|
90
|
+
result = participation_ratio(Phi, return_all=True, return_parts=True)
|
|
91
|
+
# result['naive'], result['A_naive'], result['B_naive'], ...
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Neuron dimensionality
|
|
95
|
+
|
|
96
|
+
To estimate dimensionality along the neuron axis (centering across stimuli), transpose the matrix:
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
gamma_neuron = participation_ratio(Phi.T)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## 🔢 Finite underlying matrix
|
|
105
|
+
|
|
106
|
+
When Φ is a P×Q submatrix sampled without replacement from a finite R×C population matrix, use `participation_ratio_finite`:
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
from dimensionality import participation_ratio_finite
|
|
110
|
+
|
|
111
|
+
gamma = participation_ratio_finite(Phi, R=5000, C=2000)
|
|
112
|
+
|
|
113
|
+
# With noise correction:
|
|
114
|
+
gamma = participation_ratio_finite(Phi1, R=5000, C=2000, Phi2=Phi2)
|
|
115
|
+
|
|
116
|
+
# Also return the naive estimate:
|
|
117
|
+
result = participation_ratio_finite(Phi, R=5000, C=2000, return_naive=True)
|
|
118
|
+
# result['gamma'], result['naive']
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 📊 Subsampling sweep
|
|
124
|
+
|
|
125
|
+
To assess how the estimate converges with sample size, sweep over P or Q:
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
from dimensionality import sweep_dimensionality, plot_sweep
|
|
129
|
+
|
|
130
|
+
# Sweep over number of stimuli; keep all neurons
|
|
131
|
+
result = sweep_dimensionality(Phi, axis='P', n_trials=20)
|
|
132
|
+
|
|
133
|
+
# result['values'] — array of P values used
|
|
134
|
+
# result['naive'], result['row'], result['col'], result['both'] — mean estimates
|
|
135
|
+
# result['both_sem'] — standard error of the mean
|
|
136
|
+
|
|
137
|
+
fig, ax = plot_sweep(result, true_d=50)
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
To sweep over number of neurons instead:
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
result = sweep_dimensionality(Phi, axis='Q')
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
For the finite estimator:
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
result = sweep_dimensionality(Phi, axis='P', estimator='finite', R=5000, C=2000)
|
|
150
|
+
# result['naive'], result['gamma']
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## ⚠️ Important: do not pre-center
|
|
156
|
+
|
|
157
|
+
The bias corrections rely on an algebraic three-term centering structure built into the estimator formulas. Subtracting column means from Φ before passing it to the estimator introduces statistical dependencies between rows that break the bias correction. **Pass the raw activation matrix directly.**
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## 🔧 API reference
|
|
162
|
+
|
|
163
|
+
### `participation_ratio(Phi, Phi2=None, *, return_all=False, return_parts=False)`
|
|
164
|
+
|
|
165
|
+
Estimate the task dimensionality (PR of the centered covariance) of Φ.
|
|
166
|
+
|
|
167
|
+
- **Phi** — raw activation matrix, shape (P, Q); P ≥ 4, Q ≥ 2.
|
|
168
|
+
- **Phi2** — optional second trial for noise correction.
|
|
169
|
+
- **return_all** — if `True`, return dict with all four estimator variants.
|
|
170
|
+
- **return_parts** — if `True`, include numerator A and denominator B.
|
|
171
|
+
|
|
172
|
+
Returns a scalar (`γ_both`) by default, or a dict when either flag is set.
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
### `participation_ratio_finite(Phi, R, C, Phi2=None, *, return_naive=False, return_parts=False)`
|
|
177
|
+
|
|
178
|
+
Estimate the PR of the full R×C matrix from the observed P×Q submatrix.
|
|
179
|
+
|
|
180
|
+
- **R, C** — number of rows/columns in the full underlying matrix; R ≥ P, C ≥ Q.
|
|
181
|
+
- **return_naive** — if `True`, also return the (uncorrected) naive estimate.
|
|
182
|
+
- **return_parts** — if `True`, include numerator A and denominator B.
|
|
183
|
+
|
|
184
|
+
Returns a scalar by default, or a dict when either flag is set.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
### `sweep_dimensionality(Phi, axis='P', values=None, n_trials=20, Phi2=None, estimator='infinite', R=None, C=None, ...)`
|
|
189
|
+
|
|
190
|
+
Run a subsampling sweep. Returns a dict with mean estimates and SEMs at each value. See docstring for full parameter list.
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
### `plot_sweep(result, ax=None, true_d=None, title=None, figsize=(5, 4))`
|
|
195
|
+
|
|
196
|
+
Plot the output of `sweep_dimensionality`. Returns `(fig, ax)`.
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## 🗂️ Repository structure
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
src/
|
|
204
|
+
dimensionality/
|
|
205
|
+
__init__.py # public API
|
|
206
|
+
_core.py # quartic einsum helper
|
|
207
|
+
estimators.py # participation_ratio
|
|
208
|
+
finite.py # participation_ratio_finite
|
|
209
|
+
sweep.py # sweep_dimensionality
|
|
210
|
+
plot.py # plot_sweep
|
|
211
|
+
tests/
|
|
212
|
+
test_estimators.py
|
|
213
|
+
examples/
|
|
214
|
+
demo.ipynb # interactive walkthrough on synthetic data
|
|
215
|
+
synthetic.py # Figure 1 reproduction
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## 📄 Citation
|
|
221
|
+
|
|
222
|
+
If you use this package, please cite:
|
|
223
|
+
|
|
224
|
+
```bibtex
|
|
225
|
+
@inproceedings{chun2026estimating,
|
|
226
|
+
title = {Estimating Dimensionality of Neural Representations from Finite Samples},
|
|
227
|
+
author = {Chun, Chanwoo and Canatar, Abdulkadir and Chung, SueYeon and Lee, Daniel},
|
|
228
|
+
booktitle = {International Conference on Learning Representations},
|
|
229
|
+
year = {2026},
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## License
|
|
236
|
+
|
|
237
|
+
MIT
|