# Higher order SVD in Julia like Numpy?

Hello all

I was wondering if there is any way to do higher order SVD in Julia using `LinearAlgebra.jl` like you can using numpy.linalg.svd or should I just use PyCall? I tried with `LinearAlgebra.svd` but it didn’t work out and I couldn’t find in the docs how to do it -

``````julia> A = randn(3, 5, 2)
3×5×2 Array{Float64, 3}:
[:, :, 1] =
1.69017   0.539516  -0.436762  -0.882562   2.28308
-0.180177  0.122244  -0.760002  -0.805284   1.15463
0.218088  0.524262   1.12136   -2.33447   -0.706637

[:, :, 2] =
0.850423  -1.12059    0.30392    -1.32743    -0.394143
0.296605   0.766331  -0.25429     0.0635182   0.0745694
-0.568156  -1.4385     0.0120621   1.66298     1.0844

julia> svd(A)
ERROR: MethodError: no method matching svd(::Array{Float64, 3})
Closest candidates are:
svd(::StridedVecOrMat{T}; full, alg) where T<:Union{Float16, ComplexF16} at ~/.julia/juliaup/julia-1.8.0-rc3+0.x64/share/julia/stdlib/v1.8/LinearAlgebra/src/svd.jl:181
svd(::StridedMatrix{T}, ::StridedMatrix{T}) where T<:Union{Float32, Float64, ComplexF32, ComplexF64} at ~/.julia/juliaup/julia-1.8.0-rc3+0.x64/share/julia/stdlib/v1.8/LinearAlgebra/src/svd.jl:407
svd(::StridedVecOrMat{T}; full, alg) where T at ~/.julia/juliaup/julia-1.8.0-rc3+0.x64/share/julia/stdlib/v1.8/LinearAlgebra/src/svd.jl:178
...
Stacktrace:
[1] top-level scope
@ REPL[4]:1
``````

Same thing in python -

``````In [1]: import numpy as np

In [2]: A = np.random.randn(3, 5, 2)

In [3]: np.linalg.svd(A)
Out[3]:
(array([[[-0.6037455 ,  0.58416878,  0.2178343 , -0.36421969,
0.33783197],
[ 0.32082226, -0.42888505,  0.1985067 , -0.49056635,
0.65808088],
[ 0.25303468,  0.13119474,  0.92420027,  0.16216266,
-0.19575117],
[-0.4705167 , -0.38054641,  0.15731977,  0.655918  ,
0.42287178],
[ 0.49714378,  0.55926453, -0.18506123,  0.41250882,
0.48544831]],

[[-0.53278136,  0.63028902, -0.24075323,  0.4968516 ,
-0.11855861],
[-0.5110045 , -0.19041643, -0.59981223, -0.58222151,
0.06212399],
[-0.67157959, -0.32594425,  0.66462678,  0.00804075,
-0.0307863 ],
[-0.03712789, -0.67049536, -0.37229753,  0.63951442,
0.03838423],
[-0.05119373,  0.10331337,  0.04392   ,  0.07150708,
0.98977943]],

[[-0.50891794,  0.66685684,  0.31052877, -0.10016269,
0.43571069],
[-0.41478297, -0.66256106, -0.02431718, -0.43413115,
0.44710934],
[ 0.11320181, -0.25154376,  0.9476955 ,  0.07824908,
-0.14021911],
[-0.44217126, -0.22985906, -0.06724939,  0.86055279,
0.08109132],
[ 0.60052273, -0.01433001,  0.018202  ,  0.2341443 ,
0.76420693]]]),
array([[2.27220514, 0.61766628],
[3.57499854, 1.38367195],
[2.60157849, 2.01610413]]),
array([[[ 0.42173425, -0.90671948],
[-0.90671948, -0.42173425]],

[[ 0.60493221, -0.79627697],
[ 0.79627697,  0.60493221]],

[[ 0.63651737, -0.77126237],
[ 0.77126237,  0.63651737]]]))
``````
1 Like

To be clear, this is just iterating the normal SVD for matrices over each slice of the array, right, not a generalization of SVD for higher-order tensors?

2 Likes

I need a generalization of SVD to higher order tensors. I apologize if I’m missing something, I am just starting to learn about higher order SVD and tensor networks, so I was unsure what `numpy.linalg.svd` was doing. I found ITensors.jl which seems to be doing what I require. It seems I got confused and just now realised `numpy.linalg.svd` was doing the iterative approach rather than a generalized SVD of higher-order tensors.

1 Like