Skip to content

Commit df7c093

Browse files
igorsugakfacebook-github-bot
authored andcommitted
replace uses of np.ndarray with npt.NDArray in type annotations (#387)
Summary: Pull Request resolved: #387 To facilitate PSS-2 upgrade, this uses `ndt.NDArray` instead of `nd.ndarray` in type annotations. It was backported to Numpy-1.19 (PSS-1) as alias to `nd.ndarray` -- a noop. In Numpy-1.24, `ndt.NDArray` a proper generic type, and without this change uses of `nd.ndarray` generate the following Pyre error: ```counterexample Invalid type parameters [24]: Generic type `np.ndarray` expects 2 type parameters. ``` Reviewed By: florazzz Differential Revision: D63360858
1 parent dc763d5 commit df7c093

16 files changed

+70
-54
lines changed

aepsych/benchmark/problem.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import aepsych
1111
import numpy as np
12+
import numpy.typing as npt
1213
import torch
1314
from scipy.stats import bernoulli, norm, pearsonr
1415
from aepsych.strategy import SequentialStrategy, Strategy
@@ -51,7 +52,7 @@ def metadata(self) -> Dict[str, Any]:
5152
Benchmark's output dataframe, with its associated value stored in each row."""
5253
return {"name": self.name}
5354

54-
def p(self, x: np.ndarray) -> np.ndarray:
55+
def p(self, x: npt.NDArray) -> npt.NDArray:
5556
"""Evaluate response probability from test function.
5657
5758
Args:
@@ -62,7 +63,7 @@ def p(self, x: np.ndarray) -> np.ndarray:
6263
"""
6364
return norm.cdf(self.f(x))
6465

65-
def sample_y(self, x: np.ndarray) -> np.ndarray:
66+
def sample_y(self, x: npt.NDArray) -> npt.NDArray:
6667
"""Sample a response from test function.
6768
6869
Args:
@@ -86,7 +87,7 @@ def f_hat(self, model: aepsych.models.base.ModelProtocol) -> torch.Tensor:
8687
return f_hat
8788

8889
@cached_property
89-
def f_true(self) -> np.ndarray:
90+
def f_true(self) -> npt.NDArray:
9091
"""Evaluate true test function over evaluation grid.
9192
9293
Returns:
@@ -238,7 +239,7 @@ def inverse_link(x):
238239
return inverse_link(self.thresholds).astype(np.float32)
239240

240241
@cached_property
241-
def true_below_threshold(self) -> np.ndarray:
242+
def true_below_threshold(self) -> npt.NDArray:
242243
"""
243244
Evaluate whether the true function is below threshold over the eval grid
244245
(used for proper scoring and threshold missclassification metric).

aepsych/benchmark/test_functions.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from typing import Callable
1111

1212
import numpy as np
13+
import numpy.typing as npt
1314
import pandas as pd
1415
from scipy.interpolate import CubicSpline, interp1d
1516
from scipy.stats import norm
@@ -53,7 +54,7 @@
5354
dubno_data = pd.read_csv(io.StringIO(raw))
5455

5556

56-
def make_songetal_threshfun(x: np.ndarray, y: np.ndarray) -> Callable[[float], float]:
57+
def make_songetal_threshfun(x: npt.NDArray, y: npt.NDArray) -> Callable[[float], float]:
5758
"""Generate a synthetic threshold function by interpolation of real data.
5859
5960
Real data is from Dubno et al. 2013, and procedure follows Song et al. 2017, 2018.
@@ -83,7 +84,7 @@ def f_combo(x):
8384

8485
def make_songetal_testfun(
8586
phenotype: str = "Metabolic", beta: float = 1
86-
) -> Callable[[np.ndarray, bool], np.ndarray]:
87+
) -> Callable[[npt.NDArray, bool], npt.NDArray]:
8788
"""Make an audiometric test function following Song et al. 2017.
8889
8990
To do so,we first compute a threshold by interpolation/extrapolation
@@ -129,7 +130,7 @@ def song_testfun(x, cdf=False):
129130
return song_testfun
130131

131132

132-
def novel_discrimination_testfun(x: np.ndarray) -> np.ndarray:
133+
def novel_discrimination_testfun(x: npt.NDArray) -> npt.NDArray:
133134
"""Evaluate novel discrimination test function from Owen et al.
134135
135136
The threshold is roughly parabolic with context, and the slope

aepsych/config.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import botorch
1717
import gpytorch
1818
import numpy as np
19+
import numpy.typing as npt
1920
import torch
2021

