>> ต่อจาก
บทที่ ๑๐ ในบทที่แล้วแสดงการนำชั้นมาประกอบกันเพื่อสร้างโครงข่ายประสาทเทียม
จะเห็นว่าหลังจากที่ทำการคำนวณไปข้างหน้าเสร็จก็ต้องมาเขียนขั้นตอนในการแพร่ย้อนกลับอีก
แต่ว่าจริงๆแล้วปกติเคลื่อนไปข้างหน้ายังไงก็ควรจะแพร่ย้อนกลับอย่างนั้น ตายตัวอยู่แล้ว ดังนั้นควรจะสามารถทำให้ในขณะที่ทำการคำนวณไปข้างหน้านั้นเส้นทางคำนวณการจะถูกบันทึกไปด้วย แล้วพอคำนวณไปถึงสุดท้ายก็แค่ออกคำสั่งแพร่ย้อนกลับ ก็จะเกิดการแพร่ย้อนกลับตามเส้นทางที่เดินมาจนถึงตรงนั้น
วิธีการแบบนี้เรียกว่า
การนิยามขณะวิ่ง (define by run) คือเส้นทางการคำนวณได้ถูกนิยามขึ้นทันทีในขณะวิ่งคำนวณไปข้างหน้านั้นเอง
หลักการนี้ถูกนำมาใช้จริงในเฟรมเวิร์กโครงข่ายประสาทเทียมที่ได้รับความนิยมอย่าง pytorch และ chainer เราสามารถเรียนรู้จากตรงนั้นได้
เพียงแต่ว่าของจริงที่ใช้ในนั้นจะซับซ้อนกว่าที่แนะนำในนี้มาก ในที่นี้เป็นแค่การนำแนวคิดพื้นฐานมาใช้ แต่ตัดส่วนที่ซับซ้อนออกไป
หลักการคือ สร้างคลาสของตัวแปร (Tuaprae) และคลาสของชั้น (Chan) ขึ้นมาดังนี้
ส่วนคลาสของชั้นฟังก์ชันกระตุ้นและฟังก์ชันค่าเสียหายที่เคยแนะนำในบทที่แล้วก็นิยามแบบเดิมแต่ตั้งให้เป็นคลาสย่อยของคลาส Chan เพื่อให้มีเมธอด __call__ ติดมาด้วย
ออบเจ็กต์ของคลาส Chan เวลาถูกเรียกใช้จะคำนวณไปข้างหน้าตามที่นิยามในเมธอด .pai() ในคลาสย่อย จากนั้นก็สร้างออบเจ็กต์ของคลาส Tuaprae ขึ้นมา ซึ่งจะบรรจุค่า (.kha) ที่ได้ และบันทึกไว้ด้วยว่าที่มา (.thima) ของมันมาจากชั้นไหน
ค่าตัวแปรต้นที่ป้อนให้ตอนเรียกใช้ชั้นจะเป็นค่าตัวเลขธรรมดาหรือออบเจ็กต์ของคลาส Tuaprae ก็ได้ กรณีที่ค่าที่รับมาเป็น Tuaprae จะถูกบันทึกไว้ใน .tuapraeton
แบบนี้เมื่อทำการคำนวณไปข้างหน้าเรื่อยๆตัวแปรตามที่ได้ก็จะบันทึกออบเจ็กต์ชั้นที่สร้างมันมา แล้วตัวออบเจ็กต์ชันเองก็บันทึกออบเจ็กต์ตัวแปรต้นไว้ แบบนี้ต่อไปเป็นทอดๆ
Tuaprae มีเมธอด .phraeyon() สำหรับทำการเริ่มแพร่ย้อนเมื่อคำนวณจนถึงสุดแล้ว เมื่อเริ่มเมธอดนี้จะเกิดการแพร่ย้อนแล้วคำนวณอนุพันธ์ในทุกตัวแปรและชั้นที่เป็นทางผ่านไปเรื่อยๆจนถึงต้นทาง
นอกจากนี้สำหรับชั้นที่มีพารามิเตอร์อย่าง Affin ก็ปรับให้ง่ายต่อการใช้งานขึ้น โดยสร้างคลาสใหม่ชื่อ Param สำหรับเป็นพารามิเตอร์ แล้วให้เก็บทั้งค่าตัวพารามิเตอร์และอนุพันธ์ของมันไปด้วย นอกจากนี้ก็รวมพารามิเตอร์ทั้งหมดไว้เป็นลิสต์ เก็บไว้ที่ .param
นอกจากนี้ ค่าน้ำหนัก (พารามิเตอร์ตัวแรก) ตั้งต้นในที่นี้กำหนดให้สร้างขึ้นง่ายๆโดยสร้างตามขนาดขาเข้า m0 และขนาดขาออก m1 โดยค่าตั้งต้นแจกแจงแบบปกติความกว้างเป็น sigma ค่าเหล่านี้ป้อนเข้ามาตอนสร้างออบเจ็กต์
ส่วนค่าไบแอส (พารามิเตอร์ตัวหลัง) ในที่นี้ให้เป็น 0 โดยมีขนาดเท่ากับค่าขาออก m1
รายละเอียดเกี่ยวกับเรื่องการกำหนดค่าพารามิเตอร์ตั้งต้นจะพูดถึงอีกทีใน
บทที่ ๑๓ ต่อมาลองดูตัวอย่างการนำมาใช้เพื่อสร้างคลาสของโครงข่ายประสาทเทียม
ในที่นี้ได้ลองสร้างในแบบที่แบ่งการคำนวณแต่ละส่วนแยกใส่เป็นเมธอดเพื่อให้เข้าใจง่าย
ภายในขั้นตอนวนซ้ำจะเริ่มจาก .ha_entropy() คือคำนวณไปข้างหน้าจนถึงหาเอนโทรปีออกมาเสร็จ
จากนั้นได้ค่า entropy ซึ่งเป็นออบเจ็กต์ของคลาส Tuaprae แล้วก็ใช้เมธอด .praeyon() เพื่อเริ่มการแพร่ย้อนกลับ แล้วก็จะได้ค่าอนุพันธ์ชันของพารามิเตอร์แต่ละตัวเก็บไว้
สุดท้ายก็ใช้เมธอด .prap_para() ทำการค้นว่าชั้นไหนมีพารามิเตอร์แล้วทำการปรับ แล้วพอปรับเสร็จก็ล้างค่าอนุพันธ์ให้เป็น 0 ไปด้วย
ส่วนจำนวนชั้น และจำนวนเซลล์ในแต่ละชั้นก็กำหนดโดยค่า m ตอนเริ่มสร้าง
ลองพิจารณาจำแนกกลุ่มข้อมูลชุดนี้
เริ่มจากลองใช้โครงข่าย ๒ ชั้น
หากต้องการเปลี่ยนโครงสร้างก็แค่แก้ตรงบรรทัดที่สร้างออบเจ็กต์ ส่วนที่เหลือเหมือนเดิม เช่นต้องการลอง ๔ ชั้นก็แก้เป็นแบบนี้
เทียบกันแล้วอาจเห็นได้ว่าแบบ ๔ ชั้นดูมีแนวโน้มที่จะแบ่งพื้นที่ออกมาซับซ้อนกว่า แต่แบบนี้ทำให้มีโอกาสเกิดการเรียนรู้เกินได้ง่าย จึงไม่ใช่ว่าชั้นเยอะแล้วจะดีเสมอไป
อาจลองปรับเปลี่ยนชั้นและจำนวนเซลล์ในแต่ละชั้น รวมถึงฟังก์ชันกระตุ้นและอัตราการเรียนรู้แล้วเทียบผลดูได้
สำหรับนิยามคลาสต่างๆที่ถูกสร้างในบทนี้จะถูกนำไปใช้ในบทต่อๆไปด้วย ไม่มีการเปลี่ยนแปลงแล้ว เพื่อให้หยิบมาใช้ได้สะดวกจึงได้รวบรวมคลาสต่างๆเอาไว้ในไฟล์ >>
unagi.py ในนี้รวมถึงสิ่งที่จะกล่าวถึงในบทถัดๆไปด้วย
>> อ่านต่อ
บทที่ ๑๒