시계열 계속
A. 통계적 시계열 모델 전처리
1. 정상성과 비정상성
- 비정상성 데이터란?
- 시간이 지날수록 데이터의 평균(Trend)이 증가/감소하는 경우 (추세)
- 계절성(Seasonality) 이 포함되어 특정 주기마다 패턴이 달라지는 경우
- 시간이 지날수록 데이터의 변동성(Variance)이 증가하는 경우
- 정상적이다. (Stationary) = 안정적이다.
- 추세(Trend)나 계절성이 없고, 데이터의 평균과 분산이 일정한 경우
- 주어진 시간 간격에서 변동성이 안정적이며 예측 가능한 수준
- 시계열의 통계적 특징(평균, 분산, 자기 상관)이 변하지 않는다. (일정한 패턴을 유지)
- 랜덤한 움직임을 가지지만, 시점마다 유사하게 동작하는 특징이 있어 시간에 따라 안정된 분포를 갖는다.
(2) 모든 시점 t에 대해 분산이 같다.
(3) 자기 공분산 (자기 상관관계)이 시간이 아닌 시차에 의존한다.
2. 정상성 데이터로 변화시키기
B. ARIMA 모델
- ACF, PACF
1. ACF (자기상관 함수): 시계열 데이터의 특정 시점과 이전 시점 간의 상관 관계를 나타내는 함수입니다. 시계열 데이터의 전체적인 패턴을 파악하는 데 유용하며, 데이터가 얼마나 주기적으로 반복되는지를 알 수 있습니다. ⇒ Rolling Window(이동평균 등)의 기준 2, 12

2. PACF (부분 자기상관 함수): 자기상관 함수에서 단순히 이전의 시점 간 상관만을 고려하는 것이 아니라, 특정 시점의 값이 이전의 값들과 어떻게 관계가 있는지를 고려하여 직접적인 상관만을 추출하는 함수입니다. ⇒ Lag(시차) 피처의 기준 2라

- ARIMA 모델
ARIMA 모델은 시계열 데이터의 자기상관성(AR), 차분(D), 이동 평균(MA)을 이용해 미래 값을 예측하는 시계열 통계 모델입니다.

ARIMA 모델은 자기회귀, 차분, 이동평균을 이용해 미래 값을 예측하는 통계적 시계열 모델이다. 이때 차분을 통해 비정상 데이터를 정상 데이터에 가깝게 만들고, ACF와 PACF를 참고해 p, q 값을 정한다. 계절성이 있는 데이터에는 SARIMA를 사용할 수 있으며, 일반 ARIMA 차수에 계절 차수까지 함께 고려한다.
LOT와 Batch
LOT는 제품 묶음 중심의 개념이고, Batch는 공정을 한 번 수행한 전체 과정에 가깝다. LOT는 제품 여러 개의 측정값이나 제품별 시계열 데이터를 포함할 수 있고, Batch는 하나의 공정 run 동안 긴 센서 시계열을 포함할 수 있다.
LOT 시계열 처리 방식 3가지
① 제품별 시계열 → 요약 통계(summary) → ML 모델 (LightGBM/XGBoost)
가장 보편적이고 빠르고 정확한 방식.
예:
- Pressure_mean
- Pressure_std
- Pressure_max
- Pressure_slope
- Peak_count
- FFT_peak
➡ LOT 전체를 1 row로 축약해서 품질 예측
② 제품별 시계열 → 구간(section) 분할 후 요약 → ML
예:
- 0~20% 구간 mean
- 20~50% 구간 std
- 50~100% 구간 slope
➡ Waveform의 형태(shape)를 ML feature로 간접 반영
③ LOT 내부 제품들을 집계해서 LOT-level feature 생성
예:
LOT-Level Mean Pressure = 제품별 mean의 평균
LOT-Level Std Pressure = 제품별 std의 평균
LOT-Level Defect Ratio = NG 제품 비율
➡ LOT 품질 예측에 바로 사용 가능
Batch 데이터 시계열 모델링 방법
① Batch 전체 waveform → 전역 요약(feature) 생성 → ML
예:
- 전체 평균/분산
- 전체 peak count
- 전체 slope
- DO_min_time
- Temp_integral (면적)
➡ 공정 전체 경향으로 품질 예측
② Batch를 일정 구간 %로 나누는 방식 (Normalization)
Batch 길이가 서로 다르기 때문에:
0~10%, 10~20%, … 90~100%
로 나누고:
- 구간별 mean
- 구간별 std
- 구간별 slope
- 구간별 energy(면적)
등을 뽑아서 ML 입력으로 만든다.
➡ Batch 시계열 차이를 표준화하는 제조업 전형 방법
③ Rolling/Diff 기반의 변화량 feature
Batch 공정은 시간 흐름에 따른 변화가 중요하기 때문에:
- diff_mean
- diff_std
- rolling_mean(10)의 전체 평균
- rolling_std(20)의 전체 최대값
이와 같이 변화 패턴 기반 feature가 Batch 품질 예측에 강함.
이상치 탐지 유형
1️⃣ Point Anomalies (포인트 이상치)
정의:
단일 센서 값 또는 측정값이 다른 정상 데이터와 비교했을 때 급격히 벗어난 경우. 즉, 오직 하나의 데이터에만 이상이 생긴 것

