빅데이터 QAQC_3기/빅데이터 QAQC_3기 TIL

TIL_251119

usungusung 2025. 11. 19. 22:35

Today I learned

 

 

1. 시계열과 MLops 1회차 퀴즈

 

1. 시계열 데이터의 정의와 특징

- 시계열 데이터는 순서를 섞으면 안된다.

- 시간에 따라 정렬된 데이터로, 순서를 섞게 되면 모델이 올바른 패턴(시간 종속성)을 학습할 수 없다.

 

2. 시계열 구성 요소

- 계절성: 일정한 경향에 따라 반복되는 패턴

 

3. 계절성 vs 주기성

- 계절성: 일정한 간격으로 반복되며, 규칙적이고 1년 이내의 짧은 범위에서 발생

- 주기성: 불규칙적으로 발생하며, 수 년의 장기적인 시간 범위를 가짐

 

4. 시계열 예측 vs 머신러닝 예측

- 시계열 분석은 주로 '시간'과 '측정값' 단 2개의 데이터로 이루어져 있음

- 과거의 값 자체가 피처 역할을 함

 

5. 시계열 분해와 잔차

- 잔차는 추세와 계절성을 제거한 후 남는 무작위적 변화량을 말함.

- 시계열 분해는 패턴 파악에 동무을 주며, Prophet이나 statsmodel은 시계열 분해 기능을 제공함

 

2. 태블로 활용 1회차

 

3. [라이브세션] 시계열 2회차: 확률 보행과 정상성

공분산의 개념을 시계열에 적용하기

 

 

(1) 확률 보행(Random Walk)

  • 시간이 지남에 따라 뭊가위로 이동하는 경로를 설명하는 수학 모델
  • 평균과 분산이 시간에 따라 일정하지 않은 비정상 시계열

확률 보행은 확률이 개입하는 다양한 현상을 설명하는 데 필수적인 모델

 

  • yt = 현재값
  • yt-1 = 이전 시간 단계의 값
  • C = 상수, 시계열이 가지는 평균 값
  • et = 백색소음: 표준정규분포(분산1, 평균0)을 따르는 난수, 시게열에 포함된 무작위성 요소

 

(2) 정상(Normal)이 아닌 정상(Stationary)

 

정상성?

시계열의 통계적 성질이 시간에 따라 변하지 않는 상태

 

 

 

정상 시게열의 정의와 조건 3가지

위: 비정상 시계열, 아래: 정상 시게열

 

 

- 시계열의 평균이 시간에 따라 변하지 않고 일정함

 

∀t : 모든 시간에 대하여

 

- 시계열의 분산이 시간에 따라 일정함

- 시계열의 두 시점 간 공분산이 시간 t에 의존하지 않고 시간의 차 h 에만 의존함

 

 

- 공분산?

Lesson 1: 공분산 이해하기

  1. x의 표준편차
  2. x와 y의 공분산
  3. x와 y의 상관관계
  4. 시점 t와 시점 t-1의 공분산

1.1. 표준편차

  • 개념: 데이터가 평균으로부터 평균적으로 떨어진 거리입니다.
  • 수식
  • xi: 각 데이터, x¯: 평균, n: 데이터 개수
  • 결과: 생성된 임의 데이터 x의 표준편차는 약 1.82입니다.
# 예제 데이터 생성
# numpy 라이브러리 기
x = np.random.normal(loc=10, scale=2, size=100)

# 표준편차 계산
std_x = np.std(x, ddof=1)
print(f"x의 표준편차: {std_x:.2f}")
 
sns.histplot(x, kde=True)
plt.axvline(np.mean(x), color='red', linestyle='--') # 평균선
# 예제 데이터 생성
# numpy 라이브러리 기
x = np.random.normal(loc=10, scale=20, size=100)

# 표준편차 계산
std_x = np.std(x, ddof=1)
print(f"x의 표준편차: {std_x:.2f}")
표준편차를 20으로 늘렸어용
sns.histplot(x, kde=True)
plt.axvline(np.mean(x), color='red', linestyle='--') # 평균선
 
 

