Schooling Flappy Bird: แบบฝึกหัดการเรียนรู้การเสริมแรง

เผยแพร่แล้ว: 2022-03-11

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

ในบทช่วยสอนการเรียนรู้การเสริมแรงนี้ ฉันจะแสดงวิธีที่เราสามารถใช้ PyTorch เพื่อสอนวิธีการเล่น Flappy Bird ให้กับเครือข่ายประสาทการเรียนรู้การเสริมแรง แต่ก่อนอื่น เราจะต้องครอบคลุมการสร้างบล็อคจำนวนหนึ่ง

อัลกอริธึมแมชชีนเลิร์นนิงสามารถแบ่งออกเป็นสองส่วนคร่าวๆ: อัลกอริธึมการเรียนรู้แบบดั้งเดิมและอัลกอริธึมการเรียนรู้เชิงลึก อัลกอริธึมการเรียนรู้แบบดั้งเดิมมักจะมีพารามิเตอร์ที่เรียนรู้ได้น้อยกว่าอัลกอริธึมการเรียนรู้เชิงลึกมากและมีความสามารถในการเรียนรู้น้อยกว่ามาก

นอกจากนี้ อัลกอริธึมการเรียนรู้แบบดั้งเดิมยังไม่สามารถ แยกคุณลักษณะ ได้: ผู้เชี่ยวชาญด้านปัญญาประดิษฐ์จำเป็นต้องค้นหาการแสดงข้อมูลที่ดี ซึ่งจะถูกส่งไปยังอัลกอริทึมการเรียนรู้ ตัวอย่างของเทคนิคการเรียนรู้ของเครื่องแบบดั้งเดิม ได้แก่ SVM, ฟอเรสต์แบบสุ่ม, โครงสร้างการตัดสินใจ และ $k$-mean ในขณะที่อัลกอริธึมกลางในการเรียนรู้เชิงลึกคือ โครงข่ายประสาทเทียมระดับลึก

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

เทคนิคการเรียนรู้เชิงลึกจำนวนมากเป็นที่ทราบกันดีมาเป็นเวลานาน แต่ความก้าวหน้าล่าสุดในฮาร์ดแวร์ได้กระตุ้นการวิจัยและพัฒนาการเรียนรู้เชิงลึกอย่างรวดเร็ว Nvidia รับผิดชอบในการขยายสาขาเนื่องจาก GPU ได้เปิดใช้งานการทดลองการเรียนรู้เชิงลึกอย่างรวดเร็ว

พารามิเตอร์ที่เรียนรู้ได้และไฮเปอร์พารามิเตอร์

อัลกอริธึมการเรียนรู้ของเครื่องประกอบด้วยพารามิเตอร์ที่เรียนรู้ได้ซึ่งปรับในกระบวนการฝึกอบรมและพารามิเตอร์ที่ไม่สามารถเรียนรู้ได้ซึ่งตั้งค่าไว้ก่อนกระบวนการฝึกอบรม พารามิเตอร์ที่ตั้งไว้ก่อนการเรียนรู้เรียกว่า ไฮเปอร์ พารามิเตอร์

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

อัลกอริธึมการเรียนรู้ภายใต้การดูแล ไม่ได้รับการดูแล และเสริมกำลัง

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

เมื่อเราพูดถึงการเรียนรู้ภายใต้การดูแล เราจะดูคู่ $ (x_i, y_i) $ $ x_i $ คืออินพุตของอัลกอริทึมและ $ y_i $ คือเอาต์พุต งานของเราคือค้นหาฟังก์ชันที่จะทำการจับคู่ที่ถูกต้องจาก $ x_i $ ถึง $ y_i $

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

\[MSE = \sum_{i=1}^{n} (y_i - \widehat{y_i} )^2\]

ที่นี่ $ y_i $ เป็นป้ายกำกับความจริงพื้นฐาน และ $ \widehat{y_i} $ เป็นป้ายกำกับที่คาดคะเน เครื่องมือเพิ่มประสิทธิภาพหนึ่งที่ได้รับความนิยมอย่างมากในการเรียนรู้เชิงลึกคือ stochastic gradient descent มีรูปแบบต่างๆ มากมายที่พยายามปรับปรุงวิธีการไล่ระดับสีสุ่ม: Adam, Adadelta, Adagrad และอื่นๆ

อัลกอริธึมที่ไม่ได้รับการดูแลจะพยายามค้นหาโครงสร้างในข้อมูลโดยไม่ได้ระบุป้ายกำกับไว้อย่างชัดเจน $k$-means เป็นหนึ่งในตัวอย่างของอัลกอริธึมที่ไม่มีการควบคุมซึ่งพยายามค้นหาคลัสเตอร์ที่เหมาะสมที่สุดในข้อมูล ด้านล่างเป็นรูปภาพที่มีจุดข้อมูล 300 จุด $k$-หมายถึงอัลกอริทึมพบโครงสร้างในข้อมูลและกำหนดป้ายกำกับคลัสเตอร์ให้กับแต่ละจุดข้อมูล แต่ละคลัสเตอร์มีสีของตัวเอง

