Setup
The smoothLRC method uses a smoothing parameter (\(\lambda\)) and a rank parameter (\(k\)) to produce results. This article demonstrates the selection of these parameters.
Load Data
Using the spatialLIBD package, we’ll load sample 151671 from the DLPFC data.
sample <- "151671"
sce <- spatialLIBD::fetch_data(type = "sce")
sce <- sce[, sce$sample_name == sample]
Parameter Grid
Here we’ll consider \(\lambda=(5, 10, 15)\) and \(k=(10, 20)\). Further, we’ll use 100 pixels as a test size.
lambdas <- c(5, 10, 15)
ks <- c(10, 20)
parameter_grid <- expand.grid(lambda = lambdas, k = ks)
test_size <- 100
Cross-Validation
Next, we’ll use cross-validation to select the optimal parameter values.
metrics <- NULL
for(combo in 1:nrow(parameter_grid)){
print(parameter_grid[combo,])
combination <- smooth_cv(sce, lambda = parameter_grid[combo,"lambda"], k = parameter_grid[combo,"k"], test_size, maxiter = 5)
metrics <- rbind(metrics, tibble(lambda = parameter_grid[combo,"lambda"],
k = parameter_grid[combo,"k"],
penal_lik = combination$penal_like,
cv_like = combination$cv_like)
)
}
#> lambda k
#> 1 5 10
#> [1] "Initializing components..."
#> [1] "Running smoothLRC on training set..."
#> iteration: 1 | convergence: 0.422554 | 0.0563444 | 1
#> iteration: 2 | convergence: 0.173078 | 0.0404936 | 0.00987567
#> iteration: 3 | convergence: 0.163679 | 0.0450668 | 0.0102672
#> iteration: 4 | convergence: 0.175742 | 0.0471282 | 0.0110242
#> iteration: 5 | convergence: 0.182077 | 0.0482414 | 0.0120774
#> [1] "Compute neighborhood likelihood..."
#> [1] "Done!"
#> lambda k
#> 2 10 10
#> [1] "Initializing components..."
#> [1] "Running smoothLRC on training set..."
#> iteration: 1 | convergence: 0.422057 | 0.0554037 | 1
#> iteration: 2 | convergence: 0.164508 | 0.0401319 | 0.00985858
#> iteration: 3 | convergence: 0.161535 | 0.0453195 | 0.010362
#> iteration: 4 | convergence: 0.186979 | 0.0486879 | 0.0112138
#> iteration: 5 | convergence: 0.184922 | 0.0508453 | 0.012346
#> [1] "Compute neighborhood likelihood..."
#> [1] "Done!"
#> lambda k
#> 3 15 10
#> [1] "Initializing components..."
#> [1] "Running smoothLRC on training set..."
#> iteration: 1 | convergence: 0.42013 | 0.0539799 | 1
#> iteration: 2 | convergence: 0.167513 | 0.0398524 | 0.00986839
#> iteration: 3 | convergence: 0.176619 | 0.0454105 | 0.0104753
#> iteration: 4 | convergence: 0.191349 | 0.0489113 | 0.0113943
#> iteration: 5 | convergence: 0.181778 | 0.0511128 | 0.012534
#> [1] "Compute neighborhood likelihood..."
#> [1] "Done!"
#> lambda k
#> 4 5 20
#> [1] "Initializing components..."
#> [1] "Running smoothLRC on training set..."
#> iteration: 1 | convergence: 0.496827 | 0.0727383 | 1
#> iteration: 2 | convergence: 0.234482 | 0.0531852 | 0.0114419
#> iteration: 3 | convergence: 0.209897 | 0.0595182 | 0.0125506
#> iteration: 4 | convergence: 0.185418 | 0.0596158 | 0.0143264
#> iteration: 5 | convergence: 0.183947 | 0.0612591 | 0.0167131
#> [1] "Compute neighborhood likelihood..."
#> [1] "Done!"
#> lambda k
#> 5 10 20
#> [1] "Initializing components..."
#> [1] "Running smoothLRC on training set..."
#> iteration: 1 | convergence: 0.492975 | 0.0694401 | 1
#> iteration: 2 | convergence: 0.227639 | 0.0526918 | 0.0111891
#> iteration: 3 | convergence: 0.2107 | 0.0592167 | 0.012326
#> iteration: 4 | convergence: 0.191362 | 0.0600496 | 0.0141495
#> iteration: 5 | convergence: 0.191143 | 0.0630135 | 0.0165308
#> [1] "Compute neighborhood likelihood..."
#> [1] "Done!"
#> lambda k
#> 6 15 20
#> [1] "Initializing components..."
#> [1] "Running smoothLRC on training set..."
#> iteration: 1 | convergence: 0.491289 | 0.0671663 | 1
#> iteration: 2 | convergence: 0.238924 | 0.052163 | 0.0110855
#> iteration: 3 | convergence: 0.201901 | 0.0582762 | 0.0122061
#> iteration: 4 | convergence: 0.189654 | 0.0588165 | 0.0140169
#> iteration: 5 | convergence: 0.187515 | 0.0622647 | 0.0163196
#> [1] "Compute neighborhood likelihood..."
#> [1] "Done!"
metrics %>%
ggplot(aes(x = lambda, y = cv_like)) +
geom_point() +
geom_line() +
facet_wrap(~k) +
ylab("CV Likelihood")
metrics %>%
group_by(k) %>%
slice_max(order_by = cv_like, n = 1) %>%
ungroup() %>%
mutate(Selected = ifelse(penal_lik == max(penal_lik), "Yes", "No")) %>%
ggplot(aes(x = k, y = penal_lik, label = lambda)) +
geom_point() +
geom_line() +
geom_label(aes(color = Selected)) +
ylab("Penalized Likelihood")
We can see that using the recommend procedure, the selected combination is (\(\lambda=15\), \(k=20\)). In practice, we recommend running for a much larger number of iterations (e.g. 1,000) and looking over a larger parameter space.