Compressed svd algorithm implementation

Picking the first k eigen values picked the smallest k, which you can fix by sorting them in reverse order. Here’s working code:

import TestImages
import Images
import ImageInTerminal
import LinearAlgebra

function compressed_svd(X::AbstractMatrix, k::Int, p::Int = 10)
    m, n = size(X)
    l = k + p
    Φ = rand(l, m)
    Y = Φ * X
    B = Y * Y'
    B = 0.5 * (B + B')
    D, T = LinearAlgebra.eigen(B; sortby = λ -> -λ)
    D, T = D[1:k], T[:, 1:k]
    S̃⁻¹ = LinearAlgebra.Diagonal(1 ./ sqrt.(D))
    Ṽ = Y' * T * S̃⁻¹
    Ũ = X * Ṽ
    F = LinearAlgebra.svd(Ũ)
    V = Ṽ * F.V
    return F.U, LinearAlgebra.Diagonal(F.S), V
end 

image = TestImages.testimage("mandrill")
gray_image = Images.Gray.(image);
image_matrix = Images.channelview(gray_image);
U, S, V = compressed_svd(image_matrix, 20);
M = Images.clamp01!(U * S * V');
Images.colorview(Images.Gray, M)
1 Like