Spaces:
Sleeping
Sleeping
File size: 2,477 Bytes
d445415 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# utils/prediction_utils.py
import warnings
warnings.filterwarnings("ignore")
import numpy as np
# Prophet ์๋, ์คํจ ์ Holt(์ง์ ํํ) ํด๋ฐฑ
try:
from prophet import Prophet
_HAS_PROPHET = True
except Exception:
_HAS_PROPHET = False
try:
from statsmodels.tsa.holtwinters import ExponentialSmoothing
_HAS_HOLT = True
except Exception:
_HAS_HOLT = False
import pandas as pd
def prophet_emotion_forecast(scores, steps=3):
"""
Prophet ๊ธฐ๋ฐ ์์ธก. ์
๋ ฅ: ์ ์ ๋ฆฌ์คํธ(0~100)
๋ฐํ: ์์ธก ์ ์ ๋ฆฌ์คํธ ๊ธธ์ด=steps (float)
์ฐธ๊ณ : Taylor & Letham (2018) 'Forecasting at Scale'
"""
if not _HAS_PROPHET or len(scores) < 5:
return None
df = pd.DataFrame({
'ds': pd.date_range(start='2023-01-01', periods=len(scores), freq='D'),
'y': scores
})
model = Prophet(
daily_seasonality=False, weekly_seasonality=False, yearly_seasonality=False,
changepoint_prior_scale=0.2 # ๋ณํ์ ๋ฏผ๊ฐ๋
)
model.fit(df)
future = model.make_future_dataframe(periods=steps)
forecast = model.predict(future)
tail = forecast[['yhat']].tail(steps)['yhat'].to_list()
# ์์ ํด๋ฆฌํ
return [float(np.clip(x, 0, 100)) for x in tail]
def holt_fallback_forecast(scores, steps=3):
"""
Holt ์ง์ํํ(์ถ์ธํ) ํด๋ฐฑ ์์ธก.
Prophet ์ฌ์ฉ ๋ถ๊ฐ ํ๊ฒฝ์์ ๊ฐ๋จํ๊ณ ์์ ์ .
"""
if not _HAS_HOLT or len(scores) < 4:
return None
try:
model = ExponentialSmoothing(
np.array(scores, dtype=float),
trend='add', seasonal=None
).fit()
fcast = model.forecast(steps)
return [float(np.clip(x, 0, 100)) for x in fcast.tolist()]
except Exception:
return None
def forecast_scores(scores, steps=3):
"""
ํตํฉ ์์ธก ์์ง:
1) Prophet ์ฑ๊ณต ์ Prophet ์ฌ์ฉ
2) ์๋๋ฉด Holt ํด๋ฐฑ
3) ๊ทธ๋๋ ์ ๋๋ฉด, ๋ง์ง๋ง ๊ธฐ์ธ๊ธฐ ์ ํ ์ธ์ฝ(๊ทน๋จ ํด๋ฐฑ)
"""
if len(scores) < 2:
return [scores[-1]] * steps if scores else [0.0]*steps
yhat = prophet_emotion_forecast(scores, steps=steps)
if yhat is not None:
return yhat
yhat = holt_fallback_forecast(scores, steps=steps)
if yhat is not None:
return yhat
# ๋ง์ง๋ง ๋ ์ ์ ๊ธฐ์ธ๊ธฐ๋ก ์ธ์ฝ
slope = scores[-1] - scores[-2]
return [float(np.clip(scores[-1] + slope*(i+1), 0, 100)) for i in range(steps)] |