Как рекомендует @minem, вы можете использовать пакет Rmpfr .Вот один из способов применить его к вашему случаю.
Сначала переместите множители внутри экспоненты числителя, используя тот факт, что a * exp (b) = exp (b + log (a)).Затем переписайте функцию density
, чтобы вычислить числитель журнала:
log_numerator <- function(nc, yc, X, beta, sig, k, lambda){
v <- yc - X %*% beta[,k]
res <- -sum(v*v)/(2*sig[k]) - (nc/2)*log(2*pi*sig[k]) + log(lambda[k])
drop(res)
}
Обратите внимание, что lambda
теперь передается этой функции.Также обратите внимание, что мы можем вычислить точечное произведение вектора Y - X * бета, как показано.
Теперь мы можем сгенерировать некоторые данные.Здесь я исправляю c и просто k = 1: 2.
set.seed(1)
n_c <- 340
y_c <- rnorm(340)
dat <- data.frame(fac = sample(letters[1:11], 340, replace = TRUE)
X_c <- model.matrix(~ fac, data = dat)
beta <- matrix(runif(22, -10, 10), 11, 2)
sigma <- c(21.694381, 4.267277)
lambda <- c(0.5, 0.5)
Используя вашу функцию плотности, мы имеем
x1 <- lambda[1] *density(n_c, y_c,X_c,beta,sigma,1)
y1 <- lambda[2] *density(n_c, y_c,X_c,beta,sigma,2)
x1
# [1] +exp(-1738.4)
y1
# [1] +exp(-1838.7)
as.numeric(y1/sum(x1, y1))
# [1] 2.780805e-44
Используя функцию числового логарифма, мы имеем
p <- 40
x <- mpfr(log_numerator(n_c, y_c,X_c,beta,sigma,1, lambda), p)
y <- mpfr(log_numerator(n_c, y_c,X_c,beta,sigma,2, lambda), p)
x
# 1 'mpfr' number of precision 40 bits
# [1] -1738.379327798
y
# 1 'mpfr' number of precision 40 bits
# [1] -1838.67033143
exp(y)/sum(exp(x), exp(y))
# 1 'mpfr' number of precision 53 bits
# [1] 2.780805017186589e-44
Так что, конечно, mpfr
можно использовать для получения эквивалентных результатов, но без лучшего тестового кода сложно проверить время.
Вы также можете повысить эффективность, используя больше векторизации.Например, мы можем векторизовать log_numerator
по k:
log_numerator2 <- function(nc, yc, X, beta, sig, lambda){
M <- yc - X %*% beta
res <- -colSums(M*M)/(2*sig) - (nc/2)*log(2*pi*sig) + log(lambda)
drop(res)
}
z <- log_numerator2(n_c, y_c, X_c, beta, sigma, lambda)
z
# [1] -1738.379 -1838.670
Теперь предположим, что у нас есть числовые логарифмы в матрице ac на k, для иллюстрации предположим, что все c имеют те же значения, что и z
,
log_num <- mpfr(matrix(z, byrow = TRUE, 3, 2), p)
Вы можете вычислить отношения следующим образом
num <- exp(log_num)
denom <- apply(num, 1, sum) # rowSums not implemented for mpfr
num/denom
# 'mpfrMatrix' of dim(.) = (3, 2) of precision 53 bits
# [,1] [,2]
# [1,] 1.000000000000000 2.780805017186589e-44
# [2,] 1.000000000000000 2.780805017186589e-44
# [3,] 1.000000000000000 2.780805017186589e-44