我是靠谱客的博主 粗心老鼠,最近开发中收集的这篇文章主要介绍Stan:一种统计学建模语言,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

1.Stan简介

Stan 是一种用于统计建模和高性能统计计算的先进平台。Stan已经在社会、生物和物理科学、工程和商业领域被应用于统计建模、数据分析和预测。

  • 基于Stan概率编程语言开发统计模型

  • 进行MCMC采样

  • 基于变分推理的近似贝叶斯计算

  • 基于正则项的极大似然函数的优化方法

Stan提供Python和R语言安装包,Stan可以自动化实现统计学模型转化为C++代码的功能,以方便用户进行部署调用。本文主要讲述怎样使用Stan进行统计学模型参数估计,并嵌入C++开发平台。

2.Stan模型代码结构

下面是Stan语言模型构建程序骨架:

  • functions模块包含了用户自定义函数

  • data指明定义了模型的输入数据格式及其数据类型

  • transformed data模块允许用户定义常量或从data转换过来的数据

  • parameters模块声明模型的参数

  • transformed parameters模块允许定义变量来保存由data或parameters生成的中间数据

  • model模块定义了模型的对数密度函数

  • generated quantities 模块允许基于parameters,data, 及随机数生成用户需要的数据

functions {
  // ... function declarations and definitions ...
}
data {
  // ... declarations ...
}
transformed data {
   // ... declarations ... statements ...
}
parameters {
   // ... declarations ...
}
transformed parameters {
   // ... declarations ... statements ...
}
model {
   // ... declarations ... statements ...
}
generated quantities {
   // ... declarations ... statements ...
}

3.Stan优化算法

Stan提供优化算法来搜索使用Stan语言定义的密度函数模式,此模式可被用来进行参数估计,或用来做贝叶斯后验分析。Stan提供三种优化算法,分别为牛顿法和两种近似牛顿法(BFGS、LBFGS)。

在使用优化算法过程中,一个主要问题是收敛性的监测问题,在Stan优化算法可以使用多种参数进行监测。任意一个监测参数满足时则认为该函数已经收敛。可以通过将其相应的容差参数设置为零来禁止此种收敛监测。

  • 参数收敛监测,如果参数 在第 次迭代过程中,其变化量小于tol_param时,则认为收敛,公式如下:

  • 密度函数收敛监测,如果对于 在给定数据集 上,对数密度函数 的变化量小于tot_obj,则认为收敛,公式如下:

  • 当对数密度函数的相对变化量小于tol_rel_obj,则认为收敛,公式如下:

  • 梯度收敛监测,当梯度的二范数小于容差tol_grad时,则认为收敛,公式如下:

其中 ,在第i轮迭代时的计算值。

  • 相对梯度收敛监测,当相对变化量小于tol_rel_grad时,则认为收敛,公式如下:

其中 是第i轮的 Hessian估计, 是机器精度。

4.Prophet示例

Prophet是由Facebook开源的一种基于可加模型预测时间序列数据的python分析组件,其非线性趋势与年、星期、日、季节性以及假日效应相吻合。它最适用于具有强烈季节性影响和多个季节历史数据的时间序列。Prophet 对缺失数据和趋势变化具有稳健性,并且通常可以很好地处理异常值。

经过研究其源码可以发现,其后端主要依赖于pyStan、pycmdStan等Stan相关组件,Prophet模型是由Stan语言定义的一个统计学模型。如果将Prophet嵌入到C++开发环境中,则需要用C++语言实现Prophet模型的建模,在这种情况下,可以借助Stan语言及其工具链进行集成开发。

模型定义文件prophet.stan如下(摘取部分),该文件来自Porphet源码。其中data为模型的输入数据格式及其类型,parameters 为该模型参数,model定义了该模型的密度函数。

data {
  int T;                // Number of time periods
  int<lower=1> K;       // Number of regressors
  vector[T] t;          // Time
  vector[T] cap;        // Capacities for logistic trend
  vector[T] y;          // Time series
  int S;                // Number of changepoints
  vector[S] t_change;   // Times of trend changepoints
  matrix[T,K] X;        // Regressors
  vector[K] sigmas;     // Scale on seasonality prior
  real<lower=0> tau;    // Scale on changepoints prior
  int trend_indicator;  // 0 for linear, 1 for logistic, 2 for flat
  vector[K] s_a;        // Indicator of additive features
  vector[K] s_m;        // Indicator of multiplicative features
}

