Solutions 3 - Examples in Singular Value Decomposition

Assignment 1

All functions from previous notebooks are collected in the file ModuleB.jl which contains the module ModuleB.


In [1]:
include("./ModuleB.jl")
using .ModuleB

Assignment 2

You can see the availabe images at http://timholy.github.io/TestImages.jl/.

After installing the package with Pkg.add("TestImages"), the images are located in the directory .julia/packages/TestImages/..../images.


In [4]:
# import Pkg; Pkg.add("TestImages")

In [5]:
using TestImages, Images

In [6]:
varinfo(TestImages)


Out[6]:
name size summary
TestImages 8.344 KiB Module
testimage 0 bytes typeof(testimage)

In [10]:
img=testimage("lighthouse")


Out[10]:

In [11]:
# For example
img[1,1]


Out[11]:

In [12]:
show(img[1,1])


RGB{N0f8}(0.361,0.486,0.6)

In [13]:
# Separate the image into R, G and B components
channels=channelview(img)


Out[13]:
3×512×768 reinterpret(N0f8, ::Array{RGB{N0f8},3}):
[:, :, 1] =
 0.361  0.361  0.376  0.365  0.365  0.369  …  0.663  0.702  0.459  0.443  0.0
 0.486  0.486  0.514  0.498  0.498  0.502     0.682  0.745  0.486  0.467  0.0
 0.6    0.6    0.624  0.62   0.627  0.635     0.627  0.678  0.447  0.439  0.0

[:, :, 2] =
 0.349  0.361  0.353  0.369  0.376  0.376  …  0.745  0.678  0.427  0.443  0.0
 0.475  0.498  0.49   0.506  0.51   0.51      0.776  0.722  0.467  0.467  0.0
 0.588  0.608  0.608  0.624  0.639  0.631     0.725  0.667  0.424  0.439  0.0

[:, :, 3] =
 0.345  0.361  0.361  0.365  0.361  0.365  …  0.843  0.616  0.514  0.486  0.0
 0.478  0.494  0.494  0.498  0.494  0.498     0.871  0.655  0.553  0.525  0.0
 0.588  0.616  0.616  0.62   0.616  0.62      0.82   0.612  0.518  0.49   0.0

...

[:, :, 766] =
 0.329  0.357  0.357  0.349  0.361  0.357  …  0.208  0.259  0.192  0.173  0.0
 0.463  0.486  0.482  0.475  0.486  0.482     0.255  0.31   0.231  0.204  0.0
 0.518  0.569  0.596  0.588  0.6    0.596     0.286  0.341  0.255  0.22   0.0

[:, :, 767] =
 0.345  0.349  0.349  0.353  0.361  0.365  …  0.239  0.259  0.173  0.165  0.0
 0.482  0.482  0.486  0.49   0.498  0.502     0.286  0.306  0.212  0.192  0.0
 0.525  0.565  0.596  0.6    0.608  0.612     0.325  0.349  0.235  0.2    0.0

[:, :, 768] =
 0.349  0.369  0.361  0.345  0.349  0.365  …  0.267  0.267  0.184  0.18   0.0
 0.49   0.498  0.498  0.478  0.486  0.502     0.31   0.31   0.22   0.208  0.0
 0.529  0.58   0.608  0.588  0.596  0.612     0.353  0.353  0.247  0.22   0.0

In [14]:
R=channels[1,:,:]
G=channels[2,:,:]
B=channels[3,:,:]


Out[14]:
512×768 Array{N0f8,2} with eltype Normed{UInt8,8}:
 0.6    0.588  0.588  0.624  0.616  …  0.537  0.525  0.518  0.525  0.529
 0.6    0.608  0.616  0.608  0.608     0.557  0.576  0.569  0.565  0.58 
 0.624  0.608  0.616  0.616  0.616     0.592  0.588  0.596  0.596  0.608
 0.62   0.624  0.62   0.616  0.608     0.58   0.576  0.588  0.6    0.588
 0.627  0.639  0.616  0.62   0.62      0.596  0.592  0.6    0.608  0.596
 0.635  0.631  0.62   0.62   0.624  …  0.596  0.596  0.596  0.612  0.612
 0.635  0.62   0.624  0.62   0.62      0.596  0.592  0.6    0.608  0.612
 0.635  0.62   0.608  0.624  0.62      0.596  0.6    0.6    0.588  0.616
 0.627  0.631  0.631  0.624  0.624     0.596  0.6    0.6    0.596  0.604
 0.62   0.631  0.627  0.643  0.624     0.608  0.616  0.604  0.596  0.604
 0.643  0.631  0.624  0.635  0.631  …  0.592  0.608  0.608  0.596  0.592
 0.659  0.624  0.624  0.635  0.635     0.596  0.592  0.592  0.596  0.608
 0.643  0.651  0.639  0.635  0.631     0.592  0.604  0.588  0.6    0.624
 ⋮                                  ⋱                ⋮                  
 0.137  0.125  0.145  0.196  0.31   …  0.29   0.224  0.22   0.204  0.204
 0.118  0.118  0.118  0.153  0.2       0.314  0.271  0.239  0.231  0.224
 0.11   0.122  0.153  0.145  0.082     0.333  0.314  0.325  0.314  0.294
 0.114  0.125  0.133  0.192  0.267     0.333  0.31   0.267  0.251  0.239
 0.141  0.208  0.314  0.478  0.498     0.298  0.314  0.275  0.263  0.294
 0.263  0.447  0.545  0.443  0.349  …  0.318  0.298  0.325  0.333  0.333
 0.443  0.494  0.557  0.561  0.569     0.333  0.314  0.329  0.333  0.318
 0.627  0.725  0.82   0.725  0.624     0.275  0.286  0.286  0.325  0.353
 0.678  0.667  0.612  0.529  0.494     0.341  0.341  0.341  0.349  0.353
 0.447  0.424  0.518  0.659  0.643     0.298  0.282  0.255  0.235  0.247
 0.439  0.439  0.49   0.545  0.592  …  0.22   0.22   0.22   0.2    0.22 
 0.0    0.0    0.0    0.0    0.0       0.0    0.0    0.0    0.0    0.0  