กลุ่มจุดข้อมูลที่แบ่งสี พบคลัสเตอร์โดยอัลกอริธึมที่ไม่ได้รับการดูแล

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

รางวัลจะมอบให้กับตัวแทนเมื่อมีการดำเนินการ มันบอกตัวแทนว่าการกระทำนั้นดีแค่ไหน โดยการรับรู้การสังเกตและรางวัล ตัวแทนได้เรียนรู้วิธีปฏิบัติตนอย่างเหมาะสมในสภาพแวดล้อม ฉันจะลงรายละเอียดเพิ่มเติมด้านล่าง

การเรียนรู้การเสริมแรงแบบแอคทีฟ พาสซีฟ และผกผัน

มีวิธีการที่แตกต่างกันสองสามวิธีสำหรับเทคนิคนี้ อย่างแรกเลย มีการเรียนรู้การเสริมกำลังเชิงรุก ซึ่งเราใช้ที่นี่ ในทางตรงกันข้าม มีการเรียนรู้แบบเสริมกำลังแบบพาสซีฟ โดยที่รางวัลเป็นเพียงการสังเกตอีกรูปแบบหนึ่ง และการตัดสินใจจะเป็นไปตามนโยบายที่กำหนดไว้

ในที่สุด การเรียนรู้การเสริมแรงผกผันพยายามที่จะสร้างฟังก์ชันการให้รางวัลขึ้นใหม่โดยพิจารณาจากประวัติของการกระทำและรางวัลในสถานะต่างๆ

ลักษณะทั่วไป Overfitting และ Underfitting

อินสแตนซ์ของพารามิเตอร์และไฮเปอร์พารามิเตอร์คงที่ใดๆ เรียกว่าโมเดล การทดลองแมชชีนเลิร์นนิงมักประกอบด้วยสองส่วน: การฝึกอบรมและการทดสอบ

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

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

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

ด้านล่างนี้คือรูปภาพที่แสดงการสวมใส่ที่พอดีและพอดีตัวเมื่อเปรียบเทียบกับสถานการณ์ที่สมดุลระหว่างข้อมูลโดยรวมและฟังก์ชันการคาดคะเน

กราฟ underfitting สมดุลและ overfitting ฟังก์ชันที่สมดุลติดตามแนวโน้มทั่วไปของจุดข้อมูลได้ดีพอ โดยไม่ยึดติดกับจุดข้อมูลแต่ละจุดมากเกินไป

ความสามารถในการปรับขนาด

ข้อมูลมีความสำคัญอย่างยิ่งในการสร้างแบบจำลองการเรียนรู้ของเครื่อง โดยปกติอัลกอริธึมการเรียนรู้แบบดั้งเดิมไม่ต้องการข้อมูลมากเกินไป แต่เนื่องจากความจุที่จำกัด ประสิทธิภาพก็จำกัดเช่นกัน ด้านล่างนี้คือแผนภาพที่แสดงให้เห็นว่าวิธีการเรียนรู้เชิงลึกนั้นปรับขนาดได้ดีเพียงใดเมื่อเทียบกับอัลกอริธึมการเรียนรู้ของเครื่องแบบดั้งเดิม

ประสิทธิภาพเทียบกับปริมาณข้อมูลสำหรับการเรียนรู้เชิงลึกและอัลกอริทึมแบบดั้งเดิม โครงข่ายประสาทเทียมทำงานได้ดีกว่าในขนาดต่างๆ

โครงข่ายประสาทเทียม

โครงข่ายประสาทเทียมประกอบด้วยหลายชั้น ภาพด้านล่างแสดงโครงข่ายประสาทเทียมแบบง่ายที่มีสี่ชั้น เลเยอร์แรกเป็นเลเยอร์อินพุต และเลเยอร์สุดท้ายคือเลเยอร์เอาต์พุต สองชั้นระหว่างชั้นอินพุตและเอาท์พุตเป็นชั้นที่ซ่อนอยู่

กราฟโครงข่ายประสาทเทียม แสดงทุกๆ โหนดของเลเยอร์อินพุตที่แมปกับทุกๆ โหนดของ Hidden Layer 1 ในทางกลับกัน จะถูกแมปกับทุกๆ โหนดของเลเยอร์ที่ซ่อน 2 ที่ซ่อนไว้ และสุดท้ายจะจับคู่กับเลเยอร์เอาต์พุต ซึ่งประกอบด้วยโหนดเดียว

