เราคุยกันต่อจากตอนที่แล้วที่เราให้คอมพิวเตอร์ทำการทดลองหาคำตอบที่เราไม่รู้ (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): เมื่อไรเราพอจะเชื่อค่าการทดลองโดยคอมพิวเตอร์ได้บ้าง”