計算與推斷思維 八、隨機性

八、隨機性

原文:Randomness

譯者:飛龍

協(xié)議:CC BY-NC-SA 4.0

自豪地采用谷歌翻譯

在前面的章節(jié)中,我們開發(fā)了深入描述數(shù)據所需的技能。 數(shù)據科學家也必須能夠理解隨機性。 例如,他們必須能夠隨機將個體分配到實驗組和對照組,然后試圖說明,觀察到的兩組結果之間的差異是否僅僅是由于隨機分配,或真正由于實驗所致。

在這一章中,我們開始分析隨機性。 首先,我們將使用 Python 進行隨機選擇。 在numpy中有一個叫做random的子模塊,它包含許多涉及隨機選擇的函數(shù)。 其中一個函數(shù)稱為choice。 它從一個數(shù)組中隨機選取一個項目,選擇任何項目都是等可能的。 函數(shù)調用是np.random.choice(array_name),其中array_name是要從中進行選擇的數(shù)組的名稱。

因此,下面的代碼以 50% 的幾率求值為treatment,50% 的機率為control

two_groups = make_array('treatment', 'control')
np.random.choice(two_groups)
'treatment'

上面的代碼和我們迄今運行的所有其他代碼之間的巨大差異在于,上面的代碼并不總是返回相同的值。 它可以返回treatmentcontrol,我們不會提前知道會選擇哪一個。 我們可以通過提供第二個參數(shù)來重復這個過程,它是重復這個過程的次數(shù)。

np.random.choice(two_groups, 10)
array(['treatment', 'control', 'treatment', 'control', 'control',
       'treatment', 'treatment', 'control', 'control', 'control'], 
      dtype='<U9')

隨機事件的根本問題是它們是否發(fā)生。 例如:

  • 個體是否被分配到實驗組?
  • 賭徒是否會贏錢?
  • 一個民意調查是否做出了準確的預測?

一旦事件發(fā)生,你可以對所有這些問題回答“是”或“否”。 在編程中,通常通過將語句標記為TrueFalse來執(zhí)行此操作。 例如,如果個體被分配到實驗組,那么“個體被分配到實驗組”的陳述將是真的。 如果不是,那將是假的。

布爾值和比較

在 Python 中,布爾值(以邏輯學家 George Boole 命名)表示真值,并只有兩個可能的值:TrueFalse。 無論問題是否涉及隨機性,布爾值通常都由比較運算符產生。 Python 包含了各種比較值的運算符。 例如,3大于1 + 1。

3 > 1 + 1
True

True表示比較是有效的;Python 已經證實了31 + 1的關系的這個簡單事實。 下面列出了一整套通用的比較運算符。

比較 運算符 True 示例 False 示例
小于 < 2 < 3 2 < 2
大于 > 3 > 2 3 > 3
小于等于 <= 2 <= 2 3 <= 2
大于等于 >= 3 >= 3 2 >= 3
等于 == 3 == 3 3 == 2
不等于 != 3 != 2 2 != 2

注意比較中的兩個等號==用于確定相等性。 這是必要的,因為 Python 已經使用=來表示名稱的賦值,我們之前看到過。 它不能將相同的符號用于不同的目的。 因此,如果你想檢查5是否等于10/2,那么你必須小心:5 = 10/2返回一個錯誤信息,因為 Python 假設你正試圖將表達式10/2的值賦給一個名稱,它是數(shù)字5。相反,你必須使用5 == 10/2,其計算結果為True。

5 = 10/2
  File "<ipython-input-4-5c7d3e808777>", line 1
    5 = 10/2
            ^
SyntaxError: can't assign to literal
5 == 10/2
True

一個表達式可以包含多個比較,并且它們都必須滿足,為了整個表達式為真。 例如,我們可以用下面的表達式表示1 + 113之間。

1 < 1 + 1 < 3
True

兩個數(shù)字的平均值總是在較小的數(shù)字和較大的數(shù)字之間。 我們用下面的數(shù)字xy來表示這種關系。 你可以嘗試不同的xy值來確認這種關系。

x = 12
y = 5
min(x, y) <= (x+y)/2 <= max(x, y)
True

字符串比較

字符串也可以比較,他們的順序是字典序。 較短的字符串小于以較短的字符串開頭的較長的字符串。

'Dog' > 'Catastrophe' > 'Cat'

我們回到隨機選擇。 回想一下由兩個元素組成的數(shù)組two_groups,treatmentcontrol。 為了看一個隨機分配的個體是否去了實驗組,你可以使用比較:

np.random.choice(two_groups) == 'treatment'
False

和以前一樣,隨機選擇并不總是一樣的,所以比較的結果也不總是一樣的。 這取決于是選擇treatment還是control。 對于任何涉及隨機選擇的單元格,多次運行單元格來獲得結果的變化是一個好主意。

比較數(shù)組和值

回想一下,我們可以對數(shù)組中的很多數(shù)字執(zhí)行算術運算。 例如,make_array(0, 5, 2)*2等同于make_array(0, 10, 4)。 以類似的方式,如果我們比較一個數(shù)組和一個值,則數(shù)組的每個元素都與該值進行比較,并將比較結果求值為布爾值數(shù)組。

tosses = make_array('Tails', 'Heads', 'Tails', 'Heads', 'Heads')
tosses == 'Heads'
array([False,  True, False,  True,  True], dtype=bool)

numpy方法count_nonzero計算數(shù)組的非零(即True)元素的數(shù)量。

np.count_nonzero(tosses == 'Heads')
3

條件語句

在許多情況下,行動和結果取決于所滿足的一組特定條件。例如,隨機對照試驗的個體如果被分配給實驗組,則接受實驗。賭徒如果贏了賭注就賺錢。