1.2. x와 y의 공분산

  • x y 두 변수가 같이 움직이는 패턴을 봅니다. 공분산은 각 데이터가 평균(x¯,y¯)을 기준으로 어떤 사분면에 위치하는지의 합입니다.
  • 수식

# 1. 데이터 생성 (앞 단계와 동일)
np.random.seed(42)
x = np.random.normal(loc=10, scale=2, size=100)
# y는 x와 양의 관계 + 노이즈
y = 2 * x + np.random.normal(loc=0, scale=3, size=100)

np.cov(x, y)
array([[ 3.29907957,  5.88923399],
       [ 5.88923399, 18.54597814]])
# 2. 공분산 계산
# rowvar=False로 설정하지 않으면 기본적으로 각 행을 변수로 봅니다.
# 여기서는 1차원 배열이므로 np.cov(x, y)를 하면 2x2 행렬이 나옵니다.
cov_matrix = np.cov(x, y)

# [0, 1] 또는 [1, 0] 위치가 x와 y의 공분산입니다.
cov_xy = cov_matrix[0, 1]
print(f"x와 y의 공분산: {cov_xy:.2f}")

# 3. 시각화 (사분면 강조)
plt.figure(figsize=(6, 6))
sns.scatterplot(x=x, y=y)

# 평균선 그리기 (사분면 기준)
plt.axvline(np.mean(x), color='red', linestyle='--', label='Mean X')
plt.axhline(np.mean(y), color='black', linestyle='--', label='Mean Y')

plt.title(f'Covariance Structure\nCov: {cov_xy:.2f}')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.show()

 
x와 y의 공분산: 5.89
 
  • 시각화 설명 (우측 상단 그래프):점선이 교차하는 지점이 두 변수의 평균(x¯,y¯)
  • (1, 3사분면): (xx¯) (yy¯)의 부호가 같아 곱이 양수(+). 이곳에 점이 많으면 공분산은 양수가 됩니다.
  • (2, 4사분면): 부호가 반대라 곱이 음수(-)
  • 이 그래프에서는 대다수의 점이 (우상향 대각선)에 있으므로, 양의 공분산

 

사실 상관계수와 비슷해요

1.3. x와 y의 상관계수

  • 공분산은 데이터의 단위(cm, m 등)에 따라 값이 달라지므로, 이를 표준화하여 -1과 1 사이의 값으로 바꿉니다.
  • 수식

# 1. Data Generation (same as previous steps)
np.random.seed(42)
x = np.random.normal(loc=10, scale=2, size=100)
y = 2 * x + np.random.normal(loc=0, scale=3, size=100)

# 2. Standardization for Correlation Plot
x_std = (x - np.mean(x)) / np.std(x, ddof=1)
y_std = (y - np.mean(y)) / np.std(y, ddof=1)
cov_xy = np.cov(x, y)[0, 1]
corr_xy = np.corrcoef(x, y)[0, 1]

# 3. Plotting side-by-side
fig, axes = plt.subplots(1, 2, figsize=(14, 6))

# Plot 1: Covariance (Original Scale)
sns.scatterplot(x=x, y=y, ax=axes[0], s=60, alpha=0.7)
axes[0].axvline(np.mean(x), color='black', linestyle='--', label=f'Mean X ({np.mean(x):.1f})')
axes[0].axhline(np.mean(y), color='black', linestyle='--', label=f'Mean Y ({np.mean(y):.1f})')
axes[0].set_title(f'2. Covariance (Original Scale)\nCov = {cov_xy:.2f}')
axes[0].set_xlabel('x')
axes[0].set_ylabel('y')
axes[0].legend()

# Plot 2: Correlation (Standardized Scale)
sns.scatterplot(x=x_std, y=y_std, ax=axes[1], color='orange', s=60, alpha=0.7)
axes[1].axvline(0, color='grey', linestyle='--')
axes[1].axhline(0, color='grey', linestyle='--')
axes[1].set_title(f'3. Correlation (Standardized Scale)\nCorr = {corr_xy:.2f}')
axes[1].set_xlabel('Standardized x (Z-score)')
axes[1].set_ylabel('Standardized y (Z-score)')
axes[1].axis('equal') # Important to show the scaling effect

plt.tight_layout()
plt.savefig('cov_corr_comparison.png')

 
 