2122
from aepsych.version import __version__
@@ -175,7 +176,7 @@ def _str_to_list(self, v: str, element_type: _T = float) -> List[_T]:
175176
else:
176177
return [v.strip()]
177178

178-
def _str_to_array(self, v: str) -> np.ndarray:
179+
def _str_to_array(self, v: str) -> npt.NDArray:
179180
v = ast.literal_eval(v)
180181
return np.array(v, dtype=float)
181182

aepsych/generators/manual_generator.py

+8-7
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from typing import Optional, Union, Dict
1010

1111
import numpy as np
12+
import numpy.typing as npt
1213
import torch
1314
from aepsych.config import Config
1415
from aepsych.generators.base import AEPsychGenerator
@@ -24,9 +25,9 @@ class ManualGenerator(AEPsychGenerator):
2425

2526
def __init__(
2627
self,
27-
lb: Union[np.ndarray, torch.Tensor],
28-
ub: Union[np.ndarray, torch.Tensor],
29-
points: Union[np.ndarray, torch.Tensor],
28+
lb: Union[npt.NDArray, torch.Tensor],
29+
ub: Union[npt.NDArray, torch.Tensor],
30+
points: Union[npt.NDArray, torch.Tensor],
3031
dim: Optional[int] = None,
3132
shuffle: bool = True,
3233
seed: Optional[int] = None,
@@ -101,10 +102,10 @@ class SampleAroundPointsGenerator(ManualGenerator):
101102

102103
def __init__(
103104
self,
104-
lb: Union[np.ndarray, torch.Tensor],
105-
ub: Union[np.ndarray, torch.Tensor],
106-
window: Union[np.ndarray, torch.Tensor],
107-
points: Union[np.ndarray, torch.Tensor],
105+
lb: Union[npt.NDArray, torch.Tensor],
106+
ub: Union[npt.NDArray, torch.Tensor],
107+
window: Union[npt.NDArray, torch.Tensor],
108+
points: Union[npt.NDArray, torch.Tensor],
108109
samples_per_point: int,
109110
dim: Optional[int] = None,
110111
shuffle: bool = True,

aepsych/generators/random_generator.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from typing import Dict, Optional, Union
99

1010
import numpy as np
11+
import numpy.typing as npt
1112
import torch
1213
from aepsych.config import Config
1314
from aepsych.generators.base import AEPsychGenerator
@@ -22,8 +23,8 @@ class RandomGenerator(AEPsychGenerator):
2223

2324
def __init__(
2425
self,
25-
lb: Union[np.ndarray, torch.Tensor],
26-
ub: Union[np.ndarray, torch.Tensor],
26+
lb: Union[npt.NDArray, torch.Tensor],
27+
ub: Union[npt.NDArray, torch.Tensor],
2728
dim: Optional[int] = None,
2829
):
2930
"""Iniatialize RandomGenerator.

aepsych/generators/sobol_generator.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from typing import Dict, Optional, Union
1010

1111
import numpy as np
12+
import numpy.typing as npt
1213
import torch
1314
from aepsych.config import Config
1415
from aepsych.generators.base import AEPsychGenerator
@@ -24,8 +25,8 @@ class SobolGenerator(AEPsychGenerator):
2425

2526
def __init__(
2627
self,
27-
lb: Union[np.ndarray, torch.Tensor],
28-
ub: Union[np.ndarray, torch.Tensor],
28+
lb: Union[npt.NDArray, torch.Tensor],
29+
ub: Union[npt.NDArray, torch.Tensor],
2930
dim: Optional[int] = None,
3031
seed: Optional[int] = None,
3132
stimuli_per_trial: int = 1,

aepsych/models/base.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import gpytorch
1616
import numpy as np
17+
import numpy.typing as npt
1718
import torch
1819

1920
from aepsych.config import Config, ConfigurableMixin
@@ -91,7 +92,7 @@ def _get_extremum(
9192
extremum_type: str,
9293
locked_dims: Optional[Mapping[int, List[float]]],
9394
n_samples=1000,
94-
) -> Tuple[float, np.ndarray]:
95+
) -> Tuple[float, npt.NDArray]:
9596
pass
9697

9798
def dim_grid(self, gridsize: int = 30) -> torch.Tensor:
@@ -105,7 +106,7 @@ def update(
105106
) -> None:
106107
pass
107108

108-
def p_below_threshold(self, x, f_thresh) -> np.ndarray:
109+
def p_below_threshold(self, x, f_thresh) -> npt.NDArray:
109110
pass
110111

111112

@@ -216,7 +217,7 @@ def inv_query(
216217

217218
def get_jnd(
218219
self: ModelProtocol,
219-
grid: Optional[Union[np.ndarray, torch.Tensor]] = None,
220+
grid: Optional[Union[npt.NDArray, torch.Tensor]] = None,
220221
cred_level: Optional[float] = None,
221222
intensity_dim: int = -1,
222223
confsamps: int = 500,
@@ -378,7 +379,7 @@ def _fit_mll(
378379
)
379380
return res
380381

381-
def p_below_threshold(self, x, f_thresh) -> np.ndarray:
382+
def p_below_threshold(self, x, f_thresh) -> npt.NDArray:
382383
f, var = self.predict(x)
383384
f_thresh = f_thresh.reshape(-1, 1)
384385
f = f.reshape(1, -1)

aepsych/models/gp_classification.py

+8-7
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import gpytorch
1313
import numpy as np
14+
import numpy.typing as npt
1415
import torch
1516
from aepsych.config import Config
1617
from aepsych.factory.default import default_mean_covar_factory
@@ -47,8 +48,8 @@ class GPClassificationModel(AEPsychMixin, ApproximateGP):
4748

4849
def __init__(
4950
self,
50-
lb: Union[np.ndarray, torch.Tensor],
51-
ub: Union[np.ndarray, torch.Tensor],
51+
lb: Union[npt.NDArray, torch.Tensor],
52+
ub: Union[npt.NDArray, torch.Tensor],
5253
dim: Optional[int] = None,
5354
mean_module: Optional[gpytorch.means.Mean] = None,
5455
covar_module: Optional[gpytorch.kernels.Kernel] = None,
@@ -232,7 +233,7 @@ def fit(
232233
self._fit_mll(mll, **kwargs)
233234

234235
def sample(
235-
self, x: Union[torch.Tensor, np.ndarray], num_samples: int
236+
self, x: Union[torch.Tensor, npt.NDArray], num_samples: int
236237
) -> torch.Tensor:
237238
"""Sample from underlying model.
238239
@@ -247,7 +248,7 @@ def sample(
247248
return self.posterior(x).rsample(torch.Size([num_samples])).detach().squeeze()
248249

249250
def predict(
250-
self, x: Union[torch.Tensor, np.ndarray], probability_space: bool = False
251+
self, x: Union[torch.Tensor, npt.NDArray], probability_space: bool = False
251252
) -> Tuple[torch.Tensor, torch.Tensor]:
252253
"""Query the model for posterior mean and variance.
253254
@@ -288,7 +289,7 @@ def predict(
288289
return promote_0d(fmean), promote_0d(fvar)
289290

290291
def predict_probability(
291-
self, x: Union[torch.Tensor, np.ndarray]
292+
self, x: Union[torch.Tensor, npt.NDArray]
292293
) -> Tuple[torch.Tensor, torch.Tensor]:
293294
return self.predict(x, probability_space=True)
294295

@@ -304,8 +305,8 @@ class GPBetaRegressionModel(GPClassificationModel):
304305

305306
def __init__(
306307
self,
307-
lb: Union[np.ndarray, torch.Tensor],
308-
ub: Union[np.ndarray, torch.Tensor],
308+
lb: Union[npt.NDArray, torch.Tensor],
309+
ub: Union[npt.NDArray, torch.Tensor],
309310
dim: Optional[int] = None,
310311
mean_module: Optional[gpytorch.means.Mean] = None,
311312
covar_module: Optional[gpytorch.kernels.Kernel] = None,

aepsych/models/gp_regression.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import gpytorch
1313
import numpy as np
14+
import numpy.typing as npt
1415
import torch
1516
from aepsych.config import Config
1617
from aepsych.factory.default import default_mean_covar_factory
@@ -33,8 +34,8 @@ class GPRegressionModel(AEPsychMixin, ExactGP):
3334

3435
def __init__(
3536
self,
36-
lb: Union[np.ndarray, torch.Tensor],
37-
ub: Union[np.ndarray, torch.Tensor],
37+
lb: Union[npt.NDArray, torch.Tensor],
38+
ub: Union[npt.NDArray, torch.Tensor],
3839
dim: Optional[int] = None,
3940
mean_module: Optional[gpytorch.means.Mean] = None,
4041
covar_module: Optional[gpytorch.kernels.Kernel] = None,
@@ -140,7 +141,7 @@ def fit(self, train_x: torch.Tensor, train_y: torch.Tensor, **kwargs) -> None:
140141
return self._fit_mll(mll, **kwargs)
141142

142143
def sample(
143-
self, x: Union[torch.Tensor, np.ndarray], num_samples: int
144+
self, x: Union[torch.Tensor, npt.NDArray], num_samples: int
144145
) -> torch.Tensor:
145146
"""Sample from underlying model.
146147
@@ -159,7 +160,7 @@ def update(self, train_x: torch.Tensor, train_y: torch.Tensor, **kwargs):
159160
return self.fit(train_x, train_y, **kwargs)
160161

161162
def predict(
162-
self, x: Union[torch.Tensor, np.ndarray], **kwargs
163+
self, x: Union[torch.Tensor, npt.NDArray], **kwargs
163164
) -> Tuple[torch.Tensor, torch.Tensor]:
164165
"""Query the model for posterior mean and variance.
165166

aepsych/models/monotonic_projection_gp.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import gpytorch
1313
import numpy as np
14+
import numpy.typing as npt
1415
import torch
1516
from aepsych.config import Config
1617
from aepsych.factory.default import default_mean_covar_factory
@@ -92,8 +93,8 @@ class MonotonicProjectionGP(GPClassificationModel):
9293

9394
def __init__(
9495
self,
95-
lb: Union[np.ndarray, torch.Tensor],
96-
ub: Union[np.ndarray, torch.Tensor],
96+
lb: Union[npt.NDArray, torch.Tensor],
97+
ub: Union[npt.NDArray, torch.Tensor],
9798
monotonic_dims: List[int],
9899
monotonic_grid_size: int = 20,
99100
min_f_val: Optional[float] = None,
@@ -135,7 +136,7 @@ def posterior(
135136
for i, dim in enumerate(self.monotonic_dims):
136137
# using numpy because torch doesn't support vectorized linspace,
137138
# pytorch/issues/61292
138-
grid: Union[np.ndarray, torch.Tensor] = np.linspace(
139+
grid: Union[npt.NDArray, torch.Tensor] = np.linspace(
139140
self.lb[dim],
140141
X[:, dim].numpy(),
141142
s + 1,
@@ -167,7 +168,7 @@ def posterior(
167168
return GPyTorchPosterior(mvn_proj)
168169

169170
def sample(
170-
self, x: Union[torch.Tensor, np.ndarray], num_samples: int
171+
self, x: Union[torch.Tensor, npt.NDArray], num_samples: int
171172
) -> torch.Tensor:
172173
samps = super().sample(x=x, num_samples=num_samples)
173174
if self.min_f_val is not None:

aepsych/models/monotonic_rejection_gp.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
import gpytorch
1414
import numpy as np
15+
import numpy.typing as npt
1516
import torch
1617
from aepsych.acquisition.rejection_sampler import RejectionSampler
1718
from aepsych.config import Config
@@ -52,8 +53,8 @@ class MonotonicRejectionGP(AEPsychMixin, ApproximateGP):
5253
def __init__(
5354
self,
5455
monotonic_idxs: Sequence[int],
55-
lb: Union[np.ndarray, torch.Tensor],
56-
ub: Union[np.ndarray, torch.Tensor],
56+
lb: Union[npt.NDArray, torch.Tensor],
57+
ub: Union[npt.NDArray, torch.Tensor],
5758
dim: Optional[int] = None,
5859
mean_module: Optional[Mean] = None,
5960
covar_module: Optional[Kernel] = None,
@@ -280,7 +281,7 @@ def predict(
280281
return mean, variance
281282

282283
def predict_probability(
283-
self, x: Union[torch.Tensor, np.ndarray]
284+
self, x: Union[torch.Tensor, npt.NDArray]
284285
) -> Tuple[torch.Tensor, torch.Tensor]:
285286
return self.predict(x, probability_space=True)
286287

aepsych/models/pairwise_probit.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import gpytorch
1111
import numpy as np
12+
import numpy.typing as npt
1213
import torch
1314
from aepsych.config import Config
1415
from aepsych.factory import default_mean_covar_factory
@@ -57,8 +58,8 @@ def _get_index_of_equal_row(arr, x, dim=0):
5758

5859
def __init__(
5960
self,
60-
lb: Union[np.ndarray, torch.Tensor],
61-
ub: Union[np.ndarray, torch.Tensor],
61+
lb: Union[npt.NDArray, torch.Tensor],
62+
ub: Union[npt.NDArray, torch.Tensor],
6263
dim: Optional[int] = None,
6364
covar_module: Optional[gpytorch.kernels.Kernel] = None,
6465
max_fit_time: Optional[float] = None,

0 commit comments

Comments
 (0)