Skip to content

Commit 830fa39

Browse files
authored
Fix setuptools issue, reduce dependencies (#33)
* Fix loading, and remove seaborn * Other edits * Linting
1 parent ad01af4 commit 830fa39

File tree

9 files changed

+134
-294
lines changed

9 files changed

+134
-294
lines changed

poetry.lock

Lines changed: 108 additions & 203 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
[tool.poetry]
22
name = "tensorpack"
3-
version = "0.0.7"
3+
version = "0.0.8"
44
description = "A collection of tensor methods from the Meyer lab."
55
authors = ["Your Name <[email protected]>"]
66
license = "MIT"
77

88
[tool.poetry.dependencies]
99
python = ">=3.9,<3.11"
1010
numpy = "^1.21"
11-
scipy = "^1.7"
1211
tensorly = "^0.7"
13-
scikit-learn = "^1.0.1"
1412
matplotlib = "^3.5.0"
15-
seaborn = "^0.11.2"
13+
pandas = "^1.3.5"
1614

1715
[tool.poetry.dev-dependencies]
1816
pytest = "^6.2"

setup.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
from setuptools import setup, find_packages
1+
try:
2+
from setuptools import setup, find_packages
3+
except ImportError:
4+
from distutils.core import setup, find_packages
25

36
setup(name='tensorpack',
4-
version='0.0.2',
7+
version='0.0.8',
58
description='A collection of tensor methods from the Meyer lab.',
69
url='https://github.com/meyer-lab/tensorpack',
710
license='MIT',

tensorpack/SVD_impute.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@
1010
# See the License for the specific language governing permissions and
1111
# limitations under the License.
1212

13-
from sklearn.decomposition import TruncatedSVD
14-
from sklearn.utils import check_array
13+
from tensorly import partial_svd
1514
import numpy as np
1615

1716
from .soft_impute import Solver
@@ -29,7 +28,6 @@ def __init__(
2928
rank,
3029
convergence_threshold=0.00001,
3130
max_iters=200,
32-
svd_algorithm="arpack",
3331
init_fill_method="zero",
3432
random_state=None,
3533
min_value=None,
@@ -42,7 +40,6 @@ def __init__(
4240
max_value=max_value)
4341
self.rank = rank
4442
self.max_iters = max_iters
45-
self.svd_algorithm = svd_algorithm
4643
self.convergence_threshold = convergence_threshold
4744
self.verbose = verbose
4845
self.random_state = random_state
@@ -62,15 +59,14 @@ def _converged(self, X_old, X_new, missing_mask):
6259
return (ssd / old_norm_squared) < self.convergence_threshold
6360

6461
def solve(self, X, missing_mask):
65-
X = check_array(X, force_all_finite=False)
62+
# X = check_array(X, force_all_finite=False)
6663

6764
observed_mask = ~missing_mask
6865
X_filled = X
6966
for i in range(self.max_iters):
7067
curr_rank = self.rank
71-
tsvd = TruncatedSVD(curr_rank, algorithm=self.svd_algorithm, random_state=self.random_state)
72-
X_reduced = tsvd.fit_transform(X_filled)
73-
X_reconstructed = tsvd.inverse_transform(X_reduced)
68+
U, S, V = partial_svd(X_filled, curr_rank, random_state=self.random_state)
69+
X_reconstructed = U @ np.diag(S) @ V
7470
X_reconstructed = self.clip(X_reconstructed)
7571
mae = masked_mae(
7672
X_true=X,

tensorpack/cmtf.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"""
44

55
import numpy as np
6-
from sklearn.decomposition import TruncatedSVD
6+
from tensorly import partial_svd
77
import tensorly as tl
88
from tensorly.tenalg import khatri_rao
99
from copy import deepcopy
@@ -200,8 +200,6 @@ def initialize_cp(tensor: np.ndarray, rank: int):
200200
factors = [np.ones((tensor.shape[i], rank)) for i in range(tensor.ndim)]
201201
contain_missing = (np.sum(~np.isfinite(tensor)) > 0)
202202

203-
tsvd = TruncatedSVD(n_components=rank)
204-
205203
# SVD init mode whose size is larger than rank
206204
for mode in range(tensor.ndim):
207205
if tensor.shape[mode] >= rank:
@@ -210,7 +208,7 @@ def initialize_cp(tensor: np.ndarray, rank: int):
210208
si = SoftImpute(max_rank=rank)
211209
unfold = si.fit_transform(unfold)
212210

213-
factors[mode] = tsvd.fit_transform(unfold)
211+
factors[mode] = partial_svd(unfold, rank, flip=True)[0]
214212

215213
return tl.cp_tensor.CPTensor((None, factors))
216214

tensorpack/decomposition.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import numpy as np
33
import pandas as pd
44
from numpy.linalg import norm
5-
from sklearn.decomposition import TruncatedSVD
5+
from tensorly import partial_svd
66
from .cmtf import perform_CP, calcR2X
77

88

@@ -19,9 +19,9 @@ def impute_missing_mat(dat):
1919

2020
diff = 1.0
2121
while diff > 1e-3:
22-
tsvd = TruncatedSVD(n_components=min(dat.shape)-1)
23-
scores = tsvd.fit_transform(imp)
24-
loadings = tsvd.components_
22+
U, S, V = partial_svd(imp, min(dat.shape)-1)
23+
scores = U @ np.diag(S)
24+
loadings = V
2525
recon = scores @ loadings
2626
new_diff = norm(imp[miss_idx] - recon[miss_idx]) / norm(recon[miss_idx])
2727
assert new_diff < diff, "Matrix imputation difference is not decreasing"
@@ -48,9 +48,9 @@ def perform_PCA(self, flattenon=0):
4848
if not np.all(np.isfinite(flatData)):
4949
flatData = impute_missing_mat(flatData)
5050

51-
tsvd = TruncatedSVD(n_components=max(self.rrs))
52-
scores = tsvd.fit_transform(flatData)
53-
loadings = tsvd.components_
51+
U, S, V = partial_svd(flatData, max(self.rrs))
52+
scores = U @ np.diag(S)
53+
loadings = V
5454
recon = [scores[:, :rr] @ loadings[:rr, :] for rr in self.rrs]
5555
self.PCAR2X = [calcR2X(c, mIn = flatData) for c in recon]
5656
self.sizePCA = [sum(flatData.shape) * rr for rr in self.rrs]

tensorpack/figureCommon.py

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
"""
22
This file contains functions that are used in multiple figures.
33
"""
4-
import seaborn as sns
5-
from string import ascii_lowercase
64
import matplotlib
7-
from matplotlib import gridspec, pyplot as plt
85

96

107
matplotlib.rcParams["legend.labelspacing"] = 0.2
@@ -19,39 +16,3 @@
1916
matplotlib.rcParams["legend.markerscale"] = 0.7
2017
matplotlib.rcParams["legend.borderpad"] = 0.35
2118
matplotlib.rcParams['font.sans-serif'] = "Arial"
22-
23-
24-
def getSetup(figsize, gridd, multz=None, empts=None):
25-
""" Establish figure set-up with subplots. """
26-
sns.set(style="whitegrid", font_scale=0.7, color_codes=True, palette="colorblind", rc={"grid.linestyle": "dotted", "axes.linewidth": 0.6})
27-
28-
# create empty list if empts isn't specified
29-
if empts is None:
30-
empts = []
31-
32-
if multz is None:
33-
multz = dict()
34-
35-
# Setup plotting space and grid
36-
f = plt.figure(figsize=figsize, constrained_layout=True)
37-
gs1 = gridspec.GridSpec(*gridd, figure=f)
38-
39-
# Get list of axis objects
40-
x = 0
41-
ax = list()
42-
while x < gridd[0] * gridd[1]:
43-
if x not in empts and x not in multz.keys(): # If this is just a normal subplot
44-
ax.append(f.add_subplot(gs1[x]))
45-
elif x in multz.keys(): # If this is a subplot that spans grid elements
46-
ax.append(f.add_subplot(gs1[x: x + multz[x] + 1]))
47-
x += multz[x]
48-
x += 1
49-
50-
return (ax, f)
51-
52-
53-
def subplotLabel(axs):
54-
""" Place subplot labels on figure. """
55-
for ii, ax in enumerate(axs):
56-
ax.text(-0.2, 1.2, ascii_lowercase[ii], transform=ax.transAxes, fontsize=16, fontweight="bold", va="top")
57-

tensorpack/soft_impute.py

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@
1111
# limitations under the License.
1212

1313
import numpy as np
14-
from sklearn.utils.extmath import randomized_svd
15-
from sklearn.utils import check_array
14+
from tensorly import partial_svd
1615

1716
F32PREC = np.finfo(np.float32).eps
1817

@@ -73,7 +72,7 @@ def fill(
7372
inplace : bool
7473
Modify matrix or fill a copy
7574
"""
76-
X = check_array(X, force_all_finite=False)
75+
# X = check_array(X, force_all_finite=False)
7776

7877
if not inplace:
7978
X = X.copy()
@@ -99,7 +98,7 @@ def prepare_input_data(self, X):
9998
Check to make sure that the input matrix and its mask of missing
10099
values are valid. Returns X and missing mask.
101100
"""
102-
X = check_array(X, force_all_finite=False)
101+
# X = check_array(X, force_all_finite=False)
103102
if X.dtype != "f" and X.dtype != "d":
104103
X = X.astype(float)
105104

@@ -251,11 +250,7 @@ def _svd_step(self, X, shrinkage_value, max_rank=None):
251250
"""
252251
if max_rank:
253252
# if we have a max rank then perform the faster randomized SVD
254-
(U, s, V) = randomized_svd(
255-
X,
256-
max_rank,
257-
n_iter=self.n_power_iterations,
258-
random_state=None)
253+
U, s, V = partial_svd(X, max_rank)
259254
else:
260255
# perform a full rank SVD using ARPACK
261256
(U, s, V) = np.linalg.svd(
@@ -273,15 +268,11 @@ def _svd_step(self, X, shrinkage_value, max_rank=None):
273268

274269
def _max_singular_value(self, X_filled):
275270
# quick decomposition of X_filled into rank-1 SVD
276-
_, s, _ = randomized_svd(
277-
X_filled,
278-
1,
279-
n_iter=5,
280-
random_state=None)
271+
_, s, _ = partial_svd(X_filled, 1)
281272
return s[0]
282273

283274
def solve(self, X, missing_mask):
284-
X = check_array(X, force_all_finite=False)
275+
# X = check_array(X, force_all_finite=False)
285276

286277
X_init = X.copy()
287278

tensorpack/test/atyeo.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
from os.path import join, dirname
22
import numpy as np
33
import pandas as pd
4-
from ..cmtf import perform_CP
5-
from ..figureCommon import subplotLabel, getSetup
64
from ..plot import *
7-
from ..decomposition import Decomposition
85

96
path_here = dirname(dirname(__file__))
107

@@ -58,12 +55,3 @@ def createCube():
5855
assert ~np.any(np.all(np.isnan(cube), axis=(1, 2)))
5956

6057
return cube
61-
62-
def sample_figure():
63-
ax, f = getSetup((8, 5), (2, 3))
64-
atyeo = Decomposition(createCube())
65-
atyeo.perform_tfac()
66-
atyeo.perform_PCA()
67-
tfacr2x(ax[0], atyeo)
68-
reduction(ax[1], atyeo)
69-
return f

0 commit comments

Comments
 (0)