# เทคนิคการฝึกสอน Deep Learning เมื่อเครือข่ายประสาทเทียมมีความลึกมากขึ้น การฝึกสอนเครือข่ายเหล่านี้ก็จะยิ่งท้าทายมากขึ้น หนึ่งในปัญหาหลักคือปัญหาที่เรียกว่า [vanishing gradients](https://en.wikipedia.org/wiki/Vanishing_gradient_problem) หรือ [exploding gradients](https://deepai.org/machine-learning-glossary-and-terms/exploding-gradient-problem#:~:text=Exploding%20gradients%20are%20a%20problem,updates%20are%20small%20and%20controlled.) [บทความนี้](https://towardsdatascience.com/the-vanishing-exploding-gradient-problem-in-deep-neural-networks-191358470c11) อธิบายปัญหาเหล่านี้ได้อย่างดี เพื่อทำให้การฝึกสอนเครือข่ายลึกมีประสิทธิภาพมากขึ้น มีเทคนิคบางอย่างที่สามารถนำมาใช้ได้ ## การรักษาค่าต่าง ๆ ให้อยู่ในช่วงที่เหมาะสม เพื่อให้การคำนวณเชิงตัวเลขมีความเสถียรมากขึ้น เราต้องการให้ค่าทั้งหมดในเครือข่ายประสาทเทียมของเราอยู่ในช่วงที่เหมาะสม โดยทั่วไปคือ [-1..1] หรือ [0..1] แม้ว่าจะไม่ใช่ข้อกำหนดที่เข้มงวดมากนัก แต่ธรรมชาติของการคำนวณแบบ floating point คือค่าที่มีขนาดต่างกันมากไม่สามารถจัดการได้อย่างแม่นยำ ตัวอย่างเช่น หากเราบวก 10-10 กับ 1010 เรามักจะได้ 1010 เพราะค่าที่เล็กกว่าจะถูก "แปลง" ให้มีลำดับเดียวกับค่าที่ใหญ่กว่า และ mantissa จะสูญหายไป ฟังก์ชันการกระตุ้นส่วนใหญ่มีความไม่เชิงเส้นในช่วง [-1..1] ดังนั้นจึงสมเหตุสมผลที่จะปรับขนาดข้อมูลอินพุตทั้งหมดให้อยู่ในช่วง [-1..1] หรือ [0..1] ## การกำหนดค่าเริ่มต้นของน้ำหนัก ในอุดมคติ เราต้องการให้ค่าต่าง ๆ อยู่ในช่วงเดียวกันหลังจากผ่านเลเยอร์ของเครือข่าย ดังนั้นการกำหนดค่าน้ำหนักเริ่มต้นในลักษณะที่รักษาการกระจายของค่าไว้จึงเป็นสิ่งสำคัญ การแจกแจงแบบปกติ **N(0,1)** ไม่ใช่ตัวเลือกที่ดี เพราะถ้าเรามีอินพุต *n* ค่าเบี่ยงเบนมาตรฐานของผลลัพธ์จะเป็น *n* และค่ามีแนวโน้มที่จะหลุดออกจากช่วง [0..1] การกำหนดค่าเริ่มต้นที่มักใช้ ได้แก่: * การแจกแจงแบบสม่ำเสมอ -- `uniform` * **N(0,1/n)** -- `gaussian` * **N(0,1/√n_in)** รับประกันว่าอินพุตที่มีค่าเฉลี่ยเป็นศูนย์และค่าเบี่ยงเบนมาตรฐานเป็น 1 จะยังคงมีค่าเฉลี่ย/ค่าเบี่ยงเบนมาตรฐานเดิม * **N(0,√2/(n_in+n_out))** -- ที่เรียกว่า **Xavier initialization** (`glorot`) ซึ่งช่วยให้สัญญาณอยู่ในช่วงระหว่างการส่งต่อและการส่งย้อนกลับ ## Batch Normalization แม้จะมีการกำหนดค่าน้ำหนักเริ่มต้นที่เหมาะสม น้ำหนักก็ยังสามารถมีค่าที่ใหญ่หรือเล็กเกินไปในระหว่างการฝึกสอน ซึ่งจะทำให้สัญญาณหลุดออกจากช่วงที่เหมาะสม เราสามารถนำสัญญาณกลับมาอยู่ในช่วงที่เหมาะสมได้โดยใช้เทคนิค **normalization** หนึ่งในหลาย ๆ เทคนิค แม้ว่าจะมีหลายวิธี (เช่น Weight normalization, Layer Normalization) แต่ที่ใช้บ่อยที่สุดคือ Batch Normalization แนวคิดของ **batch normalization** คือการพิจารณาค่าทั้งหมดใน minibatch และทำ normalization (เช่น ลบค่าเฉลี่ยและหารด้วยค่าเบี่ยงเบนมาตรฐาน) ตามค่าดังกล่าว โดยจะถูกนำมาใช้เป็นเลเยอร์ในเครือข่ายที่ทำ normalization หลังจากการใช้น้ำหนัก แต่ก่อนฟังก์ชันการกระตุ้น ผลลัพธ์คือเรามักจะได้ความแม่นยำที่สูงขึ้นและการฝึกสอนที่เร็วขึ้น นี่คือ [งานวิจัยต้นฉบับ](https://arxiv.org/pdf/1502.03167.pdf) เกี่ยวกับ batch normalization, [คำอธิบายใน Wikipedia](https://en.wikipedia.org/wiki/Batch_normalization) และ [บทความแนะนำที่ดี](https://towardsdatascience.com/batch-normalization-in-3-levels-of-understanding-14c2da90a338) (และอีกบทความ [ในภาษารัสเซีย](https://habrahabr.ru/post/309302/)) ## Dropout **Dropout** เป็นเทคนิคที่น่าสนใจที่ลบเซลล์ประสาทบางส่วนแบบสุ่มในระหว่างการฝึกสอน โดยจะถูกนำมาใช้เป็นเลเยอร์ที่มีพารามิเตอร์หนึ่งตัว (เปอร์เซ็นต์ของเซลล์ประสาทที่จะลบออก โดยทั่วไปคือ 10%-50%) และในระหว่างการฝึกสอนจะทำให้ค่าขององค์ประกอบบางส่วนในเวกเตอร์อินพุตเป็นศูนย์แบบสุ่มก่อนที่จะส่งไปยังเลเยอร์ถัดไป แม้ว่าจะฟังดูเป็นแนวคิดที่แปลก แต่คุณสามารถเห็นผลของ dropout ในการฝึกสอนตัวจำแนกตัวเลข MNIST ในโน้ตบุ๊ก [`Dropout.ipynb`](Dropout.ipynb) มันช่วยเร่งการฝึกสอนและช่วยให้เราบรรลุความแม่นยำที่สูงขึ้นในจำนวน epoch ที่น้อยลง ผลกระทบนี้สามารถอธิบายได้หลายวิธี: * มันสามารถถูกมองว่าเป็นปัจจัยสุ่มที่ทำให้โมเดลหลุดออกจาก local minimum * มันสามารถถูกมองว่าเป็น *implicit model averaging* เพราะในระหว่าง dropout เรากำลังฝึกโมเดลที่แตกต่างกันเล็กน้อย > *บางคนกล่าวว่าเมื่อคนเมาพยายามเรียนรู้อะไรบางอย่าง เขาจะจำสิ่งนั้นได้ดีขึ้นในเช้าวันรุ่งขึ้นเมื่อเทียบกับคนที่มีสติ เพราะสมองที่มีเซลล์ประสาทบางส่วนทำงานผิดปกติพยายามปรับตัวเพื่อเข้าใจความหมาย เราไม่เคยทดสอบว่าจริงหรือไม่* ## การป้องกัน Overfitting หนึ่งในแง่มุมที่สำคัญมากของ deep learning คือการป้องกัน [overfitting](../../3-NeuralNetworks/05-Frameworks/Overfitting.md) แม้ว่าจะน่าดึงดูดใจที่จะใช้โมเดลเครือข่ายประสาทเทียมที่ทรงพลังมาก แต่เราควรปรับสมดุลจำนวนพารามิเตอร์ของโมเดลกับจำนวนตัวอย่างการฝึกสอนเสมอ > ตรวจสอบให้แน่ใจว่าคุณเข้าใจแนวคิดของ [overfitting](../../3-NeuralNetworks/05-Frameworks/Overfitting.md) ที่เราได้แนะนำไว้ก่อนหน้านี้! มีหลายวิธีในการป้องกัน overfitting: * Early stopping -- ตรวจสอบข้อผิดพลาดในชุด validation อย่างต่อเนื่องและหยุดการฝึกสอนเมื่อข้อผิดพลาดใน validation เริ่มเพิ่มขึ้น * Explicit Weight Decay / Regularization -- เพิ่มค่าปรับในฟังก์ชัน loss สำหรับค่าน้ำหนักที่มีค่าสูง ซึ่งช่วยป้องกันโมเดลจากการให้ผลลัพธ์ที่ไม่เสถียร * Model Averaging -- ฝึกสอนโมเดลหลายตัวแล้วเฉลี่ยผลลัพธ์ ซึ่งช่วยลดความแปรปรวน * Dropout (Implicit Model Averaging) ## ตัวปรับแต่ง / อัลกอริทึมการฝึกสอน อีกแง่มุมที่สำคัญของการฝึกสอนคือการเลือกอัลกอริทึมการฝึกสอนที่ดี แม้ว่า **gradient descent** แบบคลาสสิกจะเป็นตัวเลือกที่สมเหตุสมผล แต่บางครั้งอาจช้าเกินไปหรือทำให้เกิดปัญหาอื่น ๆ ใน deep learning เราใช้ **Stochastic Gradient Descent** (SGD) ซึ่งเป็น gradient descent ที่ใช้กับ minibatches ที่สุ่มเลือกจากชุดการฝึกสอน น้ำหนักจะถูกปรับโดยใช้สูตรนี้: wt+1 = wt - η∇ℒ ### Momentum ใน **momentum SGD** เราจะเก็บส่วนหนึ่งของ gradient จากขั้นตอนก่อนหน้าไว้ มันคล้ายกับเมื่อเรากำลังเคลื่อนที่ไปในทิศทางหนึ่งด้วยแรงเฉื่อย และเราได้รับแรงกระแทกในทิศทางที่ต่างออกไป เส้นทางของเราไม่ได้เปลี่ยนทันที แต่ยังคงมีส่วนหนึ่งของการเคลื่อนที่เดิมอยู่ ที่นี่เราแนะนำเวกเตอร์ v เพื่อแสดงถึง *ความเร็ว*: * vt+1 = γ vt - η∇ℒ * wt+1 = wt+vt+1 พารามิเตอร์ γ แสดงถึงขอบเขตที่เราคำนึงถึงแรงเฉื่อย: γ=0 สอดคล้องกับ SGD แบบคลาสสิก; γ=1 เป็นสมการการเคลื่อนที่ล้วน ๆ ### Adam, Adagrad, ฯลฯ เนื่องจากในแต่ละเลเยอร์เราคูณสัญญาณด้วยเมทริกซ์ Wi ขึ้นอยู่กับ ||Wi|| gradient อาจลดลงจนใกล้ 0 หรือเพิ่มขึ้นอย่างไม่จำกัด นี่คือแก่นของปัญหา Exploding/Vanishing Gradients หนึ่งในวิธีแก้ปัญหานี้คือการใช้เฉพาะทิศทางของ gradient ในสมการ และละเว้นค่าขนาดสัมบูรณ์ เช่น wt+1 = wt - η(∇ℒ/||∇ℒ||), โดย ||∇ℒ|| = √∑(∇ℒ)2 อัลกอริทึมนี้เรียกว่า **Adagrad** อัลกอริทึมอื่น ๆ ที่ใช้แนวคิดเดียวกัน: **RMSProp**, **Adam** > **Adam** ถือว่าเป็นอัลกอริทึมที่มีประสิทธิภาพมากสำหรับหลาย ๆ การใช้งาน ดังนั้นหากคุณไม่แน่ใจว่าจะใช้อันไหน - ใช้ Adam ### Gradient clipping Gradient clipping เป็นการขยายแนวคิดข้างต้น เมื่อ ||∇ℒ|| ≤ θ เราจะพิจารณา gradient ดั้งเดิมในการปรับน้ำหนัก และเมื่อ ||∇ℒ|| > θ - เราจะแบ่ง gradient ด้วย norm ของมัน ที่นี่ θ เป็นพารามิเตอร์ ในกรณีส่วนใหญ่เราสามารถใช้ θ=1 หรือ θ=10 ### Learning rate decay ความสำเร็จของการฝึกสอนมักขึ้นอยู่กับพารามิเตอร์ learning rate η เป็นเรื่องที่สมเหตุสมผลที่จะสมมติว่าค่า η ที่ใหญ่ขึ้นส่งผลให้การฝึกสอนเร็วขึ้น ซึ่งเป็นสิ่งที่เราต้องการในช่วงเริ่มต้นของการฝึกสอน และจากนั้นค่า η ที่เล็กลงช่วยให้เราปรับแต่งเครือข่ายได้ดีขึ้น ดังนั้นในกรณีส่วนใหญ่เราต้องการลดค่า η ในกระบวนการฝึกสอน สิ่งนี้สามารถทำได้โดยการคูณค่า η ด้วยตัวเลขบางตัว (เช่น 0.98) หลังจากแต่ละ epoch ของการฝึกสอน หรือโดยใช้ **learning rate schedule** ที่ซับซ้อนกว่า ## สถาปัตยกรรมเครือข่ายที่แตกต่างกัน การเลือกสถาปัตยกรรมเครือข่ายที่เหมาะสมสำหรับปัญหาของคุณอาจเป็นเรื่องยาก โดยปกติเราจะเลือกสถาปัตยกรรมที่พิสูจน์แล้วว่าใช้ได้ผลสำหรับงานเฉพาะของเรา (หรืองานที่คล้ายกัน) นี่คือ [ภาพรวมที่ดี](https://www.topbots.com/a-brief-history-of-neural-network-architectures/) ของสถาปัตยกรรมเครือข่ายประสาทเทียมสำหรับการมองเห็นด้วยคอมพิวเตอร์ > สิ่งสำคัญคือต้องเลือกสถาปัตยกรรมที่ทรงพลังเพียงพอสำหรับจำนวนตัวอย่างการฝึกสอนที่เรามี การเลือกโมเดลที่ทรงพลังเกินไปอาจทำให้เกิด [overfitting](../../3-NeuralNetworks/05-Frameworks/Overfitting.md) อีกวิธีที่ดีคือการใช้สถาปัตยกรรมที่ปรับตัวเองให้เหมาะสมกับความซับซ้อนที่ต้องการได้ ในระดับหนึ่ง สถาปัตยกรรม **ResNet** และ **Inception** มีความสามารถในการปรับตัวเอง [ข้อมูลเพิ่มเติมเกี่ยวกับสถาปัตยกรรมการมองเห็นด้วยคอมพิวเตอร์](../07-ConvNets/CNN_Architectures.md) --- **ข้อจำกัดความรับผิดชอบ**: เอกสารนี้ได้รับการแปลโดยใช้บริการแปลภาษา AI [Co-op Translator](https://github.com/Azure/co-op-translator) แม้ว่าเราจะพยายามให้การแปลมีความถูกต้อง แต่โปรดทราบว่าการแปลอัตโนมัติอาจมีข้อผิดพลาดหรือความไม่แม่นยำ เอกสารต้นฉบับในภาษาต้นทางควรถือเป็นแหล่งข้อมูลที่เชื่อถือได้ สำหรับข้อมูลที่สำคัญ ขอแนะนำให้ใช้บริการแปลภาษามนุษย์มืออาชีพ เราจะไม่รับผิดชอบต่อความเข้าใจผิดหรือการตีความที่ผิดพลาดซึ่งเกิดจากการใช้การแปลนี้