φυβλαςのβλογ
phyblasのブログ



ความน่าจะเป็นเบื้องต้นสำหรับเขียนโปรแกรม บทที่ ๕: การแจกแจงทวินาม
เขียนเมื่อ 2020/07/25 19:09
แก้ไขล่าสุด 2023/08/26 13:16

ต่อจาก บทที่ ๔

บทที่แล้วได้พูดถึงการแจกแจงความน่าจะเป็นของค่าแบบไม่ต่อเนื่องไปแล้ว สำหรับในบทนี้จะพูดถึงตัวอย่างการแจกแจงความน่าจะเป็นรูปแบบหนึ่งที่พบได้บ่อยและเข้าใจได้ไม่ยาก นั่นคือการแจกแจงทวินาม (二项分布, binomial distribution)




การแจกแจงผลการโยนเหรียญ

ก่อนจะพูดถึงว่าการแจกแจงทวินามคืออะไร ขอเริ่มจากยกตัวอย่างการแจกแจงผลการโยนเหรียญ ซึ่งเป็นตัวอย่างการแจกแจงทวินามในรูปแบบที่ง่ายที่สุด

สมมุติว่ามีเหรียญ n เหรียญซึ่งมีโอกาสโยนแล้วได้หัวหรือก้อยเป็น 1/2 เท่ากัน ผลรวมจำนวนครั้งที่จะโยนได้หัวควรจะเป็นเท่าใด

กรณีนี้จำนวนครั้งที่โยนได้หัวคือตัวแปรสุ่ม เพราะขึ้นอยู่กับว่าโยนเหรียญ n ครั้งออกอะไรบ้าง แต่ละค่าก็มีความน่าจะเป็นต่างกันไป

สมมุติว่า ◎ แทนหัส ◯ แทนก้อย โยนเหรียญ 1 ครั้งมีโอกาสจะได้ 2 กรณีคือเหรียญนั้นเป็น ◎ กับ ◯

ให้ P(k) เป็นความน่าจะเป็นที่จะโยนเหรียญได้หัว k ครั้ง กรณีโยนเหรียญครั้งเดียวจะได้ว่า


ถ้าโยน 2​ ครั้งก็จะแบ่งเป็น 4 กรณี คือ ◎◎, ◎◯, ◯◎, ◯◯ ดังนั้นความน่าจะเป็นจะกลายเป็น


ถ้าโยน 3 ครั้งก็จะมี 8 กรณีคือ ◎◎◎, ◎◎◯, ◎◯◎, ◎◯◯, ◯◎◎, ◯◎◯, ◯◯◎, ◯◯◯ ดังนั้นความน่าจะเป็นจะกลายเป็น


ถ้าโยน 4 ครั้งก็จะมี 16 กรณีคือ
◎◎◎◎, ◎◎◎◯, ◎◎◯◎, ◎◎◯◯,
◎◯◎◎, ◎◯◎◯, ◎◯◯◎, ◎◯◯◯,
◯◎◎◎, ◯◎◎◯, ◯◎◯◎, ◯◎◯◯,
◯◯◎◎, ◯◯◎◯, ◯◯◯◎, ◯◯◯◯

ดังนั้นความน่าจะเป็นจะกลายเป็น


ไล่มาถึงตรงนี้ก็จะพอนึกภาพได้ออกว่าการแจกแจงแนวโน้มจะเป็นอย่างไรเมื่อเพิ่มจำนวนเหรียญขึ้นไป

หากโยนเหรียญ n ครั้งความน่าจะเป็นที่จะได้หัว k ครั้งเป็น


โดย C(n,k) คือจำนวนวิธีการในการจัดหมู่ (combination) ซึ่งคำนวณได้โดย


โดยเครื่องหมายตกใจในที่นี้หมายถึงแฟกทอเรียล

ในไพธอนมีฟังก์ชัน factorial() ในมอดูล math เอาไว้คำนวณค่าแฟทอเรียลได้ ลองเอามาใช้เขียนโปรแกรมเพื่อแสดงการแจกแจงตั้งแต่ n=1 ไปจนถึง n=9 ดูได้ดังนี้
import math
# n คือจำนวนเหรียญทั้งหมด
for n in range(1,9+1):
    n_hua = [] # ลิสต์เก็บความถี่ในแต่ละกรณีจำนวนที่ได้หัว k ตัว
    # k คือจำนวนเหรียญที่จะได้หัว
    for k in range(0,n+1):
        c = math.factorial(n)/(math.factorial(k)*math.factorial(n-k))
        n_hua += [c/2**n]
    print('n =',n,':',n_hua) # แสดงผล

