Tag Archives: ไพธอน

คอมขยายสมอง (1): ความน่าจะเป็นของสามเหลี่ยม

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

มีคำถามใน YouTube ว่าถ้ามีเส้นตรงหนึ่งเส้น แล้วแบ่งเป็นสามส่วนแบบสุ่มๆ จะมีโอกาสเท่าไรที่ทั้งสามส่วนจะประกอบกันเป็นสามเหลี่ยมได้พอดี:

วิธีในวิดีโอใช้ทฤษฎีบทของวิเวียนนี (Viviani’s Theorem) ที่บอกว่าสำหรับสามเหลี่ยมด้านเท่าใดๆและจุดใดๆภายในสามเหลี่ยมนั้น ผลรวมของระยะห่างจากจุดไปยังด้านทั้งสามของสามเหลี่ยม จะเท่ากับความสูงของสามเหลี่ยม ทฤษฎีบทนี้แสดงว่าเมื่อแบ่งเส้นตรงเป็นสามส่วน ความน่าจะเป็นที่ทั้งสามส่วนจะประกอบเป็นสามเหลี่ยมพอดีคือ 1/4

แต่ถ้าเราไม่เคยรู้จักทฤษฎีบทของวิเวียนนี(หรือวิธีอื่นๆ) เราจะแก้ปัญหานี้ได้อย่างไรได้บ้าง? วิธีแบบหนึ่งก็คือทำการทดลองตรงๆครับ โดยเราทดลองแบ่งเส้นตรงเป็นสามส่วนแบบสุ่มๆหลายๆครั้งแล้วดูว่าสามารถสร้างเป็นสามเหลี่ยมได้กี่ครั้ง อัตราส่วนครั้งที่เป็นสามเหลี่ยมต่อจำนวนครั้งที่ทดลองทั้งหมดจะเป็นคำตอบโดยประมาณให้เราได้

ถ้าเราทดลองด้วยมือ เราก็จะทดลองได้ไม่กี่ครั้งก่อนที่จะเหนื่อยหรือหมดเวลา แต่ถ้าเราสั่งคอมพิวเตอร์ให้ทำงานแทนเราได้ คอมพิวเตอร์จะทดลองให้เราได้อย่างรวดเร็วและไม่เหน็ดเหนื่อย วิธีตระกูลนี้(ที่ให้คอมพิวเตอร์ทำการทดลองต่างๆแทนเราแล้วเราไปดูคำตอบ)เรียกว่า computer simulation

ยกตัวอย่างฟังก์ชั่นภาษาไพธอนที่ทำการทดลองให้เราอาจมีหน้าตาประมาณนี้ จริงๆตัวโปรแกรมมีไม่กี่บรรทัดแต่มีคอมเม้นท์อธิบายเยอะหน่อยเผื่อเป็นประโยชน์สำหรับผู้เรียนรู้ครับ:

import random

def prob_triangle(ntrials):
    """
    ประมาณความน่าจะเป็นที่เส้นตรงที่ถูกแบ่งเป็นสามส่วนแบบสุ่มๆ
    จะสามารถประกอบเป็นสามเหลี่ยมได้
    
    ทำการทดลอง ntrials ครั้ง
    """
    
    # ntriangles เก็บจำนวนครั้งที่ประกอบเป็นสามเหลี่ยมได้
    ntriangles = 0 
    
    # ทำการทดลองแบ่งเส้นตรงความยาว 1 หน่วยเป็นสามส่วน
    # ทั้งหมดntrials ครั้ง
    
    for n in range(ntrials):
        
        # x, y คือตำแหน่งที่เราสุ่มตัดเส้นตรงสองตำแหน่ง
        # ทำให้แบ่งเส้นตรงเป็นสามส่วน
        # เราจะเรียงตำแหน่งให้ x <= y
        # ถ้าไม่เป็นอย่างนั้นเราจะสลับ x และy
        
        x = random.random()
        y = random.random()
        if x > y:
            x, y = y, x
        
        # เมื่อเราสุ่ม x, y มาตัดเส้นตรงได้แล้ว
        # เราจะมีเส้นตรงสามชิ้นยาว x, y-x, และ 1-y
        # เราจะเรียกชิ้นที่ยาวที่สุดว่า longest
        
        longest = max(x, y-x, 1-y)
        
        # ถ้าชิ้นที่ยาวที่สุดมีความยาวไม่เกิน 1/2 ของ
        # ความยาวเส้นตรงดั้งเดิม เราจะสามารถเอา
        # ทั้งสามชิ้นมาประกอบเป็นสามเหลี่ยมได้
        # และเราก็จะเพิ่มจำนวนครั้งที่ประกอบเป็นสามเหลี่ยมสำเร็จ
        
        if longest < 0.5:
            ntriangles += 1
            
         # ประมาณความน่าจะเป็นที่เป็นสามเหลี่ยมสำเร็จ
         # เท่ากับ (จำนวนสามเหลี่ยม)/(จำนวนครั้งที่ทดลอง)
            
    return ntriangles/ntrials

