Solar Power Prediction Model

บทความนี้ก็ยังวนเวียนอยู่กับการบ้านของ Super AI คราวนี้มาในหัวข้อ Modeling โดย Data Set ในคราวนี้อาจแตกต่างกับคนอื่นนิดหน่อย ปกติ Model แรก เขาน่าจะ”ทำนายสายพันธุ์ดอก Iris” หรือ “ทำนายคนที่มีชีวิตรอดจากเรือ Titanic” แต่ไม่ใช่กับค่ายนี้ Data Set แรกที่ทำในค่ายนี้ก็คือ
Solar Power Generation Data 「การผลิตกระแสไฟฟ้า จาก Solar Cell 」
โดยโจทย์ก็ตรงไปตรงมา ให้ทำนายค่า ‘TOTAL_YIELD’ ใน 3 วันข้างหน้า โดยใช้ข้อมูลย้อนหลัง 3 วัน , 7 วัน
TL;NR
- สามารถก็อป Code แค่ส่วน Feature Extraction 2–3 บรรทัด แล้ว Train Model เหมือนโจทย์ทั่วไปได้เลย
- Encoding สามารถทำได้หลายแบบ สำหรับคนที่จะใช้ Boosting Model แนะนำ Label Encoding
- Random Forest มักจะมีปัญหา overfiting ถ้าไม่กำหนด max_depth
- เราสามารถใช้ความเข้าใจใน Data ทำ Feature Engineering เพื่อประสิทธิภาพของ Model ได้
EDA and Data Cleaning
ก่อนที่จะทำโจทย์ Data เราต้องทำความเข้าใจกับตัว Data ก่อน ว่ามี Feature ใดบ้าง การกระจายตัวของข้อมูลเป็นอย่างไร มีข้อมูลหายไปไหม จะจัดการกับมันอย่างไรได้

เมื่อพิจารณาแต่ละ Columns
- DATE_TIME คือ วัน-เวลา ที่ทำการวัดค่า (สังเกตว่าตรวจวัดตั้งแต่ 15–05–17–06 รวม 33 วัน)
- PLANT_ID คือ ID ของ Solar Farm (ในที่นี้ มีเพียง 1 ID )(หมายถึงสามารถ Drop Column นี้ได้เลย)
- SOURCE_KEY คือรหัสของแผงโซล่า คิดภาพ Solar Farm ใหญ่ๆ มันไม่น่าจะมีแผงโซล่าตั้งอยู่แผ่นเดียว
- DC_POWER พลังงานไฟฟ้ากระแสตรง ที่ Solar Cell สร้างขึ้นได้ในช่วง 15 นาที นั้น
- AC_POWER พลังงานไฟฟ้ากระแสตรง ที่ Solar Cell สร้างขึ้นได้ในช่วง 15 นาที นั้น
- DAILY_YIELD ค่าพลังงานที่ Generate ได้ในช่วง 15 นาที นั้น (คนละหน่วยกับ DC_POWER , AC_POWER )
- TOTAL_YIELD ค่าพลังงานทั้งหมด ที่ Solar Cell นั้นๆผลิตได้ (ซึ่งเป็น Label ของโจทย์นี้เช่นกัน)
หมายความว่า TOTAL_YIELD(SOURCE_KEY = A , DATE_TIME = B) = TOTAL_YIELD( SOURCE_KEY = A , DATE_TIME = (B — 15Min)) + DAILY_YIELD(SOURCE_KEY = A , DATE_TIME = B)


Feature Extraction
ในเมื่อโจทย์คือ “ทำนายค่า ‘TOTAL_YIELD’ ใน 3 วันข้างหน้า โดยใช้ข้อมูลย้อนหลัง 3 วัน , 7 วัน” หนึ่งในข้อมูลย้อนหลัง ที่เราต้องใช้แน่ๆ ‘TOTAL_YIELD’ ของวันก่อนหน้า
(ถ้ายังจำกันได้ TOTAL_YIELD at DATE_TIME n = TOTAL_YIELD at DATE_TIME at n-1 + DAILY_YIELD at n)
แน่นอนว่า เราไม่สามารถใช้ DAILY_YIELD n ได้ (เพราะโจทย์ให้ใช้ข้อมูลย้อนหลัง) แต่ Feature หนึ่งที่ต้องมีแน่ๆคือ TOTAL_YIELD ในวันก่อนหน้า

