콘텐츠로 이동

방법론 - Load Forecasting for Households and Energy Communities

이 문서는 "Load Forecasting for Households and Energy Communities: Are Deep Learning Models Worth the Effort?" 논문에서 발췌한 주요 방법론과 수식을 정리한 것입니다.

1. 에너지 커뮤니티(EC) 구성 및 데이터셋

  • 데이터 소스: UK Power Networks 스마트 미터 데이터 (런던 4,500 가구).
  • EC 구성 (Aggregation): 1, 2, 10, 50, 100 가구를 무작위로 선택하여 가상 EC를 구성. (가구 수가 많아질수록 부하 프로파일이 평활화(Smoothing)되어 예측 오차가 감소함).
  • 입력 피처 (Input Features):
    • 시간 정보: 요일(One-hot), 시간(Cyclical sine/cosine), 연중 일자(Cyclical).
    • 지연 부하 (Lagged Load): 1주, 2주, 3주 전의 동일 시간 부하 (가장 높은 상관관계 확인).
    • 기상 데이터: 기온, 이슬점, 풍향, 풍속, 기압, 상대습도 (Meteostat 활용).

2. 예측 모델링 방법론

  • Deep Learning:
    • LSTM / xLSTM (Extended LSTM): 시계열 데이터의 장기 의존성 학습. 특히 xLSTM은 Transformer에 필적하는 성능과 선형적인 메모리 확장이 장점.
    • Transformer (Encoder-only): 장거리 의존성 및 병렬 계산에 최적화.
  • Benchmarks:
    • Persistence Forecasting (지속성 모델): 7일 전의 부하를 오늘 부하로 예측 (Baseline).
    • K-Nearest Neighbors (KNN): 과거 40개의 유사한 시간대 부하의 가중 평균 활용.

3. 전이 학습 (Transfer Learning) 기법

  • 핵심 이론: 데이터가 부족한 신규 EC(2~6개월 미만 데이터)의 경우, 공개된 합성 부하 프로파일(Synthetic Load Profiles)을 사용하여 모델을 사전 학습(Pre-training)함.
  • 도구: Python demandlib (독일 표준 부하 프로파일 생성기).
  • 효과: 2개월치 데이터만 있을 때 nMAE를 약 1.97%p 개선.

4. MILP 기반 ESS 최적 제어 (Peak Shaving 및 비용 최적화)

공유 배터리 시스템(BESS)을 활용하여 EC의 에너지 비용을 최소화하는 혼합 정수 선형 계획법(MILP) 모델입니다.

목적 함수 (Objective Function)

일일 전기 요금(\(\pi_p\)) 최소화: $\(\min_{P_{ch}, P_{dis}} \sum_{p \in P} P_{grid,p} \cdot \pi_p \cdot \Delta t\)$

주요 제약 조건 (Constraints)

  1. 전력 수지 평형 (Power Balance): $\(P_{grid,p} + P_{dis,p} = P_{ch,p} + \hat{P}_{load,p}\)$
  2. 역전송 방지 및 완충 (Grid Buffer): $\(P_{grid,p} \geq 0.15 \cdot \hat{P}_{load,p}\)$ (예측된 부하보다 실제 부하가 낮을 때 BESS 방전 에너지가 그리드로 역송되는 것을 방지)
  3. 배터리 에너지 상태 (SoC Update): $\(E_{p+1} - E_p = (\eta_{ch} P_{ch,p} - \frac{P_{dis,p}}{\eta_{dis}}) \cdot \Delta t\)$
  4. 동시 충방전 방지 (Binary variables): $\(0 \leq P_{ch,p} \leq b_{ch,p} P_{max}\)$ $\(0 \leq P_{dis,p} \leq b_{dis,p} P_{max}\)$ $\(b_{ch,p} + b_{dis,p} = 1\)$

5. 피크 부하 분석을 위한 시사점

  • 규모의 효과: EC 가구 수가 증가할수록 피크 부하의 변동성이 감소하며 예측 모델의 성능 차이도 좁혀짐 (100가구 기준 nMAE 8%대).
  • 예측 민감도: 실시간 요금(RTP) 기반 시프팅은 가격 신호에 의존적이지만, Peak Load Reduction(피크 저감)이나 Self-sufficiency(자급률) 향상을 목표로 할 때는 고품질의 예측이 훨씬 더 결정적인 역할을 함.

6. 원문 변수 및 수식 정의 (Original Definitions)

논문에서 사용된 MILP 모델의 원어 변수명과 수식 정의입니다.