หากโครงข่ายประสาทเทียมมีเลเยอร์ที่ซ่อนอยู่มากกว่าหนึ่งชั้น เราเรียกว่าโครงข่ายประสาทเทียมระดับลึก ชุดอินพุต $ X $ ถูกกำหนดให้กับโครงข่ายประสาทเทียม และรับเอาต์พุต $ y $ การเรียนรู้ทำได้โดยใช้อัลกอริธึม backpropagation ซึ่งรวมฟังก์ชันการสูญเสียและเครื่องมือเพิ่มประสิทธิภาพ

Backpropagation ประกอบด้วยสองส่วน: การส่งต่อและการส่งต่อย้อนกลับ ในการส่งต่อข้อมูลอินพุตจะถูกใส่เข้ากับอินพุตของโครงข่ายประสาทเทียมและรับเอาต์พุต การสูญเสียระหว่างความจริงภาคพื้นดินและการทำนายจะถูกคำนวณ จากนั้นในการผ่านย้อนกลับ พารามิเตอร์ของโครงข่ายประสาทเทียมจะถูกปรับตามการสูญเสีย

โครงข่ายประสาทเทียม

รูปแบบโครงข่ายประสาทเทียมแบบหนึ่งคือ โครงข่ายประสาทเทียม ใช้เป็นหลักสำหรับงานวิทัศน์คอมพิวเตอร์

เลเยอร์ที่สำคัญที่สุดในโครงข่ายประสาทเทียมคือชั้นที่เกิดการบิดเบี้ยว (จึงเป็นชื่อ) พารามิเตอร์ของมันทำจากตัวกรองที่เรียนรู้ได้หรือที่เรียกว่าเมล็ด เลเยอร์ Convolutional ใช้การดำเนินการ Convolution กับอินพุต โดยส่งผลลัพธ์ไปยังเลเยอร์ถัดไป การดำเนินการ convolution ช่วยลดจำนวนพารามิเตอร์ที่เรียนรู้ได้ ทำหน้าที่เป็นฮิวริสติกชนิดหนึ่ง และทำให้การฝึกอบรมโครงข่ายประสาทเทียมง่ายขึ้น

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

แอนิเมชันที่เน้นเคอร์เนลและการทำงานของเคอร์เนลในขณะที่รูปภาพได้รับการประมวลผล และเอาต์พุตของฟีเจอร์ที่เกี่ยวข้องกัน

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

\[ReLU = \max(0, x)\]

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

ด้านล่างเป็นโครงเรื่องของฟังก์ชัน ReLU

ฟังก์ชัน ReLU คล้ายกับเส้นทแยงมุมอย่างง่ายของกราฟ y=x แต่มีค่า x ลบทั้งหมดจับคู่กับศูนย์

อย่างที่คุณเห็น ฟังก์ชัน ReLU นี้เพียงแค่เปลี่ยนค่าลบเป็นศูนย์ ซึ่งจะช่วยป้องกันปัญหาการไล่ระดับสีที่หายไป หากการไล่ระดับสีหายไป จะไม่ส่งผลกระทบมากนักในการปรับน้ำหนักของโครงข่ายประสาทเทียม

โครงข่ายประสาทเทียมประกอบด้วยหลายชั้น: ชั้น Convolutional, ชั้น ReLU และชั้นที่เชื่อมต่ออย่างสมบูรณ์ เลเยอร์ที่เชื่อมต่ออย่างสมบูรณ์จะเชื่อมต่อเซลล์ประสาททุกเซลล์ในชั้นหนึ่งกับเซลล์ประสาททุกเซลล์ในอีกชั้นหนึ่ง ดังที่เห็นได้จากเลเยอร์ที่ซ่อนอยู่ 2 ชั้นในรูปภาพที่จุดเริ่มต้นของส่วนนี้ แมปเลเยอร์ที่เชื่อมต่ออย่างสมบูรณ์ล่าสุดจะส่งออกจากเลเยอร์ก่อนหน้าไปยังค่า number_of_actions ในกรณีนี้

แอปพลิเคชั่น

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

การเรียนรู้การเสริมแรง

การเรียนรู้การเสริมกำลังขึ้นอยู่กับ ตัวแทน ตัวแทนดำเนินการในสภาพแวดล้อมและรับการสังเกตและรางวัลจากมัน ตัวแทนต้องได้รับการฝึกอบรมเพื่อเพิ่มรางวัลสะสมสูงสุด ดังที่ระบุไว้ในบทนำ ด้วยอัลกอริธึมการเรียนรู้ของเครื่องแบบคลาสสิก วิศวกรการเรียนรู้ของเครื่องจำเป็นต้องทำการแยกคุณลักษณะ กล่าวคือ สร้างคุณลักษณะที่ดีซึ่งแสดงถึงสภาพแวดล้อมได้ดี และถูกป้อนเข้าสู่อัลกอริธึมการเรียนรู้ของเครื่อง