ได้
n = 1 : [0.5, 0.5]
n = 2 : [0.25, 0.5, 0.25]
n = 3 : [0.125, 0.375, 0.375, 0.125]
n = 4 : [0.0625, 0.25, 0.375, 0.25, 0.0625]
n = 5 : [0.03125, 0.15625, 0.3125, 0.3125, 0.15625, 0.03125]
n = 6 : [0.015625, 0.09375, 0.234375, 0.3125, 0.234375, 0.09375, 0.015625]
n = 7 : [0.0078125, 0.0546875, 0.1640625, 0.2734375, 0.2734375, 0.1640625, 0.0546875, 0.0078125]
n = 8 : [0.00390625, 0.03125, 0.109375, 0.21875, 0.2734375, 0.21875, 0.109375, 0.03125, 0.00390625]
n = 9 : [0.001953125, 0.017578125, 0.0703125, 0.1640625, 0.24609375, 0.24609375, 0.1640625, 0.0703125, 0.017578125, 0.001953125]

ลักษณะเหมือนเป็นพีรามิดซ้อนกันไปเรื่อยๆ

หากเอาค่าที่ได้นี้มาวาดกราฟแสดงการแจกแจงจะได้เป็นแบบนี้



กราฟที่ได้จะมีลักษณะสมมาตรซ้ายขวา โดยค่าสูงสุดของกราฟจะอยู่ตรงกลาง กรณีแบบนี้ค่าคาดหมายก็จะอยู่ตรงกลางซึ่งเป็นจุดสูงสุดด้วย ซึ่งจะเห็นได้ว่าจุดสูงสุดอยู่ที่ n/2

ลองมาทดลองสุ่มจริงๆโดยใช้ randint ดู
import random
n = 9 # จำนวนเหรียญ
p = [0]*(n+1) # ลิสต์เก็บค่าความถี่ของจำนวนที่ออกหัวที่ได้ตั้งแต่ 0 ถึง n
# ทำซ้ำ 10000 ครั้ง
for i in range(10000):
    n_hua = 0 # จำนวนครั้งที่ออกหัว
    # ทำซ้ำ n ครั้ง
    for j in range(n):
        # สุ่ม 0 (ก้อย) หรือ 1 (หัว) ถ้าได้หัวก็บวกเพิ่ม
        n_hua += random.randint(0,1)
    # วนครบ n ครั้ง ได้จำนวนครั้งที่ออกหัว n_hua
    p[n_hua] += 1 # เพิ่มความถี่สำหรับจำนวนหัว n_hua ที่ได้นั้น
print(p) # แสดงผลความถี่สุดท้ายของแต่ละค่าที่ได้ออกมา

ได้
13, 177, 691, 1690, 2441, 2447, 1652, 703, 158, 28]

ถ้าวาดเป็นแผนภูมิแท่งแสดงก็จะได้แบบนี้



จะเห็นว่าการแจกแจงเป็นไปตามความน่าจะเป็นกรณี n=9 ซึ่งได้คำนวณไว้ข้างต้น

ลองปรับค่าจำนวนเหรียญ n ก็จะได้การแจกแจงที่ต่างกันออกไปตามที่ควรจะเป็น




การแจกแจงผลการโยนลูกเต๋า

ต่อไปจะพูดถึงที่มาของการแจกแจงแบบนี้ และขยายความไปสู่กรณีทั่วไปมากขึ้น

ที่จริงแล้วผลที่ได้นี้เป็นไปตามทฤษฎีบททวินาม (binomial theorem) ซึ่งว่าด้วยการแจกแจงของ (x+y)n


ซึ่งจะได้ว่า


ในที่นี้ x แสดงถึงเหรียญที่ออกหัว y แสดงถึงเหรียญที่ออกก้อย โดยเลขชี้กำลังของ x แสดงถึงจำนวนเหรียญที่ออกหัว ดังนั้นสัมประสิทธิ์ของแต่ละพจน์จะแสดงความถี่ของการออกเป็นจำนวนครั้งเท่านั้น