parameters {
  real k;                   // Base trend growth rate
  real m;                   // Trend offset
  vector[S] delta;          // Trend rate adjustments
  real<lower=0> sigma_obs;  // Observation noise
  vector[K] beta;           // Regressor coefficients
}

model {
  //priors
  k ~ normal(0, 5);
  m ~ normal(0, 5);
  delta ~ double_exponential(0, tau);
  sigma_obs ~ normal(0, 0.5);
  beta ~ normal(0, sigmas);

  // Likelihood
  y ~ normal(
  trend
  .* (1 + X * (beta .* s_m))
  + X * (beta .* s_a),
  sigma_obs
  );
}

使用stanc生成prophet.hpp如下:

class prophet_model final : public model_base_crtp<prophet_model> {

 private:
  int T;
  int K;
  Eigen::Matrix<double, -1, 1> t;
  Eigen::Matrix<double, -1, 1> cap;
  Eigen::Matrix<double, -1, 1> y;
  int S;
  Eigen::Matrix<double, -1, 1> t_change;
  Eigen::Matrix<double, -1, -1> X;
  Eigen::Matrix<double, -1, 1> sigmas;
  double tau;
  int trend_indicator;
  Eigen::Matrix<double, -1, 1> s_a;
  Eigen::Matrix<double, -1, 1> s_m;
  Eigen::Matrix<double, -1, -1> A;
 
 public:
  ~prophet_model() { }
  
  inline std::string model_name() const final { return "prophet_model"; }
  
  prophet_model(stan::io::var_context& context__,
                unsigned int random_seed__ = 0,
                std::ostream* pstream__ = nullptr) : model_base_crtp(0) {
  ...
  ...
  }

模型优化计算,调用Stan优化方法搜索概率密度函数模型参数。

 int lbfgs(Model& model, const stan::io::var_context& init,
         unsigned int random_seed, unsigned int chain, double init_radius,
         int history_size, double init_alpha, double tol_obj,
         double tol_rel_obj, double tol_grad, double tol_rel_grad,
         double tol_param, int num_iterations, bool save_iterations,
         int refresh, callbacks::interrupt& interrupt,
         callbacks::logger& logger, callbacks::writer& init_writer,
         callbacks::writer& parameter_writer)

为验证方便,借助Stan辅助工具CmdStan(Command-Line Interface),直接执行 make examples/prophet/prophet 进行自动化编译,在make过程中会调用stanc转换翻译prophet.stan,同时会将该模型包装成命令行,生成prophet的可执行文件。

运行prophet模型,并将模型参数输出到csv,可以从下面的结果看到此模型在优化过程中的相对梯度达到收敛监测指标。根据优化后获取的模型参数构建模型时间序列预测函数。

./prophet method  method=optimize  algorithm=lbfgs iter=10000  data file=data_file.json init=stan_init.json random seed=10000

Initial log joint probability = -19.4685
    Iter      log prob        ||dx||      ||grad||       alpha      alpha0  # evals  Notes 
     742       8004.29   4.87051e-07       65.1727     0.04812           1      971   
Optimization terminated normally: 
  Convergence detected: relative gradient magnitude is below tolerance  

5.总结

Stan为用户提供了快速创建统计模型的中间语言,实现自动化将统计学模型快速翻译成C++语言,在统计学习模型落地部署过程中,使用户省去了大量的模型开发工作,同时Stan还提供统计模型加速优化器,为用户提供了快速求解统计模型的优化方法。同时还可利用Stan平台进行统计模型采样和基于变分推理的近似贝叶斯推理计算。

6. 参考

  • https://mc-stan.org/docs/2_27/stan-users-guide/index.html

  • https://mc-stan.org/users/interfaces/cmdstan

  • https://github.com/stan-dev/cmdstan

  • https://github.com/stan-dev/stan

  • https://facebook.github.io/prophet/

  • https://github.com/facebook/prophet

最后

以上就是粗心老鼠为你收集整理的Stan:一种统计学建模语言的全部内容,希望文章能够帮你解决Stan:一种统计学建模语言所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(38)

评论列表共有 0 条评论

立即
投稿
返回
顶部