echoss-timeseries
echoss AI Bigdata Center 시계열 데이터/모델 기반 라이브러리.
여러 도메인 프로젝트가 함께 쓰는 공통 패키지다. 통계 / 기계학습 / 딥러닝 / 트랜스포머 계열 시계열 모델을 한 구조 위에서 다루는 것을 목표로 한다.
도메인 프로젝트가 TSData / TSModel 을 상속해서 사용하는 것을 전제로 설계되었다.
데이터 로딩·리샘플링·시계열 피처 엔지니어링·진단은 기반 클래스가 담당하고,
도메인 고유의 전처리와 학습 로직만 자식 클래스에 구현한다.
설치
pip install echoss-timeseries # 데이터 · 피처 · 진단 · 모델 골격
pip install 'echoss-timeseries[plot]' # 플롯까지
pip install 'echoss-timeseries[forecast]' # darts 예측 모델과 holdout 비교
pip install 'echoss-timeseries[screening]' # autogluon 으로 후보 알고리즘 선별 (pandas 2 환경)
요구사항
- Python >= 3.12
기본 설치:
| 패키지 | 버전 | 용도 |
|---|---|---|
| echoss-fileformat | >=1.3.2 | logger, config/파일 IO |
| pandas | >=2.2,<4 | DataFrame |
| numpy | >=2.5.3 | 수치 연산 |
| scipy | >=1.18.1 | BoxCox, 통계 |
| scikit-learn | >=1.9.0 | scaler, encoder, metric |
| statsmodels | >=0.15.0 | STL, ADF/KPSS, AutoReg |
| holidays | >=0.104 | 공휴일 피처 |
| window_ops | >=0.0.15 | seasonal rolling 연산 |
| numba | >=0.68.0 | window_ops 실행 (0.67 이하는 numpy 2.5 거부) |
[plot] extras:
| 패키지 | 버전 | 용도 |
|---|---|---|
| bokeh | >=3.10.0 | 인터랙티브 플롯 |
| matplotlib | >=3.11.1 | 정적 플롯 |
[forecast] extras — darts 예측 모델 (naive_seasonal, exponential_smoothing, theta, auto_arima, lightgbm):
| 패키지 | 버전 | 용도 |
|---|---|---|
| darts | >=0.47.0 | 예측 모델 (0.46.x 의 Theta 는 statsmodels 0.15 에서 실패) |
| statsforecast | >=2.0.1 | darts AutoARIMA (2.1.0 부터 pandas<3 을 요구한다. pandas 3 환경에는 2.0.x 가 설치된다) |
| lightgbm | >=4.7.0 | darts LightGBM, 피처 표 LightGBM |
[screening] extras — autogluon 선별기 (AutogluonScreener):
| 패키지 | 버전 | 용도 |
|---|---|---|
| autogluon.tabular[lightgbm] | >=1.6.3 | 후보 알고리즘 순위. pandas<2.4 를 요구해 pandas 2 환경에 설치된다 |
lightgbm 은 알고리즘 이름 하나로 두 입력 방식을 받는다. spec 에 target_col 이 있으면 피처 표로 학습하고(LightGBM 의 scikit-learn 추정기), 없으면 목표 시계열만으로 학습한다(darts).
판매 없는 날(0)이 있는 자료에서 theta 는 hyperparameters: {season_mode: additive} 로 쓴다 (darts 기본값인 곱셈은 0 을 거부한다). 계절성·추세 방식은 additive / multiplicative / none 문자열로 지정한다. exponential_smoothing 은 계절 주기를 자료 간격으로 정한다(일 7, 주 52, 월 12). 7일처럼 배수 간격이거나, 분 단위처럼 주기를 정할 수 없는 간격이거나, 자료가 그 주기의 두 바퀴보다 짧으면 학습 전에 멈추므로, seasonal_periods 를 지정하거나 seasonal: none 으로 쓴다.
extras 없이 플롯·예측 모델·선별기를 쓰면 무엇을 설치해야 하는지 알려주는 오류가 난다.
하한은 pandas 2.2.3 과 3.0.6 에서 시험 통과를 확인한 조합이며, 각 패키지의 최소 요구 버전을 조사한 값이 아니다.
필요한 것만 적재된다. import echoss_timeseries 는 이름을 실제로 쓸 때까지 하위 모듈을
읽지 않는다. 진단 함수 하나만 쓰면 플롯 라이브러리는 올라오지 않는다.
기능
| 모듈 | 주요 export |
|---|---|
echoss_tsdata |
TSData — 데이터 로딩/캐시, split, 리샘플링, 피처 추가 진입점 |
echoss_tsmodel |
TSModel — run_models() 파이프라인 골격, forecast/classification 스코어 |
tsdiag |
stationarity_tests, lag_diagnostics, try_autoreg, naive_cv_scores, seasonal_strength, is_constant_series, analyze_series, ensure_month_start_col, validate_month_ms, ensure_datetime_freq |
autoregressive_features |
add_lag_features, add_rolling_features, add_seasonal_rolling_features, add_ewma_features |
temporal_features |
add_temporal_features, add_fourier_features, bulk_add_fourier_features |
decomposition |
BaseDecomposition, MultiSeasonalDecomposition, FourierDecomposition, DecomposeResult |
outlier |
detect_outlier_sd, detect_outlier_iqr, detect_outlier_isolation_forest |
echoss_plot_bokeh [plot] |
plot_lines, plot_datetime, plot_forecast, plot_train_test_forecast 등 |
echoss_plot_matplot [plot] |
plot_sales_intensity_heatmap |
engines |
ModelEngine, DataShape, EngineRegistry, StatsmodelsArimaEngine, SklearnTabularEngine, DartsSeriesEngine, HoldoutComparison, Ensemble, WeightedEnsemble, Screener, Candidate, AutogluonScreener |
사용법
1. TSData 상속 — 도메인 데이터 레이어
from echoss_timeseries import TSData, EventDayFeatures
class BakeryData(TSData):
"""제과점 판매 데이터. 월별 Excel 원천 -> 일별 dense DataFrame."""
def __init__(self, data_path='data', config='config/bakery_data.yaml', use_cache=False):
super().__init__(data_path, config, use_cache=use_cache)
self.id_col = self.config.get('id_col')
self.time_col = self.config.get('time_col')
self.target_col = self.config.get('target_col')
def load_raw(self):
"""도메인 원천(Excel/DB) 파싱. 기반 클래스의 add_data() 로 등록한다."""
raw_df = ... # 도메인 파싱
self.add_data(raw_df, data_key='raw_df')
def prepare_xy_data(self):
"""기반 클래스의 피처 메서드와 EventDayFeatures 를 조합한다. 각 호출은 (df, 추가된_컬럼명) 을 반환한다."""
df = self.get_dataframe('raw_df')
df = self.fill_to_frequency(df, 'D', time_col=self.time_col, id_col=self.id_col)
df, _ = self.add_temporal_features(df, time_col=self.time_col, frequency='D')
df, _ = EventDayFeatures(country="KR").add_features(df, time_col=self.time_col)
df, _ = self.add_lag_features(df, lags=[1, 7, 14], column=self.target_col, ts_id=self.id_col)
df, _ = self.add_rolling_features(df, rolls=[7, 28], column=self.target_col, ts_id=self.id_col)
self.add_data(df, data_key='daily_dense_df')
데이터는 항상 cache 에 쓰고, use_cache=True 일 때만 cache 에서 읽는다. cache 는 cache_dir(기본 cached, 실행 폴더 기준)에
{config 파일명}_{data_key} 로 저장되며, 같은 cache_dir 의 인스턴스는 cache 를 공유한다(config 가 dict 이면 이름은 cache).
나누려면 cache_dir 나 cache_suffix 를 지정한다.
2. TSModel 상속 — 도메인 모델 레이어
run_models() 가 prepare_dataset() -> training_model() -> evaluation_model() 순서로
자식 클래스 구현을 호출한다. 단계 간 데이터 전달은 self.runtime_dict 를 사용한다.
from echoss_timeseries import TSModel
class BakeryModel(TSModel):
"""2단계 예측: has_sales 분류 -> 수량 회귀."""
def prepare_dataset(self, df):
# split 은 데이터 레이어 책임 — self.ts_data 를 통해 호출한다
train_df, test_df = self.ts_data.split_data(df, split_date=self.config.get('split_date'))
self.runtime_dict['train_df'] = train_df
self.runtime_dict['test_df'] = test_df
def training_model(self):
train_df = self.runtime_dict['train_df']
# 도메인 학습 엔진 호출 (AutoGluon, pycaret 등)
self.runtime_dict['predictor'] = ...
return self.runtime_dict
def evaluation_model(self):
test_df = self.runtime_dict['test_df']
pred_df = self.runtime_dict['pred_df']
return self.calculate_forecast_score(
test_df[self.config['target_col']], pred_df['pred_y'],
)
ts_data = BakeryData(data_path='data', config='config/bakery_data.yaml')
ts_data.load_raw()
ts_data.prepare_xy_data()
model = BakeryModel(ts_data, config='config/bakery_model.yaml', result_save_path='results/')
model.run_models(data='daily_dense_df', training_kwargs={'year_month': '2026-05'})
인스턴스는 원하는 만큼 만들 수 있다. TSData 와 TSModel 의 가변 상태(data_map,
runtime_dict, scaler·encoder 맵 등)는 인스턴스마다 분리된다.
show_plot 같은 불변 플래그만 클래스 레벨에 남아 있어, 자식 클래스에서 클래스 레벨로
기본값을 바꿀 수 있다.
3. 시계열 진단 (tsdiag)
상속 없이 모듈 함수로 바로 사용한다.
from echoss_timeseries import analyze_series, stationarity_tests, naive_cv_scores
result = analyze_series(ts, freq='D', seasonal_period=7, max_ar=12, horizon=14)
print(result['predictability_score'], result['seasonal_strength'])
print(stationarity_tests(ts)) # adf_pvalue, kpss_pvalue
print(naive_cv_scores(ts, horizon=14, seasonal_period=7))
도메인 컬럼명은 라이브러리 기본값으로 두지 않는다. validate_month_ms(df, time_col='날짜')
처럼 호출부가 명시 전달한다.
알려진 한계 (1.2.0)
1.2.0 에서 고치지 않은 동작이다.
| 대상 | 한계 | 우회 |
|---|---|---|
analyze_series 의 predictability_score |
실측 판매 자료(상품 71개)에서 실제 예측 오차와 반대 방향으로 움직였다 | 모델 선택이나 예측 난이도 판정에 쓰지 않는다 |
MultiSeasonalDecomposition('fourier', ...) |
요일 주기(day_of_week) 성분의 세기가 항상 0 으로 나온다 |
요일 주기는 STL 이나 averages 방식으로 분해한다 |
seasonal_esd |
원 알고리즘(S-H-ESD)대로 추세를 빼지 않아 추세가 있는 자료에서 이상치를 놓친다 | 추세를 먼저 빼고 넘긴다 |
is_constant_series |
넘파이 불리언을 돌려준다 | is True 대신 진리값으로 비교한다 |
문서
| 문서 | 내용 |
|---|---|
prior-work.jsonl |
작업원장. 이전 작업의 결론과 다시 하지 말 것, 백로그 |
docs/known-issues.md |
사용자용. 알려진 문제와 우회 방법 |
docs/backlog.md |
개발자용. 결함 대장(B4 |
docs/design/engine-abstraction.md |
학습 엔진 계층 설계 (선별기·모델 엔진·앙상블) |
앞으로
알고리즘을 교체하고 결합할 수 있는 계층을 만들고 있다 — 후보 알고리즘을 추리는 선별기, 알고리즘 하나를 감싸는 모델 엔진, 여러 모델을 합치는 앙상블 셋으로 나눈다.
세 계층 모두 동작한다. 선별기는 autogluon.tabular 하나다([screening], pandas 2 환경).
모델 비교는 HoldoutComparison 이 holdout 지표로 순위표를 만든다.
from echoss_timeseries import EngineRegistry, WeightedEnsemble
# 알고리즘은 config 로 고른다. 이름은 알고리즘 이름이다 (라이브러리 이름이 아니다)
models = EngineRegistry.build_models({"models": [
{"name": "arima", "hyperparameters": {"order": [1, 1, 1]}},
{"name": "random_forest", "problem_type": "regression", "target_col": "y"},
]})
engine = models[0].fit(series)
pred = engine.predict(future_index) # 예측 길이는 넘긴 인덱스의 길이로 정해진다
# 여러 모델을 검증오차 역수로 가중 평균한다
ensemble = WeightedEnsemble().fit(fitted_models, (valid_x, valid_y))
print(ensemble.weights()) # 어느 모델이 얼마나 기여했는지 설명된다
선별기는 후보 순위만 낸다. 최종 모델은 후보를 이 패키지 엔진으로 다시 만든다.
from echoss_timeseries import AutogluonScreener, EngineRegistry
screener = AutogluonScreener({"time_limit": 600})
candidates = screener.screen(table, label="y", problem_type="regression", eval_metric="root_mean_squared_error")
best = next(c for c in candidates if c.resolvable) # 점수 내림차순
engine = EngineRegistry.create_model(best.to_model_spec()).fit(table)
autogluon 모델 중 이 패키지에 같은 입력으로 만들 어댑터가 있는 것(LightGBM -> lightgbm,
RandomForest -> random_forest)만 해석 가능이다. ExtraTrees·LinearModel·WeightedEnsemble 등은
목록에 남되 resolvable=False 다. 후보에는 autogluon 이 기록한 하이퍼파라미터가 담기지만,
조기 종료로 정해진 반복 횟수는 기록에 없어 넘어가지 않는다. 배깅 설정(best_quality 등)에서는
자식 모델 종류로 해석하고, refit_full 의 점수 없는(NaN) 모델은 목록 맨 뒤에 둔다.
후보로 만든 엔진은 숫자 열 표만 받는다 — autogluon 은 문자열·범주·날짜 열을 스스로 처리하지만
RandomForest·LightGBM 추정기는 그렇지 않으므로, 선별 전에 피처 표를 숫자로 맞춘다.
config 에 모르는 이름이나 키를 적으면 예외가 난다. 조용히 무시하면 그 설정이 적용되지 않은 채 실행되고, 결과만 보고는 원인을 찾을 수 없다.
설계는 docs/design/engine-abstraction.md 에 있다.
License
Apache-2.0
Metadata
Release files for echoss-timeseries 1.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| echoss_timeseries-1.2.0.tar.gz | 87.0 kB | Without provenance | Details for echoss_timeseries-1.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| echoss_timeseries-1.2.0-py3-none-any.whl | Python 3 | none | any | Details for echoss_timeseries-1.2.0-py3-none-any.whl |
Total release size: 180.3 kB
Release files / echoss_timeseries-1.2.0.tar.gz
| Download URL | echoss_timeseries-1.2.0.tar.gz |
|---|---|
| Size | 87.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8894f05855b75748b766c17e8f15963853f4dd6909fda2b0930f12100261251e
|
|
BLAKE2b-256 checksum How to use checksums |
35bc0da38ee745ab55c64e4afc3581f0dcf77084b8be2a75df7ecadcb69099a8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Release files / echoss_timeseries-1.2.0-py3-none-any.whl
| Download URL | echoss_timeseries-1.2.0-py3-none-any.whl |
|---|---|
| Size | 93.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7b4af52bfca50a24cb8655b7d64e257cde744418db021d5a8d06a359bdd2108a
|
|
BLAKE2b-256 checksum How to use checksums |
8a7a998ff9bfbd48201c918bb1fe07c5f9979a70b4df1b225a83a65b09784190
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Security for echoss-timeseries 1.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.