AI-For-Beginners/translations/th/lessons/5-NLP/16-RNN/README.md

98 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "58bf4adb210aab53e8f78c8082040e7c",
"translation_date": "2025-08-29T09:24:48+00:00",
"source_file": "lessons/5-NLP/16-RNN/README.md",
"language_code": "th"
}
-->
# เครือข่ายประสาทเทียมแบบวนซ้ำ (Recurrent Neural Networks)
## [แบบทดสอบก่อนเรียน](https://red-field-0a6ddfd03.1.azurestaticapps.net/quiz/116)
ในส่วนก่อนหน้านี้ เราได้ใช้การแสดงผลเชิงความหมายที่ซับซ้อนของข้อความและตัวจำแนกเชิงเส้นแบบง่ายที่อยู่บน embeddings สถาปัตยกรรมนี้ช่วยจับความหมายรวมของคำในประโยค แต่ไม่ได้คำนึงถึง **ลำดับ** ของคำ เนื่องจากการดำเนินการรวมบน embeddings ได้ลบข้อมูลนี้ออกไปจากข้อความต้นฉบับ ด้วยเหตุนี้ โมเดลเหล่านี้จึงไม่สามารถจำลองลำดับของคำได้ และไม่สามารถแก้ปัญหาที่ซับซ้อนหรือคลุมเครือ เช่น การสร้างข้อความหรือการตอบคำถามได้
เพื่อจับความหมายของลำดับข้อความ เราจำเป็นต้องใช้สถาปัตยกรรมเครือข่ายประสาทเทียมอีกแบบหนึ่งที่เรียกว่า **เครือข่ายประสาทเทียมแบบวนซ้ำ** หรือ RNN ใน RNN เราจะส่งประโยคผ่านเครือข่ายทีละสัญลักษณ์ และเครือข่ายจะสร้าง **สถานะ** ซึ่งเราจะส่งกลับเข้าไปในเครือข่ายพร้อมกับสัญลักษณ์ถัดไป
![RNN](../../../../../translated_images/rnn.27f5c29c53d727b546ad3961637a267f0fe9ec5ab01f2a26a853c92fcefbb574.th.png)
> ภาพโดยผู้เขียน
เมื่อได้รับลำดับอินพุตของโทเค็น X<sub>0</sub>,...,X<sub>n</sub> RNN จะสร้างลำดับของบล็อกเครือข่ายประสาทเทียม และฝึกฝนลำดับนี้แบบ end-to-end โดยใช้ backpropagation แต่ละบล็อกเครือข่ายจะรับคู่ (X<sub>i</sub>,S<sub>i</sub>) เป็นอินพุต และสร้าง S<sub>i+1</sub> เป็นผลลัพธ์ สถานะสุดท้าย S<sub>n</sub> หรือ (ผลลัพธ์ Y<sub>n</sub>) จะถูกส่งไปยังตัวจำแนกเชิงเส้นเพื่อสร้างผลลัพธ์ บล็อกเครือข่ายทั้งหมดใช้เวทเดียวกัน และถูกฝึกแบบ end-to-end โดยใช้ backpropagation เพียงครั้งเดียว
เนื่องจากเวกเตอร์สถานะ S<sub>0</sub>,...,S<sub>n</sub> ถูกส่งผ่านเครือข่าย มันจึงสามารถเรียนรู้ความสัมพันธ์เชิงลำดับระหว่างคำได้ ตัวอย่างเช่น เมื่อคำว่า *not* ปรากฏในลำดับ มันสามารถเรียนรู้ที่จะปฏิเสธองค์ประกอบบางอย่างในเวกเตอร์สถานะ ส่งผลให้เกิดการปฏิเสธ
> ✅ เนื่องจากเวทของบล็อก RNN ทั้งหมดในภาพด้านบนถูกแชร์ ภาพเดียวกันนี้สามารถแสดงเป็นบล็อกเดียว (ทางขวา) ที่มีลูปป้อนกลับ ซึ่งส่งสถานะผลลัพธ์ของเครือข่ายกลับไปยังอินพุต
## โครงสร้างของเซลล์ RNN
มาดูกันว่าเซลล์ RNN แบบง่าย ๆ ถูกจัดระเบียบอย่างไร มันรับสถานะก่อนหน้า S<sub>i-1</sub> และสัญลักษณ์ปัจจุบัน X<sub>i</sub> เป็นอินพุต และต้องสร้างสถานะผลลัพธ์ S<sub>i</sub> (และบางครั้งเราก็สนใจผลลัพธ์อื่น Y<sub>i</sub> ด้วย เช่นในกรณีของเครือข่ายแบบสร้าง)
เซลล์ RNN แบบง่ายมีเมทริกซ์เวทสองตัวภายใน: ตัวหนึ่งแปลงสัญลักษณ์อินพุต (เรียกว่า W) และอีกตัวหนึ่งแปลงสถานะอินพุต (H) ในกรณีนี้ ผลลัพธ์ของเครือข่ายคำนวณเป็น σ(W×X<sub>i</sub>+H×S<sub>i-1</sub>+b) โดยที่ σ คือฟังก์ชันการกระตุ้น และ b คือ bias เพิ่มเติม
<img alt="RNN Cell Anatomy" src="images/rnn-anatomy.png" width="50%"/>
> ภาพโดยผู้เขียน
ในหลายกรณี โทเค็นอินพุตจะถูกส่งผ่านเลเยอร์ embedding ก่อนเข้าสู่ RNN เพื่อลดมิติข้อมูล ในกรณีนี้ หากมิติของเวกเตอร์อินพุตคือ *emb_size* และเวกเตอร์สถานะคือ *hid_size* - ขนาดของ W คือ *emb_size*×*hid_size* และขนาดของ H คือ *hid_size*×*hid_size*
## หน่วยความจำระยะยาวและระยะสั้น (LSTM)
หนึ่งในปัญหาหลักของ RNN แบบดั้งเดิมคือปัญหา **การหายไปของกราเดียนต์** เนื่องจาก RNN ถูกฝึกแบบ end-to-end ใน backpropagation ครั้งเดียว มันจึงมีความยากลำบากในการส่งผ่านข้อผิดพลาดไปยังเลเยอร์แรกของเครือข่าย และทำให้เครือข่ายไม่สามารถเรียนรู้ความสัมพันธ์ระหว่างโทเค็นที่อยู่ห่างไกลได้ วิธีหนึ่งในการหลีกเลี่ยงปัญหานี้คือการแนะนำ **การจัดการสถานะอย่างชัดเจน** โดยใช้สิ่งที่เรียกว่า **เกต** มีสถาปัตยกรรมที่เป็นที่รู้จักสองแบบในลักษณะนี้: **Long Short Term Memory** (LSTM) และ **Gated Relay Unit** (GRU)
![ภาพตัวอย่างเซลล์ LSTM](../../../../../lessons/5-NLP/16-RNN/images/long-short-term-memory-cell.svg)
> แหล่งที่มาของภาพ TBD
เครือข่าย LSTM ถูกจัดระเบียบในลักษณะที่คล้ายกับ RNN แต่มีสองสถานะที่ถูกส่งผ่านจากเลเยอร์หนึ่งไปยังอีกเลเยอร์หนึ่ง: สถานะจริง C และเวกเตอร์ซ่อน H ในแต่ละหน่วย เวกเตอร์ซ่อน H<sub>i</sub> จะถูกเชื่อมต่อกับอินพุต X<sub>i</sub> และพวกมันควบคุมสิ่งที่เกิดขึ้นกับสถานะ C ผ่าน **เกต** แต่ละเกตเป็นเครือข่ายประสาทเทียมที่มีฟังก์ชัน sigmoid (ผลลัพธ์ในช่วง [0,1]) ซึ่งสามารถคิดว่าเป็นหน้ากากแบบบิตเมื่อคูณกับเวกเตอร์สถานะ มีเกตดังต่อไปนี้ (จากซ้ายไปขวาในภาพด้านบน):
* **เกตลืม** รับเวกเตอร์ซ่อนและกำหนดว่าคอมโพเนนต์ใดของเวกเตอร์ C ที่เราต้องลืม และคอมโพเนนต์ใดที่ต้องส่งผ่าน
* **เกตอินพุต** รับข้อมูลบางส่วนจากอินพุตและเวกเตอร์ซ่อน และแทรกข้อมูลนั้นลงในสถานะ
* **เกตเอาต์พุต** แปลงสถานะผ่านเลเยอร์เชิงเส้นที่มีการกระตุ้นแบบ *tanh* จากนั้นเลือกคอมโพเนนต์บางส่วนโดยใช้เวกเตอร์ซ่อน H<sub>i</sub> เพื่อสร้างสถานะใหม่ C<sub>i+1</sub>
คอมโพเนนต์ของสถานะ C สามารถคิดว่าเป็นแฟล็กที่สามารถเปิดและปิดได้ ตัวอย่างเช่น เมื่อเราพบชื่อ *Alice* ในลำดับ เราอาจต้องการสมมติว่ามันหมายถึงตัวละครหญิง และยกแฟล็กในสถานะว่าเรามีคำนามเพศหญิงในประโยค เมื่อเราพบวลี *and Tom* ต่อไป เราจะยกแฟล็กว่ามีคำนามพหูพจน์ ดังนั้นโดยการจัดการสถานะ เราสามารถติดตามคุณสมบัติทางไวยากรณ์ของส่วนต่าง ๆ ของประโยคได้
> ✅ แหล่งข้อมูลที่ยอดเยี่ยมสำหรับการทำความเข้าใจภายในของ LSTM คือบทความที่ยอดเยี่ยมนี้ [Understanding LSTM Networks](https://colah.github.io/posts/2015-08-Understanding-LSTMs/) โดย Christopher Olah
## RNN แบบสองทิศทางและหลายเลเยอร์
เราได้พูดถึงเครือข่ายแบบวนซ้ำที่ทำงานในทิศทางเดียว จากจุดเริ่มต้นของลำดับไปจนถึงจุดสิ้นสุด ซึ่งดูเป็นธรรมชาติ เพราะมันคล้ายกับวิธีที่เราอ่านและฟังคำพูด อย่างไรก็ตาม เนื่องจากในหลายกรณีที่ใช้งานจริง เราสามารถเข้าถึงลำดับอินพุตแบบสุ่มได้ จึงอาจสมเหตุสมผลที่จะดำเนินการคำนวณแบบวนซ้ำในทั้งสองทิศทาง เครือข่ายดังกล่าวเรียกว่า **RNN แบบสองทิศทาง** เมื่อจัดการกับเครือข่ายแบบสองทิศทาง เราจะต้องมีเวกเตอร์สถานะซ่อนสองตัว หนึ่งตัวสำหรับแต่ละทิศทาง
เครือข่ายแบบวนซ้ำ ไม่ว่าจะเป็นแบบทิศทางเดียวหรือสองทิศทาง จะจับรูปแบบบางอย่างภายในลำดับ และสามารถเก็บรูปแบบเหล่านั้นไว้ในเวกเตอร์สถานะหรือส่งผ่านไปยังผลลัพธ์ เช่นเดียวกับเครือข่ายแบบคอนโวลูชัน เราสามารถสร้างเลเยอร์แบบวนซ้ำอีกเลเยอร์หนึ่งบนเลเยอร์แรกเพื่อจับรูปแบบระดับสูงและสร้างจากรูปแบบระดับต่ำที่สกัดโดยเลเยอร์แรก สิ่งนี้นำเราไปสู่แนวคิดของ **RNN แบบหลายเลเยอร์** ซึ่งประกอบด้วยเครือข่ายแบบวนซ้ำสองเลเยอร์หรือมากกว่า โดยที่ผลลัพธ์ของเลเยอร์ก่อนหน้าจะถูกส่งไปยังเลเยอร์ถัดไปเป็นอินพุต
![ภาพแสดง RNN แบบหลายเลเยอร์ LSTM](../../../../../translated_images/multi-layer-lstm.dd975e29bb2a59fe58b429db833932d734c81f211cad2783797a9608984acb8c.th.jpg)
*ภาพจาก [โพสต์ที่ยอดเยี่ยมนี้](https://towardsdatascience.com/from-a-lstm-cell-to-a-multilayer-lstm-network-with-pytorch-2899eb5696f3) โดย Fernando López*
## ✍️ แบบฝึกหัด: Embeddings
เรียนรู้เพิ่มเติมในโน้ตบุ๊กต่อไปนี้:
* [RNNs with PyTorch](RNNPyTorch.ipynb)
* [RNNs with TensorFlow](RNNTF.ipynb)
## สรุป
ในหน่วยนี้ เราได้เห็นว่า RNN สามารถใช้สำหรับการจัดประเภทลำดับได้ แต่ในความเป็นจริงแล้ว มันสามารถจัดการงานอื่น ๆ ได้อีกมากมาย เช่น การสร้างข้อความ การแปลภาษา และอื่น ๆ เราจะพิจารณางานเหล่านั้นในหน่วยถัดไป
## 🚀 ความท้าทาย
อ่านวรรณกรรมเกี่ยวกับ LSTM และพิจารณาการใช้งาน:
- [Grid Long Short-Term Memory](https://arxiv.org/pdf/1507.01526v1.pdf)
- [Show, Attend and Tell: Neural Image Caption
Generation with Visual Attention](https://arxiv.org/pdf/1502.03044v2.pdf)
## [แบบทดสอบหลังเรียน](https://red-field-0a6ddfd03.1.azurestaticapps.net/quiz/216)
## การทบทวนและการศึกษาด้วยตนเอง
- [Understanding LSTM Networks](https://colah.github.io/posts/2015-08-Understanding-LSTMs/) โดย Christopher Olah
## [การบ้าน: โน้ตบุ๊ก](assignment.md)
---
**ข้อจำกัดความรับผิดชอบ**:
เอกสารนี้ได้รับการแปลโดยใช้บริการแปลภาษา AI [Co-op Translator](https://github.com/Azure/co-op-translator) แม้ว่าเราจะพยายามให้การแปลมีความถูกต้อง แต่โปรดทราบว่าการแปลโดยอัตโนมัติอาจมีข้อผิดพลาดหรือความไม่ถูกต้อง เอกสารต้นฉบับในภาษาดั้งเดิมควรถือเป็นแหล่งข้อมูลที่เชื่อถือได้ สำหรับข้อมูลที่สำคัญ ขอแนะนำให้ใช้บริการแปลภาษามืออาชีพ เราไม่รับผิดชอบต่อความเข้าใจผิดหรือการตีความผิดที่เกิดจากการใช้การแปลนี้