第6章 行列分解

80

svd.r <- function(z, r) {
  n <- min(nrow(z), ncol(z))
  ss <- svd(z) 
  return(ss$u %*% diag(c(ss$d[1:r], rep(0, n - r))) %*% ## 空欄(1) ##)
}

## r を 2 以上に限定するなら以下でもよい。R言語の仕様で,行列とベクトルは違う扱いになる。
svd.r <- function(z, r) {
  ss <- svd(z)
  return(ss$u[, 1:r] %*% diag(ss$d[1:r]) %*% ## 空欄(2) ##)
}
m <- 100
n <- 80
z <- matrix(rnorm(m * n), nrow = m) 
F.norm <- NULL
for (r in 1:n) {
  m <- svd.r(z, r)
  F.norm <- c(F.norm, norm(z - m, "F"))
}
plot(1:n, F.norm, type = "l", xlab = "階数", ylab = "Frobenius ノルム")

81

library(jpeg)

image <- readJPEG('lion.jpg')
rank.seq <- c(2, 5, 10, 20, 50, 100)
mat <- array(0, dim = c(nrow(image), ncol(image), 3))
for (j in rank.seq) {
  for (i in 1:3)
    mat[, , i] <- svd.r(image[, , i], j)
  writeJPEG(mat, paste("compressed/lion_compressed", "_svd_rank_", j, ".jpg', sep="))
}

82

library(jpeg)

mat.r <- function(z, mask, r) {
  z <- as.matrix(z)
  min <- Inf
  m <- nrow(z)
  n <- ncol(z)
  for (j in 1:5) {
    guess <- matrix(rnorm(m * n), nrow = m)
    for (i in 1:10)
      guess <- svd.r(mask * z + (1 - mask) * guess, r)
    value <- norm(mask * (z - guess), "F")
    if (value < min) {
      min.mat <- ## 空欄(1) ##
      min <- ## 空欄(2) ##
    }
  }
  return(min.mat)
}

image <- readJPEG('lion.jpg')
m <- nrow(image)
n <- ncol(image)
mask <- matrix(rbinom(m * n, 1, 0.5), nrow = m)
rank.seq <- c(2, 5, 10, 20, 50, 100)
mat <- array(0, dim = c(nrow(image), ncol(image), 3))
for (j in rank.seq) {
  for (i in 1:3)
    mat[, , i] <- mat.r(image[, , i], mask, j)
  writeJPEG(mat, paste("compressed/lion_compressed", "_mat_rank_", j, ".jpg', sep="))
}

87

soft.svd <- function(lambda, z) {
  n <- ncol(z)
  ss <- svd(z)
  dd <- pmax(ss$d - lambda, 0)
  return(## 空欄 ##)
}
library(jpeg)

mat.lasso <- function(lambda, z, mask) {
  z <- as.matrix(z)
  m <- nrow(z)
  n <- ncol(z)
  guess <- matrix(rnorm(m * n), nrow = m)
  for (i in 1:20)
    guess <- soft.svd(lambda, mask * z + (1 - mask) * guess)
  return(guess)
}

image <- readJPEG('lion.jpg')
m <- nrow(image[, , 1])
n <- ncol(image[, , 1])
p <- 0.5
lambda <- 0.5
mat <- array(0, dim = c(m, n, 3))
mask <- matrix(rbinom(m * n, 1, p), ncol = n)
for (i in 1:3)
  mat[, , i] <- mat.lasso(lambda, image[, , i], mask)
writeJPEG(mat, paste("compressed/lion_compressed", "_mat_soft.jpg', sep="))