🛠 제조 예시:
- 온도 센서가 갑자기 비정상적으로 높은 값을 기록 (예: 정상 범위 20~50°C인데 100°C가 기록됨).
- 특정 부품의 길이, 무게, 두께 등의 측정값이 허용 공차를 초과.
2️⃣ Contextual Anomalies (문맥적 이상치)
정의:
값 자체는 정상 범위에 있지만, 특정 조건이나 문맥에서 비정상적인 경우. 즉, 데이터의 맥락(Contextual)을 고려했을 때 생긴 이상이 생긴 것

🛠 제조 예시:
- 온도 센서 데이터: 일반적으로 밤에는 온도가 낮아야 하는데, 특정 공정에서 낮보다 높은 온도 기록.
- 진동 데이터: 정상적으로 기계가 작동할 때는 진동이 강해야 하는데, 부하가 적은 공정에서 강한 진동이 발생.
3️⃣ Collective Anomalies (집단적 이상치)
정의:
개별 값들은 정상 범위 내에 있지만, 여러 값이 특정한 패턴을 이루며 비정상적인 경우 즉, 복수의 데이터 포인터들에게서 이상이 생긴 것(연속적)

🛠 제조 예시:
- 모터 전류 데이터: 특정 시간 동안 꾸준히 정상 범위를 유지하던 전류가 갑자기 연속적으로 변동이 심해짐.
- 생산 공정 시간: 개별적인 조립 공정 시간은 정상이지만, 조립 후 검사 시간이 연속적으로 길어짐.
- 불량률 패턴 변화: 개별 불량률은 낮지만, 한 시간 동안 연속적으로 작은 불량이 누적되는 경우.

이상치 모델
Isolation Forest (격리 기반 이상치 탐지) ⇒ point 이상치에 적합
개념
- 트리 구조를 사용하여 데이터를 무작위로 분할하며, 이상치는 정상 데이터보다 더 빠르게 격리(Isolation)되는 특성을 이용한 방법.
- 이상치는 다른 데이터보다 고립되기 쉬우므로(트리에서 더 적은 단계에서 분리됨) 이상으로 판단

특징
✔ 비지도 학습(Unsupervised Learning)
✔ 빠른 연산 속도: 트리 구조 기반으로 대용량 데이터에서도 빠르게 동작.
✔ 정규 분포가 아닌 데이터에도 적합
✔ 고차원 데이터에서도 효과적
import numpy as np
import matplotlib.pyplot as plt
from sklearn.ensemble import IsolationForest
# 1. 샘플 데이터 생성 (정상 + 이상치)
rng = np.random.RandomState(42)
# 정상 데이터 100개 (2D Gaussian)
X_normal = 0.3 * rng.randn(100, 2) + [2, 2]
# 이상치 10개 (멀리 떨어진 위치)
X_outliers = rng.uniform(low=-4, high=8, size=(10, 2))
# 전체 데이터 결합
X = np.vstack([X_normal, X_outliers])
# 데이터 확인 (전체 분포 시각화)
plt.scatter(X[:, 0], X[:, 1], c='gray')
plt.title("Generated Data (with outliers)")
plt.xlabel("Feature 1")
plt.ylabel("Feature 2")
plt.show()
# 2. Isolation Forest 모델 생성 및 학습
iso_forest = IsolationForest(contamination=0.05, random_state=42)
y_pred = iso_forest.fit_predict(X) # 정상: 1, 이상치: -1
# 3. 이상치 탐지 결과 시각화
plt.scatter(X[:, 0], X[:, 1], c=y_pred, cmap='coolwarm')
plt.title("Isolation Forest Anomaly Detection")
plt.xlabel("Feature 1")
plt.ylabel("Feature 2")
plt.show()
Local Outlier Factor (LOF, 지역적 밀도 기반 이상치 탐지) ⇒가끔
개념
- 데이터의 밀도를 계산하여 이웃 데이터들과의 상대적인 차이를 분석하여 이상치를 탐지하는 방법.
- 이상치의 특징: 주변 밀도가 낮고, 정상 데이터와의 밀도 차이가 클 경우 이상치로 판별.

