3 เทคนิค Statsmodels เพิ่มประสิทธิภาพพยากรณ์ข้อมูลอนุกรมเวลา

โมเดล statsmodels ที่ผ่านการ fit เรียบร้อยแล้วสามารถคำนวณและให้ข้อมูลได้มากกว่าแค่ชุดตัวเลขทั่วไปที่นักพัฒนาส่วนใหญ่ดึงมาใช้งาน การพยากรณ์แบบจุด (point forecast) เป็นเพียงฟังก์ชันพื้นฐานที่สุดที่มันทำได้
ทุกเทคนิคเริ่มต้นจากการดึงสิ่งที่ออบเจ็กต์ผลลัพธ์ (results object) คำนวณไว้อยู่แล้วออกมาใช้งาน แทนที่จะต้องเสียเวลาสร้างใหม่ด้วยตัวเอง โดยทั้งสามวิธีที่จะกล่าวถึงนี้ถูกรันด้วยข้อมูลอนุกรมเวลารายเดือนชุดเดียวกันและใช้โมเดลชุดเดียวกัน สิ่งที่แตกต่างกันมีเพียงแค่การเรียกใช้ method บนออบเจ็กต์ที่ fit ส่งกลับมาเท่านั้น ทั้งนี้ข้อมูลทั้งหมดได้รับการตรวจสอบกับ statsmodels 0.15.0 เรียบร้อยแล้ว
เริ่มด้วยการติดตั้ง statsmodels:
pip install statsmodelsเทคนิคที่ 1: การขอช่วงความเชื่อมั่น ไม่ใช่แค่ตัวเลขเดียว
การใช้ res.forecast(12) จะให้ผลลัพธ์เป็นตัวเลข 12 ค่า แต่หากเปลี่ยนมาใช้ res.get_forecast(12) คุณจะได้ออบเจ็กต์ PredictionResults แทน ซึ่งออบเจ็กต์นี้จะเก็บค่าความไม่แน่นอน (uncertainty) ที่โมเดลประมาณการไว้แล้ว ประกอบด้วย predicted_mean สำหรับค่าพยากรณ์จุด, conf_int สำหรับช่วงความเชื่อมั่น และ summary_frame() เพื่อดูข้อมูลทั้งสองส่วนพร้อมกัน
ช่วงความเชื่อมั่นเหล่านี้ไม่ใช่ภาระงานเพิ่มเติมของระบบ เพราะเป็นผลลัพธ์จากการคำนวณเดิมอยู่แล้ว การใช้ method ที่สั้นกว่าเพียงแค่โยนข้อมูลสำคัญเหล่านี้ทิ้งไปโดยไม่จำเป็น:
import statsmodels.api as sm
from statsmodels.tsa.arima.model import ARIMA
co2 = sm.datasets.co2.load_pandas().data["co2"]
co2 = co2.resample("MS").mean().ffill()
train, recent = co2[:-12], co2[-12:]
res = ARIMA(train, order=(1, 1, 1), seasonal_order=(1, 1, 1, 12)).fit()
print(res.get_forecast(12).summary_frame().head())ผลลัพธ์ (Output):
co2 mean mean_se mean_ci_lower mean_ci_upper
2001-01-01 370.523929 0.322722 369.891406 371.156452
2001-02-01 371.253673 0.388214 370.492787 372.014559
2001-03-01 372.200726 0.429518 371.358887 373.042566
2001-04-01 373.468351 0.463501 372.559905 374.376797
2001-05-01 373.856957 0.494157 372.888427 374.825487หากคุณต้องการค่าที่ถูก fit เหนือข้อมูลประวัติศาสตร์ (in-sample) แทนการพยากรณ์อนาคต สามารถใช้ get_prediction ซึ่งเป็นแนวคิดเดียวกันในการเรียกดูช่วงความเชื่อมั่นได้เช่นกัน
เทคนิคที่ 2: การเพิ่มข้อมูลใหม่โดยไม่ต้อง Fit ซ้ำ
เมื่อมีข้อมูลใหม่เข้ามา การนำไปต่อท้ายข้อมูลเก่าแล้วสั่ง .fit() ใหม่ทั้งหมดเป็นวิธีที่ประหยัดทรัพยากรน้อยที่สุดเพราะต้องคำนวณพารามิเตอร์ใหม่ทั้งหมด แต่การใช้ append จะช่วยสร้างออบเจ็กต์ผลลัพธ์ใหม่บนข้อมูลที่รวมกันโดยยังคงพารามิเตอร์เดิมไว้เมื่อตั้งค่า refit=False ซึ่งช่วยประหยัดเวลาการประมวลผลได้อย่างมาก:
updated = res.append(recent, refit=False)
print(updated.get_forecast(6).summary_frame().head())ผลลัพธ์ (Output):
co2 mean mean_se mean_ci_lower mean_ci_upper
2002-01-01 371.969954 0.322722 371.337432 372.602477
2002-02-01 372.750021 0.388214 371.989135 373.510907
2002-03-01 373.654908 0.429518 372.813068 374.496748
2002-04-01 374.834276 0.463501 373.925830 375.742722
2002-05-01 375.328719 0.494157 374.360189 376.297248นอกจากการใช้ append เพื่อรันตัวกรองซ้ำบนข้อมูลทั้งหมดแล้ว ยังมี method อื่นที่ใกล้เคียงกันคือ extend สำหรับกรองเฉพาะข้อมูลใหม่ (เหมาะกับข้อมูลประวัติที่ยาวมาก) และ apply สำหรับใช้กับชุดข้อมูลที่แตกต่างกันออกไปโดยสิ้นเชิง
เทคนิคที่ 3: ปล่อยให้ STL จัดการเรื่องฤดูกาล (Seasonality)
การจัดการฤดูกาลแบบทำเองมักมีความยุ่งยากและเสี่ยงต่อการผิดพลาดในการจัดดัชนี (index) STLForecast จึงถูกออกแบบมาเพื่อรวมลูปการทำงานทั้งหมดไว้ในออบเจ็กต์เดียว ตั้งแต่การแยกส่วนประกอบ (decompose) พยากรณ์ส่วนที่ปรับแก้ฤดูกาลแล้ว และบวกองค์ประกอบฤดูกาลกลับเข้าไปโดยอัตโนมัติ:
from statsmodels.tsa.forecasting.stl import STLForecast
stlf = STLForecast(train, ARIMA, model_kwargs={"order": (1, 1, 1), "trend": "t"})
print(stlf.fit().forecast(12).head())ผลลัพธ์ (Output):
2001-01-01 370.529117
2001-02-01 370.963627
2001-03-01 371.921080
2001-04-01 373.137720
2001-05-01 373.144192
Freq: MS, dtype: float64จุดที่ต้องระวังคือการส่งค่าเข้าไปใน STLForecast ต้องส่งเป็นคลาส ARIMA ไม่ใช่อินสแตนซ์ที่ fit แล้ว โดยกำหนดอาร์กิวเมนต์แยกต่างหากใน model_kwargs ซึ่งเป็นจุดที่ผู้ใช้งานมักทำผิดพลาดบ่อยที่สุด
บทสรุป
เทคนิคเหล่านี้เป็น method ที่มีอยู่แล้วในตัว ซึ่งช่วยให้โค้ดสั้นลง รันได้เร็วขึ้น และลดโอกาสเกิดข้อผิดพลาด การหันมาให้ความสำคัญกับรายละเอียดในออบเจ็กต์ผลลัพธ์ที่ได้จาก .fit() จะช่วยให้คุณทำงานกับข้อมูลอนุกรมเวลาได้อย่างมีประสิทธิภาพมากกว่าการเขียนฟังก์ชันเสริมขึ้นมาเองซ้ำๆ
ความคิดเห็น (0)
เข้าสู่ระบบเพื่อร่วมแสดงความเห็น
สมัครสมาชิกมาเป็นคนแรกที่แสดงความเห็นกันเลยโบร