ซึ่งสัมประสิทธิ์นี้ก็คือ C(n,k) ดังนั้นเมื่อหารด้วยจำนวนเหตุการณ์ทั้งหมด ซึ่งก็คือ 2n ก็จะเป็นความน่าจะเป็นที่จะออกหัวเป็นจำนวนครั้งเท่านั้น


การโยนเหรียญหัวก้อยนั้นเป็นตัวอย่างกรณี ๒ ทางเลือกที่มีโอกาสเท่าๆกันคือ 1/2 แต่เหตุการณ์โดยทั่วไปอาจมีความน่าจะเป็นในการเกิดขึ้นเป็นเท่าไหร่ก็ได้ตั้งแต่ 0 ถึง 1

ยกตัวอย่างเช่นทอยลูกเต๋าแล้วพิจารณาเหตุการณ์ที่จะได้ 1 กับเหตการณ์ที่จะได้แต้มอื่น แบบนี้ความน่าจะเป็นที่จะทอยได้ 1 คือ


กรณีนี้จะต่างจากกรณีโยนเหรียญตรงที่โอกาสมีแค่ 1/6 ไม่ใช่ 1/2 โอกาสไม่ได้เท่ากัน ดังนั้นจะแจกแจงแบบกรณีโยนเหรียญไม่ได้

การโยนเหรียญนั้นเทียบได้กับ ((x+y)/2)n แต่ถ้าโอกาสไม่เท่ากันก็จะเปลี่ยนเป็นตามสัดส่วนนั้น เช่นกรณีลูกเต๋าก็จะเป็น


ลองเขียนโปรแกรมแสดงการแจกแจงเช่นเดียวกับกรณีโยนเหรียญ
import math
for n in range(1,24+1):
    n_dai1 = [] # ลิสต์เก็บความถี่
    # k คือจำนวนหน้าลูกเต๋าที่ออกแต้ม 1
    for k in range(0,n+1):
        c = math.factorial(n)/(math.factorial(k)*math.factorial(n-k))
        n_dai1 +=[c*((1/6)**k)*((5/6)**(n-k))]
    print('n = %d:\n'%n, n_dai1)

ค่าที่แสดงออกมาจะมีเยอะมาก ในที่นี้ของไม่นำมาแสดงตรงนี้ แต่หากวาดกราฟก็จะได้เช่นนี้



การแจกแจงส่วนใหญ่จะอยู่ในส่วนของจำนวนน้อยๆ โดยจุดสูงสุดในกรณีที่ลูกเต๋าเป็น 6,12,18,24 คือ 1,2,3,4 ตามลำดับ ซึ่งก็เป็นไปตามสามัญสำนึกที่ว่าถ้าโอกาส 1/6 โยน 6 ครั้งก็ควรจะได้ครั้งหนึ่ง

คราวนี้จำลองการโยนลูกเต๋าดู
import random
n = 24 # จำนวนเหรียญ
p = [0]*(n+1) # ลิสต์เก็บค่าความถี่ของจำนวนที่หน้าเต๋าได้แต้ม 1 ได้ตั้งแต่ 0 ถึง n
# ทำซ้ำ 10000 ครั้ง
for i in range(10000):
    n_dai1 = 0 # บวกสะสมจำนวนครั้งที่ได้แต้ม 1
    for j in range(n):
        # สุ่มเลข 1-6 ถ้าได้ 1 ก็บวกเพิ่ม
        if(random.randint(1,6)==1):
            n_dai1 += 1
    p[n_dai1] += 1
print(p) # แสดงผลความถี่สุดท้ายของแต่ละค่าที่ได้ออกมา

