三個樣例各自是negative binomial迴歸(過離散的泊松數據)。gamma迴歸(右偏的連續數據)和beta-binomial迴歸(過離散的二項數據)。css
現在若是咱們手頭有服從負二項分佈的響應變量y以及k個解釋變量X。改用方程形式表示即:git
# 載入包
library(arm) # 利用裏面的invlogit函數
library(emdbook) # 利用裏面的rbetabinom function函數
library(rstanarm) # 利用launch_shinystan函數
# 生成服從負二項分佈的仿真數據
# 解釋變量
N <- 100 # 樣本量
dat <- data.frame(x1 = runif(N, -2, 2), x2 = runif(N, -2, 2))
# 模型
X <- model.matrix( ~ x1*x2, dat)
K <- dim(X)[2] # 迴歸係數維度
# 迴歸的斜率
betas <- runif(K, -1, 1)
# 設定仿真數據的過離散度
ph i<- 5
# 生成響應變量
y_nb < -rnbinom(100, size = phi, mu = exp(X%*%betas))
# 擬合模型
m_nb<-stan(file = "neg_bin.stan", data = list(N=N, K=K, X=X, y=y_nb), pars = c("beta","phi","y_rep"))
# 利用shinystan診斷模型
launch_shinystan(m_nb)
一些選項超出了我有限的知識範圍(如對數後驗vs樣本階梯大小),因此我一般關注迴歸係數的後驗分佈(Diagnose -> NUTS (plots) -> By model parameter),出現的柱形圖應該比較接近正態。我也會關注後驗預測檢驗(Diagnose -> PPcheck -> Distribution of observed data vs replications)。y_rep的分佈應當與觀測數據一樣。瀏覽器
# 計算後驗預測值和對應的可信區間
post <- as.array(m_nb)
# 咱們來看看x2在x3的三個取值上的變化性
new_X <- model.matrix( ~ x1*x2, expand.grid(x2=seq(-2, 2, length=10), x1=c(min(dat$x1), mean(dat$x1), max(dat$x1))))
# 計算每個樣本的預測值
pred <- apply(post[, , 1:4], c(1, 2), FUN = function(x) new_X%*%x)
# 每條鏈會存在不一樣的矩陣,並將信息重組存於一個矩陣內
dim(pred) <- c(30, 4000)
# 提取預測中位數和95%可信區間
pred_int <- apply(pred, 1, quantile, probs=c(0.025, 0.5, 0.975))
# 繪圖
plot(dat$x2, y_nb, pch=16)
lines(new_X[1:10,3], exp(pred_int[2,1:10]), col="orange", lwd=5)
lines(new_X[1:10,3], exp(pred_int[1,1:10]), col="orange", lwd=3, lty=2)
lines(new_X[1:10,3], exp(pred_int[3,1:10]), col="orange", lwd=3, lty=2)
lines(new_X[1:10,3], exp(pred_int[2,11:20]), col="red", lwd=5)
lines(new_X[1:10,3], exp(pred_int[1,11:20]), col="red", lwd=3, lty=2)
lines(new_X[1:10,3], exp(pred_int[3,11:20]), col="red", lwd=3, lty=2)
lines(new_X[1:10,3], exp(pred_int[2,21:30]), col="blue", lwd=5)
lines(new_X[1:10,3], exp(pred_int[1,21:30]), col="blue", lwd=3, lty=2)
lines(new_X[1:10,3], exp(pred_int[3,21:30]), col="blue", lwd=3, lty=2)
legend("topleft", legend=c("Min", "Mean", "Max"), ncol=3, col = c("orange", "red", "blue"), lwd = 3, bty="n", title="Value of x1")
上述模型在連接空間裏作出了預測,若是咱們想把結果繪製於響應空間,咱們要利用連接函數的反函數(本例中是指數函數)來將預測值變換回去。markdown
這一類數據可以利用對數正態分佈(將響應變量作對數變換)或者gamma分佈建模。此處我將利用gamma分佈擬合數據,若是咱們有服從gamma分佈的對應變量y和一些解釋變量X,方程形式例如如下:app
# 生成服從gamma分佈的數據
mus <- exp(X%*%betas)
y_g <- rgamma(100, shape = mus**2/phi, rate = mus/phi)
# 模型
m_g <- stan(file = "gamma.stan", data = list(N=N, K=K, X=X, y=y_g), pars = c("betas","phi","y_rep"))
# 模型檢驗
launch_shinystan(m_g)
# 生成Beta-Binomial數據
W <- rep(20, 100) # 試驗次數
y_bb <- rbetabinom(100, prob = invlogit(X%*%betas), size = W, theta = phi)
# 模型
m_bb <- stan(file = "beta_bin.stan", data = list(N=N, W=W, K=K, X=X, y=y_bb), pars=c("betas", "phi", "y_rep"))
# 模型檢驗
launch_shinystan(m_bb)
# 計算後驗預測值和置信區間
post<-as.array(m_bb) # 後驗抽樣
# 後驗預測值
pred<-apply(post[,,1:4],c(1,2),FUN = function(x) new_X%*%x)
# 每條鏈都存在重組信息的不一樣矩陣裏
dim(pred)<-c(30,4000)
# 獲得後驗越策值的中位數和95%置信區間
pred_int<-apply(pred,1,quantile,probs=c(0.025,0.5,0.975))
# 繪圖
plot(dat$x2, y_bb, pch = 16)
lines(new_X[1:10,3], 20*invlogit(pred_int[2,1:10]), col="orange", lwd=5)
lines(new_X[1:10,3], 20*invlogit(pred_int[1,1:10]), col="orange", lwd=3, lty=2)
lines(new_X[1:10,3], 20*invlogit(pred_int[3,1:10]), col="orange", lwd=3, lty=2)
lines(new_X[1:10,3], 20*invlogit(pred_int[2,11:20]), col="red", lwd=5)
lines(new_X[1:10,3], 20*invlogit(pred_int[1,11:20]), col="red", lwd=3, lty=2)
lines(new_X[1:10,3], 20*invlogit(pred_int[3,11:20]), col="red", lwd=3, lty=2)
lines(new_X[1:10,3], 20*invlogit(pred_int[2,21:30]), col="blue", lwd=5)
lines(new_X[1:10,3], 20*invlogit(pred_int[1,21:30]), col="blue", lwd=3, lty=2)
lines(new_X[1:10,3], 20*invlogit(pred_int[3,21:30]), col="blue", lwd=3, lty=2)
legend("topleft", legend = c("Min", "Mean", "Max"), ncol=3, col = c("orange", "red", "blue"), lwd = 3, bty="n", title="Value of x1")
STAN是一個很靈活的工具,可以擬合許不一樣分佈和多類參數形式(參看參考手冊),其可能性僅僅受到你的若是的限制(也許還有你的數學水平。。。)。在這裏我聲明一下,rsranarm包可以讓你在不寫出模型形式的狀況下擬合STAN模型。僅僅需要寫一些諸如glm函數的典型的R代碼(請參考此文)。那麼,咱們還需要學習STAN嗎?這取決於你的目的,若是你的模型比較常用。那麼利用rstanarm包可以節約大量時間,讓你把精力集中於科研。並且rstanarm包內已有的函數執行速度很快。但若是有一天你認爲你會在模型上有所突破,需要擬合一個個性化的模型,那麼STAN會是一種很靈活和高效的建模語言。函數
/* *簡單負二項迴歸樣例 *使用負二項迴歸的另一種參數形式 *細節參看Stan參考手冊 section 40.1-3 */
data {
int N; //the number of observations
int K; //the number of columns in the model matrix
int y[N]; //the response
matrix[N,K] X; //the model matrix
}
parameters {
vector[K] beta; //the regression parameters
real phi; //the overdispersion parameters
}
transformed parameters {
vector[N] mu;//the linear predictor
mu <- exp(X*beta); //using the log link
}
model {
beta[1] ~ cauchy(0,10); //prior for the intercept following Gelman 2008
for(i in 2:K)
beta[i] ~ cauchy(0,2.5);//prior for the slopes following Gelman 2008
y ~ neg_binomial_2(mu,phi);
}
generated quantities {
vector[N] y_rep;
for(n in 1:N){
y_rep[n] <- neg_binomial_2_rng(mu[n],phi); //posterior draws to get posterior predictive checks
}
}
/* *簡單gamma分佈樣例 *注意我使用了對數連接函數,大多數時候它比典型反向連接更有意義 */
data {
int N; //the number of observations
int K; //the number of columns in the model matrix
real y[N]; //the response
matrix[N,K] X; //the model matrix
}
parameters {
vector[K] betas; //the regression parameters
real phi; //the variance parameter
}
transformed parameters {
vector[N] mu; //the expected values (linear predictor)
vector[N] alpha; //shape parameter for the gamma distribution
vector[N] beta; //rate parameter for the gamma distribution
mu <- exp(X*betas); //using the log link
alpha <- mu .* mu / phi;
beta <- mu / phi;
}
model {
betas[1] ~ cauchy(0,10); //prior for the intercept following Gelman 2008
for(i in 2:K)
betas[i] ~ cauchy(0,2.5);//prior for the slopes following Gelman 2008
y ~ gamma(alpha,beta);
}
generated quantities {
vector[N] y_rep;
for(n in 1:N){
y_rep[n] <- gamma_rng(alpha[n],beta[n]); //posterior draws to get posterior predictive checks
}
}
/* *簡單beta-binomial樣例 */
data {
int N; //the number of observations
int K; //the number of columns in the model matrix
int y[N]; //the response
matrix[N,K] X; //the model matrix
int W[N]; //the number of trials per observations, ie a vector of 1 for a 0/1 dataset
}
parameters {
vector[K] betas; //the regression parameters
real phi; //the overdispersion parameter
}
transformed parameters {
vector[N] mu; //the linear predictor
vector[N] alpha; //the first shape parameter for the beta distribution
vector[N] beta; //the second shape parameter for the beta distribution
for(n in 1:N)
mu[n] <- inv_logit(X[n,]*betas); //using logit link
alpha <- mu * phi;
beta <- (1-mu) * phi;
}
model {
betas[1] ~ cauchy(0,10); //prior for the intercept following Gelman 2008
for(i in 2:K)
betas[i] ~ cauchy(0,2.5);//prior for the slopes following Gelman 2008
y ~ beta_binomial(W,alpha,beta);
}
generated quantities {
vector[N] y_rep;
for(n in 1:N){
y_rep[n] <- beta_binomial_rng(W[n],alpha[n],beta[n]); //posterior draws to get posterior predictive checks
}
}