การใช้การเรียนรู้เชิงลึกทำให้สามารถสร้างระบบแบบ end-to-end ที่รับอินพุตที่มีมิติสูง เช่น วิดีโอ และจากระบบจะเรียนรู้กลยุทธ์ที่เหมาะสมที่สุดสำหรับตัวแทนในการดำเนินการที่ดี

ในปี 2013 DeepMind สตาร์ทอัพจากลอนดอน AI ได้สร้างความก้าวหน้าครั้งยิ่งใหญ่ในการเรียนรู้ที่จะควบคุมตัวแทนโดยตรงจากอินพุตทางประสาทสัมผัสที่มีมิติสูง พวกเขาตีพิมพ์บทความเรื่อง Playing Atari with Deep Reinforcement Learning ซึ่งแสดงให้เห็นว่าพวกเขาสอนโครงข่ายประสาทเทียมให้เล่นเกม Atari ได้อย่างไรเพียงแค่มองหน้าจอ พวกเขาได้มาโดย Google แล้วจึงตีพิมพ์บทความใหม่ใน Nature พร้อมการปรับปรุงบางอย่าง: การควบคุมระดับมนุษย์ผ่านการเรียนรู้การเสริมแรงเชิงลึก

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

ขณะนี้ ตัวแทนตั้งอยู่ในสภาพแวดล้อม ซึ่งอยู่ในสถานะหนึ่ง เพื่ออธิบายรายละเอียดเพิ่มเติม เราใช้กระบวนการตัดสินใจของ Markov ซึ่งเป็นวิธีอย่างเป็นทางการในการสร้างแบบจำลองสภาพแวดล้อมการเรียนรู้แบบเสริมกำลังนี้ ประกอบด้วยชุดของสถานะ ชุดของการกระทำที่เป็นไปได้ และกฎ (เช่น ความน่าจะเป็น) สำหรับการเปลี่ยนจากสถานะหนึ่งไปยังอีกสถานะหนึ่ง

กราฟกระบวนการตัดสินใจของมาร์กอฟ: รัฐ (ทำเครื่องหมาย 'S') ดำเนินการ (ทำเครื่องหมาย 'a') ซึ่งมีความเป็นไปได้ต่างๆ ที่ระบุว่าตัวแทนจะจบลงในครั้งต่อไป เส้นทางที่ตามมาบางเส้นทางยังบ่งบอกถึงรางวัล

เอเจนต์สามารถดำเนินการเปลี่ยนแปลงสภาพแวดล้อมได้ เราเรียกรางวัล $ R_t $ เป็นสัญญาณตอบรับแบบสเกลาร์ที่บ่งชี้ว่าตัวแทนดำเนินการในขั้นตอนที่ $t$ ได้ดีเพียงใด

ตัวแทนเครือข่ายประสาทตัดสินใจว่าจะดำเนินการใดในขั้นตอนใดตามการสังเกตและรางวัล

เพื่อผลงานที่ดีในระยะยาว จะต้องไม่คำนึงถึงรางวัลในทันทีแต่รวมถึงรางวัลในอนาคตด้วย รางวัลรวมสำหรับหนึ่งตอนจากขั้นตอนเวลา $t$ คือ $ R_t = r_t + r_{t+1} + r_{t+2} + \ldots + r_n $ อนาคตเป็นสิ่งที่ไม่แน่นอนและยิ่งเราดำเนินต่อไปในอนาคต การคาดการณ์ในอนาคตอาจแตกต่างออกไปมากขึ้น ด้วยเหตุนี้ จึงใช้รางวัลส่วนลดในอนาคต: $ R_t = r_t +\gamma r_{t+1} + \gamma^2r_{t+2} + \ldots + \gamma^{nt}r_n = r_t + \gamma R_{t+1} $. ตัวแทนควรเลือกการดำเนินการที่จะเพิ่มผลตอบแทนในอนาคตที่มีส่วนลดสูงสุด

การเรียนรู้ Q ลึก

ฟังก์ชัน $ Q(s, a) $ แสดงถึงรางวัลในอนาคตที่มีส่วนลดสูงสุดเมื่อดำเนินการ $ a $ ในสถานะ $ s $:

\[Q(s_t, a_t) = \max R_{t+1}\]