변수 정의 (Variables)

  • \(p \in \mathcal{P}\): 시구간(Periods), \(\mathcal{P} = \{0, \dots, 23\}\)
  • \(t \in \mathcal{T}\): 시점(Time points), \(\mathcal{T} = \{0, \dots, 24\}\)
  • \(E_t\): \(t\) 시점의 BESS 에너지 보유량 (State variable)
  • \(P_{ch,p}, P_{dis,p}\): \(p\) 구간의 충전 및 방전 전력 (Process variables)
  • \(\hat{P}_{load,p}\): \(p\) 구간의 예측된 전력 부하
  • \(P_{grid,p}\): \(p\) 구간의 그리드 구매 전력
  • \(\pi_p\): \(p\) 구간의 실시간 전기 요금 (RTP)
  • \(\eta_{ch}, \eta_{dis}\): 충전 및 방전 효율 (각각 92.2%)

수식 정의 (Formulations)

  1. 목적 함수 (Objective): $\(\min_{P_{ch}, P_{dis}} \sum_{p \in \mathcal{P}} P_{grid,p} \cdot \pi_p \cdot \Delta t\)$
  2. 그리드 전력 제약 (Grid Power Balance): $\(P_{grid,p} = P_{ch,p} - P_{dis,p} + P_{load,p}\)$
  3. 그리드 버퍼 (Grid Buffer - Eq. 7): $\(P_{grid,p} \geq 0.15 \cdot \hat{P}_{load,p}\)$ (역송 방지용 안전 마진)
  4. 에너지 상태 전이 (SoC Update - Eq. 9): $\(E_{t+1} = E_t + (\eta_{ch} P_{ch,p} - \frac{P_{dis,p}}{\eta_{dis}}) \cdot \Delta t\)$

Case Study Code (by Gemini)

import pulp
import numpy as np

def optimize_bess_cost(load_forecast, prices, num_households=10):
    """
    논문의 MILP 모델을 기반으로 한 BESS 최적화 함수
    """
    # 1. 파라미터 설정
    T = len(load_forecast)  # 보통 24시간
    dt = 1.0  # 시간 단위

    # BESS 사양 (논문 기준)
    cap_per_hh = 12.0  # 가구당 12kWh
    total_capacity = cap_per_hh * num_households
    max_power = total_capacity * 0.25  # C-rate 0.25
    eta_ch = 0.922  # 충전 효율
    eta_dis = 0.922 # 방전 효율
    soc_min = 0.1 * total_capacity # 최소 SOC (가정)
    soc_max = 0.9 * total_capacity # 최대 SOC (가정)

    # 2. 문제 정의 (비용 최소화)
    prob = pulp.LpProblem("EC_Cost_Minimization", pulp.LpMinimize)

    # 3. 결정 변수
    p_ch = [pulp.LpVariable(f"p_ch_{t}", lowBound=0, upBound=max_power) for t in range(T)]
    p_dis = [pulp.LpVariable(f"p_dis_{t}", lowBound=0, upBound=max_power) for t in range(T)]
    p_grid = [pulp.LpVariable(f"p_grid_{t}", lowBound=0) for t in range(T)]
    e_bess = [pulp.LpVariable(f"e_bess_{t}", lowBound=soc_min, upBound=soc_max) for t in range(T + 1)]

    # 4. 목적 함수: Sum(P_grid * Price * dt)
    prob += pulp.lpSum([p_grid[t] * prices[t] * dt for t in range(T)])

    # 5. 제약 조건
    # 초기 에너지 상태 (50% 가정)
    prob += e_bess[0] == 0.5 * total_capacity

    for t in range(T):
        # 전력 수지 평형 (Eq 6/22): P_grid = P_ch - P_dis + P_load
        prob += p_grid[t] == p_ch[t] - p_dis[t] + load_forecast[t]

        # 배터리 에너지 업데이트 (Eq 9): E(t+1) = E(t) + (P_ch*eta - P_dis/eta)*dt
        prob += e_bess[t+1] == e_bess[t] + (p_ch[t] * eta_ch - p_dis[t] / eta_dis) * dt

        # 역송 방지 버퍼 (Eq 7): P_grid >= 0.15 * P_load_forecast
        prob += p_grid[t] >= 0.15 * load_forecast[t]

    # 마지막 시간 SOC가 초기와 같게 설정 (지속 가능 운영 가정)
    prob += e_bess[T] >= e_bess[0]

    # 6. 최적화 실행
    prob.solve(pulp.PULP_CBC_CMD(msg=0))

    # 7. 결과 정리
    if pulp.LpStatus[prob.status] == 'Optimal':
        total_cost = pulp.value(prob.objective)
        grid_usage = [pulp.value(p_grid[t]) for t in range(T)]
        return total_cost, grid_usage
    else:
        return None, None