🤖มาลอง forecast ราคาหุ้นแบบง่ายๆ ด้วย Deep Learning — LSTM (Python)
Introduction
สัปดาห์นี้เราจะมาลอง forecast ราคาหุ้น โดยใช้ deep learning โมเดล LSTM บน Python กัน โดยสิ่งที่เราจะได้จาก tutorial นี้ คงจะไม่ใช่ผลพยากรณ์ราคาหุ้นสำหรับเก็งกำไรอย่างแม่นยำ แต่เป็นขั้นตอนการทำงานกับข้อมูลประเภท time series หลายตัวแปร หรือ multi-variate timeseries และการใช้โมเดล deep learning แบบพื้นฐาน อย่าง LSTM เพื่อนำไปต่อยอดกับโมเดลอื่นๆ ที่มีความซับซ้อนกว่าในอนาคต
LSTM คือ อะไร
Long Short Term Memory หรือ LSTM คือ โมเดล deep learning ที่สร้างขึ้นมาจำลองรูปแบบความจำของคน (memory) ที่มีความจุของความทรงจำอยู่จำกัด เมื่อมีเหตุการณ์ใหม่ๆ เข้ามาในความทรงจำ สมองจะเลือกที่จะรับ หรือไม่รับเหตุการณ์ใหม่เข้ามาในความทรงจำ ตามความสำคัญของเหตุการณ์ และเมื่อสมองเลือกที่จะรับเหตุการณ์ใหม่ๆ ที่มีความสำคัญเข้ามาเก็บไว้ในระบบความทรงจำแล้ว (memorize) ก็จำเป็นจะต้องมีเหตุการณ์บางอย่างในอดีตที่ถูกลืมไปนั่นเอง (forget)!
โครงสร้างพื้นฐานของ LSTM คือ มี forget gate มาจำลองเหตุการณ์ “ลืม” และ memory gate มาจำลองเหตุการณ์ “จำ” จำตามภาพ 1
ด้วยโครงสร้างของ LSTM จึงทำให้โมเดลดังกล่าว เหมาะสมกับการข้อมูลที่มีลักษณะเป็นลำดับเหตุการณ์ เช่น การทำ sentiment analysis หรือ intent finding ในข้อมูลประเภท text และ การทำ forecast ในข้อมูลประเภท time series
มีบทความดีๆ เขียนอธิบาย LSTM ไว้ ผมเลือกมาให้ 2 บทความตามนี้
Overview
ขั้นตอนที่เราจะ forecast ราคาหุ้น มีดังนี้
- ดึงข้อมูลหุ้นผ่าน API
- เตรียมข้อมูลก่อนเข้าโมเดล — time series data format
- เตรียมข้อมูลก่อนเข้าโมเดล — train&test split
- สร้างโมเดล LSTM และ train โมเดล
- สรุปผล
โดย tutorial นี้ ถูกดัดแปลง และอ้างอิงมาจากบทความด้านล่างนี้ครับ
1. ดึงข้อมูลหุ้นผ่าน API
เริ่มต้นจากดึงข้อมูลหุ้นผ่าน API Yahoo Finance โดยใช้ library pandas_datareader โดยเราจะดึงข้อมูลย้อนหลังตั้งแต่ต้นปี 2010 (ใครจะย้อนไปมากกว่านี้ก็ได้) ถึงสิ้นเดือนพฤศจิกายน ปี 2018 ของหุ้น KBANK , SCB, BBL , KTB (ตอนทำโมเดล เราจะใช้ข้อมูลจาก KBANK เท่านั้น ใครจะลองตัวอื่นที่สนใจก็ได้ครับ)
หน้าตาข้อมูลหุ้น KBANK ที่ได้มาจาก API ตามภาพ 1 ประกอบไปด้วย column High-ราคาสูงสุด, Low-ราคาต่ำสุด, Open-ราคาเปิด, Close-ราคาปิด, Volume-ปริมาณการเทรดประจำวัน, และ Adj Close-ราคาปิด แบบปรับกับการแตก par หุ้นแล้ว โดยเราจะใช้ Adj Close เป็น target ที่เราต้องการจะ forecast และ จะไม่ใช้ column Close
2. เตรียมข้อมูลก่อนเข้าโมเดล — time series data format
การทำ forecast ข้อมูลประเภท time series แบบหลายตัวแปร คือ การพยากรณ์ค่า target ในอนาคต (ในที่นี้คือ Adj Close) จากค่า target ในอดีต บวกกับค่า feature อื่นๆ ในอดีต (ถ้าทำพยากรณ์จากค่า target ในอดีตอย่างเดียว เป็นการทำ forecast แบบตัวแปรเดียว หรือ univariate time series) โดยฟอร์แมตข้อมูลเริ่มต้นตามภาพ 1 จะต้องถูกจัดรูปให้ข้อมูลใน 1 แถว ประกอบไปด้วยค่า feature + target ในอดีต สำหรับเป็น feature ของข้อมูลที่จัดรูปใหม่แล้ว และ target ในอนาคตที่ต้องการจะ forecast (feature อื่นๆ ในเวลาเดียวกันจะไม่ถูกนำมารวม) ตามภาพ 2
เราสามารถกำหนดได้ว่าต้องการจะใช้ค่า feature + target ในอดีต ทั้งหมดเป็นเวลาย้อนหลังกี่หน่วย ในการสร้าง feature และกำหนดได้ว่าต้องการจะพยากรณ์ค่า target ล่วงหน้าทั้งหมดกี่เป็นเวลากี่หน่วย ตามภาพ 2
สำหรับ code ที่เราจะใช้สำหรับเตรียมข้อมูลให้เป็นตามฟอร์แมตในภาพ 2 หลักๆ เราจะใช้ method shift ของ DataFrame ใน pandas ซึ่ง method ดังกล่าวจะ เลื่อน index ของ DataFrame (จะมองว่าเลื่อน index หรือ column ก็ได้) ขึ้นหรือลง ตาม input ที่ใส่เข้าไปเป็น integer ซึ่ง index ของข้อมูล time series ก็คือ เวลา ดังนั้นการ shift จึงเป็นการเลื่อนค่า feature + target ในอดีต หรือในอนาคต มาให้ตรงกับเวลานั้นๆ นั่นเอง
ใน tutorial นี้ เราจะ forecast ราคาปิดของหุ้นล่วงหน้า 3 วัน โดยใช้ข้อมูลย้อนหลัง 30 วัน
หลังเตรียมข้อมูลเสร็จเรียบร้อย จะได้ออกมาฟอร์แมตตามภาพ 3 คือ แต่ละแถวประกอบไปด้วย feature: High, Low, Open,และ Volume และ target: Adj Close ย้อนหลัง 30 วัน เป็น feature และ Adj Close ใน 3 วันข้างหน้า เป็น target ของข้อมูลหลังจัดรูปแล้ว
3. เตรียมข้อมูลก่อนเข้าโมเดล — train&test split
ขั้นตอนต่อมาคือ แบ่งข้อมูลสำหรับ train&test โดยการแบ่งข้อมูลประเภท time series ต้องระวังไม่ให้ ข้อมูลในอนาคตใน test set มาปนกับข้อมูลในอดีตใน train set ดังนั้นเราจะแบ่งข้อมูลโดยใช้ index เป็นตัวกำหนด (โดยปกติ index จะถูก sort มาอยู่แล้ว) โดยเราจะแบ่งข้อมูล 10% สำหรับ test โมเดลของเรา
ในขั้นตอนนี้นอกเหนือจากการทำ trian&test split แล้ว เรายังต้องปรับ shape หรือ dimension ของข้อมูลให้เป็น 3 มิติ ก่อนจะป้อนข้อมูลเข้าโมเดล LSTM เราจะจัด shape ของข้อมูลให้มีขนาด คือจำนวนแถว x timesteps x จำนวน feature โดยกำหนด timesteps = 1 เนื่องจากเราจัดรูปข้อมูลให้มาอยู่ในแถวเดียวกันแล้ว ในขั้นตอนที่ 2 ส่วนจำนวน feature ก็จะเท่ากับจำนวน column ของ feature ทั้งหมดหลังจัดรูปข้อมูลแล้ว (5 column ย้อนหลัง 30 วัน -> 5x30 = 150 features)
4. สร้างโมเดล LSTM และ train โมเดล
เราจะใช้โมเดล LSTM จาก library keras ซึ่งเป็น library สำหรับทำ deep learning ใช้งานง่าย ไม่ซับซ้อน รันอยู่บน library tensorflow ของ Google อีกที โดย class ที่ใช้สำหรับการสร้าง deep learning โมเดลใน keras เรียกว่า Sequential ซึ่งเป็นเสมือนโครงสร้างเปล่าๆ ที่เราสามารถเพิ่ม layer ต่างๆ เข้าไปได้ โดยโครงสร้างที่เราจะใช้ใน tutorial นี้จะไม่ซับซ้อน ประกอบไปด้วย layer แรก คือ LSTM ซึ่งเราสามารถกำหนดขนาดของ hidden layer ได้ ซึ่งในที่นี้จะกำหนดไว้ที่ 50 และ กำหนด shape ของข้อมูลที่จะ input เข้ามาให้สอดคล้องกับขั้นตอนที่ 3
ขนาดของ output จากโมเดลที่เราจะสร้างจะเท่ากับ 3 กำหนดโดยขนาดของ layer Dense ที่เราจะเพิ่มไปท้ายสุด ซึ่งจะเท่ากับจำนวนวันที่เราต้องการจะ forecast ราคาล่วงหน้า 3 วัน นั่นเอง
ระหว่าง train เราจะเก็บค่า loss ของแต่ละ epoch ไว้ (รอบของการ train) ซึ่งเราเลือกใช้ค่า mae หรือ mean absolute error จะเห็นว่าค่า loss เริ่มที่จะไม่ลดลงหลังจาก train โมเดลไปได้ 80 epoch
5. สรุปผล
ขั้นตอนสุดท้ายหลังจาก train โมเดลเสร็จเรียบร้อย ถึงเวลามาดูผล forecast ราคาปิดของหุ้น KBANK จากข้อมูล test set กันบ้าง โดยกราฟในภาพ 5 จะแสดงราคาปิดหุ้นจริง ด้วยเส้นสีน้ำเงิน และ ราคาปิดที่ forecast ด้วย LSTM ด้วยเส้นสีแดง โดยจะแสดงราคาย้อนหลัง 30 วันก่อนทำ forecast เนื่องจากเป็นข้อมูลที่เรานำมาเข้าโมเดลด้วย
Voila! เราทำ forecast ราคาหุ้นด้วยโมเดล deep learning อย่างง่ายๆ เสร็จเรียบร้อย ผลอาจจะออกมาดูประหลาดตา หรือไม่แม่นยำ แต่เราสามารถนำเทคนิคต่างๆ ในการทำงานกับข้อมูลประเภท time series ประเภทหลายตัวแปร ใน tutorial นี้ ไปประยุกต์ใช้งานต่อได้
ทิ้งท้าย
จาก code ใน tutorial นี้ เรายังสามารถทดลองปรับปรุงการทำ forecast ราคาหุ้นให้แม่นยำมากยิ่งขึ้น ด้วยเทคนิคอื่นๆ ที่ใช้กับข้อมูลประเภท timeseries เช่น 1) การ transform ข้อมูล ให้แต่ละ feature มีลักษณะเป็น stationary (คือ ค่า mean และ variance ไม่เปลี่ยนตามเวลา) ด้วยการดึง trend และ seasonal ออก 2) นอกเหนือจากนี้ยังสามารถลองเพิ่ม feature อื่นๆ เช่น ราคาหุ้นอื่นๆ ในกลุ่มธนาคารที่เกี่ยวข้อง หรือ ราคาดัชนี SET เข้ามาอีกก็ได้
ติดตามบทความดีๆ ด้าน data science ได้ที่ FB page: Datawiz
code เต็ม บน Google Colab