좌: 공분산, 우: 상관관계 비슷하쥬??

  • 왼쪽과 오른쪽 그래프는 완전히 동일한 데이터를 사용. 차이점은 축의 스케일(단위) 뿐
  • 왼쪽: 공분산 (Covariance)데이터
    • 원래 데이터 x, y 그대로 사용.
    • 중심: 데이터의 평균 (x¯,y¯) 인 약 (10, 20) 지점에 십자선
    • 의미: x,y가 평균으로부터 같은 방향(1, 3사분면)으로 움직이는 경향이 강해서 공분산이 양수(5.89)가 나옵니다. 하지만 이 값(5.89)만 봐서는 관계가 얼마나 강한지 알기 어렵습니다. (단위에 따라 값이 변함)
  • 오른쪽: 상관관계 (Correlation)데이터
    • 평균을 0, 분산을 1로 맞춘 표준화된 데이터 사용.중심: 무조건 (0, 0)이 중심입니다.
    • 의미: 단위를 제거했기 때문에 기울기와 퍼짐 정도가 정규화. 여기서 구해진 상관계수(0.75)는 절대적인 척도로 사용할 수 있음 (1에 가까울수록 강한 양의 관계)이 비교를 통해 "상관관계는 공분산을 표준화하여 보기 좋게 만든 버전"임을 이해할 수 있음

1.4. 시점 t와 시점 t-h의 간의 공분산

-4분기 마다 존슨앤존슨의 주당 수익

 

 

 

- 분기별로 똑같은 흐름이 나타나는 것이 합리적이다 라고 생각을 해보자.

1960년 1월 1일 ~ 1960년 12월 1일 ~ 12월 1일 까지의 흐름이 비슷할 것이라고 보는게 정상시계열

# 1. Load Data
df = pd.read_csv('/content/TimeSeriesForecastingInPython/data/jj.csv')

# --- Part 1: Lag 4 (h=4) Data Construction and Visualization ---

# Create Lag 4 Data
df['t'] = df['data']
df['t-4'] = df['data'].shift(4)

# 데이터가 4개씩 밀려있는것 확인
df.head(20)
# Drop NaNs for calculation and plotting
df_lag4 = df[['t', 't-4']].dropna()


# Calculate Covariance for Lag 4
cov_lag4 = np.cov(df_lag4['t'], df_lag4['t-4'])[0, 1]

# --- Part 2: Autocovariance Function (Lags 0 to 20) ---

lags = range(21)
covariances = []

for h in lags:
    if h == 0:
        cov = np.var(df['data'], ddof=1)
    else:
        # Slice data for lag h
        y_t = df['data'][h:]
        y_t_h = df['data'][:-h]
        cov = np.cov(y_t, y_t_h)[0, 1]
    covariances.append(cov)

# --- Visualization ---
fig, axes = plt.subplots(1, 2, figsize=(16, 6))

# Plot 1: Scatter Plot for Lag 4
sns.scatterplot(x='t-4', y='t', data=df_lag4, ax=axes[0], color='magenta', s=80, alpha=0.7)
mean_t = df_lag4['t'].mean()
mean_t4 = df_lag4['t-4'].mean()
axes[0].axvline(mean_t4, color='black', linestyle='--')
axes[0].axhline(mean_t, color='black', linestyle='--')
axes[0].set_title(f'1. Lag-4 Scatter Plot (h=4)\nCovariance: {cov_lag4:.2f}')
axes[0].set_xlabel('Value at t-4 (4 quarters ago)')
axes[0].set_ylabel('Value at t (Current)')

# Plot 2: Autocovariance by Lag
axes[1].stem(lags, covariances, basefmt=" ")
axes[1].set_title('2. Autocovariance by Lag (h=0 to 20)')
axes[1].set_xlabel('Lag (h)')
axes[1].set_ylabel('Covariance')
axes[1].set_xticks(lags)
axes[1].grid(True, axis='y', linestyle='--', alpha=0.7)

# Highlight Lag 4 on the Autocovariance Plot
axes[1].plot(4, covariances[4], 'ro', markersize=10, label='Lag 4')
axes[1].legend()

plt.tight_layout()
plt.savefig('lag4_and_autocovariance.png')