ได้
[116, 626, 1372, 2075, 2153, 1706, 1076, 539, 208, 88, 31, 8, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

ซึ่งก็สอดคล้องกับการกระจายความน่าจะเป็นที่คำนวณได้ และจะเห็นว่าตัวหลังๆเป็น 0 หมดเพราะความเป็นไปได้ต่ำมาก

นำมาวาดแผนภูมิแท่งแสดงความถี่ก็จะได้แบบนี้






รูปทั่วไปของการแจกแจงทวินาม

จากตัวอย่างกรณีโยนเหรียญและทอยลูกเต๋า สามารถนำไปสู่กรณีที่ทั่วไปกว่านั้น คือหากแบ่งเป็นเกิดกับไม่เกิดเหตุการณ์ที่พิจารณา โดยมีค่าความน่าจะเป็นที่จะเกิดเหตุการณ์เป็น p การแจกแจงจะได้เป็น


นำมาลองแจกแจงจนถึง 5 จะได้เป็นลักษณะแบบนี้


ดังนั้นความน่าจะเป็นที่จะได้ผลที่ต้องการ k ครั้งก็จะเป็นไปตามสัมประสิทธิ์ที่นำหน้า นั่นคือ


นี่ก็คือรูปทั่วไปของการแจกแจงความน่าจะเป็นแบบทวินาม

ตรงนี้ถ้า p=1/2 ก็จะกลับไปสู่สมการของกรณีการโยนเหรียญหัวก้อย

ถ้า n=1 จะเป็นกรณีเฉพาะที่เรียกว่าเป็นการแจกแจงแบร์นุลลี (伯努利分布, Bernoulli distribution)





การแจกแจงเหตุการณ์ที่มีโอกาสเกิดขึ้นเป็น p

ยกตัวอย่างสถานการณ์เช่นเวลาที่เล่นเกมที่มีการตีมอนสเตอร์ เมื่อชนะเสร็จก็จะมีโอกาสดร็อปไปเท็ม สมมุติว่าเมื่อฆ่ามังกรได้มีโอกาสได้เขียวมังกรอยู่ 5% (หรือ 1/20) ถ้าฆ่ามังกรไป n ตัวจะได้เขี้ยวมังกรสักกี่อัน

ใช้สูตรแจกแจงทวินามมาคำนวณอีกเช่นเคย คราวนี้ p=1/20 ลองดูกรณีที่ n เป็น 10,20,...,200
import math
p = 1/20
for n in range(10,200+1,10):
    n_drop = []
    for k in range(0,n+1): # k คือจำนวนไอเท็มที่ดร็อปได้
        c = math.factorial(n)/(math.factorial(k)*math.factorial(n-k))
        n_drop +=[c*(p**k)*((1-p)**(n-k))]    
    print('n = %d:\n'%n, n_drop)

ผลที่ได้ถ้านำมาวาดกราฟก็จะได้แบบนี้ ในที่นี้ขอแสดงแค่ช่วงจนถึง k=20 แม้ว่าค่าจริงๆจะมีถึง 200 เพราะถัดจากตรงนี้ไปก็แทบเป็น 0 หมดแล้ว



คราวนี้ก็ทดลองเขียนโปรแกรมสุ่มดูจริงๆอีก
import random
n = 200 # จำนวนมอนสเตอร์ที่จัดการไป
p = [0]*(30+1) # ลิสต์เก็บจำนวนที่ดร็อปได้ เอาถึงแค่ 30 ก็พอ
# ทำซ้ำ 10000 ครั้ง
for i in range(10000):
    n_drop = 0 # บวกสะสมจำนวนครั้งที่ดร็อปได้
    for j in range(n):
        # สุ่มเลข 1-100 ถ้าได้ไม่เกิน 5 ถือว่าได้
        if(random.randint(1,100)<=5):
            n_drop += 1
    if(n_drop<=30): # บันทึกเฉพาะที่ไม่เกิน 30
        p[n_drop] += 1
print(p) # แสดงผลความถี่สุดท้ายของแต่ละค่าที่ได้ออกมา

ได้
[0, 5, 21, 63, 171, 382, 639, 956, 1090, 1242, 1259, 1197, 959, 708, 541, 339, 185, 133, 60, 22, 19, 4, 3, 1, 1, 0, 0, 0, 0, 0, 0]

ถ้านำมาวาดแผนภูมิแท่งดูการแจกแจงก็จะได้



ค่าสูงสุดอยู่ที่ 10 สอดคล้องกับที่ควรจะเป็นว่าถ้าโอกาสดร็อป 1/20 จัดการไป 200 ก็จะได้มา 200/20=10




ค่าคาดหมายของการแจกแจงทวินาม

ถ้านำการแจกแจงทวินาม n ครั้งที่ความน่าจะเป็น p มาหาค่าคาดหมายจะได้


ถ้า np เป็นจำนวนเต็ม ตรงนั้นก็จะเป็นจุดยอดสูงสุดด้วย

ซึ่งตรงนี้แสดงให้เห็นว่า หากทำอะไรที่มีโอกาสทำสำเร็จได้ 1 ใน n พอทำไป n ครั้งก็ควรจะต้องทำสำเร็จ 1 ครั้ง ถ้าทำ 2n ครั้งก็จะสำเร็จ 2 ครั้ง ซึ่งก็ตรงกับสามัญสำนึก ส่วนโอกาสที่จะได้เป็นจำนวนอื่นก็ลดหลั่นลงไปจากนี้ จะเป็นเท่าใดก็ดูได้จากการแจกแจง

วิธีพิสูจน์






ค่าความแปรปรวนของการแจกแจงทวินาม

ค่าความแปรปรวนของการแจกแจงทวินามคือ


พิสูจน์ได้ดังนี้


โดยค่าคาดหวัง E(k)=np




บทถัดไป >> บทที่ ๖



-----------------------------------------

囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧

ดูสถิติของหน้านี้

หมวดหมู่

-- คณิตศาสตร์ >> ความน่าจะเป็น
-- คอมพิวเตอร์ >> เขียนโปรแกรม >> python

ไม่อนุญาตให้นำเนื้อหาของบทความไปลงที่อื่นโดยไม่ได้ขออนุญาตโดยเด็ดขาด หากต้องการนำบางส่วนไปลงสามารถทำได้โดยต้องไม่ใช่การก๊อปแปะแต่ให้เปลี่ยนคำพูดเป็นของตัวเอง หรือไม่ก็เขียนในลักษณะการยกข้อความอ้างอิง และไม่ว่ากรณีไหนก็ตาม ต้องให้เครดิตพร้อมใส่ลิงก์ของทุกบทความที่มีการใช้เนื้อหาเสมอ

目次

日本による名言集
モジュール
-- numpy
-- matplotlib

-- pandas
-- manim
-- opencv
-- pyqt
-- pytorch
機械学習
-- ニューラル
     ネットワーク
javascript
モンゴル語
言語学
maya
確率論
日本での日記
中国での日記
-- 北京での日記
-- 香港での日記
-- 澳門での日記
台灣での日記
北欧での日記
他の国での日記
qiita
その他の記事

記事の類別



ติดตามอัปเดตของบล็อกได้ที่แฟนเพจ

  記事を検索

  おすすめの記事

ตัวอักษรกรีกและเปรียบเทียบการใช้งานในภาษากรีกโบราณและกรีกสมัยใหม่
ที่มาของอักษรไทยและความเกี่ยวพันกับอักษรอื่นๆในตระกูลอักษรพราหมี
การสร้างแบบจำลองสามมิติเป็นไฟล์ .obj วิธีการอย่างง่ายที่ไม่ว่าใครก็ลองทำได้ทันที
รวมรายชื่อนักร้องเพลงกวางตุ้ง
ภาษาจีนแบ่งเป็นสำเนียงอะไรบ้าง มีความแตกต่างกันมากแค่ไหน
ทำความเข้าใจระบอบประชาธิปไตยจากประวัติศาสตร์ความเป็นมา
เรียนรู้วิธีการใช้ regular expression (regex)
การใช้ unix shell เบื้องต้น ใน linux และ mac
g ในภาษาญี่ปุ่นออกเสียง "ก" หรือ "ง" กันแน่
ทำความรู้จักกับปัญญาประดิษฐ์และการเรียนรู้ของเครื่อง
ค้นพบระบบดาวเคราะห์ ๘ ดวง เบื้องหลังความสำเร็จคือปัญญาประดิษฐ์ (AI)
หอดูดาวโบราณปักกิ่ง ตอนที่ ๑: แท่นสังเกตการณ์และสวนดอกไม้
พิพิธภัณฑ์สถาปัตยกรรมโบราณปักกิ่ง
เที่ยวเมืองตานตง ล่องเรือในน่านน้ำเกาหลีเหนือ
ตระเวนเที่ยวตามรอยฉากของอนิเมะในญี่ปุ่น
เที่ยวชมหอดูดาวที่ฐานสังเกตการณ์ซิงหลง
ทำไมจึงไม่ควรเขียนวรรณยุกต์เวลาทับศัพท์ภาษาต่างประเทศ

ไทย

日本語

中文