在本節(jié)中,我們將學習如何使用代碼來描述這種情況。條件語句是一個多行語句,它允許 Python 根據表達式的真值選擇不同的選項。雖然條件語句可以出現(xiàn)在任何地方,但它們通常出現(xiàn)在函數(shù)體內,以便根據參數(shù)值執(zhí)行可變的行為。

條件語句總是以if開頭,這是一行,后面跟著一個縮進的主體。只有當if后面的表達式(稱為if表達式)求值為真時,才會執(zhí)行主體。如果if表達式的計算結果為False,則跳過if的主體。

讓我們開始定義一個返回數(shù)字符號的函數(shù)。

def sign(x):

    if x > 0:
        return 'Positive'
sign(3)
'Positive'

如果輸入是正數(shù),則此函數(shù)返回正確的符號。 但是,如果輸入不是正數(shù),那么if表達式的計算結果為false,所以return語句被跳過,函數(shù)調用沒有值(為None)。

sign(-3)

所以,讓我們改進我們的函數(shù)來返回負數(shù),如果輸入是負數(shù)。 我們可以通過添加一個elif子句來實現(xiàn),其中elif是 Python 的else, if的縮寫。

def sign(x):

    if x > 0:
        return 'Positive'

    elif x < 0:
        return 'Negative'

現(xiàn)在當輸入為-3時,sign返回正確答案。

sign(-3)
'Negative'

那么如果輸入是0呢?為了處理這個情況,我們可以添加elif子句:

def sign(x):

    if x > 0:
        return 'Positive'

    elif x < 0:
        return 'Negative'

    elif x == 0:
        return 'Neither positive nor negative'
sign(0)
'Neither positive nor negative'

與之等價,我們可以用else子句替換最后的elif子句,只有前面的所有比較都是false,才會執(zhí)行它的正文。 也就是說,輸入值等于0的時候。

def sign(x):

    if x > 0:
        return 'Positive'

    elif x < 0:
        return 'Negative'

    else:
        return 'Neither positive nor negative'
sign(0)
'Neither positive nor negative'

一般形式

條件語句也可以有多個具有多個主體的子句,只有其中一個主體可以被執(zhí)行。 多子句的條件語句的一般格式如下所示。

if <if expression>:
    <if body>
elif <elif expression 0>:
    <elif body 0>
elif <elif expression 1>:
    <elif body 1>
...
else:
    <else body>

總是只有一個if子句,但是可以有任意數(shù)量的elif子句。 Python 將依次求解頭部的ifelif表達式,直到找到一個真值,然后執(zhí)行相應的主體。 else子句是可選的。 當提供else頭部時,只有在前面的子句的頭部表達式都不為真時才執(zhí)行else頭部。 else子句必須總是在最后(或根本沒有)。

示例:"另一個"

現(xiàn)在我們將使用條件語句來定義一個看似相當虛假和對立的函數(shù),但是在本章后面的章節(jié)中會變得方便。 它需要一個數(shù)組,包含兩個元素(例如,redblue),以及另一個用于比較的元素。 如果該元素為red,則該函數(shù)返回blue。 如果元素是(例如)blue,則函數(shù)返回red。 這就是為什么我們要將函數(shù)稱為other_one。

def other_one(x, a_b):

    """Compare x with the two elements of a_b;
    if it is equal to one of them, return the other one;
    if it is not equal to either of them, return an error message.
    """
    if x == a_b.item(0):
        return a_b.item(1)

    elif x == a_b.item(1):
        return a_b.item(0)

    else:
        return 'The input is not valid.'
colors = make_array('red', 'blue')
other_one('red', colors)
'blue'
other_one('blue', colors)
'red'
other_one('potato', colors)
'The input is not valid.'

迭代

編程中經常出現(xiàn)這樣的情況,特別是在處理隨機性時,我們希望多次重復一個過程。 例如,要檢查np.random.choice是否實際上是隨機選取的,我們可能需要多次運行下面的單元格,以查看Heads是否以大約 50% 的幾率出現(xiàn)。

np.random.choice(make_array('Heads', 'Tails'))
'Heads'

我們可能希望重新運行代碼,帶有稍微不同的輸入或其他稍微不同的行為。 我們可以多次復制粘貼代碼,但是這很枯燥,容易出現(xiàn)拼寫錯誤,如果我們想要這樣做一千次或一百萬次,忘記它吧。

更自動化的解決方案是使用for語句遍歷序列的內容。 這被稱為迭代。 for語句以單詞for開頭,后面跟著一個名字,我們要把這個序列中的每個項目賦給它,后面跟著單詞in,最后以一個表達式結束,它求值為一個序列。 對于序列中的每個項目,for語句的縮進主體執(zhí)行一次。

for i in np.arange(3):
    print(i)
0
1
2

想象一下,沒有for語句的情況下,完全實現(xiàn)for語句功能的代碼,這樣很有幫助。 (這被稱為循環(huán)展開。)for語句簡單地復制了內部的代碼,但是在每次迭代之前,它從給定的序列中將我們選擇的名稱賦為一個新的值。 例如,以下是上面循環(huán)的展開版本:

i = np.arange(3).item(0)
print(i)
i = np.arange(3).item(1)
print(i)
i = np.arange(3).item(2)
print(i)
0
1
2

譯者注:實際的實現(xiàn)方式不是這樣,但是效果一樣。這里不做深究。

請注意,我的名字是任意的,就像我們用=賦值的名字一樣。

在這里我們用一個更為現(xiàn)實的方式使用for語句:我們從數(shù)組中打印5個隨機選項。

coin = make_array('Heads', 'Tails')

for i in np.arange(5):
    print(np.random.choice(make_array('Heads', 'Tails')))
Heads
Heads
Tails
Heads
Heads

在這種情況下,我們只執(zhí)行了幾次完全相同的(隨機)操作,所以我們for語句中的代碼實際上并不涉及到i。

擴展數(shù)組

