Block-wise Gram accumulation of positive random features for large N
Source:R/nmfkc.rff.positive.R
nmfkc.rff.positive.gram.RdThe nmfkc.rff.positive counterpart of
nmfkc.signed.rff.gram: walks the columns of U in
blocks, generates the non-negative feature block
\(\Phi_b\) with the same random map, accumulates
\(S = \Phi\Phi^\top\) (\(D \times D\)) and \(G_0 = Y\Phi^\top\)
(\(P \times D\)), and discards the block, so the \(D \times N\)
feature matrix never exists in memory. Because the features are
non-negative, the returned "nmfkc.gram" object is accepted by
nmfkc (as well as by nmfkc.signed), and the
NMF-LAB membership interpretation of \(B = \Theta\Phi\) is retained.
Arguments
- Y
Non-negative \(P \times N\) response matrix (e.g. one-hot labels).
NAis not allowed.- U
A \(p \times N\) numeric matrix of inputs; columns are samples.
- beta
Positive scalar. Gaussian kernel bandwidth. Ignored when
parsis supplied.- D
Integer. Number of random features. Required (no \(N/2\) default here). Ignored when
parsis supplied.- seed
Optional integer seed for \(\omega\); the caller's stream is restored. Ignored when
parsis supplied.- block.size
Integer. Columns of
Uper block. Default: about 256 MB of features per block (2^25 / Dcolumns), capped atN.- ...
Hidden options
pars(reuse a random map fromnmfkc.rff.positiveor a previous call) andhyperbolic(seenmfkc.rff.positive).
Value
An object of class "nmfkc.gram" with S, G0,
N, D, type = "prf", signed = FALSE,
pars, beta, block.size, n.blocks,
A.block (block generator) and rownames = NULL. Features
for new data: nmfkc.rff.positive(U.new, pars = g$pars)$Z.
References
Choromanski, K. et al. (2021). Rethinking attention with Performers. ICLR. arXiv:2009.14794.
See also
nmfkc.rff.positive, nmfkc,
nmfkc.kernel.gram (Nystr\"om), nmfkc.signed.rff.gram
Examples
# \donttest{
data(iris)
set.seed(1)
idx <- sample(nrow(iris), 100)
mn <- colMeans(iris[idx, 1:4]); sc <- apply(iris[idx, 1:4], 2, sd)
U.train <- t(scale(iris[idx, 1:4], center = mn, scale = sc))
U.test <- t(scale(iris[-idx, 1:4], center = mn, scale = sc))
levs <- levels(iris$Species)
Y.train <- sapply(iris$Species[idx], function(s) as.integer(levs == s))
rownames(Y.train) <- levs
beta <- nmfkc.kernel.beta.nearest.med(U.train)$beta
g <- nmfkc.rff.positive.gram(Y.train, U.train, beta = beta, D = 200,
seed = 1, block.size = 25)
g
#> Gram summary of positive random features (non-negative) for nmfkc()
#> N (samples): 100
#> D (features): 200
#> Y rows (P): 3
#> beta (bandwidth): 5.778
#> blocks: 4 x 25 columns
#> S = A A^T: 200 x 200
#> G0 = Y A^T: 3 x 200
#> Pass as `A` to nmfkc(); use `$pars` with nmfkc.rff.positive() for new data.
res <- nmfkc(Y.train, A = g, rank = 3, verbose = FALSE) # standard NMF-LAB
Z.test <- nmfkc.rff.positive(U.test, pars = g$pars)$Z
pred <- predict(res, newA = Z.test, type = "class")
mean(pred == as.character(iris$Species[-idx]))
#> [1] 0.38
# }