Data Analytics | Insights & Research

PUAY101

Tag: Probability for Data Folks

  • EP.2: ผลตรวจเป็นบวก! สรุปว่าเราป่วยจริงไหม? – ไขปมความน่าจะเป็นแบบมีเงื่อนไข

    EP.2: ผลตรวจเป็นบวก! สรุปว่าเราป่วยจริงไหม? – ไขปมความน่าจะเป็นแบบมีเงื่อนไข

    ซีรีส์: Probability for Data Folks | เมื่อโค้ดไขความลับความน่าจะเป็น

    ในตอนที่แล้ว เราได้เห็นพลังของ กฎว่าด้วยจำนวนมาก (Law of Large Numbers) ที่พิสูจน์ว่ายิ่งทดลองซ้ำๆ ผลลัพธ์ก็จะยิ่งวิ่งเข้าหาทฤษฎี

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

    ลองจินตนาการถึงสถานการณ์นี้ครับ…

    สมมติว่ามีโรคหายากโรคหนึ่ง ซึ่งมีคนป่วยแค่ 1% ของประชากรทั้งหมด โชคดีที่มีชุดตรวจที่แม่นยำมากๆ ถึง 99% วันหนึ่งคุณไปตรวจสุขภาพ และได้รับผลว่า “เป็นบวก”

    คำถาม: เราสามารถสรุปได้เลยว่าโอกาสที่คุณจะป่วยเป็นโรคนั้นจริงๆ คือ 99% ได้ไหม?

    ถ้าคุณตอบว่า “ใช่” หรือ “ใกล้เคียง 99%”… คุณคือคนส่วนใหญ่ที่ตกหลุมพรางของสัญชาตญาณครับ คำตอบที่แท้จริงอาจจะน้อยกว่าที่คุณคิดไปไกลลิบเลยทีเดียว

    ปรากฏการณ์นี้คือหัวใจของ ความน่าจะเป็นแบบมีเงื่อนไข (Conditional Probability) ซึ่งเป็นแนวคิดที่สำคัญอย่างยิ่งในโลกของ Data Science และวันนี้เราจะมาไขความลับข้อนี้กัน

    มาวิเคราะห์โจทย์กันก่อน (The Devil is in the Details)

    ปัญหานี้ซับซ้อนกว่าการโยนเหรียญ เพราะมีข้อมูลหลายส่วนที่เราต้องทำความเข้าใจให้ชัดเจน:

    1. ความชุกของโรค (Base Rate หรือ Prevalence): มีคนป่วยแค่ 1% ของประชากรทั้งหมด (หรือ 0.01) นี่คือข้อมูลสำคัญที่คนมักจะมองข้าม
    2. ความแม่นยำของชุดตรวจ (Accuracy): 99% แต่คำว่า “แม่นยำ” ต้องแยกเป็น 2 กรณี
      • ถ้าคุณป่วยจริงๆ ชุดตรวจจะบอกว่า “บวก” ถูกต้อง 99% (True Positive Rate) และจะพลาดบอกว่า “ลบ” แค่ 1% (False Negative Rate)
      • ถ้าคุณไม่ป่วยจริงๆ ชุดตรวจจะบอกว่า “ลบ” ถูกต้อง 99% (True Negative Rate) และจะพลาดบอกว่า “บวก” แค่ 1% (False Positive Rate)

    คำถามของเราคือ P(textป่วย∣textผลเป็นบวก) หรือ “ความน่าจะเป็นที่จะป่วย เมื่อได้รับเงื่อนไขว่า ผลตรวจเป็นบวก”

    คิดแบบไม่ใช้สูตร: ลองจินตนาการถึงคน 100,000 คน

    การคำนวณด้วยสูตรอาจจะน่าปวดหัว งั้นเรามาใช้วิธีที่ “จับต้องได้” ที่สุดกันครับ ลองจินตนาการว่าเรามีประชากรอยู่ 100,000 คน

    Step 1: ใน 100,000 คนนี้ มีคนป่วยกี่คน? จากความชุกของโรค 1% หมายความว่า:

    • คนป่วยจริงๆ: 100,000 * 1% = 1,000 คน
    • คนที่ไม่ป่วย: 100,000 – 1,000 = 99,000 คน

    Step 2: เอาคนป่วย 1,000 คนไปตรวจ จากความแม่นยำ 99% ของชุดตรวจ:

    • ผลตรวจเป็น “บวก” (และป่วยจริง – True Positive): 1,000 * 99% = 990 คน
    • ผลตรวจเป็น “ลบ” (ทั้งที่ป่วยจริง – False Negative): 1,000 * 1% = 10 คน

    Step 3: เอาคนที่ไม่ป่วย 99,000 คนไปตรวจ นี่คือจุดที่สำคัญที่สุด! แม้คนเหล่านี้จะไม่ป่วย แต่ชุดตรวจก็มีโอกาสพลาดได้ 1%:

    • ผลตรวจเป็น “บวก” (ทั้งที่ไม่ป่วย – False Positive): 99,000 * 1% = 990 คน
    • ผลตรวจเป็น “ลบ” (และไม่ป่วยจริง – True Negative): 99,000 * 99% = 98,010 คน

    Step 4: หาคำตอบ! ตอนนี้เรามาตอบคำถามเดิมกัน: “ถ้าผลตรวจของคุณเป็นบวก โอกาสที่คุณจะป่วยจริงๆ เป็นเท่าไหร่?”

    • ก่อนอื่น มาดูกลุ่มคนที่ได้ผล “บวก” ทั้งหมดกันก่อน ซึ่งมาจาก 2 กลุ่ม:
      • คนที่ป่วยจริงและผลเป็นบวก: 990 คน
      • คนที่ไม่ป่วยแต่ผลเป็นบวก: 990 คน
      • รวมคนที่มีผลตรวจเป็นบวกทั้งหมด = 990 + 990 = 1,980 คน
    • ในบรรดา 1,980 คนที่เดินออกจากห้องตรวจพร้อมผล “บวก” นี้ มีคนที่ป่วยจริงๆ กี่คน?
      • คำตอบคือ 990 คน (กลุ่ม True Positive)

    ดังนั้น ความน่าจะเป็นที่จะป่วยจริง เมื่อผลตรวจเป็นบวก คือ:

    ใช่แล้วครับ… 50% เท่านั้น! น่าตกใจใช่ไหมครับ? แม้ชุดตรวจจะแม่นยำถึง 99% แต่โอกาสที่คุณจะป่วยจริงๆ กลับมีแค่ 50% เหตุผลก็เพราะโรคนี้มัน “หายาก” มากๆ ทำให้จำนวนคนที่ “ไม่ป่วยแต่ดันได้ผลบวก” (False Positive) มีจำนวนพอๆ กับคนที่ “ป่วยและได้ผลบวก” (True Positive) เลยทีเดียว

    ให้ Code พิสูจน์ความจริง

    ตอนนี้เรามาสร้าง Simulation ด้วย Python เพื่อยืนยันแนวคิดที่หักมุมนี้กันครับ เราจะสร้างประชากรเสมือนจริง 1 ล้านคน แล้วจำลองการตรวจโรคทั้งหมด

    Python

    import random
    # 1. Setup the parameters of our world
    population_size = 1_000_000
    disease_prevalence = 0.01 # 1% of the population is sick
    test_accuracy = 0.99 # 99% accuracy
    # For clarity in simulation
    true_positive_rate = test_accuracy
    false_positive_rate = 1 – test_accuracy
    # 2. Create lists to hold our results
    # We will store tuples of (is_sick, test_result)
    population_data = []
    # 3. Simulate the entire population
    for i in range(population_size):
    # Determine if this person is sick based on prevalence
    is_sick = (random.random() < disease_prevalence)
    test_result = ''
    if is_sick:
    # It's a sick person, use the true positive rate
    if random.random() < true_positive_rate:
    test_result = 'Positive'
    else:
    test_result = 'Negative'
    else:
    # It's a healthy person, use the false positive rate
    if random.random() < false_positive_rate:
    test_result = 'Positive'
    else:
    test_result = 'Negative'
    population_data.append((is_sick, test_result))
    # 4. Analyze the results
    total_positives = 0
    true_positives = 0
    for person in population_data:
    is_sick, test_result = person
    if test_result == 'Positive':
    total_positives += 1
    if is_sick: # and they are actually sick
    true_positives += 1
    # 5. Calculate the final conditional probability
    # Handle the case where total_positives might be zero
    if total_positives > 0:
    conditional_probability = true_positives / total_positives
    else:
    conditional_probability = 0
    print(f"Simulation based on {population_size:,} people:")
    print(f"Total people who tested 'Positive': {total_positives:,}")
    print(f"People who are actually sick AND tested 'Positive': {true_positives:,}")
    print("-" * 30)
    print(f"The probability of being sick given a positive test is: {conditional_probability:.4f}")
    view raw ep2.py hosted with ❤ by GitHub

    Result:

    Simulation based on 1,000,000 people:
    Total people who tested 'Positive': 19,891
    People who are actually sick AND tested 'Positive': 9,933
    ------------------------------
    The probability of being sick given a positive test is: 0.4994
    

    ผลลัพธ์จาก Code ยืนยันสิ่งที่เราคำนวณด้วยมืออย่างชัดเจน! ความน่าจะเป็นที่ได้เข้าใกล้ 0.5 หรือ 50% อย่างไม่น่าเชื่อ

    เรื่องนี้เกี่ยวกับ Data Science อย่างไร?

    สิ่งที่เราเพิ่งทำไปคือการประยุกต์ใช้แนวคิดของ ทฤษฎีของเบย์ (Bayes’ Theorem) ซึ่งเป็นหนึ่งในเครื่องมือที่สำคัญที่สุดของ Data Scientist สูตรของมันคือ:

    โดยที่:

    • P(A∣B) คือสิ่งที่เราอยากรู้ (โอกาสป่วย เมื่อผลบวก)
    • P(B∣A) คือความแม่นยำของเทส (โอกาสผลบวก เมื่อป่วย)
    • P(A) คือความชุกของโรค (โอกาสที่จะป่วยตั้งแต่แรก)
    • P(B) คือโอกาสทั้งหมดที่จะได้ผลบวก

    หลักการนี้ถูกนำไปใช้ในหลายๆ ที่:

    • Spam Filters: คำนวณความน่าจะเป็นที่อีเมลจะเป็น “สแปม” เมื่อ มันมีคำว่า “โปรโมชั่น” หรือ “ฟรี”
    • Recommendation Engines: แนะนำสินค้าโดยคำนวณความน่าจะเป็นที่ลูกค้าจะ “ชอบสินค้า A” เมื่อ พวกเขาเคย “ซื้อสินค้า B” มาก่อน
    • A/B Testing: ประเมินความน่าจะเป็นว่า “เวอร์ชัน B ดีกว่า” เมื่อ เราได้ “เห็นข้อมูลผลลัพธ์” แบบนี้

    บทสรุปสุดท้าย

    • บทเรียนสำคัญที่สุดในวันนี้คือ “อย่าลืม Base Rate” หรือข้อมูลพื้นฐานเริ่มต้น
    • ความน่าจะเป็นแบบมีเงื่อนไขสอนให้เรามองภาพรวมและไม่ด่วนสรุปจากข้อมูลเพียงชิ้นเดียว

    สุดท้าย>>ขอขอบคุณทุกๆคนเลยครับที่อ่านจนมาถึงตรงนี้หวังว่าจะชอบกันนะครับ

    ในตอนหน้าของซีรีส์… เราจะไปคำนวณ “ความสิ้นหวัง” ที่ทุกคนคุ้นเคยกันดีในหัวข้อ: “EP.3: ทำไมเราถึงไม่เคยถูกหวย”

    ฝากติดตามตอนต่อไปด้วยนะคร้าบบ 😁😁😁

  • EP.1: โยนเหรียญทายใจคอม – ความน่าจะเป็น 101 ที่พิสูจน์ได้ด้วย Code

    EP.1: โยนเหรียญทายใจคอม – ความน่าจะเป็น 101 ที่พิสูจน์ได้ด้วย Code

    ซีรีส์: Probability for Data Folks | เมื่อโค้ดไขความลับความน่าจะเป็น

    “ถ้าเราโยนเหรียญ 10 ครั้ง จะออกหัวกี่ครั้ง?”

    คำตอบแรกที่แวบเข้ามาในหัวของคนส่วนใหญ่ก็คือ “5 ครั้ง” ซึ่งก็สมเหตุสมผลดี เพราะเราทุกคนต่างเรียนมาว่าโอกาสที่เหรียญจะออก”หัว”หรือ”ก้อย” มันเท่ากัน คือ 50/50

    แต่ในโลกความจริง… ถ้าเราลองหยิบเหรียญมาโยน 10 ครั้งจริงๆ ผลลัพธ์อาจจะเป็น หัว 6 ก้อย 4 หรือบางทีอาจจะสุดโต่งไปทาง หัว 8 ก้อย 2 เลยก็ได้ แล้วแบบนี้… ไอ้ทฤษฎี 50% ที่เราเชื่อมั่นกัน มันจะเชื่อถือได้แค่ไหนกัน?

    ถ้าจะให้พิสูจน์เรื่องนี้ด้วยการนั่งโยนเหรียญเป็นพันๆ หมื่นๆ ครั้งคงเป็นเรื่องที่น่าเบื่อและเสียเวลา..ในบทความนี้เราเลยจะมา Simulation การโยนเหรีญ ขึ้นมา โดยใช้ Python

    ในบทความแรกของซีรีส์นี้ เราจะเปลี่ยนคอมพิวเตอร์ของเราให้กลายเป็น “ห้องทดลองความน่าจะเป็น” เพื่อตอบคำถามง่ายๆ ที่ทรงพลังข้อนี้กันครับ

    ทบทวนความน่าจะเป็น

    ก่อนจะไปเขียน Code เรามาทบทวนความเข้าใจกันสักนิด ความน่าจะเป็น (Probability) ถ้าจะพูดแบบบ้านๆ ที่สุด มันคือ “ตัวเลขที่ใช้วัด ‘ความเชื่อ’ ของเราว่าเหตุการณ์นั้นๆ มีโอกาสเกิดขึ้นมากน้อยแค่ไหน”

    โดยตัวเลขนี้จะวิ่งอยู่ระหว่าง 0 ถึง 1 เท่านั้น:

    • 0 หมายถึง ไม่มีทางเกิดขึ้นแน่นอน
    • 1 หมายถึง เกิดขึ้นแน่นอน 100%

    สำหรับเหรียญของเรา การโยน 1 ครั้งมีผลลัพธ์ที่เป็นไปได้ทั้งหมด 2 แบบ คือ ‘หัว’ (Heads) กับ ‘ก้อย’ (Tails) ดังนั้น โอกาสที่จะออก ‘หัว’ จึงคำนวณได้ง่ายๆ ว่า:

    นี่คือ “ความน่าจะเป็นตามทฤษฎี” (Theoretical Probability) ที่เราท่องจำกันมา และก็ถึงเวลามาพิสูจน์ด้วยการทดลองแล้วครับ

    Hands-on Python

    เราจะใช้ไลบรารีพื้นฐานของ Python ที่ชื่อว่า random ซึ่งมีติดมาให้อยู่แล้ว ไม่ต้องติดตั้งอะไรเพิ่มเติม (ใน Code เราจะใช้คำว่า Heads แทน ‘หัว’ และ Tails แทน ‘ก้อย’ )

    ขั้นตอนที่ 1: จำลองการโยนเหรียญ 1 ครั้ง

    เปิดโปรแกรมเขียน Python ของคุณขึ้นมา แล้วลองพิมพ์ตามนี้ได้เลย:

    import random
    # Possible outcomes of a coin flip
    outcomes = ['Heads', 'Tails']
    # Randomly choose one from the outcomes
    result = random.choice(outcomes)
    print(f"Single coin flip result: {result}")
    view raw s_1.py hosted with ❤ by GitHub
    --Result--
    Single coin flip result: Tails 

    ทุกครั้งที่คุณรัน Code ชุดนี้ ผลลัพธ์ก็จะสลับไปมาระหว่าง ‘Heads’ กับ ‘Tails’ ง่ายๆ แค่นี้เลยครับ! เราเพิ่งจำลองการโยนเหรียญครั้งแรกสำเร็จแล้ว

    ขั้นตอนที่ 2: จำลองการโยนเหรียญ 10,000 ครั้ง!

    การโยนครั้งเดียวมันยังไม่เห็นภาพ งั้นเรามาสั่งให้คอมพิวเตอร์โยนเหรียญให้เราสัก 10,000 ครั้ง แล้วนับดูสิว่ามันออก ‘Heads’ ไปกี่ครั้ง

    import random
    # 1. Setup the experiment
    total_flips = 10000
    head_counts = 0
    outcomes = ['Heads', 'Tails']
    # 2. Start the simulation loop
    for _ in range(total_flips):
    # In each loop, simulate one flip
    result = random.choice(outcomes)
    # 3. Check the result and increment the counter if it's 'Heads'
    if result == 'Heads':
    head_counts += 1
    print(f"Total flips: {total_flips}")
    print(f"Total 'Heads' results: {head_counts}")
    view raw s_2.py hosted with ❤ by GitHub
    --Result--
    Total flips: 10000
    Total 'Heads' results: 4928

    และแล้ว… ผลลัพธ์ก็ปรากฏ

    หลังจากรัน Code ด้านบนแล้ว เรามีจำนวนครั้งที่โยนทั้งหมด (total_flips) และจำนวนครั้งที่ออกหัว (head_counts) อยู่ในมือ สิ่งที่เราต้องทำต่อก็คือการคำนวณ “ความน่าจะเป็นที่ได้จากการทดลอง”

    มาเพิ่ม Code อีกนิดหน่อยเพื่อดูผลลัพธ์กันฮะ:

    import random
    # 1. Setup the experiment
    total_flips = 10000
    head_counts = 0
    outcomes = ['Heads', 'Tails']
    # 2. Start the simulation loop
    for _ in range(total_flips):
    # In each loop, simulate one flip
    result = random.choice(outcomes)
    # 3. Check the result and increment the counter if it's 'Heads'
    if result == 'Heads':
    head_counts += 1
    print(f"Total flips: {total_flips}")
    print(f"Total 'Heads' results: {head_counts}")
    view raw s_2.py hosted with ❤ by GitHub
    Total flips: 10000
    Total 'Heads' results: 4987
    Simulated probability of Heads is: 0.4987

    สังเกตุว่าตัวเลข 0.4987 ที่ได้ ใกล้เคียงกับ 0.5 ตามทฤษฎีของเราอย่างไม่น่าเชื่อ

    นี่คือหัวใจสำคัญที่เราอยากแสดงให้เห็นในวันนี้ ปรากฏการณ์นี้มีชื่อเรียกเท่ๆ ว่า กฎว่าด้วยจำนวนมาก (Law of Large Numbers) ซึ่งกล่าวไว้ว่า:

    “ยิ่งเราทำการทดลองแบบสุ่มซ้ำๆ เป็นจำนวนมากเท่าไหร่ ผลลัพธ์เฉลี่ยที่ได้จากการทดลอง ก็จะยิ่งวิ่งเข้าใกล้ค่าที่คาดหวังตามทฤษฎีมากขึ้นเท่านั้น”

    พูดง่ายๆ ก็คือ การโยนเหรียญแค่ 10 ครั้งอาจจะดู “มั่ว” แต่ถ้าโยนเป็นหมื่นเป็นแสนครั้ง ความ “มั่ว” นั้นจะค่อยๆ หายไป และผลลัพธ์จะลู่เข้าหาความจริงตามทฤษฎี

    แล้วเรื่องนี้มันสำคัญยังไง? 🤔

    คุณอาจจะคิดว่า “ก็แค่เรื่องโยนเหรียญ… แล้วมันไปเกี่ยวกับ Data Science ตรงไหน?”

    จริงๆ แล้วนี่คือหลักการพื้นฐานที่ทรงพลังมาก:

    • A/B Testing: เวลาบริษัทเทคฯ อยากรู้ว่าปุ่มสีเขียวกับสีแดง ปุ่มไหนมีคนคลิกมากกว่ากัน พวกเขาจะปล่อยให้คนเป็นหมื่นเป็นแสนคนใช้งาน แล้วดูผลลัพธ์ มันคือหลักการเดียวกับที่เราโยนเหรียญเป็นหมื่นครั้งนี่แหละครับ
    • บริษัทประกัน: บริษัทประกันไม่รู้หรอกว่า “นาย ก.” จะป่วยเมื่อไหร่ แต่พวกเขามีข้อมูลคนเป็นล้านๆ คน (เหมือนการทดลองจำนวนมาก) ทำให้สามารถ “ทำนาย” ได้อย่างแม่นยำว่าในภาพรวมแล้วจะมีคนป่วยกี่คน เพื่อคำนวณเบี้ยประกันได้อย่างเหมาะสม
    • การสร้างแบบจำลอง: เทคนิคการจำลองแบบนี้คือพื้นฐานของ “Monte Carlo Simulation” ซึ่งเป็นเครื่องมือที่ Data Scientist ใช้จำลองสถานการณ์ที่ซับซ้อนมากๆ เช่น การคาดการณ์ราคาหุ้น หรือความเสี่ยงของพอร์ตการลงทุน

    บทสรุป🚀

    วันนี้ เราได้เปลี่ยนคำถามง่ายๆ เกี่ยวกับการโยนเหรียญ ให้กลายเป็นการทดลองที่จับต้องได้ด้วย Python เราได้พิสูจน์แนวคิดพื้นฐานของความน่าจะเป็น และได้เห็นกฎว่าด้วยจำนวนมาก (Law of Large Numbers) ทำงานให้เห็นกับตา

    Challenge สำหรับคุณ: ลองคัดลอก Code ด้านบนไปเล่นดูครับ

    1. เปลี่ยนค่า total_flips ให้เป็น 100, 1,000, 1,000,000 แล้วดูสิว่าผลลัพธ์ที่ได้มันเข้าใกล้ 0.5 มากขึ้นเรื่อยๆ จริงไหม
    2. ลองปรับ Code เพื่อจำลอง “การทอยลูกเต๋า” (dice roll) 1 ลูก แล้วดูว่าโอกาสที่จะได้เลข 6 เข้าใกล้ 1/6 (ประมาณ 0.1667) หรือเปล่า

    ในตอนหน้าของซีรีส์ เราจะไปเจอกับปัญหาที่ซับซ้อนและสนุกยิ่งกว่านี้ในหัวข้อ: “EP.2: ผลตรวจเป็นบวก! สรุปว่าเราป่วยจริงไหม?” ฝากติดตามด้วยนะครับบ