雖然上面的for語句確實模擬了五次硬幣投擲的結果,但結果只是簡單地打印出來,并不是我們可以用來計算的形式。 因此,for語句的典型用法是創(chuàng)建一個結果數(shù)組,每次都擴展它。

numpy中的append方法可以幫助我們實現(xiàn)它。 調用np.append(array_name,value)將求出一個新的數(shù)組,它是由value擴展的array_name。在使用append時請記住,數(shù)組的所有條目必須具有相同的類型。

pets = make_array('Cat', 'Dog')
np.append(pets, 'Another Pet')
array(['Cat', 'Dog', 'Another Pet'], 
      dtype='<U11')

這會使pets數(shù)組保持不變。

pets
array(['Cat', 'Dog'], 
      dtype='<U3')

但是在擴展數(shù)組的時候,通常使用for循環(huán)來修改它很方便。 這通過將擴展后的數(shù)組賦給原始數(shù)組的相同名稱來實現(xiàn)。

pets = np.append(pets, 'Another Pet')
pets
array(['Cat', 'Dog', 'Another Pet'], 
      dtype='<U11')

示例:計算正面的數(shù)量

現(xiàn)在我們可以模擬一個硬幣的五次投擲,并把結果放入一個數(shù)組中。 我們將從創(chuàng)建一個空數(shù)組開始,然后附加每次投擲的結果。

coin = make_array('Heads', 'Tails')

tosses = make_array()

for i in np.arange(5):
    tosses = np.append(tosses, np.random.choice(coin))

tosses
array(['Tails', 'Heads', 'Tails', 'Heads', 'Tails'], 
      dtype='<U32')

讓我們將for語句展開,重寫單元格。

coin = make_array('Heads', 'Tails')

tosses = make_array()

i = np.arange(5).item(0)
tosses = np.append(tosses, np.random.choice(coin))
i = np.arange(5).item(1)
tosses = np.append(tosses, np.random.choice(coin))
i = np.arange(5).item(2)
tosses = np.append(tosses, np.random.choice(coin))
i = np.arange(5).item(3)
tosses = np.append(tosses, np.random.choice(coin))
i = np.arange(5).item(4)
tosses = np.append(tosses, np.random.choice(coin))

tosses
array(['Heads', 'Heads', 'Tails', 'Tails', 'Heads'], 
      dtype='<U32')

通過將結果捕獲到數(shù)組中,我們自己有能力使用數(shù)組方法進行計算。 例如,我們可以使用np.count_nonzero來計算五次投擲中的正面數(shù)量。

np.count_nonzero(tosses == 'Heads')
2

迭代是一個強大的技術。 例如,通過為 1000 次投擲運行完全相同的代碼,而不是5次,我們可以計算1000次投擲的正面數(shù)量。

tosses = make_array()

for i in np.arange(1000):
    tosses = np.append(tosses, np.random.choice(coin))

np.count_nonzero(tosses == 'Heads')
481

示例:100 次投擲中的正面數(shù)量

預測 100 次硬幣投擲中有 50 個正面是很自然的,或多或少。

但多少是“或多或少”呢? 獲得正好 50 個正面的幾率是多少? 像數(shù)據科學這樣的問題,不僅因為它們涉及隨機性的有趣方面,而且因為它們可以用于分析試驗,其中實驗和控制組的分配由硬幣的投擲決定。

在這個例子中,我們將模擬以下實驗的 10,000 次重復:

  • 擲硬幣 100 次,記錄正面數(shù)量。

我們的結果的直方圖會讓我們了解有多少個正面。

作為一個預熱,請注意,np.random.choice接受可選的第二個參數(shù)來指定選擇的數(shù)量。 默認情況下,選擇使用替換來進行。 這里是一個硬幣 10 次投擲的模擬:

np.random.choice(coin, 10)
array(['Tails', 'Heads', 'Heads', 'Tails', 'Tails', 'Heads', 'Tails',
       'Tails', 'Heads', 'Tails'], 
      dtype='<U5')

現(xiàn)在我們來研究 100 次投擲。 我們將首先創(chuàng)建一個名為heads的空數(shù)組。 然后,在每個一萬次重復中,我們會拋硬幣 100 次,計算正面的數(shù)量,并將其附加到heads上。

N = 10000

heads = make_array()

for i in np.arange(N):
    tosses = np.random.choice(coin, 100)
    heads = np.append(heads, np.count_nonzero(tosses == 'Heads'))

heads
array([ 46.,  64.,  59., ...,  56.,  54.,  56.])

讓我們將結果收集到表格中,并繪制直方圖:

results = Table().with_columns(
    'Repetition', np.arange(1, N+1),
    'Number of Heads', heads
)

results
Repetition Number of Heads
1 46
2 64
3 59
4 57
5 54
6 47
7 45
8 50
9 44
10 57

(省略了 9990 行)

這里是數(shù)據的直方圖,桶的寬度為 1,中心為每個正面數(shù)量的值。

results.select('Number of Heads').hist(bins=np.arange(30.5, 69.6, 1))

https://gitee.com/wizardforcel/data8-textbook-zh/raw/master/img/8-1.png

毫不奇怪,直方圖看起來大約關于 50 個正面左右對稱。 50 處的條形的高度大約是每單位 8%。 由于每個條形的寬度都是 1 個單位,這就是說,8% 的重復正好產生了 50 個正面。 這不是一個很大的百分比,但是與其他數(shù)量的正面相比,這是最大的。

直方圖還顯示,在幾乎所有的重復中,100 次投擲的正面數(shù)量在 35 到 65 之間。事實上,大部分的重復產生 45 到 55 個正面數(shù)量。

理論上,正面數(shù)量可能在 0 到 100 之間,但模擬顯示可能值的范圍要小得多。

這是一個更普遍現(xiàn)象的例子,關于擲硬幣中的變化,我們將在后面看到。

Monty Hall 問題

多年來這個問題已經使許多人感到困惑,包括數(shù)學家在內。 讓我們看看我們是否可以解決。

這個設定來源于一個名為“讓我們做個交易”(Let's Make a Deal)的電視游戲節(jié)目。Monty Hall 在二十世紀六十年代主持了這個節(jié)目,從此產生了一些副產品。 這個節(jié)目令人興奮的一部分是,雖然參賽者有機會贏得大獎,但他們可能最終會選擇不那么理想的“zonks”。 這就是現(xiàn)在所謂的 Monty Hall 問題的基礎。

這個設定是一個游戲節(jié)目,參賽者面對三個閉著的門。 在其中一扇門的后面是一輛奇特的汽車,另外兩扇門后面有一只山羊。 參賽者不知道汽車的位置,必須按照以下規(guī)則進行嘗試。

  • 參賽者進行初步選擇,但不打開那個門。
  • 其他兩個門中至少有一個門的后面必須有一只山羊。Monty 打開這些門之一來展示山羊,維基百科中顯示了他所有的榮耀。

https://gitee.com/wizardforcel/data8-textbook-zh/raw/master/img/8-2.png

  • 還剩下兩個門,其中一個是參賽者的原始選擇。 其中一扇門后面有車,另一扇有一只山羊。 參賽者現(xiàn)在可以選擇打開兩扇門中的哪一扇。

參賽者需要作出決定。 如果她想要這輛車,她應該選擇打開哪扇門? 她應該堅持最初的選擇,還是轉向另一個門? 這是 Monty Hall 問題。

解法

在涉及幾率的任何問題中,重要的隨機性的假設。 假設有三分之一的幾率,參賽者的最初選擇是后面有車的門,這是合理的。

在這個假設下,解決這個問題的方法非常簡單,盡管簡單的解決方案并不能說服每個人。 無論如何就是這樣。

  • 汽車在原來選擇的門后面的幾率是 1/3。
  • 汽車在原來選擇的門后面或者剩余的門后面。 它不能在其他地方。
  • 因此,汽車在剩余的門后的幾率是 2/3。
  • 因此,選手應該更改選擇。
  • 就是這樣,故事結束了。

不相信? 那么讓我們模擬游戲,看看結果如何。

模擬

我們開始建立兩個實用的數(shù)組,doorsgoats,這會讓我們區(qū)分三個門和兩只山羊。

doors = make_array('Car', 'Goat 1', 'Goat 2')
goats = make_array('Goat 1', 'Goat 2')

現(xiàn)在我們定義一個函數(shù)monty_hall來模擬游戲,并按照這個順序返回含有三個字符串的數(shù)組:

  • 參賽選手的原始選擇的什么
  • Monty 排除了什么
  • 剩下的門是什么

如果選手的原始選擇是帶山羊的門,蒙蒂必須扔掉另一只山羊,剩下的就是這輛車。 如果最初的選擇是帶車的門,蒙蒂必須扔掉兩只山羊中的一只,剩下的就是另一只羊。

因此很顯然,在前一節(jié)中定義的函數(shù)將是有用的。 它需要一個字符串和一個兩個元素的數(shù)組; 如果字符串等于其中一個元素,則返回另一個元素。

def other_one(x, a_b):
    if x == a_b.item(0):
        return a_b.item(1)
    elif x == a_b.item(1):
        return a_b.item(0)
    else:
        return 'Input Not Valid'

如果選手的原始選擇是山羊,游戲的結果是這二者之一:

original = 'Goat 1'
make_array(original, other_one(original, goats), 'Car')
array(['Goat 1', 'Goat 2', 'Car'], 
      dtype='<U6')
original = 'Goat 2'
make_array(original, other_one(original, goats), 'Car')
array(['Goat 2', 'Goat 1', 'Car'], 
      dtype='<U6')

現(xiàn)在我們可以把所有這些代碼放到monty_hall函數(shù)中,來模擬一次游戲的結果。 該函數(shù)不帶任何參數(shù)。

參賽者的原始選擇將是三門之中隨機選擇的門。

為了檢查原始選擇是否是山羊,我們首先寫一個名為is_goat的小函數(shù):

def is_goat(door_name):

    """ Check whether the name of a door (a string) is a Goat.
    
    Examples:
    =========
    
    >>> is_goat('Goat 1')
    True
    >>> is_goat('Goat 2')
    True
    >>> is_goat('Car')
    False
    """
    if door_name == "Goat 1":
        return True
    elif door_name == "Goat 2":
        return True
    else:
        return False


def monty_hall():

    """ Play the Monty Hall game once
    and return an array of three strings:
    
    original choice, what Monty throws out, what remains
    """

    original = np.random.choice(doors)

    if is_goat(original):
        return make_array(original, other_one(original, goats), 'Car')

    else:
        throw_out = np.random.choice(goats)
        return make_array(original, throw_out, other_one(throw_out, goats))

讓我們玩幾次這個游戲。這里是一個結果。你應該運行幾次單元格來觀察結果如何變化。

monty_hall()
array(['Car', 'Goat 2', 'Goat 1'], 
      dtype='<U6')

為了衡量不同結果發(fā)生的頻率,我們必須玩多次游戲并收集結果。 為此,我們將使用for循環(huán)。

我們將首先定義三個空數(shù)組,每個數(shù)組對應原始選擇,Monty 排除了什么,剩下的是什么。然后我們將玩這個游戲 N 次并收集結果。我們已經將 N 設為 10,000,但是你可以改變它。

# Number of times we'll play the game
N = 10000

original = make_array()     # original choice
throw_out = make_array()    # what Monty throws out
remains = make_array()      # what remains

for i in np.arange(N): 
    result = monty_hall()    # the result of one game

    # Collect the results in the appropriate arrays
    original = np.append(original, result.item(0))
    throw_out = np.append(throw_out, result.item(1))
    remains = np.append(remains, result.item(2))

# The for-loop is done! Now put all the arrays together in a table.
results = Table().with_columns(
    'Original Door Choice', original,
    'Monty Throws Out', throw_out,
    'Remaining Door', remains
)
results
Original Door Choice Monty Throws Out Remaining Door
Car Goat 1 Goat 2
Goat 1 Goat 2 Car
Goat 2 Goat 1 Car
Car Goat 2 Goat 1
Car Goat 2 Goat 1
Goat 1 Goat 2 Car
Goat 1 Goat 2 Car
Goat 1 Goat 2 Car
Goat 2 Goat 1 Car
Goat 1 Goat 2 Car

(省略了 9990 行)

為了看看選手是否應該堅持原來的選擇或更改,讓我們看看她的兩個選項后面的車的頻率。

results.group('Original Door Choice')
Original Door Choice count
Car 3312
Goat 1 3382
Goat 2 3306
results.group('Remaining Door')
Remaining Door count
Car 6688
Goat 1 1640
Goat 2 1672

我們的解決方案說明了,這輛車有三分之二的幾率在剩下的門后面,這是相當不錯的近似值。 如果參賽者更改了她的選擇,她有兩倍的可能性會得到車。

為了使結果可視化,我們可以將上面的兩個表格連接在一起并繪制疊加的條形圖。

results_o = results.group('Original Door Choice')
results_r = results.group('Remaining Door')
joined = results_o.join('Original Door Choice', results_r, 'Remaining Door')
combined = joined.relabeled(0, 'Item').relabeled(1, 'Original Door').relabeled(2, 'Remaining Door')
combined
Item Original Door Remaining Door
Car 3312 6688
Goat 1 3382 1640
Goat 2 3306 1672
combined.barh(0)

https://gitee.com/wizardforcel/data8-textbook-zh/raw/master/img/8-3.png

注意三條藍色條形幾乎相等 - 原始選擇有同等可能是三個可用條目中的任何一條。 但是,汽車對應的金色條形是藍色條形的兩倍。

模擬證實了,如果參賽者改變選擇,她有兩倍的可能性獲勝。

發(fā)現(xiàn)概率

幾個世紀以來,對于什么是概率存在哲學爭論。有些人認為概率是相對頻率;其他人認為他們是長期的相對頻率較長;還有一些人認為概率是個人不確定性程度的主觀測量。

在這個課程中,大多數(shù)概率將是相對頻率,盡管許多人會有主觀的解釋。無論如何,在不同的解釋中,概率計算和組合的方式是一致的。

按照慣例,概率是介于 0 和 1 之間的數(shù)字,或者 0% 和 100% 之間。不可能的事件概率為 0。確定的事件概率為 1。

數(shù)學是準確發(fā)現(xiàn)概率的主要工具,盡管計算機也可用于此目的。模擬可以提供出色的近似,具有很高的概率。在本節(jié)中,我們將以非正式方式制定一些簡單的規(guī)則來管理概率的計算。在隨后的章節(jié)中,我們將回到模擬來近似復雜事件的概率。

我們將使用標準符號 https://www.zhihu.com/equation?tex=P%28%5Cmbox%7Bevent%7D%29 來表示“事件”發(fā)生的概率,我們將交替使用“幾率”和“概率”兩個字。

事件不會發(fā)生的時候

如果事件發(fā)生的概率是 40%,不發(fā)生的幾率就是 60%。這個自然的計算可以這樣秒速:

https://www.zhihu.com/equation?tex=P%28%5Cmbox%7Ban%20event%20doesn%27t%20happen%7D%29%20%7E%3D%7E%201%20-%20P%28%5Cmbox%7Bthe%20event%20happens%7D%29

所有結果等可能的時候

如果你投擲一個普通的骰子,一個自然的假設是,所有六個面都是等可能的。 那么一個面出現(xiàn)的概率可以很容易地計算出來。 例如,骰子顯示偶數(shù)的幾率是:

https://www.zhihu.com/equation?tex=%5Cfrac%7B%5Cmbox%7Bnumber%20of%20even%20faces%7D%7D%7B%5Cmbox%7Bnumber%20of%20all%20faces%7D%7D%20%7E%3D%7E%20%5Cfrac%7B%5C%23%5C%7B2%2C%204%2C%206%5C%7D%7D%7B%5C%23%5C%7B1%2C%202%2C%203%2C%204%2C%205%2C%206%5C%7D%7D%20%7E%3D%7E%20%5Cfrac%7B3%7D%7B6%7D

與之相似:

https://www.zhihu.com/equation?tex=P%28%5Cmbox%7Bdie%20shows%20a%20multiple%20of%203%7D%29%20%7E%3D%7E%20%5Cfrac%7B%5C%23%5C%7B3%2C%206%5C%7D%7D%7B%5C%23%5C%7B1%2C%202%2C%203%2C%204%2C%205%2C%206%5C%7D%7D%20%7E%3D%7E%20%5Cfrac%7B2%7D%7B6%7D

通常:

https://www.zhihu.com/equation?tex=P%28%5Cmbox%7Ban%20event%20happens%7D%29%20%7E%3D%7E%20%5Cfrac%7B%5C%23%5C%7B%5Cmbox%7Boutcomes%20that%20make%20the%20event%20happen%7D%5C%7D%7D%20%7B%5C%23%5C%7B%5Cmbox%7Ball%20outcomes%7D%5C%7D%7D

前提是所有的結果都是等可能的。

并非所有的隨機現(xiàn)象都像骰子一樣簡單。 下面的兩個主要的概率規(guī)則甚至允許數(shù)學家在復雜的情況下找到概率。

兩個事件必須同時發(fā)生時

假設你有一個盒子,包含三張紙條:一張紅色,一張藍色和一張綠色。 假設你隨機抽兩張紙條而不放回;也就是你把三張紙條打亂,抽一張,打亂其余兩張,再從這兩張中抽出一張。 你先得到綠色紙條,然后是紅色紙條的幾率是多少?

有六種可能的顏色對:RB,BR,RG,GR,BG,GB(我們已經縮寫了每種顏色的名字,就是它的第一個字母)。 所有這些都是抽樣方案是等可能的,只有其中一個(GR)使事件發(fā)生。所以:

https://www.zhihu.com/equation?tex=%24%24%20P%28%5Cmbox%7Bgreen%20first%2C%20then%20red%7D%29%20%7E%3D%7E%20%5Cfrac%7B%5C%23%5C%7B%5Cmbox%7BGR%7D%5C%7D%7D%7B%5C%23%5C%7B%5Cmbox%7BRB%2C%20BR%2C%20RG%2C%20GR%2C%20BG%2C%20GB%7D%5C%7D%7D%20%7E%3D%7E%20%5Cfrac%7B1%7D%7B6%7D

但是還有另外一種方法來得到答案,可以用兩個階段來思考這個事件。 必須首先抽取綠色紙條。幾率是 1/3,也就是說在所有實驗的大約 1/3 的重復中,先抽取了綠色紙條,但事件還沒完成。在這 1/3 的重復中,必須再次抽取紅色紙條。這個發(fā)生在大約 1/2 的重復中,所以:

https://www.zhihu.com/equation?tex=P%28%5Cmbox%7Bgreen%20first%2C%20then%20red%7D%29%20%7E%3D%7E%20%5Cfrac%7B1%7D%7B2%7D%20%7E%5Cmbox%7Bof%7D%7E%20%5Cfrac%7B1%7D%7B3%7D%20%7E%3D%7E%20%5Cfrac%7B1%7D%7B6%7D

這個計算通常按照事件順序,像這樣:

https://www.zhihu.com/equation?tex=P%28%5Cmbox%7Bgreen%20first%2C%20then%20red%7D%29%20%7E%3D%7E%20%5Cfrac%7B1%7D%7B3%7D%20%7E%5Ctimes%7E%20%5Cfrac%7B1%7D%7B2%7D%20%7E%3D%7E%20%5Cfrac%7B1%7D%7B6%7D

因數(shù) 1/2 叫做“假設第一次出現(xiàn)了綠色紙條,第二次出現(xiàn)紅色紙條的條件幾率”。

通常,我們擁有乘法規(guī)則:

https://www.zhihu.com/equation?tex=P%28%5Cmbox%7Btwo%20events%20both%20happen%7D%29%20%7E%3D%7E%20P%28%5Cmbox%7Bone%20event%20happens%7D%29%20%5Ctimes%20P%28%5Cmbox%7Bthe%20other%20event%20happens%2C%20given%20that%20the%20first%20one%20happened%7D%29

兩個事件同時發(fā)生的概率,等于第一個事件發(fā)生的概率,乘上第一個事件發(fā)生的情況下第二個事件發(fā)生的概率。

因此,這里有兩個條件 - 一個事件必須發(fā)生,另一個也是 - 幾率是分數(shù)的分數(shù),這比兩個因數(shù)的任何一個都要小。 滿足的條件越多,滿足的可能性就越小。

事件以兩種不同的方式發(fā)生

相反,假設我們希望兩張紙條中的一張是綠色的,另一張是紅色的。 此事件不指定顏色必須出現(xiàn)的順序。所以他們可以以任何順序出現(xiàn)。

解決這樣的問題的一個好方法就是對事件進行劃分,以便它正好能夠以幾種不同的方式之一發(fā)生。 “一綠一紅”的自然劃分是:GR,RG。

根據上面的計算,GR 和 RG 每個的幾率都是 1/6。所以你可以通過把它們相加來計算一綠一紅的概率。

https://www.zhihu.com/equation?tex=P%28%5Cmbox%7Bone%20green%20and%20one%20red%7D%29%20%7E%3D%7E%20P%28%5Cmbox%7BGR%7D%29%20&plus;%20P%28%5Cmbox%7BRG%7D%29%20%7E%3D%7E%20%5Cfrac%7B1%7D%7B6%7D%20&plus;%20%5Cfrac%7B1%7D%7B6%7D%20%7E%3D%7E%20%5Cfrac%7B2%7D%7B6%7D

通常,我們擁有加法規(guī)則:

https://www.zhihu.com/equation?tex=P%28%5Cmbox%7Ban%20event%20happens%7D%29%20%7E%3D%7E%20P%28%5Cmbox%7Bfirst%20way%20it%20can%20happen%7D%29%20&plus;%20P%28%5Cmbox%7Bsecond%20way%20it%20can%20happen%7D%29%20%7E%7E%7E%20%5Cmbox%7B%7D

事件發(fā)生的概率,等于以第一種方式發(fā)生的概率,加上以第二種方式發(fā)生的概率。

只要事件正好以兩種方式之一發(fā)生。

因此,當事件以兩種不同的方式之一發(fā)生時,發(fā)生的幾率是一些幾率的總和,因此比任何一種方式的幾率都大。

乘法規(guī)則可以自然擴展到兩個以上的事件,我們將在下面看到。 所以這個加法規(guī)則也有自然的擴展,事件可以以幾種不同的方式之一發(fā)生。

我們將所有這些規(guī)則組合成示例,并用示例來結束該部分。

至少有一個成功

數(shù)據科學家經常使用來自總體的隨機樣本。 有時候問題就來了,就是總體中的一個特定個體選進樣本的可能性。為了找出幾率,這個個體被稱為“成功”,問題是要找到樣本包含成功的幾率。

要看看如何計算這樣的幾率,我們從一個更簡單的設定開始:投擲硬幣兩次。

如果你投擲硬幣兩次,有四個等可能的結果:HH,HT,TH 和 TT。 我們把正面縮寫為 H ,反面縮寫為 T。至少有一個正面的幾率是 3/4。

得出這個答案的另一種方法是,弄清楚如果你不能得到至少一個正面,會發(fā)生什么事情:這兩次投擲都必須是反面。所以:

https://www.zhihu.com/equation?tex=P%28%5Cmbox%7Bat%20least%20one%20head%20in%20two%20tosses%7D%29%20%7E%3D%7E%201%20-%20P%28%5Cmbox%7Bboth%20tails%7D%29%20%7E%3D%7E%201%20-%20%5Cfrac%7B1%7D%7B4%7D%20%7E%3D%7E%20%5Cfrac%7B3%7D%7B4%7D

要注意根據乘法規(guī)則:

https://www.zhihu.com/equation?tex=P%28%5Cmbox%7Bboth%20tails%7D%29%20%7E%3D%7E%20%5Cfrac%7B1%7D%7B4%7D%20%7E%3D%7E%20%5Cfrac%7B1%7D%7B2%7D%20%5Ccdot%20%5Cfrac%7B1%7D%7B2%7D%20%7E%3D%7E%20%5Cleft%28%5Cfrac%7B1%7D%7B2%7D%5Cright%29%5E2

這兩個觀察使我們能夠在任何給定數(shù)量的投擲中找到至少一個正面的幾率。 例如:

https://www.zhihu.com/equation?tex=P%28%5Cmbox%7Bat%20least%20one%20head%20in%2017%20tosses%7D%29%20%7E%3D%7E%201%20-%20P%28%5Cmbox%7Ball%2017%20are%20tails%7D%29%20%7E%3D%7E%201%20-%20%5Cleft%28%5Cfrac%7B1%7D%7B2%7D%5Cright%29%5E%7B17%7D

而現(xiàn)在我們有能力找到在骰子的投擲中,六點至少出現(xiàn)一次的幾率:

https://www.zhihu.com/equation?tex=P%28%5Cmbox%7Ba%20single%20roll%20is%20not%206%7D%29%20%7E%3D%7E%20P%281%29%20&plus;%20P%282%29%20&plus;%20P%283%29%20&plus;%20P%284%29%20&plus;%20P%285%29%20%7E%3D%7E%20%5Cfrac%7B5%7D%7B6%7D

https://www.zhihu.com/equation?tex=P%28%5Cmbox%7Bat%20least%20one%206%20in%20two%20rolls%7D%29%20%7E%3D%7E%201%20-%20P%28%5Cmbox%7Bboth%20rolls%20are%20not%206%7D%29%20%7E%3D%7E%201%20-%20%5Cleft%28%5Cfrac%7B5%7D%7B6%7D%5Cright%29%5E2%20%24%24%20and%20%24%24%20P%28%5Cmbox%7Bat%20least%20one%206%20in%2017%20rolls%7D%29%20%7E%3D%7E%201%20-%20%5Cleft%28%5Cfrac%7B5%7D%7B6%7D%5Cright%29%5E%7B17%7D

下表展示了,這些概率隨著投擲數(shù)量從 1 增加到 50 而增加。

rolls = np.arange(1, 51, 1)
results = Table().with_columns(
    'Rolls', rolls,
    'Chance of at least one 6', 1 - (5/6)**rolls
)
results
Rolls Chance of at least one 6
1 0.166667
2 0.305556
3 0.421296
4 0.517747
5 0.598122
6 0.665102
7 0.720918
8 0.767432
9 0.806193
10 0.838494

(省略了 40 行)

隨著投擲數(shù)量的增加,六點至少出現(xiàn)一次的幾率迅速增加。

results.scatter('Rolls')

https://gitee.com/wizardforcel/data8-textbook-zh/raw/master/img/8-4.png

在 50 次投擲中,你幾乎肯定能得到至少一個六。

results.where('Rolls', are.equal_to(50))
Rolls Chance of at least one 6
50 0.99989

像這樣的計算可以用來找到,隨機樣本中選擇特定個體的幾率。 準確的計算將取決于抽樣方案。 但是我們上面的觀察的通??梢员煌茝V:增加隨機樣本的大小增加了選擇個體的幾率。

抽樣

現(xiàn)在我們來仔細看看抽樣,例子基于top_movies.csv數(shù)據集。

top1 = Table.read_table('top_movies.csv')
top2 = top1.with_column('Row Index', np.arange(top1.num_rows))
top = top2.move_to_start('Row Index')

top.set_format(make_array(3, 4), NumberFormatter)
Row Index Title Studio Gross Gross (Adjusted) Year
0 Star Wars: The Force Awakens Buena Vista (Disney) 906,723,418 906,723,400 2015
1 Avatar Fox 760,507,625 846,120,800 2009
2 Titanic Paramount 658,672,302 1,178,627,900 1997
3 Jurassic World Universal 652,270,625 687,728,000 2015
4 Marvel's The Avengers Buena Vista (Disney) 623,357,910 668,866,600 2012
5 The Dark Knight Warner Bros. 534,858,444 647,761,600 2008
6 Star Wars: Episode I - The Phantom Menace Fox 474,544,677 785,715,000 1999
7 Star Wars Fox 460,998,007 1,549,640,500 1977
8 Avengers: Age of Ultron Buena Vista (Disney) 459,005,868 465,684,200 2015
9 The Dark Knight Rises Warner Bros. 448,139,099 500,961,700 2012

(省略了 190 行)

對表格的行進行抽樣

數(shù)據表的每一行代表一個個體;最重要的是,每個個體都是一部電影。 因此可以通過表格的行的抽樣來實現(xiàn)對個體的抽樣。

一行的內容是在同一個個體上測量的不同變量的值。 因此,行的內容的抽樣形成了每個變量值的樣本。

確定性樣本

當你只是簡單地指定,你要選擇的集合中的哪些元素時,就不會涉及任何幾率,可以創(chuàng)建確定性樣本。

你已經做了很多次了,例如使用take

top.take(make_array(3, 18, 100))
Row Index Title Studio Gross Gross (Adjusted) Year
3 Jurassic World Universal 652,270,625 687,728,000 2015
18 Spider-Man Sony 403,706,375 604,517,300 2002
100 Gone with the Wind MGM 198,676,459 1,757,788,200 1939

你也使用了where

top.where('Title', are.containing('Harry Potter'))
Row Index Title Studio Gross Gross (Adjusted) Year
22 Harry Potter and the Deathly Hallows Part 2 Warner Bros. 381,011,219 417,512,200 2011
43 Harry Potter and the Sorcerer's Stone Warner Bros. 317,575,550 486,442,900 2001
54 Harry Potter and the Half-Blood Prince Warner Bros. 301,959,197 352,098,800 2009
59 Harry Potter and the Order of the Phoenix Warner Bros. 292,004,738 369,250,200 2007
62 Harry Potter and the Goblet of Fire Warner Bros. 290,013,036 393,024,800 2005
69 Harry Potter and the Chamber of Secrets Warner Bros. 261,988,482 390,768,100 2002
76 Harry Potter and the Prisoner of Azkaban Warner Bros. 249,541,069 349,598,600 2004

雖然這些是電影的樣本,它們并不涉及幾率。

概率抽樣

很多數(shù)據科學都根據隨機樣本中的數(shù)據得到結論。 根據隨機樣本的正確解釋分析,需要數(shù)據科學家準確地檢查隨機樣本。

總體是從中抽取樣本的所有元素的集合。

概率樣本是一種樣本,在抽取樣本之前,可以計算出的元素的任何子集將進入樣本的幾率。

在概率樣本中,所有的元素不需要有相同的選中幾率。

隨機抽樣方案

例如,假設根據以下方案,從三個個體 A,B 和 C 組成的總體中選擇兩個個體:

  • 個體 A 選中概率為 1。
  • 個體 B 或 C 根據擲硬幣來選擇:如果硬幣為正面,選擇 B,否則,選擇 C。

這是一個大小為 2 的概率樣本。下面是所有非空子集的選中幾率:

A: 1 
B: 1/2
C: 1/2
AB: 1/2
AC: 1/2
BC: 0
ABC: 0

個體 A 比 B 或 C 有更高的選中幾率;的確,個體 A 肯定會被選中。由于這些差異是已知的和量化的,所以在處理樣本時可以考慮這些差異。

系統(tǒng)樣本

想象一下,總體的所有元素都列出在序列中。 抽樣的一種方法是,先從列表中選擇一個隨機的位置,然后是它后面的等間隔的位置。樣本由這些位置上的元素組成。這樣的樣本被稱為系統(tǒng)樣本。

在這里,我們將選擇頂部一些行的系統(tǒng)樣本。我們最開始隨機選取前 10 行中的一行,然后我們將選取它后面的每個第 10 行。

"""Choose a random start among rows 0 through 9;
then take every 10th row."""

start = np.random.choice(np.arange(10))
top.take(np.arange(start, top.num_rows, 10))
Row Index Title Studio Gross Gross (Adjusted) Year
6 Star Wars: Episode I - The Phantom Menace Fox 474,544,677 785,715,000 1999
16 Iron Man 3 Buena Vista (Disney) 409,013,994 424,632,700 2013
26 Spider-Man 2 Sony 373,585,825 523,381,100 2004
36 Minions Universal 336,045,770 354,213,900 2015
46 Iron Man 2 Paramount 312,433,331 341,908,200 2010
56 The Twilight Saga: New Moon Sum. 296,623,634 338,517,700 2009
66 Meet the Fockers Universal 279,261,160 384,305,300 2004
76 Harry Potter and the Prisoner of Azkaban Warner Bros. 249,541,069 349,598,600 2004
86 The Exorcist Warner Bros. 232,906,145 962,212,800 1973
96 Back to the Future Universal 210,609,762 513,740,700 1985

(省略了 10 行)

運行單元個幾次,看看輸出如何變化。

這個系統(tǒng)樣本是一個概率樣本。 在這個方案中,所有的行都有機會被選中。 例如,當且僅當?shù)?3 行被選中時,第 23 行才被選中,并且其幾率是 1/10。