In [16]:
# Let us take a look at the red component
colorview(Gray,G)


Out[16]:

In [17]:
using LinearAlgebra

In [18]:
# Compute the SVD of each component
UR,σR,VR=svd(R)
UG,σG,VG=svd(G)
UB,σB,VB=svd(B);

In [19]:
# Plot the singular values
using Plots
x=collect(1:minimum(size(img)))
plot(x,[σR σG σB])


Out[19]:
0 100 200 300 400 500 0 100 200 300 y1 y2 y3

In [24]:
# Watch the compression quality
k=150
Rc=UR[:,1:k]*Diagonal(σR[1:k])*VR[:,1:k]'
Gc=UG[:,1:k]*Diagonal(σG[1:k])*VG[:,1:k]'
Bc=UB[:,1:k]*Diagonal(σB[1:k])*VB[:,1:k]'
colorview(RGB, Rc, Gc, Bc)


Out[24]:

Assignment 3


In [25]:
# Part of the preamble of lapack.jl
const liblapack = Base.liblapack_name
import LinearAlgebra.BLAS.@blasfunc
# import ..LinAlg: BlasFloat, Char, BlasInt, LAPACKException,
    # DimensionMismatch, SingularException, PosDefException, chkstride1, chksquare
import LinearAlgebra.BlasInt
function chklapackerror(ret::BlasInt)
    if ret == 0
        return
    elseif ret < 0
        throw(ArgumentError("invalid argument #$(-ret) to LAPACK call"))
    else # ret > 0
        throw(LAPACKException(ret))
    end
end


Out[25]:
chklapackerror (generic function with 1 method)

In [29]:
for (gesvj, elty) in
    ((:dgesvj_,:Float64),
    (:sgesvj_,:Float32))
    @eval begin
        function gesvj!(A::Array{$elty})
            joba='G'
            jobu='U'
            jobv='V'
            m,n = size(A)
            lda=m
            sva=Array{$elty}(undef,n)
            mv=1
            V=Array{$elty}(undef,n,n)
            ldv=n
            lwork=max(6,m+n)
            work = Array{$elty}(undef,lwork)
            info = Array{BlasInt}(undef,1)
            ccall((@blasfunc($gesvj), liblapack), Cvoid,
            (Ref{UInt8}, Ref{UInt8}, Ref{UInt8}, 
            Ref{BlasInt}, Ref{BlasInt}, Ptr{$elty},
            Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt},
            Ptr{$elty}, Ref{BlasInt}, Ptr{$elty},
            Ref{BlasInt}, Ref{BlasInt}),
                joba, jobu, jobv, 
                m, n, A, 
                lda, sva, mv,
                V, ldv, work, 
                lwork, info)
                chklapackerror(info[])
            A, sva, V
        end
    end
end

In [30]:
# Small, strongly scaled matrix
m=20
n=15
using Random
Random.seed!(421)
B=rand(m,n)
D=exp.(80*(rand(n).-0.5))
A=B*Diagonal(D);

In [31]:
U,σ,V=ModuleB.myJacobiR(A)
U₁,σ₁,V₁=gesvj!(copy(A))
(sort(σ,rev=true)-σ₁)./σ₁


Out[31]:
15-element Array{Float64,1}:
  4.268401770476411e-16 
  6.078735165862111e-16 
  5.621953385178811e-16 
  5.422078468025897e-16 
  4.937338474602337e-16 
  2.654059021360239e-16 
  1.0452054006950505e-15
  5.417485920556403e-16 
  4.834325068703124e-16 
  6.664460448973878e-16 
  5.623499103704912e-16 
  3.526050739825378e-16 
 -6.571825807079988e-16 
  0.0                   
  0.0                   

In [33]:
# Timing for large matrices
n=1000
A=rand(n,n)
@time svd(A);
@time gesvj!(A);


  1.535576 seconds (17 allocations: 45.899 MiB, 20.55% gc time)
  6.054055 seconds (10 allocations: 7.653 MiB)

In [ ]: