Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

概覽

頭文件和名字空間

這個庫的所有代碼都在boost::math名字空間中。

為了使用一個分佈my_distribution ,你需要包含頭文件<boost/math/distributions/my_distribution.hpp> 或"包含所有(include everything)"頭文件:<boost/math/distributions.hpp>。

例如,為了使用學生t分佈(Students-t distribution),包含頭文件<boost/math/distributions/students_t.hpp> 或 <boost/math/distributions.hpp>

分佈都是對像

每一種分佈在這個庫中都是一個類類型(class type)。

策略提供了對這些類的行為的更好粒度(fine-grained)的控制,允許用戶定制這些類的行為:例如,如何處理錯誤, 離散分佈的分位點(quantiles)如何工作(behave)。

[Tip] 提示

如果你很熟悉使用函數而不是對象的統計類庫,而且 '統計作為對像(Distributions as Objects)' 看起來很陌生,參考與其它統計類庫的比較

將統計作為類類型(class type)完成了兩件事情:

雖然在這個庫中的所有分佈類都是模板, 但提供了關於類型double 的使用分佈的常見名字的typedef (除了與一個具有相同名字的函數發生衝突:beta 和 gamma,在這種情況下,使用缺省的模板參數- RealType = double - 也差不多方便)。可能有95%的使用情況由這些typedefs覆蓋。

using namespace boost::math;

// 使用自由度(degree of freedom)為4來構造一個學生t分佈(students_t distribution):
students_t d1(4);

// 構造一個double精度的β分佈(beta distribution) 
// 參數為 a = 10, b = 20
beta_distribution<> d2(10, 20); // 注意: _distribution<> 下標(suffix) !

如果你想要使用一個不是double類型的分佈對象,那麼你可以直接實例化這個模板:模板的名字與double typedef是相同的,但是附加了一個 _distribution 後綴,例如:Students t DistributionBinomial Distribution

// 構造一個float類型的學生t分佈(student t distribution),
//自由度數(degree of freedom)為4
students_t_distribution<float> d3(4);

// 構造一個long double類型的二項分佈(binomial distribution), 
// 概率分數(probability of success)為 0.3
// 總共20次試驗:
binomial_distribution<long double> d4(20, 0.3);

傳遞給這些分佈的參數可以通過成員獲取函數(getter member functions)來訪問:

d1.degrees_of_freedom();  // 返回 4.0 

這是很好的,但是到目前為止還不是很有用。我們經常想要做的是對這些分佈計算累積分佈函數(cumulative distribution functions )和分位點(quantiles )等等。.

對所有分佈都通用的操作是非成員函數

想要計算一個分佈的PDF (概率密度函數)嗎? 沒問題,使用:

pdf(my_dist, x);  // 返回分佈my_dist在點x處的PDF(密度).

或者計算CDF (累積分佈函數):

cdf(my_dist, x);  // 返回分佈my_dist的CDF (積分形式 -從無窮到點x處)
                  

分位點(quantiles)也是一樣的:

quantile(my_dist, p);  // 返回返回變量x的值
                       // 滿足 cdf(my_dist, x) == p.

如果你在考慮為什麼這些函數不是成員函數,原因是使得這個庫更容易擴展:如果你想要添加通用的操作-比方說第n個矩 n'th moment-那麼所有你需要做的僅僅是添加合適的非成員函數,針對每個實現的分佈類型進行重載。

[Tip] 提示

近似於分佈的分位點(Quantile)的隨機數(Random numbers)

如果你想獲得以一種特定方式分佈的隨機數,例如,以均勻,正態或三角形方式分佈,參考Boost.Random.

然而,在原理上沒有什麼能阻止你使用分位點函數(quantile function)來將均勻分佈的隨機數轉換成另外一種分佈。實際上,存在更高效的隨機數生成算法。

例如,二項分佈(binomial distribution)有兩個參數: n (試驗次數) 和 p (單次試驗的成功概率)。

binomial_distribution 構造函數有兩個參數:

binomial_distribution(RealType n, RealType p);

對於這個分佈,隨機變量是 k:觀測到的成功試驗數。 概率 密度/質量 函數 (pdf) 寫作:f(k; n, p).

[Note] 注意

隨機變量和分佈參數