การประมาณการของรางวัลในอนาคตกำหนดโดยสมการ Bellman: $ Q(s, a) = r + \gamma \max_{a'}Q(s', a') $ กล่าวอีกนัยหนึ่ง รางวัลสูงสุดในอนาคตที่มอบให้รัฐ $ s $ และการกระทำ $ a $ คือรางวัลทันทีบวกรางวัลสูงสุดในอนาคตสำหรับสถานะถัดไป

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

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

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

“อัลกอริธึม Deep Q-learning พร้อมการเล่นซ้ำของประสบการณ์” จากบทความของ DeepMind Playing Atari พร้อม Deep Reinforcement Learning แสดงไว้ด้านล่าง

Deep Q-learning พร้อมอัลกอริธึม Experience Replay ใน pseudocode

DeepMind หมายถึงเครือข่าย Convolutional ที่ได้รับการฝึกอบรมด้วยวิธีการของพวกเขาเป็น Deep Q-networks (DQN)

ตัวอย่างการเรียนรู้ Q แบบลึกโดยใช้ Flappy Bird

Flappy Bird เป็นเกมมือถือยอดนิยมที่พัฒนาโดยศิลปินวิดีโอเกมชาวเวียดนามและโปรแกรมเมอร์ Dong Nguyen ในนั้นผู้เล่นควบคุมนกและพยายามบินระหว่างท่อสีเขียวโดยไม่โดนพวกมัน

ด้านล่างนี้เป็นภาพหน้าจอจากโคลน Flappy Bird ที่เข้ารหัสโดยใช้ PyGame:

ภาพหน้าจอจาก FlapPyBird ซึ่งเป็นโคลน Flappy Bird ที่เข้ารหัสโดยใช้ PyGame

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

สกรีนช็อตของ DeepLearningFlappyBird ซึ่งเป็นทางแยกของโคลนพร้อมกราฟิกแบบง่าย

แต่แทนที่จะใช้ TensorFlow ฉันได้สร้างกรอบการเรียนรู้การเสริมแรงเชิงลึกโดยใช้ PyTorch PyTorch เป็นเฟรมเวิร์กการเรียนรู้เชิงลึกสำหรับการทดลองที่รวดเร็วและยืดหยุ่น ให้บริการเทนเซอร์และโครงข่ายประสาทเทียมแบบไดนามิกใน Python พร้อมการเร่งความเร็ว GPU ที่แข็งแกร่ง

สถาปัตยกรรมโครงข่ายประสาทเทียมเหมือนกับ DeepMind ที่ใช้ในกระดาษ การควบคุมระดับมนุษย์ผ่านการเรียนรู้การเสริมแรงเชิงลึก

ชั้น ป้อนข้อมูล ขนาดตัวกรอง สไตรด์ จำนวนตัวกรอง การเปิดใช้งาน เอาท์พุต
Conv1 84x84x4 8x8 4 32 ReLU 20x20x32
Conv2 20x20x32 4x4 2 64 ReLU 9x9x64
Conv3 9x9x64 3x3 1 64 ReLU 7x7x64
fc4 7x7x64 512 ReLU 512
fc5 512 2 เชิงเส้น 2

มีสามชั้น convolutional และสองชั้นที่เชื่อมต่ออย่างสมบูรณ์ แต่ละชั้นใช้การเปิดใช้งาน ReLU ยกเว้นชั้นสุดท้ายซึ่งใช้การเปิดใช้งานเชิงเส้น โครงข่ายประสาทเทียมจะแสดงค่าสองค่าที่แสดงถึงการกระทำที่เป็นไปได้ของผู้เล่นเท่านั้น: "บินขึ้น" และ "ไม่ทำอะไรเลย"

อินพุตประกอบด้วยภาพขาวดำขนาด 84x84 ต่อเนื่องกันสี่ภาพ ด้านล่างนี้คือตัวอย่างรูปภาพสี่ภาพที่ส่งไปยังโครงข่ายประสาทเทียม

คุณจะสังเกตเห็นว่าภาพถูกหมุน นั่นเป็นเพราะผลลัพธ์ของเอ็นจิ้นเกมของโคลนถูกหมุน แต่ถ้าโครงข่ายประสาทได้รับการสอนและทดสอบโดยใช้ภาพดังกล่าว จะไม่ส่งผลต่อประสิทธิภาพของโครงข่าย

เฟรมขาวดำสี่เฟรมต่อเนื่องกันของโคลน Flappy Bird ที่ป้อนโดยตรงไปยังโครงข่ายประสาท

คุณอาจสังเกตเห็นว่ารูปภาพถูกครอบตัดโดยที่พื้นถูกละไว้ เนื่องจากไม่เกี่ยวข้องกับงานนี้ พิกเซลทั้งหมดที่แสดงท่อและนกเป็นสีขาว และพิกเซลทั้งหมดที่แสดงพื้นหลังเป็นสีดำ

นี่เป็นส่วนหนึ่งของรหัสที่กำหนดโครงข่ายประสาทเทียม น้ำหนักของโครงข่ายประสาทเทียมถูกกำหนดให้เป็นไปตามการกระจายแบบสม่ำเสมอ $\mathcal{U}(-0.01, 0.01)$ ส่วนอคติของพารามิเตอร์ของโครงข่ายประสาทเทียมถูกตั้งค่าเป็น 0.01 มีการทดลองเริ่มต้นที่แตกต่างกันหลายอย่าง (ชุด Xavier, Xavier ปกติ, ชุด Kaiming, Kaiming ปกติ, ชุดและปกติ) แต่การเริ่มต้นข้างต้นทำให้โครงข่ายประสาทเทียมมาบรรจบกันและฝึกได้เร็วที่สุด ขนาดของโครงข่ายประสาทเทียมคือ 6.8 MB

 class NeuralNetwork(nn.Module): def __init__(self): super(NeuralNetwork, self).__init__() self.number_of_actions = 2 self.gamma = 0.99 self.final_epsilon = 0.0001 self.initial_epsilon = 0.1 self.number_of_iterations = 2000000 self.replay_memory_size = 10000 self.minibatch_size = 32 self.conv1 = nn.Conv2d(4, 32, 8, 4) self.relu1 = nn.ReLU(inplace=True) self.conv2 = nn.Conv2d(32, 64, 4, 2) self.relu2 = nn.ReLU(inplace=True) self.conv3 = nn.Conv2d(64, 64, 3, 1) self.relu3 = nn.ReLU(inplace=True) self.fc4 = nn.Linear(3136, 512) self.relu4 = nn.ReLU(inplace=True) self.fc5 = nn.Linear(512, self.number_of_actions) def forward(self, x): out = self.conv1(x) out = self.relu1(out) out = self.conv2(out) out = self.relu2(out) out = self.conv3(out) out = self.relu3(out) out = out.view(out.size()[0], -1) out = self.fc4(out) out = self.relu4(out) out = self.fc5(out) return out

ในตัวสร้าง คุณจะสังเกตเห็นว่ามีไฮเปอร์พารามิเตอร์ที่กำหนดไว้ การเพิ่มประสิทธิภาพไฮเปอร์พารามิเตอร์ไม่ได้ทำเพื่อจุดประสงค์ในการโพสต์บล็อกนี้ ส่วนใหญ่จะใช้ไฮเปอร์พารามิเตอร์จากเอกสารของ DeepMind แทน ในที่นี้ ไฮเปอร์พารามิเตอร์บางตัวได้รับการปรับขนาดให้ต่ำกว่าในบทความของ DeepMind เนื่องจาก Flappy Bird มีความซับซ้อนน้อยกว่าเกม Atari ที่ใช้ในการปรับแต่ง

นอกจากนี้ epsilon ถูกเปลี่ยนให้สมเหตุสมผลมากขึ้นสำหรับเกมนี้ DeepMind ใช้ epsilon หนึ่งตัว แต่ที่นี่เราใช้ 0.1 นี่เป็นเพราะว่าเอปซิลอนที่สูงขึ้นบังคับให้นกกระพือปีกมาก ซึ่งผลักนกไปที่ขอบด้านบนของตะแกรง ส่งผลให้นกชนเข้ากับท่อในที่สุด

รหัสการเรียนรู้การเสริมแรงมีสองโหมด: ฝึกและทดสอบ ในระหว่างขั้นตอนการทดสอบ เราจะเห็นได้ว่าอัลกอริทึมการเรียนรู้แบบเสริมกำลังเรียนรู้การเล่นเกมได้ดีเพียงใด แต่ก่อนอื่น โครงข่ายประสาทเทียมต้องได้รับการฝึกอบรม เราจำเป็นต้องกำหนดฟังก์ชันการสูญเสียที่จะย่อให้เล็กสุดและตัวเพิ่มประสิทธิภาพซึ่งจะลดฟังก์ชันการสูญเสียให้น้อยที่สุด เราจะใช้วิธีการปรับให้เหมาะสมของ Adam และค่าคลาดเคลื่อนกำลังสองเฉลี่ยสำหรับฟังก์ชันการสูญเสีย:

 optimizer = optim.Adam(model.parameters(), lr=1e-6) criterion = nn.MSELoss()

เกมควรสร้างอินสแตนซ์:

 game_state = GameState()

หน่วยความจำเล่นซ้ำถูกกำหนดเป็นรายการ Python:

 replay_memory = []

ตอนนี้เราต้องเริ่มต้นสถานะแรก การกระทำคือเทนเซอร์สองมิติ:

  • [1, 0] หมายถึง "ไม่ทำอะไรเลย"
  • [0, 1] หมายถึง “บินขึ้นไป”

เมธอด frame_step จะแสดงหน้าจอถัดไป รางวัล และข้อมูลว่าสถานะถัดไปคือเทอร์มินัลหรือไม่ รางวัลคือ 0.1 สำหรับการเคลื่อนไหวของนกแต่ละตัวโดยไม่ตายเมื่อไม่ผ่านท่อ 1 หากนกผ่านท่อได้สำเร็จและ -1 หากนกตก

ฟังก์ชัน resize_and_bgr2gray จะครอบตัดพื้น ปรับขนาดหน้าจอเป็นรูปภาพขนาด 84x84 และเปลี่ยนพื้นที่สีจาก BGR เป็นขาวดำ ฟังก์ชัน image_to_tensor จะแปลงรูปภาพเป็นเมตริกซ์ PyTorch และใส่ไว้ในหน่วยความจำ GPU หากมี CUDA ในที่สุด หน้าจอต่อเนื่องสี่หน้าจอสุดท้ายจะถูกต่อเข้าด้วยกันและพร้อมที่จะส่งไปยังโครงข่ายประสาทเทียม

 action = torch.zeros([model.number_of_actions], dtype=torch.float32) action[0] = 1 image_data, reward, terminal = game_state.frame_step(action) image_data = resize_and_bgr2gray(image_data) image_data = image_to_tensor(image_data) state = torch.cat((image_data, image_data, image_data, image_data)).unsqueeze(0)

epsilon เริ่มต้นถูกตั้งค่าโดยใช้บรรทัดของรหัสนี้:

 epsilon = model.initial_epsilon

วงอนันต์หลักดังต่อไปนี้ ความคิดเห็นเขียนในโค้ด และคุณสามารถเปรียบเทียบโค้ดกับ Deep Q-learning ด้วยอัลกอริธึม Experience Replay ที่เขียนไว้ด้านบน

อัลกอริทึมจะสุ่มตัวอย่างมินิแบตช์จากหน่วยความจำรีเพลย์และอัปเดตพารามิเตอร์ของโครงข่ายประสาทเทียม การดำเนินการจะดำเนินการโดยใช้ การสำรวจความโลภของเอปซิลอน Epsilon กำลังถูกอบอ่อนเมื่อเวลาผ่านไป ฟังก์ชั่นการสูญเสียที่ถูกย่อเล็กสุดคือ $ L = \frac{1}{2}\left[\max_{a'}Q(s', a') - Q(s, a)\right]^2 $ $ Q(s, a) $ คือค่าความจริงภาคพื้นดินที่คำนวณโดยใช้สมการ Bellman และได้ $ \max_{a'}Q(s', a') $ จากโครงข่ายประสาทเทียม โครงข่ายประสาทเทียมให้ค่า Q สองค่าสำหรับการกระทำที่เป็นไปได้ทั้งสองอย่าง และอัลกอริทึมจะดำเนินการด้วยค่า Q สูงสุด

 while iteration < model.number_of_iterations: # get output from the neural network output = model(state)[0] # initialize action action = torch.zeros([model.number_of_actions], dtype=torch.float32) if torch.cuda.is_available(): # put on GPU if CUDA is available action = action.cuda() # epsilon greedy exploration random_action = random.random() <= epsilon if random_action: print("Performed random action!") action_index = [torch.randint(model.number_of_actions, torch.Size([]), dtype=torch.int) if random_action else torch.argmax(output)][0] if torch.cuda.is_available(): # put on GPU if CUDA is available action_index = action_index.cuda() action[action_index] = 1 # get next state and reward image_data_1, reward, terminal = game_state.frame_step(action) image_data_1 = resize_and_bgr2gray(image_data_1) image_data_1 = image_to_tensor(image_data_1) state_1 = torch.cat((state.squeeze(0)[1:, :, :], image_data_1)).unsqueeze(0) action = action.unsqueeze(0) reward = torch.from_numpy(np.array([reward], dtype=np.float32)).unsqueeze(0) # save transition to replay memory replay_memory.append((state, action, reward, state_1, terminal)) # if replay memory is full, remove the oldest transition if len(replay_memory) > model.replay_memory_size: replay_memory.pop(0) # epsilon annealing epsilon = epsilon_decrements[iteration] # sample random minibatch minibatch = random.sample(replay_memory, min(len(replay_memory), model.minibatch_size)) # unpack minibatch state_batch = torch.cat(tuple(d[0] for d in minibatch)) action_batch = torch.cat(tuple(d[1] for d in minibatch)) reward_batch = torch.cat(tuple(d[2] for d in minibatch)) state_1_batch = torch.cat(tuple(d[3] for d in minibatch)) if torch.cuda.is_available(): # put on GPU if CUDA is available state_batch = state_batch.cuda() action_batch = action_batch.cuda() reward_batch = reward_batch.cuda() state_1_batch = state_1_batch.cuda() # get output for the next state output_1_batch = model(state_1_batch) # set y_j to r_j for terminal state, otherwise to r_j + gamma*max(Q) y_batch = torch.cat(tuple(reward_batch[i] if minibatch[i][4] else reward_batch[i] + model.gamma * torch.max(output_1_batch[i]) for i in range(len(minibatch)))) # extract Q-value q_value = torch.sum(model(state_batch) * action_batch, dim=1) # PyTorch accumulates gradients by default, so they need to be reset in each pass optimizer.zero_grad() # returns a new Tensor, detached from the current graph, the result will never require gradient y_batch = y_batch.detach() # calculate loss loss = criterion(q_value, y_batch) # do backward pass loss.backward() optimizer.step() # set state to be state_1 state = state_1

เมื่อชิ้นส่วนทั้งหมดพร้อมแล้ว ต่อไปนี้คือภาพรวมระดับสูงของการไหลของข้อมูลโดยใช้โครงข่ายประสาทเทียมของเรา:

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

นี่เป็นลำดับสั้นๆ ลำดับหนึ่งที่มีโครงข่ายประสาทเทียมที่ผ่านการฝึกอบรมมาแล้ว

แอนิเมชั่นของโคลน Flappy Bird ที่เล่นโดยโครงข่ายประสาทที่ได้รับการฝึก

โครงข่ายประสาทเทียมที่แสดงด้านบนได้รับการฝึกฝนโดยใช้ GPU Nvidia GTX 1080 ระดับไฮเอนด์เป็นเวลาสองสามชั่วโมง โดยใช้โซลูชันที่ใช้ CPU แทน งานนี้จะใช้เวลาหลายวัน FPS ของเอ็นจิ้นเกมถูกตั้งค่าเป็นจำนวนมากระหว่างการฝึก: 999…999—กล่าวอีกนัยหนึ่งคือ ให้มากที่สุดเท่าที่จะมากได้ต่อวินาที ในขั้นตอนการทดสอบ FPS ถูกตั้งค่าเป็น 30

ด้านล่างนี้คือแผนภูมิที่แสดงให้เห็นว่าค่า Q สูงสุดเปลี่ยนแปลงไปอย่างไรในระหว่างการทำซ้ำ การแสดงซ้ำทุกๆ 10,000 ครั้ง การพุ่งสูงขึ้นหมายความว่าสำหรับเฟรมใดเฟรมหนึ่ง (การวนซ้ำหนึ่งครั้งเป็นหนึ่งเฟรม) โครงข่ายประสาทเทียมคาดการณ์ว่านกจะได้รับรางวัลที่ต่ำมากในอนาคต กล่าวคือ มันจะพังในไม่ช้า

แผนภูมิแสดงการเปลี่ยนแปลงค่า Q สูงสุดในระหว่างการทำซ้ำ เริ่มต้นที่ศูนย์และด้วยการเพิ่มขึ้นอย่างรวดเร็วหลายครั้ง มันแสดงแนวโน้มโดยรวมไปสู่ค่า Q สูงสุดที่ประมาณ 12 หรือ 13 หลังจากการทำซ้ำประมาณหนึ่งล้านครั้ง

ดูโค้ดฉบับเต็มและรุ่นก่อนการฝึกอบรมได้ที่นี่

การเรียนรู้การเสริมแรงอย่างล้ำลึก: 2D, 3D และแม้แต่ชีวิตจริง

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

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

บริษัทต่างๆ เช่น DeepMind, Maluuba และ Vicarious กำลังทำงานอย่างเข้มข้นในการเรียนรู้การเสริมกำลังเชิงลึก เทคโนโลยีดังกล่าวถูกใช้ใน AlphaGo ซึ่งเอาชนะ Lee Sedol หนึ่งในผู้เล่นที่ดีที่สุดในโลกที่ Go ในขณะนั้นถือว่าต้องใช้เวลาอย่างน้อยสิบปีกว่าที่เครื่องจักรจะสามารถเอาชนะผู้เล่นที่ดีที่สุดของโกได้

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


ข้อมูลอ้างอิง:

  • ตอกย้ำการเรียนรู้การเสริมแรงอย่างลึกซึ้ง
  • การเรียนรู้การเสริมแรงอย่างล้ำลึกสำหรับ Flappy Bird
  • “โครงข่ายประสาทเทียม” ที่วิกิพีเดีย
  • “การเรียนรู้การเสริมกำลัง” ที่ Wikipedia
  • “กระบวนการตัดสินใจของ Markov” ที่ Wikipedia
  • หลักสูตร University College London ในRL
ที่เกี่ยวข้อง: บทช่วยสอนการเรียนรู้เชิงลึก: จาก Perceptrons ถึง Deep Networks