เมื่อเราบอกให้คอมพิวเตอร์ทดลองให้เราหลายๆครั้ง (เช่นในที่นี้คือ 1 แสนครั้ง) เราก็จะได้คำตอบมาประมาณ 1/4 ดังนี้:

ntrials = 100_000
print(f"ทดลองแบ่งเส้นตรงแบบสุ่มๆเป็นสามชิ้นทั้งหมด {ntrials:,} ครั้ง")
print("แล้วดูว่าทั้งสามชิ้นสามารถประกอบเป็นสามเหลี่ยมได้ไหม\n")
print(f"ความน่าจะเป็นที่ได้สามเหลี่ยม = {prob_triangle(ntrials):.2f}")

ผลที่ได้คือ:

ทดลองแบ่งเส้นตรงแบบสุ่มๆเป็นสามชิ้นทั้งหมด 100,000 ครั้ง
แล้วดูว่าทั้งสามชิ้นสามารถประกอบเป็นสามเหลี่ยมได้ไหม

ความน่าจะเป็นที่ได้สามเหลี่ยม = 0.25

วิธีตระกูล computer simulation นี้เป็นวิธีสำคัญที่มนุษยชาติใช้หาคำตอบต่างๆครับ ในหลายๆกรณีมนุษยชาติยังไม่มีความรู้ที่จะหาคำตอบโดยตรงด้วยทฤษฎีต่างๆ ก็หาคำตอบโดยให้คอมพิวเตอร์คำนวณหรือทำการทดลองให้

หวังว่าผู้อ่านจะได้ไอเดียหรือประโยชน์บ้างนะครับ ถ้ามีคำแนะนำหรือข้อสงสัยส่งข้อความอินบ๊อกซ์ไปที่เพจวิทย์พ่อโก้บนเฟซบุ๊คได้ครับ: https://www.facebook.com/witpokosci/

