คอมขยายสมอง (2): เมื่อไรเราพอจะเชื่อค่าการทดลองโดยคอมพิวเตอร์ได้บ้าง

เราคุยกันต่อจากตอนที่แล้วที่เราให้คอมพิวเตอร์ทำการทดลองหาคำตอบที่เราไม่รู้ (computer simulation)

คำถามคือเอาเส้นตรงมาหนึ่งเส้น แบ่งเป็นสามท่อน ความน่าจะเป็นที่ทั้งสามท่อนสามารถมาประกอบกันเป็นสามเหลี่ยมได้พอดีมีเท่าไร คำตอบจริงๆจากทฤษฎีคือ 1/4 แต่เนื่องจากเราไม่รู้คำตอบจากทฤษฎีเราจึงให้คอมพิวเตอร์ทดลองแบ่งเส้นตรงเป็นสามท่อนแบบสุ่มๆหลายๆครั้งแล้วนับจำนวนครั้งที่ประกอบเป็นสามเหลี่ยมได้สำเร็จ เปรียบเทียบกับจำนวนการทดลองทั้งหมด อัตราส่วนก็คือค่าความน่าจะเป็นโดยประมาณ

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

(ถึงตอนนี้ถ้าอยู่ในห้องเรียน เราก็ควรถามเด็กๆว่าเด็กๆคิดว่าควรทำยังไงดี ให้เขาคิดและเสนอความคิดกัน)

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

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

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

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

การทดลองครั้งที่ 1, ความน่าจะเป็นที่ได้สามเหลี่ยม = 0.249
การทดลองครั้งที่ 2, ความน่าจะเป็นที่ได้สามเหลี่ยม = 0.249
การทดลองครั้งที่ 3, ความน่าจะเป็นที่ได้สามเหลี่ยม = 0.250
การทดลองครั้งที่ 4, ความน่าจะเป็นที่ได้สามเหลี่ยม = 0.250
การทดลองครั้งที่ 5, ความน่าจะเป็นที่ได้สามเหลี่ยม = 0.253
การทดลองครั้งที่ 6, ความน่าจะเป็นที่ได้สามเหลี่ยม = 0.252
การทดลองครั้งที่ 7, ความน่าจะเป็นที่ได้สามเหลี่ยม = 0.250
การทดลองครั้งที่ 8, ความน่าจะเป็นที่ได้สามเหลี่ยม = 0.251
การทดลองครั้งที่ 9, ความน่าจะเป็นที่ได้สามเหลี่ยม = 0.246
การทดลองครั้งที่ 10, ความน่าจะเป็นที่ได้สามเหลี่ยม = 0.252

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

วิธีดูว่าหน้าตาคำตอบเป็นอย่างไรที่มีประโยชน์มากคือดูด้วยฮิสโตแกรม (histogram) ซึ่งจะบอกว่าค่าคำตอบที่ได้แต่ละค่าเกิดบ่อยแค่ไหน

ก่อนอื่นเราต้องทำการทดลองหลายๆครั้งก่อน เช่นทำสิบครั้ง:

nexperiments = 10 #จำนวนครั้งที่ทำการทดลอง
ntrials = 100_000 #จำนวนเส้นตรงที่ลองแบ่งเป็นสามส่วนในการทดลองแต่ละครั้ง
answers = [] #เก็บคำตอบจากการทดลองทั้งหมดไว้ในนี้
for e in range(1,nexperiments+1):
    answers.append(prob_triangle(ntrials))

print(answers)

คำตอบเราเก็บไว้ในลิสต์ชื่อ answers ซึ่งเราสามารถเอาไปทำอะไรต่อได้เช่นวาดฮิสโตแกรม ตอนนี้เราทำการทดลองแค่ 10 ครั้งมีหน้าตาประมาณนี้:

[0.2516, 0.251, 0.25219, 0.25302, 0.25189, 0.25049, 0.24938, 0.24922, 0.24566, 0.2502]

เราเอามาวาดฮิสโตแกรมได้ด้วย matplotlib แบบนี้ (หรือใช้อย่างอื่นเช่น Excel วาดก็ได้):

