Skip to content

Commit c57f851

Browse files
authored
Merge pull request #3883 from pavlin-policar/lazy-load-tsne
[ENH] t-SNE: Load openTSNE lazily
2 parents 514ae98 + c851e6c commit c57f851

File tree

1 file changed

+23
-12
lines changed

1 file changed

+23
-12
lines changed

Orange/projection/manifold.py

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@
88
from scipy.sparse.linalg import eigsh as arpack_eigh
99
import sklearn.manifold as skl_manifold
1010

11-
import openTSNE
12-
import openTSNE.affinity
13-
import openTSNE.initialization
14-
1511
import Orange
1612
from Orange.data import Table, Domain, ContinuousVariable
1713
from Orange.distance import Distance, DistanceModel, Euclidean
@@ -21,10 +17,6 @@
2117
__all__ = ["MDS", "Isomap", "LocallyLinearEmbedding", "SpectralEmbedding",
2218
"TSNE"]
2319

24-
# Disable t-SNE user warnings
25-
openTSNE.tsne.log.setLevel(logging.ERROR)
26-
openTSNE.affinity.log.setLevel(logging.ERROR)
27-
2820

2921
def torgerson(distances, n_components=2, eigen_solver="auto"):
3022
"""
@@ -190,6 +182,23 @@ def __init__(self, n_components=2, affinity='nearest_neighbors', gamma=None,
190182
self.params = vars()
191183

192184

185+
class lazy_openTSNE:
186+
"""openTSNE uses numba, which is slow to load, so load it lazily."""
187+
def __getattr__(self, item):
188+
import sys
189+
import openTSNE
190+
import openTSNE.affinity
191+
import openTSNE.initialization
192+
if "openTSNE" in sys.modules:
193+
# Disable t-SNE user warnings
194+
openTSNE.tsne.log.setLevel(logging.ERROR)
195+
openTSNE.affinity.log.setLevel(logging.ERROR)
196+
return getattr(openTSNE, item)
197+
198+
199+
openTSNE = lazy_openTSNE()
200+
201+
193202
class TSNEModel(Projection):
194203
"""A t-SNE embedding object. Supports further optimization as well as
195204
adding new data into the existing embedding.
@@ -204,8 +213,8 @@ class TSNEModel(Projection):
204213
pre_domain : Domain
205214
Original data domain
206215
"""
207-
def __init__(self, embedding: openTSNE.TSNEEmbedding, table: Table,
208-
pre_domain: Domain):
216+
def __init__(self, embedding, table, pre_domain):
217+
# type: (openTSNE.TSNEEmbedding, Table, Domain) -> None
209218
transformer = TransformDomain(self)
210219

211220
def proj_variable(i):
@@ -221,7 +230,8 @@ def proj_variable(i):
221230
class_vars=table.domain.class_vars,
222231
metas=table.domain.metas)
223232

224-
def transform(self, X: np.ndarray, learning_rate=1, **kwargs) -> openTSNE.PartialTSNEEmbedding:
233+
def transform(self, X, learning_rate=1, **kwargs):
234+
# type: (np.ndarray, int, ...) -> openTSNE.PartialTSNEEmbedding
225235
if sp.issparse(X):
226236
raise TypeError(
227237
"A sparse matrix was passed, but dense data is required. Use "
@@ -481,7 +491,8 @@ def prepare_embedding(self, affinities, initialization):
481491
callbacks_every_iters=self.callbacks_every_iters,
482492
)
483493

484-
def fit(self, X: np.ndarray, Y: np.ndarray = None) -> openTSNE.TSNEEmbedding:
494+
def fit(self, X, Y=None):
495+
# type: (np.ndarray, Optional[np.ndarray]) -> openTSNE.TSNEEmbedding
485496
# Compute affinities and initial positions and prepare the embedding object
486497
affinities = self.compute_affinities(X)
487498
initialization = self.compute_initialization(X)

0 commit comments

Comments
 (0)