DEV Community

Cover image for ทำนายการขายไข่ด้วย SARIMA
BiozW
BiozW

Posted on

ทำนายการขายไข่ด้วย SARIMA

หากเรามีข้อมูลที่เก็บซ้ำๆ ต่อเนื่องกันเป็นเวลานาน แล้วต้องการคาดเดาว่าในอนาคตจะมีแนวโน้มเป็นอย่างไร สิ่งที่สามารถทำนายได้คือ SARIMA

SARIMA คืออะไร

SARIMA นั้นเป็นส่วนขยายมาจาก ARIMA

  • AR - Autoregressive : จำนวนครั้งที่ข้อมูลในช่วงเวลาก่อนหน้าถูกใช้เป็นตัวแปรอิสระในการคำนวณค่าในช่วงเวลาปัจจุบัน
  • I - Integrated : ทำให้ข้อมูลมีลักษณะคงที่
  • MA - Moving Average : จำนวนครั้งที่ค่าเฉลี่ยของข้อมูลในช่วงเวลาก่อนหน้าถูกใช้ในการคำนวณค่าในช่วงเวลาปัจจุบัน

โดยมีการใช้พารามิเตอร์ p, d, และ q เพื่อกำหนดโครงสร้างของโมเดล ARIMA ที่เหมาะสมกับชุดข้อมูลที่กำลังวิเคราะห์

เหมาะสำหรับการจัดการกับข้อมูลชุดเวลาที่มีแนวโน้มหรือลักษณะซ้ำซาก
การทำ ARIMA มักนิยมใช้ในงานทางการเงิน การวิเคราะห์ภาวะเศรษฐกิจ หรือการทำนายภัยพิบัติทางธรรมชาติ ที่มีข้อมูลบันทึกไว้ซ้ำๆ ตลอดก่อนหน้า

ส่วนที่เพิ่มเข้ามา คือ

  • S - Seasonal : ช่วงฤดูกาล มีการใช้พารามิเตอร์ s เพิ่มเข้าไป

นั่นคือการคำนึงถึงช่วงเวลาฤดูกาลเข้าไปใน ARIMA กลายเป็น SARIMA นั่นเอง

ขั้นตอน

อธิบายคร่าวๆ ถึงการทำ SARIMA

นำเข้า Libraries

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from statsmodels.tsa.statespace.sarimax import SARIMAX
from statsmodels.tsa.stattools import adfuller
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
from sklearn.metrics import mean_absolute_error, mean_squared_error
Enter fullscreen mode Exit fullscreen mode

นำเข้าชุดข้อมูล (Dataset)

โดยชุดข้อมูลที่ใช้คือ Egg Sales of a local shop for 30 years

df = pd.read_csv('/content/train_egg_sales.csv', sep=';')
Enter fullscreen mode Exit fullscreen mode

เนื่องจากชุดข้อมูลที่นำมาใช้นั้นมีข้อมูลรวมกันอยู่ จำเป็นต้องใช้ sep=';'
หากชุดข้อมูลอื่นแยกมาอยู่แล้ว ก็ไม่จำเป็น

sales_data=df[['Date','Egg Sales']]
sales_data=pd.DataFrame(sales_data)
sales_data['Date'] = pd.to_datetime(sales_data['Date'], errors='coerce')
df.head()
Enter fullscreen mode Exit fullscreen mode

ในขั้นตอนนี้ สามารถดูข้อมูลที่นำเข้ามาเพื่อตรวจสอบความถูกต้องของจำนวนข้อมูล
ด้วยdf.info()
Image description

รวมช่วงเวลา

จากข้อมูลที่เป็นต่อวัน รวมกันให้เป็นต่อเดือน

df1 = sales_data.set_index('Date')

monthly_sales = df1.resample('M').mean()
monthly_sales.head()
Enter fullscreen mode Exit fullscreen mode

แสดงกราฟยอดขายแต่ละเดือน

plt.figure(figsize=(12, 6))
plt.plot(monthly_sales['Egg Sales'], linewidth=1, c='cyan')
plt.title("Monthly sales")
plt.xlabel("Date")
plt.ylabel("Egg Sales")
plt.show()
Enter fullscreen mode Exit fullscreen mode

เมื่อดูผลกราฟแล้ว จะเห็นว่าเส้นมีการขึ้นลงที่รูปแบบซ้ำใกล้เคียงกัน
Image description

ตรวจสอบความคงที่

