7

I see that the documentation for both sklearn.decomposition.TruncatedSVD and scipy.sparse.linalg.svds mention that they both perform SVD for sparse matrices. What is the difference between them?

Thanks.

abhinavkulkarni
  • 2,284
  • 4
  • 36
  • 54

2 Answers2

19

TruncatedSVD is more feature-rich. It has the scikit-learn API, so you can put it in a sklearn.Pipeline object and call transform on a new matrix instead of having to figure out the matrix multiplications yourself. It offers two algorithms: either a fast randomized SVD solver (the default), or scipy.sparse.svds.

(Full disclosure: I wrote TruncatedSVD.)

Fred Foo
  • 355,277
  • 75
  • 744
  • 836
  • 1
    I think it's just confusing because the name "TruncatedSVD" seems to imply it might not use standard SVD methods at all. Based on your answer it sounds like this is in fact just SVD at the core? – Jason F Nov 14 '14 at 18:40
  • 1
    @JasonF SciPy's `svds` *is* a truncated SVD solver. It cannot compute the full SVD; its maximum number of components in the number of columns in the input, minus one. – Fred Foo Nov 15 '14 at 15:17
  • Can I get U,S,V matrices from it? Could not figure out. – Moonwalker May 31 '15 at 11:50
3

There are doing the same

#check how to use TRuncatedSVD
X=[[1,2,3],[1,4,2],[4,1,7],[5,6,8]]

# TRUNCATED SVD
from sklearn.decomposition import TruncatedSVD
svd = TruncatedSVD(n_components=2, n_iter=7, random_state=42)

US=svd.fit_transform(X)

V=svd.components_
S=svd.singular_values_ 
print('u,s,v', US,S,V)
print('X_restored dot way',np.round(np.dot(US,V),1),'svdinverse way',np.round(svd.inverse_transform(U),1))

# LINALG SVD

U1,S1,V1=np.linalg.svd(X)

print('u1,s1,v1 remark negative mirrored',U1[:,:2]*S1[:2],V1[:2,:])
print('X restored u1,s1,v1, 2 components',np.round( np.dot( U1[:,:2]*S1[:2],V1[:2,:] ),1 ) ) 

# sparse svd
from scipy.sparse import csc_matrix
from scipy.sparse.linalg import svds, eigs
A = csc_matrix(X, dtype=float)

u2, s2, vt2 = svds(A, k=2)

print('sparse reverses !',u2*s2,vt2)
print('x restored',np.round( np.dot(u2*s2,vt2),1) )

RESULT

    u,s,v [[ 3.66997034 -0.34754761]
 [ 3.82764223 -2.51681397]
 [ 7.61154768  2.83860088]
 [11.13470337 -0.96070751]] [14.49264657  3.92883644] [[ 0.44571865  0.46215842  0.76664495]
 [ 0.23882889 -0.88677195  0.39572247]]
X_restored dot way
 [[1.6 2.  2.7]
 [1.1 4.  1.9]
 [4.1 1.  7. ]
 [4.7 6.  8.2]]
svdinverse way
 [[1.6 2.  2.7]
 [1.1 4.  1.9]
 [4.1 1.  7. ]
 [4.7 6.  8.2]]
u1,s1,v1 remark negative mirrored
 [[ -3.66997034   0.34754761]
 [ -3.82764223   2.51681397]
 [ -7.61154768  -2.83860088]
 [-11.13470337   0.96070751]] [[-0.44571865 -0.46215842 -0.76664495]
 [-0.23882889  0.88677195 -0.39572247]]
X restored u1,s1,v1, 2 components
 [[1.6 2.  2.7]
 [1.1 4.  1.9]
 [4.1 1.  7. ]
 [4.7 6.  8.2]]
sparse reverses !
 [[-0.34754761  3.66997034]
 [-2.51681397  3.82764223]
 [ 2.83860088  7.61154768]
 [-0.96070751 11.13470337]]
 [[ 0.23882889 -0.88677195  0.39572247]
 [ 0.44571865  0.46215842  0.76664495]]
x restored
 [[1.6 2.  2.7]
 [1.1 4.  1.9]
 [4.1 1.  7. ]
 [4.7 6.  8.2]]
[[-0.25322982  0.0884607   0.88223679]
 [-0.26410926  0.64060034  0.16752502]
 [-0.52520067 -0.72250421  0.11259767]
 [-0.76830021  0.24452723 -0.42534148]]
 [14.49264657  3.92883644  0.72625043]
 [[-0.44571865 -0.46215842 -0.76664495]
 [-0.23882889  0.88677195 -0.39572247]
 [-0.86272571 -0.00671608  0.50562757]]
 [[1. 2. 3.]
 [1. 4. 2.]
 [4. 1. 7.]
 [5. 6. 8.]]