แต่ปัญหาของการ Group by Shift ที่จะต้องเจอคือ ถ้าไม่มีข้อมูลในวันก่อนหน้า (ซึ่งจาก EDA เรามั่นใจได้ว่ามีไม่ครบแน่นอน) เราจะได้ข้อมูลของ 2 วันก่อนมาแทน แต่เราจะมองข้ามมัน เพราะว่า ไม่รู้จะเติมข้อมูลที่หายไปอย่างไร // ไม่ใช่ เพราะหายไปเพียงแค่ ~ 1% จากการ EDA
Encoding
มาตรฐานเราจะใช้การแปลงแบบ One-Hot Encoding กัน ซึ่งทุกคนน่าจะทราบกันดีแล้ว ในบทความจึงอยากแนะนำการแปลงอีกแบบหนึ่ง ชื่อว่า Label Encoding

ที่ต้องรู้สำหรับการใช้ Label Encoding คือ Model ที่จะรับตัวแปรจาก Label Encoder ได้ ต้องเป็นประเภท Boosting เท่านั้น (XGBoost , Catboost , Gradient Boosting Tree ) ซึ่ง Model กลุ่มนี้ ‘มักจะ’ จะใช้ Label Encoding ได้ ดีกว่า One-Hot Encoding
ต้องอธิบายเพิ่มเล็กน้อยว่า One-Hot Encoding มีข้อเสียคือ สมมุติมี Class เยอะมากๆ เราจะได้ Feature เพิ่มมาหลาย Feature มาก (สามารถแก้ไขด้วยการยุบ Class เช่น รวม Class แมว เสือ สิงโต เป็น Felidae ) และ Model จะไม่รู้สิ่งสำคัญอย่างหนึ่งว่า แต่ละ Class ไม่สามารถเป็น 1 ได้พร้อมกัน
นอกจากนี้ มีวิธี Encoding อีกวิธี ที่เป็นที่นิยม คือ Target Encoding ซึ่งเอามาขายในบทความต่อๆไป // อ้าว
Modeling
Model ส่วนใหญ่ หลังจาก import มาแล้ว สามารถใช้ได้ทันทีผ่าน
- model.fit(train_x,train_y) : เพื่อ Training Model
- model.predict(test_x) : เพื่อใช้งาน Model ที่ผ่านการ Training แล้ว
evaluation

ถ้าเราใช้หลาย Model เราสามารถหาเศษความแม่นยำหลังตู้เย็นได้ ด้วยการเอาผลลัพท์ของ Model มารวมกันตามอัตราส่วน (ส่วนจะ Model ไหนอัตราส่วนเท่าไหร่นี่ Magic Number แต่เบื้องต้นคือ ตัวที่แม่นยำที่สุดต้องมีอัตราส่วนเยอะสุด แต่ไม่เสมอไป)
ข้อที่ต้องระวัง เวลาใช้ Random Forest
ลองนำ Hyper Parameter max depth ของ RF ออก จะพบว่า MAE ของ RF จะต่ำมากๆ (อยู่หลักร้อย) แต่ตัว Tree จะมี depth หลัก10 ทั้งๆที่มีเพียง 4 Feature
อันนี้เป็นปัญหาที่เรียกว่า Overfit เพราะสมมุติเรา Train Model ในวันที่ 1 ตอน 12:00 , 12:15 , 12:45 , 13:00 , etc. แต่ Test วันที่ 1 ตอน 12:30
สังเกตว่า Model แทบจะเห็นข้อมูลครบแล้ว การที่จะตอบด้วยข้อมูลระหว่าง 12:15 , 12:45 จึงทำได้ไม่ยาก (ในสถาณการณ์จริง เราไม่สามารถ Train ด้วยข้อมูลในอนาคตได้แน่ๆ)
จริงๆตระกูล Boosting ก็เกิดปัญหานี้ได้เหมือนกัน แต่ hyper parameter ที่ default ไว้ถูกตั้งไว้ดีกว่า จึงเกิดปัญหาได้น้อยกว่า (แน่สิ ออกหลังเขาตั้งหลายปี)
Feature Extraction (ต่อ)
เนื่องจากโจทย์เขาให้ พิจารณา ข้อมูลย้อนหลัง 7 วันด้วย