def check_stationarity(timeseries):
    # Perform the Dickey-Fuller test
    result = adfuller(timeseries, autolag='AIC')
    p_value = result[1]
    print(f'ADF Statistic: {result[0]}')
    print(f'p-value: {p_value}')
    print('Stationary' if p_value < 0.05 else 'Non-Stationary')

check_stationarity(monthly_sales['Egg Sales'])
Enter fullscreen mode Exit fullscreen mode

ซึ่งการตรวจสอบที่ออกมานั้นเป็น Non-Stationary ซึ่งแสดงว่าข้อมูลนี้ไม่มีความคงที่

Image description

หาพารามิเตอร์ของโมเดล

# Plot ACF and PACF
plot_acf(monthly_sales)
plot_pacf(monthly_sales)
plt.show()
Enter fullscreen mode Exit fullscreen mode

ACF กับ PACF คืออะไร

  • ACF - Autocorrelation Function
    วัดความสัมพันธ์ระหว่างจุดข้อมูลและจุดข้อมูลก่อนหน้าโดยมีความล่าช้าต่างกัน

  • PACF - Partial Autocorrelation Function
    ความสัมพันธ์ระหว่างจุดข้อมูลและความล่าช้า

Image description

สร้าง Model

กำหนดให้ p d q และ P D Q เป็น 1

  • ค่าเปลี่ยนแปลงไปตาม ACF และ PACF กำหนด s ตามจำนวนเดือน
# Define SARIMA parameters
p, d, q = 1, 1, 1
P, D, Q, s = 1, 1, 1, 12  # Assuming monthly seasonality

# Fit the SARIMA model
model = SARIMAX(monthly_sales, order=(p, d, q), seasonal_order=(P, D, Q, s))
results = model.fit()
model
print(results.summary())
Enter fullscreen mode Exit fullscreen mode

ลองทำนาย

โดยลองทำนายว่า 3 ปีต่อไปจะเป็นแบบไหน โดยใส่ค่า forecast_periods = 36

# Forecast future values
forecast_periods = 36  # Forecast the next 36 months
forecast = results.get_forecast(steps=forecast_periods)
forecast_mean = forecast.predicted_mean
forecast_ci = forecast.conf_int()

# Plot the forecast
plt.figure(figsize=(12, 6))
plt.plot(monthly_sales, label='Observed')
plt.plot(forecast_mean, label='Forecast', color='red')
plt.fill_between(forecast_ci.index, forecast_ci.iloc[:, 0], forecast_ci.iloc[:, 1], color='pink')
plt.title("Sales Forecast")
plt.xlabel("Date")
plt.ylabel("Sales")
plt.legend()
plt.show()
Enter fullscreen mode Exit fullscreen mode

Image description

วัดประสิทธิภาพของโมเดล

  • MAE (Mean Absolute Error) คือค่าเฉลี่ยของความต่างระหว่างค่าที่ทำนายและค่าจริง
  • MSE (Mean Squared Error) คือค่าเฉลี่ยของความต่างระหว่างค่าที่ทำนายและค่าจริง โดยยกกำลังสองของความต่างแต่ละค่า
observed = monthly_sales[-forecast_periods:]
mae = mean_absolute_error(observed, forecast_mean)
mse = mean_squared_error(observed, forecast_mean)
print(f'MAE: {mae}')
print(f'MSE: {mse}')
Enter fullscreen mode Exit fullscreen mode

ค่า MAE และ MSE มีค่าค่อนข้างมาก ซึ่งอาจไม่แม่นยำต่อความเป็นจริง
Image description

สรุป

การทำนายด้วย SARIMA นั้นแสดงค่าของการขายไข่ที่เพิ่มขึ้นในอีก 3 ปี

แต่อย่างไรก็ตาม ชุดข้อมูลที่ใช้นี้เป็น Non-Stationary หรือไม่คงที่
ทำให้เกิดการคาดเคลื่อนค่อนข้างมาก ซึ่งสามารถหาชุดข้อมูลอื่นที่เมื่อตรวจสอบเป็น Stationary จะให้ความแม่นยำมากกว่า หรือการแปลง Non-Stationary เป็น Stationary จากอ้างอิงได้

อ้างอิง

  • ข้อมูลที่เกี่ยวข้อง

https://www.geeksforgeeks.org/sarima-seasonal-autoregressive-integrated-moving-average/
https://www.kaggle.com/code/shubhammisar/air-passenger-data-forecasting-sarima/notebook
https://www.kaggle.com/code/tanmay111999/air-passenger-forecast-arima-sarima/notebook

  • ชุดข้อมูล

https://www.kaggle.com/datasets/kanchana1990/egg-sales-of-a-local-shop-for-30-years/data

Top comments (0)