๐ ๊ณต๋ถํ๋ ์ง์ง์ํ์นด๋ ์ฒ์์ด์ง?
ADTK (Anomaly detection toolkit) ์๊ณ์ด ์ด์ํ์ง ์คํ์์ค ๋ณธ๋ฌธ
ADTK (Anomaly detection toolkit) ์๊ณ์ด ์ด์ํ์ง ์คํ์์ค
์ง์ง์ํ์นด 2022. 9. 6. 09:52220906 ์์ฑ
<๋ณธ ๋ธ๋ก๊ทธ๋ analyticsindiamag ๋์ ๋ธ๋ก๊ทธ๋ฅผ ์ฐธ๊ณ ํด์ ๊ณต๋ถํ๋ฉฐ ์์ฑํ์์ต๋๋ค :-) >
https://analyticsindiamag.com/a-hands-on-guide-to-anomaly-detection-in-time-series-using-adtk/
A hands-on guide to anomaly detection in time series using ADTK
ADTK is an open-source python package for time series anomaly detection. The name ADTK stands for Anomaly detection toolkit.
analyticsindiamag.com
๐1. ADTK๋ ?
- ๊ณผ๊ฑฐ ๋ฐ์ดํฐ์์ ๋น์ ์ ๋ฐ์ดํฐ๋ฅผ ๊ฑฐ์ ์ฐพ์ง ๋ชปํ๊ณ ์ง๋ ๋ชจ๋ธ์ ๊ตฌ์ถํ๋ ๋ฐ ๋ฌธ์ ์์
- ๊ด์ฌ ์๋ ์ด๋ฒคํธ ์ ํ์ ์ดํดํ๊ธฐ ์ํด ํญ์ ๋น์ ์์ ๊ฐ์งํด์ผ ํ๋ ์๊ตฌ ์ฌํญ ์์
- ์ด์๊ฐ ๊ฐ์ง๊ธฐ
- ๋ฐ์ดํฐ์์ ์ด์๊ฐ์ ๊ฐ์ง
- ์๊ณ๊ฐ ๊ฐ์ง, ๊ณ์ ๊ฐ์ง, ํ๊ท ๊ฐ์ง ๋ฑ๊ณผ ๊ฐ์ ์๊ณ์ด์ ๋ชจ๋ ์ ํ์ ๊ฐ์ง์ ๋์์ด ๋๋ ๋ค์ํ ๋ชจ๋
- ๋ณํ๊ธฐ
- ๋ฐ์ดํฐ๋ฅผ ๋ณํ
- ์ด ํด๋์ค์๋ ๋กค๋ง ์ง๊ณ, ๊ณ์ ๋ถํด ๋ฑ์ ๋ชจ๋๊ณผ ๊ฐ์ ๋ค์ํ ๋ชจ๋
- ๊ท์น ์ฒด์ธ ์ง๊ณ๊ธฐ
- ๋ชจ๋ ๊ท์น์ ๋ฐ๋ผ ์ค์ ๋ ์์ ์ ์๋ณํ๊ณ ์ง๊ณ
- ์ด์๊ฐ ๊ฐ์ง๊ธฐ
๐2. ์ฝ๋๊ตฌํ
1๏ธโฃ Data Load
- yfinance : ์ผํ ํ์ด๋ธ์ค์์ ํฌ๋กค๋งํ ๋ฐ์ดํฐ๋ฅผ ์ ๊ณตํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
pip install yfinance
- ์ธ๋ ๊ตญ์ ์ํ์์ ์ฃผ๊ฐ ๋ฐ์ดํฐ๋ฅผ ์ถ์ถ
import datetime as dt
from datetime import datetime as dt
from dateutil.relativedelta import relativedelta
import yfinance as yf
end = dt.today()
start = dt.today() - relativedelta(years=1)
data = yf.download('SBIN.NS', start, end)
data.tail()
- ์ฃผ๊ฐ ์๊ฐ, ๊ณ ๊ฐ, ์ ๊ฐ ๋ฐ ์ข ๊ฐ์ ์ฃผ์์ ๊ฑฐ๋๋์ด ๋ณ์
2๏ธโฃ ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ
- ์ฃผ์ ์์ฅ์ด ์ด๋ฆฌ์ง ์๋ ์ฃผ๋ง์ด ์์! -> ๊ฒฐ์ธก์น ๋ฐ์
- ์ด ๊ฒฉ์ฐจ๋ฅผ ๋ฉ์์ผ ํ์ง๋ง ๊ทธ ์ ์ ๋ฐ์ดํฐ์ ๋๋ฝ๋ ๋ ์ง๊ฐ ๋ช ๊ฐ์ธ์ง ํ์ธ
import pandas as pd
# pandas.date_range() : ๊ณ ์ ๋น๋ DatetimeIndex๋ฅผ ๋ฐํํ๋ ๋ฐ ์ฌ์ฉ๋๋ Pandas์ ์ผ๋ฐ ํจ์
pd.date_range(start = start, end = end ).difference(data.index)
# difference : data์ columns์์ ๋ถ๋ฆฌํด๋ด๋ method
- ๊ฒฐ์ธก์น ์ฑ์ฐ๊ธฐ
- reindex : ํน์ ์ถ์ ๋ค๋ผ ์ ๋ ฅ๋ ๋ฐฐ์ด์ ๋ค๋ผ ๋ฐ์ดํฐ ์์๋ฅผ ์กฐ์
idx = pd.date_range(start, end)
# reindex : ํน์ ์ถ์ ๋ค๋ผ ์
๋ ฅ๋ ๋ฐฐ์ด์ ๋ค๋ผ ๋ฐ์ดํฐ ์์๋ฅผ ์กฐ์
data = data.reindex(idx)
# fillna : DataFrame์์ ๊ฒฐ์ธก๊ฐ์ ์ํ๋ ๊ฐ์ผ๋ก ๋ณ๊ฒฝ
# ffill : ๊ฒฐ์ธก๊ฐ์ด ๋ฐ๋ก ์๊ฐ๊ณผ ๋์ผํ๊ฒ ์ค์
data.fillna(method="ffill", inplace = True)
- ๊ฒฐ์ธก์น ์๋์ง ๋ค์ ํ์ธ
pd.date_range(start = start, end = end ).difference(data.index)
3๏ธโฃ ๋ฐ์ดํฐ ๊ฒ์ฆ ๋ฐ ์๊ฐํ
- ADTK์ ๋ชจ๋๋ก ์์ ํ๋ ค๋ฉด ํจํค์ง๋ก ๋ฐ์ดํฐ๋ฅผ ๊ฒ์ฆ
# ๋น์ง๋/๊ท์น ๊ธฐ๋ฐ ์๊ณ์ด ์ด์ ํ์ง๋ฅผ ์ํ Python ํจํค์ง
from adtk.data import validate_series
data = validate_series(data)
print(data)
- ์๊ฐํ
from adtk.visualization import plot
plot(data)
4๏ธโฃ ๊ณ์ ์ ์ด์ ํ์ง
- ์ด์ ํ์ ๋ฐ ๋ณผ๋ฅจ ๋ณ์์ ์ํ ๊ณ์ ํจํด ์๋ฐ์ ๊ฐ์ง
from adtk.detector import SeasonalAD
seasonal_vol = SeasonalAD()
anomalies = seasonal_vol.fit_detect(data['Volume'])
anomalies.value_counts()
plot(data, anomaly=anomalies, anomaly_color="orange", anomaly_tag="marker")
5๏ธโฃ ์๊ณ๊ฐ ๊ฐ์ง
- ์๊ณ์ด์ด ์ด ์๊ณ๊ฐ์ ๋ฒ์ด๋๋ ์ง์ ์ ๊ฐ์ง
print('Average closing price', data['Close'].mean())
print('Minimum closing price', data['Close'].min())
print('Maximum closing price',data['Close'].max())
from adtk.detector import ThresholdAD
threshold_val = ThresholdAD(high=530, low=180)
anomalies_thresh = threshold_val.detect(data['Close'])
- ์ด์์งํ๊ฐ ๋ฌด์์ธ๊ฐ?
- True ๊ฐ์
anomalies_thresh.value_counts()
- ์๊ฐํ
from adtk.visualization import plot
plot(data, anomaly=anomalies_thresh, ts_linewidth=1, ts_markersize=3, anomaly_markersize=5, anomaly_color='black');
ํ๋ค๊ฐ ๊ฒฐ์ธก์น ์ฑ์ฐ๋ ๋ถ๋ถ์์ data ๊ฐ์ด NaN ๊ฐ์ผ๋ก ๋์๋ค..
์ด์ ๊ฐ ๊ถ๊ธํ๋ค reindex๋ ์ฒจ์ด๋ผ..