(ตอนต่อไปอยู่ที่ https://witpoko.com/?p=7499 นะครับ)

วิทย์ม.ต้น: Machine Learning ใน 5 นาที, ที่ฝึก ML, คำสอนปิดม.ต้น

วิทย์โปรแกรมมิ่งวันศุกร์สัปดาห์นี้ เด็กม.3 ได้ดูคลิปการสั่งให้คอมพิวเตอร์เรียนรู้จากตัวอย่าง (machine learning หรือ ML) ได้พิมพ์ตามคลิปนี้ครับ:

ผมเล่าให้ฟังว่าถ้าเรามีข้อมูลตัวอย่างเยอะๆดีๆเราก็สามารถให้คอมพิวเตอร์เรียนรู้ด้วยเทคนิคด้าน machine learning เพื่อช่วยทำงานต่างๆให้เราได้ ยกตัวอย่างเช่นอาจช่วยวินิจฉัยโรค ช่วยรู้จักหน้าคน รู้จักคัดตัวอย่างผลไม้ ตรวจหาวัชพืช แยกแยะแมลงมีประโยชน์และมีโทษ ช่วยวาดรูป ช่วยแต่งเพลง ฯลฯ โดยตัวอย่าง (ที่ไม่สมจริง) ที่ผมลองพิมพ์ให้ดูก็เช่นแยกระหว่างไข้หวัดใหญ่และโควิด-19:

ผมแนะนำให้เด็กๆไปศึกษาวิธีบอกให้คอมพิวเตอร์ช่วยงานด้านนี้ โดยใช้เวลาว่างเข้าไปเรียนรู้ที่ https://www.kaggle.com/learn/overview

เนื่องจากเด็กๆม.สามจะกระจายไปตามโรงเรียนต่างๆไม่ได้เรียนกับผมแล้วผมฝากข้อแนะนำสุดท้ายไว้ว่าให้ฝึกฝนเพื่อทำงานร่วมกับเครื่องจักรและโปรแกรมฉลาดๆให้ความสามารถของตนทวีคูณเป็นสิบเป็นร้อยเท่า อย่ารอให้คนอื่นใช้เครื่องจักรและโปรแกรมฉลาดๆมาแข่งกับเราก่อนเพราะเราจะเดือดร้อน และเมื่อเรียนคณิตศาสตร์ม.ปลายแล้วไม่รู้ว่าจะเรียนไปทำอะไรนอกจากสอบ ให้อ่านหนังสือ “คเณิร์ตศาสตร์” ที่ผมแจกไปให้

วิทย์ม.ต้น: Birthday Paradox ต่อ

วิทย์โปรแกรมมิ่งวันศุกร์นี้ เด็กๆม.3 เขียนโปรแกรมไล่ดูว่าต้องมีคนสักกี่คนอยู่ด้วยกันแล้วความน่าจะเป็นที่จะมีคนวันเกิดซ้ำกันบ้างเกิน 50% พบว่าต้องมีคน 23 คนครับ

หน้าตาฟังก์ชั่นคำนวณความน่าจะเป็นที่คน k คนจะไม่มีวันเกิดซ้ำกันเลย และมีวันเกิดซ้ำกันบ้างจะเป็นประมาณนี้ครับ:

เราวาดกราฟดูด้วย matplotlib ได้ดังนี้ครับ:

เราสามารถดูปัญหาคล้ายๆกันคือแทนที่จะเป็นวันเกิดอาจจะเป็นสิ่งต่างๆจำนวนหลายชิ้น แล้วมีคนจำนวนหนึ่งมาเลือกสุ่มๆ ดูความน่าจะเป็นที่จะเลือกซ้ำกันก็ได้ครับ ถ้าจะแก้ปัญหาทั่วไปแบบนี้เราก็ดัดแปลงฟังก์ชั่นให้ยืดหยุ่นมากขึ้นดังนี้:

เช่นสมมุติว่ามีคนหลายคนใส่นาฬิกาโดยที่ไม่ได้ตั้งกันมาให้ตรงกับเวลามาตรฐานก่อน เข็มวินาทีของแต่ละคนก็อาจจะชี้เลขจาก 0 ถึง 59 ถ้าเราสมมุติว่าโอกาสที่เข็มชี้เลขต่างๆด้วยความน่าจะเป็นเท่าๆกัน เราก็สามารถหาโอกาสที่คน k คนจะมีเข็มวินาทีซ้ำกันอยู่ได้ด้วยฟังก์ชั่น prob_some_repeat(60, k) เราจะพบว่าเมื่อมีคน 10 คน ความน่าจะเป็นที่มีเข็มชี้ไปที่วินาทีซ้ำๆกันบ้างจะมากกว่า 50% ครับ

ด้วยคณิตศาสตร์ระดับสูงขึ้นไป เราจะสามารถคำนวณได้ว่าถ้ามีของให้เลือก N ชิ้น แล้วมีคน k คนมาเลือกสุ่มๆโดยโอกาสเลือกของแต่ละชิ้นเท่าๆกัน ความน่าจะเป็นที่จะมีการเลือกซ้ำจะมีค่า 50% เมื่อ k มีค่าประมาณ 1.2 √N เท่านั้นครับ

การบ้านคือให้เด็กๆไปทดลองหาว่าสำหรับของ 10, 10^2, 10^3, 10^4, 10^5, 10^6 ชิ้นต้องมีคนกี่คนเลือกถึงมีโอกาสเลือกซ้ำกันประมาณ 50% และใกล้กับค่า 1.2 √N ไหม