특징
✔ 밀도 기반 이상치 탐지 → 데이터 분포가 균일하지 않아도 탐지 가능
✔ 지역적(Local) 패턴을 반영 → 특정 영역에서의 이상치 감지 가능
✔ 비정규 분포 데이터에서도 효과적
import numpy as np
import matplotlib.pyplot as plt
from sklearn.neighbors import LocalOutlierFactor
# 1. 샘플 데이터 생성 (정상 + 이상치)
rng = np.random.RandomState(42)
# 정상 데이터 100개 (2D Gaussian)
X_normal = 0.3 * rng.randn(100, 2) + [2, 2]
# 이상치 10개 (멀리 떨어진 위치)
X_outliers = rng.uniform(low=-4, high=8, size=(10, 2))
# 전체 데이터 결합
X = np.vstack([X_normal, X_outliers])
# 전체 데이터 확인
plt.scatter(X[:, 0], X[:, 1], c='gray')
plt.title("Generated Data (with outliers)")
plt.xlabel("Feature 1")
plt.ylabel("Feature 2")
plt.show()
# 2. LOF 모델 생성 및 이상치 탐지
lof = LocalOutlierFactor(n_neighbors=20, contamination=0.05)
y_pred = lof.fit_predict(X) # 정상: 1, 이상치: -1
# 3. 결과 시각화
plt.scatter(X[:, 0], X[:, 1], c=y_pred, cmap='coolwarm')
plt.title("Local Outlier Factor (LOF) Anomaly Detection")
plt.xlabel("Feature 1")
plt.ylabel("Feature 2")
plt.show()
- Derivative (기울기, 변화량) 기반 탐지 ⇒ diff 많이써요
- 개념: 값 자체가 아니라, 변화량에 이상 탐지 적용
- 활용 예시:
- 5초 내에 온도가 10도 이상 급등 → 이상
- 전류가 1초에 3A 이상 급격히 상승
import numpy as np
import matplotlib.pyplot as plt
# 예시 시계열: 100 이후 급변
data = np.concatenate([
np.linspace(0, 1, 100),
np.linspace(1, 10, 20),
np.linspace(10, 11, 80)
])
# 변화량(기울기) 계산
gradient = np.diff(data)
threshold = 0.1 # 기울기 임계값
# 이상 지점 감지
anomalies = np.where(np.abs(gradient) > threshold)[0]
# 시각화
plt.figure(figsize=(10, 4))
plt.plot(data, label="Signal")
plt.scatter(anomalies, data[anomalies], color='red', label="Anomalies")
plt.title("Derivative-based Anomaly Detection")
plt.legend()
plt.grid(True)
plt.show()
변화량(기울기)을 감시하면 정상 범위 안의 급격한 변화도 잡을 수 있음
- Moving Average + Change Point Detection
- 기법: 일정 구간의 평균/분산과 현재 값을 비교 → 급변 시점 감지
- 도구: ruptures, changefinder, Bayesian Change Point
import numpy as np
import ruptures as rpt
import matplotlib.pyplot as plt
# 시계열 신호 생성
signal = np.concatenate([
np.random.normal(1, 0.1, 100),
np.random.normal(5, 0.1, 100),
np.random.normal(3, 0.1, 100)
])
# 모델 및 알고리즘 선택
model = "rbf" # 비선형 변화 감지
algo = rpt.Pelt(model=model).fit(signal)
result = algo.predict(pen=10) # pen 값으로 민감도 조절
# 시각화
rpt.display(signal, result)
plt.title("Ruptures - Change Point Detection")
plt.show()
이동 평균(Moving Average) 기반의 간단한 이상치 탐지(Anomaly Detection)
import numpy as np
import matplotlib.pyplot as plt
# 예시 시계열
data = np.concatenate([
np.random.normal(0, 0.1, 100),
np.random.normal(3, 0.1, 100)
])
# 이동 평균
window = 10
moving_avg = np.convolve(data, np.ones(window)/window, mode='same')
# 이동 평균 기준 변화량 계산
diff = np.abs(data - moving_avg)
threshold = 0.5 # 변화량 기준
# 이상 지점
anomalies = np.where(diff > threshold)[0]
# 시각화
plt.figure(figsize=(10, 4))
plt.plot(data, label="Signal")
plt.plot(moving_avg, label="Moving Average", linestyle='--')
plt.scatter(anomalies, data[anomalies], color='red', label="Anomalies")
plt.title("Moving Average + Change Detection")
plt.legend()
plt.grid(True)
plt.show()
ChangeFinder 알고리즘을 사용한 이상 탐지 / 변화 탐지
방식과는 다르게, 실시간환경에 적합하고, 통계 기반으로 설계된 알고리즘
import changefinder
import numpy as np
import matplotlib.pyplot as plt
# 시계열 데이터 생성
data = np.concatenate([
np.random.normal(1, 0.1, 100),
np.random.normal(5, 0.1, 100),
np.random.normal(3, 0.1, 100)
])
# ChangeFinder 초기화
cf = changefinder.ChangeFinder(r=0.01, order=1, smooth=5)
# 점수 계산
scores = [cf.update(d) for d in data]
# 시각화
plt.figure(figsize=(10, 4))
plt.plot(data, label="Signal")
plt.plot(scores, label="Anomaly Score")
plt.title("ChangeFinder - Anomaly Detection")
plt.legend()
plt.show()
CUSUM (Cumulative Sum Control Chart) 알고리즘을 이용한 변화 탐지 (Change Detection)
CUSUM은 통계적 공정 관리(SPC)에서도 많이 쓰이며, 평균이 갑자기 변하는 시점을 빠르게 포착할 수 있는 강력한 방법
import numpy as np
import matplotlib.pyplot as plt
# 예제 데이터
data = np.concatenate([
np.random.normal(0, 1, 100),
np.random.normal(4, 1, 100)
])
target_mean = np.mean(data[:50])
k = 0.5 # 민감도 조절
h = 5 # 임계값
cusum_pos = [0]
cusum_neg = [0]
anomalies = []
for i in range(1, len(data)):
s_pos = max(0, cusum_pos[-1] + data[i] - target_mean - k)
s_neg = max(0, cusum_neg[-1] - data[i] + target_mean - k)
cusum_pos.append(s_pos)
cusum_neg.append(s_neg)
if s_pos > h or s_neg > h:
anomalies.append(i)
plt.plot(data, label="Signal")
plt.scatter(anomalies, data[anomalies], color="red", label="Change Detected")
plt.title("CUSUM Change Detection")
plt.legend()
plt.show()
Variance-based Rule
Variance-based Rule은 일정한 기간(슬라이딩 윈도우 또는 구간) 동안의 분산(혹은 표준편차) 을 계산하고, 그 분산이 사전에 설정한 임계값(threshold)을 초과하면, “여기서 뭔가 변화가 생겼다(또는 이상하다)”라고 판단하는 방식
왜 분산을 기준으로 삼는가?
- 정상 구간은 일반적으로 분산이 작고 일정합니다.
- 이상 구간은 평균이 바뀌거나, 급격한 값의 진동이 생기며 분산이 커집니다.
- 따라서 분산이 갑자기 튀는 지점을 이상 또는 변화점으로 탐지할 수 있습니다.
1. 일정 길이의 윈도우를 설정 (예: 20개 샘플)
2. 각 윈도우마다 분산(variance) 또는 표준편차(std)를 계산
3. 기준 분산 또는 임계값과 비교
4. 기준보다 높으면 이상 or 변화점으로 판단
import numpy as np
import matplotlib.pyplot as plt
# 정상 데이터 + 분산 증가
data = np.concatenate([
np.random.normal(10, 0.2, 100),
np.random.normal(10, 2.0, 100) # 분산이 급격히 증가
])
# 이동 분산 계산 (rolling window)
window = 20
variances = [np.var(data[i-window:i]) if i >= window else 0 for i in range(len(data))]
# 임계값 기준 이상 감지
threshold = 1.0
anomalies = np.where(np.array(variances) > threshold)[0]
# 시각화
plt.figure(figsize=(10, 4))
plt.plot(data, label="Signal")
plt.plot(variances, label="Rolling Variance", color='orange')
plt.scatter(anomalies, data[anomalies], color='red', label="Variance-based Anomaly")
plt.title("Variance-based Rule Detection")
plt.legend()
plt.grid(True)
plt.show()
Gaussian Tail Probability
정규분포(Gaussian distribution) 를 따르는 데이터에서,
평균으로부터 특정 거리 이상 떨어진 값이 나올 확률
이 확률은 곧 "이 값이 정상 구간 밖에 있을 가능성" 이며,
일종의 이상치(outlier) 점수로 활용할 수 있어요.
- 이상치 탐지: 꼬리 확률이 매우 작으면 "이 값은 정상 분포에서 거의 안 나오는 값 → 이상"
- p-value 계산: 통계 검정에서 유의확률(p-value)을 계산할 때도 tail probability 사용
확률적 스코어링: 확률 기반 이상 탐지에 사용
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm
x = np.linspace(-5, 5, 1000)
y = norm.pdf(x, 0, 1)
plt.plot(x, y, label='Gaussian PDF')
plt.fill_between(x, y, where=(x > 2), color='red', alpha=0.3, label='Right Tail (Z > 2)')
plt.fill_between(x, y, where=(x < -2), color='blue', alpha=0.3, label='Left Tail (Z < -2)')
plt.title("Gaussian Tail Probability")
plt.legend()
plt.grid(True)
plt.show()

'QAQC_5기 부트캠프 > 시계열 데이터' 카테고리의 다른 글
| [내일배움캠프] QA/QC_5기 본캠프(0526) - 1 (0) | 2026.05.26 |
|---|