但并不是所有的子集都有相同的選中幾率。 由于選中的行是等間隔的,大多數(shù)行的子集都沒有機會被選中。 唯一可能的子集是由所有間隔為 10 的行構成的子集。任何這些子集都以 1/10 的幾率被選中。 其他子集,如包含表格前 11 行的子集,選中幾率都是 0。

放回或不放回的隨機抽樣

在這個課程中,我們將主要處理兩個最直接的抽樣方法。

首先是帶放回的隨機抽樣,它(如我們前面所見)是np.random.choice從數(shù)組中抽樣時的默認行為。

另一個稱為“簡單隨機樣本”,是隨機抽取的樣本,不帶放回。在下一個個體被抽中之前,抽中的個體不會放回總體。例如,當你發(fā)牌時,就會發(fā)生這種抽樣。

在下一章中,我們將使用模擬來研究帶放回和不放回的大樣本隨機抽取。

繪制隨機樣本需要謹慎和精確。這不是隨便的,即使這是“隨機”一詞的口語意義。如果你站在街頭,選取前十名經過的人作為樣本,你可能會認為你在隨機抽樣,因為你沒有選擇誰走過。但它不是一個隨機樣本 - 這是一個方便的例子。你沒有提前知道每個人進入樣本的概率,也許甚至你沒有具體指定誰在總體中。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容