В случае моделей Пуассона я бы также сказал, что приложение часто диктует, будут ли ваши ковариаты действовать аддитивно (что затем будет означать идентификационную ссылку) или мультипликативно в линейном масштабе (что затем будет подразумевать лог-ссылку). Но модели Пуассона с тождественной связью также, как правило, имеют смысл и могут стабильно подходить только в том случае, если на навязанные коэффициенты накладываются ограничения неотрицательности - это можно сделать с помощью nnpois
функции в addreg
пакете R или с помощью nnlm
функции вNNLM
пакет. Поэтому я не согласен с тем, что модели Пуассона следует согласовывать как с идентификационной, так и с журнальной связью, и посмотреть, какая из них в итоге будет иметь лучший AIC, и вывести лучшую модель на основе чисто статистических соображений - скорее, в большинстве случаев это диктуется основная структура проблемы, которую каждый пытается решить, или данные под рукой.
Например, в хроматографии (анализ ГХ / МС) часто измеряют наложенный сигнал из нескольких пиков приблизительно гауссовой формы, и этот наложенный сигнал измеряется с помощью умножителя электронов, что означает, что измеренный сигнал представляет собой счетчик ионов и, следовательно, распределение Пуассона. Поскольку каждый из пиков по определению имеет положительную высоту и действует аддитивно, а шумом является Пуассон, здесь будет уместна неотрицательная модель Пуассона с тождественной связью, а логарифмическая связь - модель Пуассона будет совершенно неверной. В разработке потеря Кулбека-Лейблера часто используется в качестве функции потерь для таких моделей, и минимизация этой потери эквивалентна оптимизации вероятности неотрицательной модели Пуассона с тождественным звеном (есть также другие меры расхождения / потери, такие как расхождение альфа или бета что есть пуассон как частный случай).
Ниже приведен числовой пример, включающий демонстрацию того, что обычная неограниченная тождественная ссылка Пуассона GLM не подходит (из-за отсутствия ограничений неотрицательности), и некоторые подробности о том, как подобрать неотрицательные модели Пуассона с тождественной связью, используяnnpois
здесь, в контексте деконволюции измеренной суперпозиции хроматографических пиков с пуассоновским шумом на них, используя полосчатую ковариатную матрицу, которая содержит сдвинутые копии измеренной формы одного пика. Неотрицательность здесь важна по нескольким причинам: (1) это единственная реалистичная модель для имеющихся данных (пики здесь не могут иметь отрицательную высоту), (2) это единственный способ стабильно согласовать модель Пуассона с тождественной связью (как в противном случае предсказания для некоторых ковариатных значений могут стать отрицательными, что не имеет смысла и приведет к численным проблемам, когда кто-то попытается оценить вероятность), (3) неотрицательность действует для регуляризации проблемы регрессии и значительно помогает получить стабильные оценки (например, Вы, как правило, не получаете проблем с переоснащением, как с обычной неограниченной регрессией,ограничения неотрицательности приводят к более редким оценкам, которые часто ближе к основной истине; для проблемы деконволюции, приведенной ниже, например, производительность примерно такая же, как и для регуляризации LASSO, но без необходимости настройки какого-либо параметра регуляризации. ( Штрафная регрессия L0-псевдонорм все еще работает немного лучше, но с большими вычислительными затратами )
# we first simulate some data
require(Matrix)
n = 200
x = 1:n
npeaks = 20
set.seed(123)
u = sample(x, npeaks, replace=FALSE) # unkown peak locations
peakhrange = c(10,1E3) # peak height range
h = 10^runif(npeaks, min=log10(min(peakhrange)), max=log10(max(peakhrange))) # unknown peak heights
a = rep(0, n) # locations of spikes of simulated spike train, which are assumed to be unknown here, and which needs to be estimated from the measured total signal
a[u] = h
gauspeak = function(x, u, w, h=1) h*exp(((x-u)^2)/(-2*(w^2))) # peak shape function
bM = do.call(cbind, lapply(1:n, function (u) gauspeak(x, u=u, w=5, h=1) )) # banded matrix with peak shape measured beforehand
y_nonoise = as.vector(bM %*% a) # noiseless simulated signal = linear convolution of spike train with peak shape function
y = rpois(n, y_nonoise) # simulated signal with random poisson noise on it - this is the actual signal as it is recorded
par(mfrow=c(1,1))
plot(y, type="l", ylab="Signal", xlab="x", main="Simulated spike train (red) to be estimated given known blur kernel & with Poisson noise")
lines(a, type="h", col="red")
# let's now deconvolute the measured signal y with the banded covariate matrix containing shifted copied of the known blur kernel/peak shape bM
# first observe that regular OLS regression without nonnegativity constraints would return very bad nonsensical estimates
weights <- 1/(y+1) # let's use 1/variance = 1/(y+eps) observation weights to take into heteroscedasticity caused by Poisson noise
a_ols <- lm.fit(x=bM*sqrt(weights), y=y*sqrt(weights))$coefficients # weighted OLS
plot(x, y, type="l", main="Ground truth (red), unconstrained OLS estimate (blue)", ylab="Peak shape", xlab="x", ylim=c(-max(y),max(y)))
lines(x,-y)
lines(a, type="h", col="red", lwd=2)
lines(-a_ols, type="h", col="blue", lwd=2)
# now we use weighted nonnegative least squares with 1/variance obs weights as an approximation of nonnegative Poisson regression
# this gives very good estimates & is very fast
library(nnls)
library(microbenchmark)
microbenchmark(a_wnnls <- nnls(A=bM*sqrt(weights),b=y*sqrt(weights))$x) # 7 ms
plot(x, y, type="l", main="Ground truth (red), weighted nnls estimate (blue)", ylab="Signal (black) & peaks (red & blue)", xlab="Time", ylim=c(-max(y),max(y)))
lines(x,-y)
lines(a, type="h", col="red", lwd=2)
lines(-a_wnnls, type="h", col="blue", lwd=2)
# note that this weighted least square estimate in almost identical to the nonnegative Poisson estimate below and that it fits way faster!!!
# an unconstrained identity-link Poisson GLM will not fit:
glmfit = glm.fit(x=as.matrix(bM), y=y, family=poisson(link=identity), intercept=FALSE)
# returns Error: no valid set of coefficients has been found: please supply starting values
# so let's try a nonnegativity constrained identity-link Poisson GLM, fit using bbmle (using port algo, ie Quasi Newton BFGS):
library(bbmle)
XM=as.matrix(bM)
colnames(XM)=paste0("v",as.character(1:n))
yv=as.vector(y)
LL_poisidlink <- function(beta, X=XM, y=yv){ # neg log-likelihood function
-sum(stats::dpois(y, lambda = X %*% beta, log = TRUE)) # PS regular log-link Poisson would have exp(X %*% beta)
}
parnames(LL_poisidlink) <- colnames(XM)
system.time(fit <- mle2(
minuslogl = LL_poisidlink ,
start = setNames(a_wnnls+1E-10, colnames(XM)), # we initialise with weighted nnls estimates, with approx 1/variance obs weights
lower = rep(0,n),
vecpar = TRUE,
optimizer = "nlminb"
)) # very slow though - takes 145s
summary(fit)
a_nnpoisbbmle = coef(fit)
plot(x, y, type="l", main="Ground truth (red), nonnegative Poisson bbmle ML estimate (blue)", ylab="Signal (black) & peaks (red & blue)", xlab="Time", ylim=c(-max(y),max(y)))
lines(x,-y)
lines(a, type="h", col="red", lwd=2)
lines(-a_nnpoisbbmle, type="h", col="blue", lwd=2)
# much faster is to fit nonnegative Poisson regression using nnpois using an accelerated EM algorithm:
library(addreg)
microbenchmark(a_nnpois <- nnpois(y=y,
x=as.matrix(bM),
standard=rep(1,n),
offset=0,
start=a_wnnls+1.1E-4, # we start from weighted nnls estimates
control = addreg.control(bound.tol = 1e-04, epsilon = 1e-5),
accelerate="squarem")$coefficients) # 100 ms
plot(x, y, type="l", main="Ground truth (red), nonnegative Poisson nnpois estimate (blue)", ylab="Signal (black) & peaks (red & blue)", xlab="Time", ylim=c(-max(y),max(y)))
lines(x,-y)
lines(a, type="h", col="red", lwd=2)
lines(-a_nnpois, type="h", col="blue", lwd=2)
# or to fit nonnegative Poisson regression using nnlm with Kullback-Leibler loss using a coordinate descent algorithm:
library(NNLM)
system.time(a_nnpoisnnlm <- nnlm(x=as.matrix(rbind(bM)),
y=as.matrix(y, ncol=1),
loss="mkl", method="scd",
init=as.matrix(a_wnnls, ncol=1),
check.x=FALSE, rel.tol=1E-4)$coefficients) # 3s
plot(x, y, type="l", main="Ground truth (red), nonnegative Poisson nnlm estimate (blue)", ylab="Signal (black) & peaks (red & blue)", xlab="Time", ylim=c(-max(y),max(y)))
lines(x,-y)
lines(a, type="h", col="red", lwd=2)
lines(-a_nnpoisnnlm, type="h", col="blue", lwd=2)