Time based Cross Validation ในแบบ Sliding window
วิธีทำ Time series Cross Validation แบบ Sliding window
ช่วงนี้ยังคงอยู่กับเทคนิคการทำ Cross Validation จากเนื้อหาที่เคยได้เขียนมาเกี่ยวกับ Cross Validation บนข้อมูลที่เป็น Time series ซึ่งเคยเขียนวิธีการที่เรียกว่า Forward chaining ไปแล้วทั้งบน Python และ Implement ด้วย SAS
สำหรับตอนนี้ยังคงอยู่กับเนื้อหาการทำ Cross Validation เหมือนเดิม ยังอยู่บนข้อมูล Time series เหมือนเดิม แต่เป็นอีกวิธีการหนึ่งที่เรียกว่า Sliding window สำหรับเนื้อหาตอนก่อนหน้านี้ทั้ง 2 ภาษาโปรแกรม สามารถอ่านได้จาก Links ที่ให้ไว้ด้านล่าง
Sliding window
ความแตกต่างระหว่างการทำ Time based Cross Validation ทั้งสองวิธีคือการใช้จุดเริ่มต้นข้อมูลที่ไม่เหมือนกัน จากรูปตัวอย่างเห็นได้ว่า วิธีการ Forward chaining (รูปด้านล่าง) เป็นการ Fix จุดเริ่มต้นไว้ที่เดิมเสมอ และ Training set รอบต่อไป จะใช้ Testing set จากรอบก่อนหน้าเก็บกลับเข้าไปด้วย และไปเรื่อย ๆ จนสิ้นสุด Time series
สำหรับวิธีการ Sliding window สิ่งที่แตกต่างจาก Forward chaining คือจุดเริ่มต้นของแต่ละรอบที่ Training จะไม่เหมือนเดิม เพราะข้อมูลต้องมีการขยับไปเรื่อย ๆ จุดเริ่มต้นของข้อมูลในรอบถัดไป อาจเป็นจุดเริ่มต้นของ Testing set หรือเป็นจุดที่ต่อจาก Testing set ก็ได้
Code
เนื่องจากไม่มี Built-in function หรือ Library ที่ Support การทำงานในลักษณะนี้ใน Python ทำให้ต้อง Implement method นี้ขึ้นมาใช้งานเอง ซึ่งการเขียน Function สำหรับการทำงานในลักษณะนี้ค่อนข้างตรงไปตรงมา ลองมาใช้ข้อมูลที่ใช้จากตอนก่อนหน้านี้กับ Method นี้ เพื่อดูผลลัพธ์ที่เกิดขึ้นว่ามีความต่างกันมากน้อยอย่างไร
Libraries ที่ใช้มีไม่เยอะ ไม่จำเป็นต้อง Load library พิเศษอะไร เพราะต้องเขียน Function ขึ้นมาใช้งานเองอยู่แล้ว เพื่อให้เห็นภาพการทำงานของ Sliding window ขอแสดงเป็น Index จาก Code ตามด้านล่าง
- กำหนด
trainSize
คือขนาดของ Training window และกำหนดtestSize
คือขนาดของ Testing window - จากนั้นใช้ Iteration เพื่อวนตัวแปร
i
ในrange()
ไปจนถึง Index ตามขนาดของจำนวนแถวทั้งหมดใน Dataset - ใน
range()
สามารถกำหนดstep
ได้ จากตัวอย่างนี้เป็นการกำหนดstep = trainSize + testSize
หมายความว่า Iteration ต่อไป จะเริ่มต่อจาก Index ใน Testing set ก่อนหน้านี้ - ใน Iteration ที่ 1 Training window มีขนาดเท่ากับ
9 — 9, 9
หมายความว่านับ Index ตั้งแต่ Index ที่ 0 ไปจนถึง Index ที่ 8 เป็นต้น - ใน Iteration ที่ 1 Testing window มีขนาดเท่ากับ
9, 9 + 3
หมายความว่านับ Index ตั้งแต่ Index ที่ 9 ไปจนถึง Index ที่ 11 เป็นต้น
เมื่อวนตัวแปรจนครบแล้ว ผลลัพธ์ของ Index ในแต่ละ Iteration จะเป็นเหมือน Output ด้านล่าง
Train index: [0 1 2 3 4 5 6 7 8]
Test index: [9 10 11]
Train index: [12 13 14 15 16 17 18 19 20]
Test index: [21 22 23]
Train index: [24 25 26 27 28 29 30 31 32]
Test index: [33 34 35]
Train index: [36 37 38 39 40 41 42 43 44]
Test index: [45 46 47]
ต่อมาเป็นการนำเอา Logic มาทำเป็น Function เพื่อเรียกใช้งานง่าย ๆ เนื่องจาก Logic เหมือนเดิม ขออธิบายเฉพาะส่วนที่ใช้งานกับ Dataset จริงเท่านั้น
- ต้องการให้ Function สามารถเลือก Option ที่จุดเริ่มต้นใหม่ของ Training set ให้ Iteration ต่อ ๆ ไปได้ เลยสร้างเป็น Argument
True False
โดยให้True
เป็นการเริ่มจุด Training set ต่อจาก Testing set และFalse
เป็นการเริ่มจุด Training set ที่จุดแรกของ Testing set - จาก Code logic ใช้เป็น Numpy array เพื่อเป็นตัวอย่าง ดังนั้นเวลาใช้งานกับข้อมูลที่เป็น DataFrame จึใช้เป็น
.iloc[]
เพื่อเลือกตำแหน่งแทน - Code ส่วนที่เหลือเป็นการรันโมเดล และการจัดการผลลัพธ์ในรูปแบบตาราง และการ Plot กราฟ
ทดสอบการ Execute function timeSlide()
โดยผ่าน Argument parameter เป็น True
เพื่อให้ Split ข้อมูลออกเป็นตามตัวอย่างที่เขียนไว้
Plot ผลลัพธ์ของการ Training ด้วยข้อมูล Time series โดยใช้โมเดลที่เกิดจากข้อมูลใน Training set ไป Predict ข้อมูล Testing set ในแต่ละรอบ จึงได้ผลลัพธ์ตามกราฟด้านบน สุดท้ายสามารถหาเฉลี่ยจากโมเดลได้จาก Numpy array ที่เก็บค่า Score ของแต่ละ Iteration ไว้
ลองเปลี่ยน Argument parameter ให้เป็น False เพื่อให้การ Split แตกต่างออกไป ขอแสดงผลลัพธ์แค่ส่วนหนึ่ง เพราะไม่อยากให้มีรูปกราฟเยอะจนเกินไป
จากกราฟรูปแรกมีความเหมือนกันทุกอย่าง เพราะเป็นจุดเริ่มต้นของข้อมูล แต่รูปที่ 2 สังเกตได้ว่า Training set ได้ตัดข้อมูล 3 Index แรกออกไป และต่อ Testing index จาก Iteration ก่อนหน้ามาเป็น Training set แทน Logic นี้จะนำไปใช้กับทั้งชุดข้อมูล ดังนั้นหมายความว่าการ Split ด้วย Logic นี้ชุดข้อมูลจึงมีมากขึ้น ตามตารางค่าเฉลี่ยสุดท้ายด้านล่าง
Conclusion
จริง ๆ แล้วการ Cross Validation ด้วยรูปนี้ไม่ได้มีอะไรที่ซับซ้อน แต่เนื่องจาก Function ต้องมีการ Implement ขึ้นมาเอง ดังนั้นจึงอาจจำเป็นต้องเขียนเยอะกว่า Built-in function