inverse_chi_squared_bayes_eg.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. // inverse_chi_squared_bayes_eg.cpp
  2. // Copyright Thomas Mang 2011.
  3. // Copyright Paul A. Bristow 2011.
  4. // Use, modification and distribution are subject to the
  5. // Boost Software License, Version 1.0.
  6. // (See accompanying file LICENSE_1_0.txt
  7. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  8. // This file is written to be included from a Quickbook .qbk document.
  9. // It can still be compiled by the C++ compiler, and run.
  10. // Any output can also be added here as comment or included or pasted in elsewhere.
  11. // Caution: this file contains Quickbook markup as well as code
  12. // and comments: don't change any of the special comment markups!
  13. #include <iostream>
  14. // using std::cout; using std::endl;
  15. //#define define possible error-handling macros here?
  16. #include "boost/math/distributions.hpp"
  17. // using ::boost::math::inverse_chi_squared;
  18. int main()
  19. {
  20. using std::cout; using std::endl;
  21. using ::boost::math::inverse_chi_squared;
  22. using ::boost::math::inverse_gamma;
  23. using ::boost::math::quantile;
  24. using ::boost::math::cdf;
  25. cout << "Inverse_chi_squared_distribution Bayes example: " << endl <<endl;
  26. cout.precision(3);
  27. // Examples of using the inverse_chi_squared distribution.
  28. //[inverse_chi_squared_bayes_eg_1
  29. /*`
  30. The scaled-inversed-chi-squared distribution is the conjugate prior distribution
  31. for the variance ([sigma][super 2]) parameter of a normal distribution
  32. with known expectation ([mu]).
  33. As such it has widespread application in Bayesian statistics:
  34. In [@http://en.wikipedia.org/wiki/Bayesian_inference Bayesian inference],
  35. the strength of belief into certain parameter values is
  36. itself described through a distribution. Parameters
  37. hence become themselves modelled and interpreted as random variables.
  38. In this worked example, we perform such a Bayesian analysis by using
  39. the scaled-inverse-chi-squared distribution as prior and posterior distribution
  40. for the variance parameter of a normal distribution.
  41. For more general information on Bayesian type of analyses,
  42. see:
  43. * Andrew Gelman, John B. Carlin, Hal E. Stern, Donald B. Rubin, Bayesian Data Analysis,
  44. 2003, ISBN 978-1439840955.
  45. * Jim Albert, Bayesian Compution with R, Springer, 2009, ISBN 978-0387922973.
  46. (As the scaled-inversed-chi-squared is another parameterization of the inverse-gamma distribution,
  47. this example could also have used the inverse-gamma distribution).
  48. Consider precision machines which produce balls for a high-quality ball bearing.
  49. Ideally each ball should have a diameter of precisely 3000 [mu]m (3 mm).
  50. Assume that machines generally produce balls of that size on average (mean),
  51. but individual balls can vary slightly in either direction
  52. following (approximately) a normal distribution. Depending on various production conditions
  53. (e.g. raw material used for balls, workplace temperature and humidity, maintenance frequency and quality)
  54. some machines produce balls tighter distributed around the target of 3000 [mu]m,
  55. while others produce balls with a wider distribution.
  56. Therefore the variance parameter of the normal distribution of the ball sizes varies
  57. from machine to machine. An extensive survey by the precision machinery manufacturer, however,
  58. has shown that most machines operate with a variance between 15 and 50,
  59. and near 25 [mu]m[super 2] on average.
  60. Using this information, we want to model the variance of the machines.
  61. The variance is strictly positive, and therefore we look for a statistical distribution
  62. with support in the positive domain of the real numbers.
  63. Given the expectation of the normal distribution of the balls is known (3000 [mu]m),
  64. for reasons of conjugacy, it is customary practice in Bayesian statistics
  65. to model the variance to be scaled-inverse-chi-squared distributed.
  66. In a first step, we will try to use the survey information to model
  67. the general knowledge about the variance parameter of machines measured by the manufacturer.
  68. This will provide us with a generic prior distribution that is applicable
  69. if nothing more specific is known about a particular machine.
  70. In a second step, we will then combine the prior-distribution information in a Bayesian analysis
  71. with data on a specific single machine to derive a posterior distribution for that machine.
  72. [h5 Step one: Using the survey information.]
  73. Using the survey results, we try to find the parameter set
  74. of a scaled-inverse-chi-squared distribution
  75. so that the properties of this distribution match the results.
  76. Using the mathematical properties of the scaled-inverse-chi-squared distribution
  77. as guideline, we see that that both the mean and mode of the scaled-inverse-chi-squared distribution
  78. are approximately given by the scale parameter (s) of the distribution. As the survey machines operated at a
  79. variance of 25 [mu]m[super 2] on average, we hence set the scale parameter (s[sub prior]) of our prior distribution
  80. equal to this value. Using some trial-and-error and calls to the global quantile function, we also find that a
  81. value of 20 for the degrees-of-freedom ([nu][sub prior]) parameter is adequate so that
  82. most of the prior distribution mass is located between 15 and 50 (see figure below).
  83. We first construct our prior distribution using these values, and then list out a few quantiles:
  84. */
  85. double priorDF = 20.0;
  86. double priorScale = 25.0;
  87. inverse_chi_squared prior(priorDF, priorScale);
  88. // Using an inverse_gamma distribution instead, we could equivalently write
  89. // inverse_gamma prior(priorDF / 2.0, priorScale * priorDF / 2.0);
  90. cout << "Prior distribution:" << endl << endl;
  91. cout << " 2.5% quantile: " << quantile(prior, 0.025) << endl;
  92. cout << " 50% quantile: " << quantile(prior, 0.5) << endl;
  93. cout << " 97.5% quantile: " << quantile(prior, 0.975) << endl << endl;
  94. //] [/inverse_chi_squared_bayes_eg_1]
  95. //[inverse_chi_squared_bayes_eg_output_1
  96. /*`This produces this output:
  97. Prior distribution:
  98. 2.5% quantile: 14.6
  99. 50% quantile: 25.9
  100. 97.5% quantile: 52.1
  101. */
  102. //] [/inverse_chi_squared_bayes_eg_output_1]
  103. //[inverse_chi_squared_bayes_eg_2
  104. /*`
  105. Based on this distribution, we can now calculate the probability of having a machine
  106. working with an unusual work precision (variance) at <= 15 or > 50.
  107. For this task, we use calls to the `boost::math::` functions `cdf` and `complement`,
  108. respectively, and find a probability of about 0.031 (3.1%) for each case.
  109. */
  110. cout << " probability variance <= 15: " << boost::math::cdf(prior, 15.0) << endl;
  111. cout << " probability variance <= 25: " << boost::math::cdf(prior, 25.0) << endl;
  112. cout << " probability variance > 50: "
  113. << boost::math::cdf(boost::math::complement(prior, 50.0))
  114. << endl << endl;
  115. //] [/inverse_chi_squared_bayes_eg_2]
  116. //[inverse_chi_squared_bayes_eg_output_2
  117. /*`This produces this output:
  118. probability variance <= 15: 0.031
  119. probability variance <= 25: 0.458
  120. probability variance > 50: 0.0318
  121. */
  122. //] [/inverse_chi_squared_bayes_eg_output_2]
  123. //[inverse_chi_squared_bayes_eg_3
  124. /*`Therefore, only 3.1% of all precision machines produce balls with a variance of 15 or less
  125. (particularly precise machines),
  126. but also only 3.2% of all machines produce balls
  127. with a variance of as high as 50 or more (particularly imprecise machines). Moreover, slightly more than
  128. one-half (1 - 0.458 = 54.2%) of the machines work at a variance greater than 25.
  129. Notice here the distinction between a
  130. [@http://en.wikipedia.org/wiki/Bayesian_inference Bayesian] analysis and a
  131. [@http://en.wikipedia.org/wiki/Frequentist_inference frequentist] analysis:
  132. because we model the variance as random variable itself,
  133. we can calculate and straightforwardly interpret probabilities for given parameter values directly,
  134. while such an approach is not possible (and interpretationally a strict ['must-not]) in the frequentist
  135. world.
  136. [h5 Step 2: Investigate a single machine]
  137. In the second step, we investigate a single machine,
  138. which is suspected to suffer from a major fault
  139. as the produced balls show fairly high size variability.
  140. Based on the prior distribution of generic machinery performance (derived above)
  141. and data on balls produced by the suspect machine, we calculate the posterior distribution for that
  142. machine and use its properties for guidance regarding continued machine operation or suspension.
  143. It can be shown that if the prior distribution
  144. was chosen to be scaled-inverse-chi-square distributed,
  145. then the posterior distribution is also scaled-inverse-chi-squared-distributed
  146. (prior and posterior distributions are hence conjugate).
  147. For more details regarding conjugacy and formula to derive the parameters set
  148. for the posterior distribution see
  149. [@http://en.wikipedia.org/wiki/Conjugate_prior Conjugate prior].
  150. Given the prior distribution parameters and sample data (of size n), the posterior distribution parameters
  151. are given by the two expressions:
  152. __spaces [nu][sub posterior] = [nu][sub prior] + n
  153. which gives the posteriorDF below, and
  154. __spaces s[sub posterior] = ([nu][sub prior]s[sub prior] + [Sigma][super n][sub i=1](x[sub i] - [mu])[super 2]) / ([nu][sub prior] + n)
  155. which after some rearrangement gives the formula for the posteriorScale below.
  156. Machine-specific data consist of 100 balls which were accurately measured
  157. and show the expected mean of 3000 [mu]m and a sample variance of 55 (calculated for a sample mean defined to be 3000 exactly).
  158. From these data, the prior parameterization, and noting that the term
  159. [Sigma][super n][sub i=1](x[sub i] - [mu])[super 2] equals the sample variance multiplied by n - 1,
  160. it follows that the posterior distribution of the variance parameter
  161. is scaled-inverse-chi-squared distribution with degrees-of-freedom ([nu][sub posterior]) = 120 and
  162. scale (s[sub posterior]) = 49.54.
  163. */
  164. int ballsSampleSize = 100;
  165. cout <<"balls sample size: " << ballsSampleSize << endl;
  166. double ballsSampleVariance = 55.0;
  167. cout <<"balls sample variance: " << ballsSampleVariance << endl;
  168. double posteriorDF = priorDF + ballsSampleSize;
  169. cout << "prior degrees-of-freedom: " << priorDF << endl;
  170. cout << "posterior degrees-of-freedom: " << posteriorDF << endl;
  171. double posteriorScale =
  172. (priorDF * priorScale + (ballsSampleVariance * (ballsSampleSize - 1))) / posteriorDF;
  173. cout << "prior scale: " << priorScale << endl;
  174. cout << "posterior scale: " << posteriorScale << endl;
  175. /*`An interesting feature here is that one needs only to know a summary statistics of the sample
  176. to parameterize the posterior distribution: the 100 individual ball measurements are irrelevant,
  177. just knowledge of the sample variance and number of measurements is sufficient.
  178. */
  179. //] [/inverse_chi_squared_bayes_eg_3]
  180. //[inverse_chi_squared_bayes_eg_output_3
  181. /*`That produces this output:
  182. balls sample size: 100
  183. balls sample variance: 55
  184. prior degrees-of-freedom: 20
  185. posterior degrees-of-freedom: 120
  186. prior scale: 25
  187. posterior scale: 49.5
  188. */
  189. //] [/inverse_chi_squared_bayes_eg_output_3]
  190. //[inverse_chi_squared_bayes_eg_4
  191. /*`To compare the generic machinery performance with our suspect machine,
  192. we calculate again the same quantiles and probabilities as above,
  193. and find a distribution clearly shifted to greater values (see figure).
  194. [graph prior_posterior_plot]
  195. */
  196. inverse_chi_squared posterior(posteriorDF, posteriorScale);
  197. cout << "Posterior distribution:" << endl << endl;
  198. cout << " 2.5% quantile: " << boost::math::quantile(posterior, 0.025) << endl;
  199. cout << " 50% quantile: " << boost::math::quantile(posterior, 0.5) << endl;
  200. cout << " 97.5% quantile: " << boost::math::quantile(posterior, 0.975) << endl << endl;
  201. cout << " probability variance <= 15: " << boost::math::cdf(posterior, 15.0) << endl;
  202. cout << " probability variance <= 25: " << boost::math::cdf(posterior, 25.0) << endl;
  203. cout << " probability variance > 50: "
  204. << boost::math::cdf(boost::math::complement(posterior, 50.0)) << endl;
  205. //] [/inverse_chi_squared_bayes_eg_4]
  206. //[inverse_chi_squared_bayes_eg_output_4
  207. /*`This produces this output:
  208. Posterior distribution:
  209. 2.5% quantile: 39.1
  210. 50% quantile: 49.8
  211. 97.5% quantile: 64.9
  212. probability variance <= 15: 2.97e-031
  213. probability variance <= 25: 8.85e-010
  214. probability variance > 50: 0.489
  215. */
  216. //] [/inverse_chi_squared_bayes_eg_output_4]
  217. //[inverse_chi_squared_bayes_eg_5
  218. /*`Indeed, the probability that the machine works at a low variance (<= 15) is almost zero,
  219. and even the probability of working at average or better performance is negligibly small
  220. (less than one-millionth of a permille).
  221. On the other hand, with an almost near-half probability (49%), the machine operates in the
  222. extreme high variance range of > 50 characteristic for poorly performing machines.
  223. Based on this information the operation of the machine is taken out of use and serviced.
  224. In summary, the Bayesian analysis allowed us to make exact probabilistic statements about a
  225. parameter of interest, and hence provided us results with straightforward interpretation.
  226. */
  227. //] [/inverse_chi_squared_bayes_eg_5]
  228. } // int main()
  229. //[inverse_chi_squared_bayes_eg_output
  230. /*`
  231. [pre
  232. Inverse_chi_squared_distribution Bayes example:
  233. Prior distribution:
  234. 2.5% quantile: 14.6
  235. 50% quantile: 25.9
  236. 97.5% quantile: 52.1
  237. probability variance <= 15: 0.031
  238. probability variance <= 25: 0.458
  239. probability variance > 50: 0.0318
  240. balls sample size: 100
  241. balls sample variance: 55
  242. prior degrees-of-freedom: 20
  243. posterior degrees-of-freedom: 120
  244. prior scale: 25
  245. posterior scale: 49.5
  246. Posterior distribution:
  247. 2.5% quantile: 39.1
  248. 50% quantile: 49.8
  249. 97.5% quantile: 64.9
  250. probability variance <= 15: 2.97e-031
  251. probability variance <= 25: 8.85e-010
  252. probability variance > 50: 0.489
  253. ] [/pre]
  254. */
  255. //] [/inverse_chi_squared_bayes_eg_output]