Solar Power Prediction Model

Pawut Jingjit
4 min readSep 29, 2020

--

สาระ สิ่งที่ Solar Cell ต้องการคือ ความเข้มแสง ไม่ใช่อุณหภูมิ ฉะนั้น ในบางประเทศที่มีหิมะก็ติดตั้ง Solar Cell ได้ Credit : revisionenergy

บทความนี้ก็ยังวนเวียนอยู่กับการบ้านของ 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 ได้
สำหรับผู้ที่ใช้ Colab สามารถ ใช้ Path นี้แทนการเอาไฟล์ขึ้น Drive ได้

EDA and Data Cleaning

ก่อนที่จะทำโจทย์ Data เราต้องทำความเข้าใจกับตัว Data ก่อน ว่ามี Feature ใดบ้าง การกระจายตัวของข้อมูลเป็นอย่างไร มีข้อมูลหายไปไหม จะจัดการกับมันอย่างไรได้

ประกอบด้วย 68778 Rows , 7 Columns

เมื่อพิจารณาแต่ละ 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)

พิจารณา Missing Value
Data ถูก Clean มาแล้วระดับหนึ่ง ไม่มี Missing Value
เมื่อพิจารณา ข้อมูลที่ส่งมาจากแต่ละแผง สังเกตได้ว่า “แต่ละแผงส่งข้อมูลมา จำนวนครั้งไม่เท่ากัน” ข้อมูลที่ควรได้รับต่อแผง ต้องมี 4*24*33 = 3168 สังเกตว่าข้อมูลหายไปไม่ถึง 1%

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 นี่ แทบจะต้องเปิดบทความใหม่มาสอน เพื่อนๆรออ่านได้เลย จึงขอละรายละเอียดไว้ก่อน แต่เบื้องต้นคือ เลือก Total Yield ที่มี Key เดียวกัน เวลาเดียวกัน ของตัวก่อนหน้ามาใช้ (หมายถึง Key เดียวกัน เวลาเดียวกัน ของวันก่อนหน้านั่นเอง)
ผลลัพท์ของการ Group by Shift สังเกตว่า จะได้ค่า Y ของวันก่อนหน้ามา สมมุติอยากทำนายวันที่ 25 TY1,TY2,TY3 จะเป็นวันที่ 21 , 20 ,19 ตามอันดับ

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

เราไม่สามารถใช้ข้อมูลที่เป็นค่าปัจจุบันได้ จึงต้อง Drop Role ดังกล่าว

Encoding

เพราะเราไม่สามารถนำค่าที่ไม่ใช่ตัวเลข ( Numerical เข้า Model ได้ จึงต้องแปลง Source_key เป็นตัวเลขก่อน)

มาตรฐานเราจะใช้การแปลงแบบ 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 ซึ่งเอามาขายในบทความต่อๆไป // อ้าว

แบ่งข้อมูลเป็น 10 fold by index ตามโจทย์

Modeling

Model ส่วนใหญ่ หลังจาก import มาแล้ว สามารถใช้ได้ทันทีผ่าน

  • model.fit(train_x,train_y) : เพื่อ Training Model
  • model.predict(test_x) : เพื่อใช้งาน Model ที่ผ่านการ Training แล้ว
ตอนแรกกะจะใช้แค่ตระกูล Boosting เพราะใช้ Label Encoder แต่ RandomForest ก็มีจุดที่น่าสนใจ
ข้อมูลตัวไหนมี NA ที่เกิดจากการ Shift แล้วไม่มีข้อมูล จะ Drop เลย (เฉพาะ Case ทำ Time Series แนะนำให้ Drop เลย เราจะเสียข้อมูลแค่ช่วง 3–7 วันแรกเท่านั้น จากข้อมูลที่มี 33 วัน แต่ทำให้จัดการได้ง่ายกว่า เพราะปกติโจทย์ทั่วไปจะให้ข้อมูลมาหลายปีอยู่แล้ว)
เป็นมาตรฐานไปแล้ว สำหรับการ fit,predict ต่อให้มาจากคนละ Library กัน ก็สามารถใช้ร่วมกันได้

evaluation

สังเกตว่า lgb ทำผลงานได้ดีที่สุด // แต่มันก็มีช่องว่างระหว่างทำผลงานได้ดีที่สุด กับ default hyper param ไม่ดีอยู่
ผลลัพท์จาก ทั้ง 4 Model และ การ Stack

ถ้าเราใช้หลาย 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 วันด้วย

ผลลัพท์เมื่อใช้ Data ย้อนหลัง 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 Engineer สังเกตว่า Model ทำงานได้ดียิ่งขึ้น
เผื่ออยากรู้ว่า Feature แต่ละอันที่เรานั่งปั้มเข้า Model มีผลกับ Model ไหม
ยิ่งเลขเยอะ แสดงว่ามีผลกับ Model มาก diff 5,7 ผมมีประโยชน์กว่าข้อมูลของ 2 วันก่อนหน้าอีกนะ

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

โจทย์ต้องการเป็น Cross Validation สามารถเขียนโค๊ตได้ดังรูป (จริงๆแค่เอาทุกอย่างไปยัด Function แล้ว for รอบเดียวนั่นละ)

振り返ればそこにある スタートライン未だ進んじゃいない

「ยามเหลียวหลังกลับมา พบว่าตัวฉันไม่ได้ก้าวไปจากจุดเริ่มต้น(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% เถอะ~~

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

No responses yet

Write a response