Feature Engineering
ในความเป็นจริง เราสามารถสร้างตัวแปรใหม่ที่มีความหมายจากตัวแปรเดิมได้ เพื่อไกด์ทางให้ Model ของเราทำงานได้ดียิ่งขึ้น
- เรารู้ดีว่า TOTAL_YIELD ของวันก่อนหน้ามีความสัมพันธ์กับ TOTAL_YIELD โดยเฉพาะวันก่อนหน้า 1 วัน ย่อมใกล้เคียงที่สุด แต่วันก่อนหน้า 1 วันอาจจะมีหิมะตก พายุซากุระเข้า etc. การรวม Mean 3,5 วันย้อนหลัง ‘อาจจะเป็น Feature’ สำคัญหนึ่ง
- ถ้าสภาพอากาศแบบเดิม “ผลต่างของ TOTAL_YIELD วันนี้และเมื่อวาน” กับ “ผลต่างของ TOTAL_YIELD เมื่อวานและ 2 วันก่อน” ย่อมมีค่าเท่ากัน เราสามารถ ไกด์โมเดลด้วยการสร้างตัวแปร diff ที่เป็น “ผลต่างของ TOTAL_YIELD เมื่อวานและ 2 วันก่อน” ซึ่งอาจจะเป็น Feature ตัวหนึ่งที่สำคัญ
- สมมุติ 2 วันที่แล้ว diff เท่ากัน วันนี้ก็น่าจะ diff เท่ากันด้วย? ก็อาจจะเป็นอีก Feature หนึ่ง


ตรงนี้อยากจะฝากเพื่อนๆลองคิด Feature ที่น่าสนใจ แล้วลองใส่เพิ่ม แล้วลองดูผลลัพท์ หลายๆคนที่ตามการแข่ง Data ก็พูดเป็นเสียงเดียวกันว่า เป็นส่วนสำคัญที่ทำให้ความแม่นยำเพิ่มขึ้น และ ควรใช้เวลากับขั้นตอนนี้ที่สุด
振り返ればそこにある スタートライン未だ進んじゃいない
「ยามเหลียวหลังกลับมา พบว่าตัวฉันไม่ได้ก้าวไปจากจุดเริ่มต้น(Start Line)เลย」
ถ้าใครคิดว่า งานเสร็จแล้วนี่ คิดผิดอย่างยิ่ง อย่าลืมว่าเราพึ่งพิจารณาไปเพียงแค่ TOTAL_YIELD เพียงเท่านั้น ยังมี AC,DC หรือจะเป็นสภาพอากาศ อุณหภูมิ ในอีก Data Frame หนึ่งอีก ตรงนี้อยากให้เป็นการบ้านให้เพื่อนๆที่ตามบทความ ลองเขียนเพิ่มเองดู แน่นอนว่าไม่ยากครับ
สำหรับใครเป็นมือใหม่แล้วหลุดมาอ่านถึงตรงนี้ได้ เจ้าของบทความแนะนำให้เพื่อนๆลอง เพิ่ม Feature ทั้งจากการ Feature Engineering หรืออาจจะเพิ่มฟีเจอร์ DC , AC ย้อนหลัง 3–7 วัน กับลองเปลี่ยน Model ดู จะลองใช้ Linear Reg ดูว่าเวิร์คไหม Etc.
ถ้ามือใหม่แกะโค๊ตเจ้าของบทความแล้วทำตามข้างบนได้ เจ้าของบทความจะถือว่าตัวเองประสบความสำเร็จแล้ว // หวังน้อยไปมะ
เผื่อใครบางคนอยากเห็นผลลัพท์ สามารถเยี่ยมชม Colabได้ที่ https://colab.research.google.com/drive/17iB0GMS_PCJ24csVG41MACZgsSZYvPsV
ท้ายที่สุดก็ขอขอบคุณทุกคนที่อ่านถึงบรรทัดนี้นะครับ ใครซักคนเคยบอกว่า มีเพียง คน 3% ที่อ่าน “Big Data ดัดจริต” จบ
ขอให้บทความนี้มีคนอ่านจบมากกว่า 3% เถอะ~~