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

· By: SirilukP

3 Statsmodels Tricks for Time Series Analysis & Forecasting

โมเดล 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() จะช่วยให้คุณทำงานกับข้อมูลอนุกรมเวลาได้อย่างมีประสิทธิภาพมากกว่าการเขียนฟังก์ชันเสริมขึ้นมาเองซ้ำๆ

Source: KDnuggets
ดูแลงานแปลและเรียบเรียงโดย SirilukP

ความคิดเห็น (0)

เข้าสู่ระบบเพื่อร่วมแสดงความเห็น

สมัครสมาชิก

มาเป็นคนแรกที่แสดงความเห็นกันเลยโบร