# Print results
print(f"시차 4 (Lag 4) 공분산: {cov_lag4:.4f}")
print(f"시차별 공분산 (0~5): {[round(c, 2) for c in covariances[:6]]}")
 
 
  1. 시차 4 (h=4)일 때의 데이터와 공분산이제 현재 시점 t와 4분기(1년) 전 시점 t-4의 관계를 봅니다. jj.csv는 분기별 데이터이므로, 시차 4는 정확히 '작년 이맘때'와의 비교를 의미합니다.
  • 산점도 (왼쪽 그래프):
    • 패턴: 직선에 더 가깝게 모여 있는 것을 볼 수 있습니다.
    • 공분산 값: 약 16.19
    • 해석: 1년 전 실적(t-4)과 현재 실적(t)은 매우 강한 양의 상관관계를 가집니다. 이는 계절성(Seasonality)이 뚜렷함을 시사합니다.
  1. 시차별 공분산 그래프 (Autocovariance Function)
  • 오른쪽 그래프에서 빨간색 점으로 표시된 부분이 Lag 4의 공분산 위치
  • 그래프 해석
    • Lag 4의 공분산(16.19)은 Lag 5(15.25)보다 약간 더 높음.보통 계절성이 있는 데이터는 주기(여기서는 4)마다 상관성이 튀어 오르는 경향이 있는데, 이 데이터는 전체적인 추세(우상향)가 너무 강해서 계절성보다는 추세의 영향이 지배적으로 나타나고 있음 또한, 모든 시차에서 공분산이 매우 높음

 

(3) 정상성 확보를 위한 데이터 변환 기법

- 차분(Differencing)

시계열에서 추세 및 계절성을 제거하기 위한 방법

특정 시점과 그 직전 시점 사이 발생하는 일련의 변화를 계산

  • yt: 원본 데이터
  • yt' : 차분 후 데이터

분산 안정화

  • 로그 변환
    • 시계열 데이터의 분산을 안정화하여 효과적, 큰 값을 축소시켜 분산의 변동을 줄임
  • 제곱근 변환
    • 분산을 줄이는 방법으로, 양수 데이터를 대상으로 사용
  • z-score 표준화
    • 데이터의 평균과 분산을 일정하게 만들기 위해 표준화를 사용
    • 평균 0, 분산 1
  • Box-Cox 변환
    • 분산을 안정화 할 뿐만 아니라 데이터의 정규성을 보장하는 데도 유용

 

(4) 정상 시계열 검정방법

- ADF 검정과 단위근(Unit root)

  • 본격적인 모형을 적용하기 전에, 시계열 데이터가 정상성을 만족하는지 검정 필요
  • ADF(Augmented Dickey Fuller)는 단위근의 존재 여부를 테스트하여 시계열의 정상성 여부를 판단
  • **단위근(Unit Root)**이란 자기회귀 계수 $\phi$가 1인 경우를 말함

 

  • $H_0$: 시계열에 단위근(unit root)이 존재한다. 즉, 시계열이 비정상 시계열이다.
  • $H_1$: 데이터에서는 단위근이 존재하지 않는다. 즉, 정상 시계열이다.
  • [참고]ADF 에 대한 식$$ \Delta y_t = \alpha + \rho y_{t-1} + \epsilon_t $$
    • $\Delta y_t$: $y_{t} - y_{t-1}$, 차분 값
    • $\alpha$: 상수항
    • $\rho$(”로우”): 자기회귀계수, 현재 시계열데이터가 이전시점 값에 의존하는 정도
      • if 자기회귀 계수 $\rho=1$ : 단위근 있음, 비정상 시계열
      • if 자기회귀 계수 $\rho=0$: 단위근 없음 ,정상시계열
  • ADF 테스트는 다음과 같은 수식을 기반으로 시계열 데이터의 정상성을 평가

'빅데이터 QAQC_3기 > 빅데이터 QAQC_3기 TIL' 카테고리의 다른 글

TIL_251121  (1) 2025.11.21
TIL_251120  (0) 2025.11.20
TIL_251118  (0) 2025.11.18
TIL_251117  (0) 2025.11.17
TIL_251114  (0) 2025.11.14