隨機變量分佈參數 按照慣例進行區分 (例如在 Wikipedia 和 Wolfram MathWorld通過在隨機變量後面放置一個 semi-colon (或者有時是vertical bar),來區分隨機變量與定義這個分佈形狀的形狀參數(shape parameter)。

就像上面提到的那樣,非成員函數pdf有一個分佈類型的參數,以及另一個隨機變量類型的參數。以二項分佈為例( binomial distribution),我們可以寫出如下代碼:

pdf(binomial_distribution<RealType>(n, p), k);

允許和支持的隨機變量值的範圍可以通過rangesupport這兩個函數來測試。

在一個範圍上分佈 (實際上是隨機變量)是得到 "支持的" 就是說"補集的概率為0的最小的封閉集合". MathWorld 對這個範圍使用詞語 '定義(defined)' 。非數學家( Non-mathematicians)可能會說它的含義是 : 隨機變量 x 的'interesting'最小範圍,使得函數cdf的值從零到單位元素(unity)。在這個範圍之外是"uninteresting zones",函數pdf 的值為0,且函數cdf的為0或單位元素(unity)。

對於大多數的分佈,具有概率分佈函數的分佈可以描述為「 運行良好的(well-behaved) 」, 如果端點是不連續的,我們認為對支持的範圍排除類似於剛好為0的值是很有幫助的。例如,隨著隨機變量x朝0遞減,韋泊爾分佈(Weibull Distribution)(尺度參數為1,形狀參數為1)順利地(smoothly)向單位元素(unity)推進。但在x = zero處,依照定義,函數pdf的值突然變為0。如果你在為pdf函數繪圖(plot),或計算pdf函數,對於支持的下限,0並不是最有用的值,就像我們發現的那樣。因此對於這個分佈,以及類似的分佈,我們決定將最接近0的值min_value作為支持的範圍的下限在數值上是很有用的。(範圍仍然是從0開始,因此你仍會得到pdf(weibull, 0) == 0)。(指數分佈和γ分佈也有類似的不連續函數)。

在數學上,對於(+ 或 -)無窮值這些函數是有意義的,但是除了一些特殊情況(在柯西分佈和正態分佈中),這個庫的實現將對於RealType類型的隨機變量的值限定為從maxmin的有限值。 (參考處理浮點類型無限值 瞭解原理)。

[Note] 注意

離散概率分佈

注意離散概率分佈(discrete distributions),包括二項分佈(binomial distribution), 負二項分佈(negative binomial distribution), 泊松分佈(Poisson distribution ) & 伯努利分佈(Bernoulli distribution),都在數學上定義為離散函數( discrete functions):也就是說函數cdfpdf 只針對於整數的隨機變量進行定義。

然而,因為計算方法經常使用連續函數,所以把它們當作「好像是」連續函數來對待會帶來方便,並且允許它們的參數為非整數值。

用戶想要確保一個嚴格的數學模型,可以在調用這個分佈函數之前使用函數floorceil

這些分佈的分位點函數(quantile functions)在某種程度上很難一直滿足所有人的需要而得到具體指定。缺省的行為是返回一個將結果向外捨入(outwards)整數值:這就是說,下分位點(lower quantiles)-概率小於0.5是向下捨入,而對於上分位點(upper quantile)-概率大於0.5是向上捨入。這種行為確保如果返回一個X%分位點值,那麼至少標的覆蓋範圍將會在中心區域顯示,不是要求的覆蓋範圍將會在尾部(tails)顯示。

這種行為可以改變,使得分位點函數可以進行不同的捨入,或者甚至使用策略來返回一個實值(real-valued)。在你使用二項分佈的分位點函數之前,強烈推薦你閱讀理解分佈的分位點參考文檔 描述了如何為這些分佈改變捨入策略。

出於類似的原因,對於參數類似於「自由度(degree of freedom)」為整數的連續分佈,參數被當作實數看待(如果需要的話,會從整數提升為浮點數)。然而在這種情況下,有少數的情況,非整數自由度(degree of freedom)的確有一個真實的含義( genuine meaning)。

補集也得到支持

你經常不想得到CDF的值,而是它的補集的值,也就是說你想得到1-p 而不是 p。你可以計算CDF 然後用1減去這個結果,但是如果p 非常接近於1 ,那麼消去錯誤(cancellation error)將會使用你丟失有效數字。在極端的情況下, p 可能實際上等於 1, 即使補集的真值( true value)是非零的。.

參見"為什麼有補集( complements)?"

在這個庫中,無論何時你想要得到一個補集(complement),把所有的函數參數包裝在對函數complement(...)的調用之中 ,例如:

students_t dist(5);
cout << "CDF at t = 1 is " << cdf(dist, 1.0) << endl;
cout << "Complement of CDF at t = 1 is " << cdf(complement(dist, 1.0)) << endl;

但請等一下,現在我們有一個補集(complement),我們必須也能夠使用它。任何的接受一個概率作為參數的函數同樣也可以接受將所有的參數包裝在對函數 complement(...)中產生的補集,例如:

students_t dist(5);

for(double i = 10; i < 1e10; i *= 10)
{
   // 計算1 in i chance中的分位點:
   double t = quantile(complement(dist, 1/i));
   // 打印出來 :
   cout << "Quantile of students-t with 5 degrees of freedom\n"
           "for a 1 in " << i << " chance is " << t << endl;
}
[Tip] 提示

臨界值(Critical values)就是分位點(quantiles)

一些資料談及quantiles,另一些資料談及臨界值( critical values),基本原則是:

下臨界值(Lower critical values) 與分位點(quantile)是相同的。

上臨界值(Upper critical values) 與概率補集的分位點(quantile)是相同的。

例如,我們有一個伯努利過程(Bernoulli process),產生一個成功比(success ratio)為0.1且總共100次試驗的伯努利分佈(binomial distribution)。概率為0.05的下臨界值(lower critical value) 由下面給定:

quantile(binomial(100, 0.1), 0.05)

上臨界值(upper critical value) 由下面給定:

quantile(complement(binomial(100, 0.1), 0.05))

分別返回4.82 和14.63。

[Tip] 提示

為什麼要擔心(bother)補集(complements)?

省掉補集(complements)是非常誘人的,並且在需要的時候只是簡單地用1減去概率。然而,考慮當概率非常常於1時會發生什麼:假設概率以浮點數表示為 0.999999940f,那麼1 - 0.999999940f = 5.96046448e-008,但是結果實際上只精確到一個bit: 沒有消去(cancel out)的唯一一個bit!

或者以另一種方式來看待這個問題:假定我們想要在一個樣本大小為10,000的學生t分佈(student's t distribution)中錯誤拒絕(reject)虛假設(null-hypothesis)的風險(risk)為十億分之一。這給出的概率為 1 - 10-9,當以float精度計算時剛好為1。在這種情況下,使用補集來計算分位點(quantile)巧妙地解決了這個問題,例如:quantile(complement(students_t(10000), 1e-9))

返回期望的 t-statistic 6.00336,因為:

quantile(students_t(10000), 1-1e-9f)

產生一個溢出錯誤,因為它與 下面等價:

quantile(students_t(10000), 1)

這就沒有有限值的結果。

參數可以被計算

有時你需要查找定義這個分佈的參數。假設,例如,你已經針對相等均值並且結果是邊界(borderline)構造了一個學生t分佈(Student's t Distribution)。或許你的兩個樣本彼此不同,或許它們不是彼此不同;基於計算的結果你並不能確定。一個合理的問題是「在我獲得一個樣本的區別是真實的概率為X%時我需要進行多少次的測量?」參數查找可以回答這個問題,並且對於每個分佈的回答都不同。它們作為分佈的靜態成員函數來實現。例如:

students_t::find_degrees_of_freedom(
   1.3,        // 要檢測的與真實均值的差值(difference from true mean to detect)
   0.05,       // 錯誤否決虛假設的最大風險值(maximum risk of falsely rejecting the null-hypothesis).
   0.1,        // 錯誤否決虛假設的最大風險值(maximum risk of falsely failing to reject the null-hypothesis).
   0.13);      // 樣本標準差(sample standard deviation)

獲得在均值中觀測到的差值沒有下降到偶然的獨立事件(chance alone)的概率為95%時所需要的自由度(degree of freedom)。在這種情況下,邊界( borderline )學生t分佈測試(Students-t test)結果已經在前面獲得,這可以用來估算在觀測的差值被認為是有效的之前 ,樣本的大小應當變為多大 。這需要假設,當然, 樣本均值與標準差對於樣本大小是不變的。

總結

現在你瞭解了所有的基本信息,下一部分查看一些可運行的例子。


PrevUpHomeNext