%matplotlib inline
import matplotlib.pyplot as plt #เรียกใช้ฟังก์ชั่นวาดกราฟต่างๆ

plt.hist(answers) #เอาข้อมูล answers ใส่ฮิสโตแกรม
plt.xlabel("ความน่าจะเป็นที่เป็นสามเหลี่ยม", fontname="Tahoma")
plt.ylabel("จำนวนครั้งที่เกิด",fontname="Tahoma")
plt.show() #วาดฮิสโตแกรม

ฮิสโตแกรมที่ได้หน้าตาตลกดี เพราะจำนวนครั้งที่ทดลองมีเพียงสิบครั้ง แต่อย่างไรก็ตามคำตอบทั้งสิบอยู่ในช่วง 0.246 ถึง 0.253:

เราเพิ่มจำนวนครั้งที่ทดลองเป็น 100 ครั้งโดยเปลี่ยนตัวแปร nexperiments จาก 10 เป็น 100 แล้ววาดฮิสโตแกรมใหม่:

nexperiments = 100 #จำนวนครั้งที่ทำการทดลอง
ntrials = 100_000 #จำนวนเส้นตรงที่ลองแบ่งเป็นสามส่วนในการทดลองแต่ละครั้ง
answers = [] #เก็บคำตอบจากการทดลองทั้งหมดไว้ในนี้
for e in range(1,nexperiments+1):
    answers.append(prob_triangle(ntrials))

plt.hist(answers) #เอาข้อมูล answers ใส่ฮิสโตแกรม
plt.xlabel("ความน่าจะเป็นที่เป็นสามเหลี่ยม", fontname="Tahoma")
plt.ylabel("จำนวนครั้งที่เกิด",fontname="Tahoma")
plt.show() #วาดฮิสโตแกรม

หน้าตาฮิสโตแกรมดูดีขี้น ค่าตรงกลางๆสูงกว่าขอบๆอย่างเห็นได้ชัด

ถ้าเราทำการทดลองหลายๆครั้งมากๆ ให้เป็น 10,000 ครั้งแทนที่จะเป็น 100 ครั้ง ฮิสโตแกรมเราจะหน้าตาแบบนี้ ค่าคำตอบกระจุกตัวอยู่แถวๆ 0.25 ไม่มีตำตอบไหนอยู่ห่างไกลนัก:

ถ้าเรามีเวลานานพอ (หรือเรามีวิธีทำให้ไพธอนเร็วขึ้นอีก–ซึ่งจะพูดถึงในตอนต่อไป) เราสามารถทำการทดลองเป็นล้านครั้งเพื่อดูว่าค่าตอบของเราอยู่แถวไหนได้อย่างมั่นใจมากยิ่งขึ้น ตัวอย่างหน้าตาฮิสโตแกรมของการทดลอง 1 ล้านครั้งครับ:

หลังจากเราดูภาพฮิสโตแกรมว่าคำตอบอยู่เป็นกลุ่ม ไม่กระจัดกระจายเกินไป เราอาจจะสรุปคำตอบที่ได้มาด้วยค่าเฉลี่ย (mean) และค่าเบี่ยงเบนมาตรฐาน (standard deviation) เช่นการคำนวณด้วย Numpy แบบนี้ครับ:

import numpy as np #เรียกใช้ฟังก์ชั่นต่างๆใน numpy
print(f"จากการทดลอง {nexperiments:,} ครั้ง")
print(f"ค่าเฉลี่ยของคำตอบคือ {np.mean(answers):.3f}")
print(f"ค่าเบี่ยงเบนมาตรฐานคือ {np.std(answers):.3f}")
จากการทดลอง 1,000 ครั้ง
ค่าเฉลี่ยของคำตอบคือ 0.250
ค่าเบี่ยงเบนมาตรฐานคือ 0.001

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

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

(ตอนที่แล้วอยู่ที่ https://witpoko.com/?p=7485 ตอนต่อไปอยู่ที่ https://witpoko.com/?p=7526)

2 thoughts on “คอมขยายสมอง (2): เมื่อไรเราพอจะเชื่อค่าการทดลองโดยคอมพิวเตอร์ได้บ้าง”

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.