Professional Field

ETL : Airflow / DW(Snowflake) | AI : Python | BI : Tableau / Power BI

Portfolio

[DL] RNN / LSTM 태양광 발전량 예측 모델

K_CY 2024. 7. 12. 10:14
  • 프로젝트 추진 배경

위 [그림]을 보면 연간 연료원별 발전비중을 나타낸 차트를 보면 해가 지날수록 신재생에너지(초록색) 영역이 넓어지는 모습이 보이며, 2019년도 신재생에너지 발전설비 비중은 전체의 13%로 증가하였다. 그리고 이를 에너지원별로 다시 쪼개보면 전체 신재생에너지의 67%를 태양광이 차지했으며 풍력(10%), 일반수력(10%), 바이오/매립가스(6%)가 그 뒤를 이음을 알 수 있다. 
 
 또한, 2017년 29,802대였던 국내 발전설비는 이후 연마다 33.6%, 54.7% 증가하여 2019년 61,603대가 되었다. 이 중 태양광 발전설비는 60,433대로 전체 발전설비 숫자의 대부분을 태양광 발전설비가 차지하고 있다는 것을 확인할 수 있다. 이처럼 태양광발전 설비와 기술력이 발전함에 따라 태양광 발전 시장 구조가 커져가고 있는 현황이다. 
 
 이렇듯 시장이 커져가면서 태양광에 관련된 사업들이 점차 늘어나고 있다.

 

  • 국내 태양광 활용 사례
  • 태양광가로등: 태양광을 받아 생산하는 시간에 사용하는 것이 아닌, 생산이 되지 않는 밤 시간대에 사용하게 되는 시설물. 태양광으로 생산된 전기를 저장하는 에너지 저장장치를 함께 설치하여 사용하면, 낮에는 태양광에너지를 생산하고, 밤에는 그 에너지를 사용하여 불을 밝힐 수 있다.
  • 자립마을: 섬이나 산등기존에 전기가 들어오기 힘들었던 곳에서도 태양광을 활용하여 자체 생산하여 전기를 사용할 수 있게 되면서 태양광에너지를 활용한 자립마을이 생겨나고 있다.
  • 주식회사 해줌: 해줌은 태양광 발전량 예측 기술을 가진 기업이다. 머신러닝을 이용해 72시간 뒤 미래까지의 태양광발전량을 예측하는 기술을 갖고 있고, 이 기술을 사용하여 태양광발전소의 이상감지와 원인진단, 수익성을 예측하는 시스템을 운영하고 있다. 제공되는 시스템을 더 자세히 알아보면, 기후데이터를 이용한 월별 평균발전량으로 수익성을 예측하고, 과거 기상자료를 통해 시뮬레이션을 돌려보며 발전량과 수익분석을 실행하고 있다. 또한, 예측한 정상 발전량패턴에서 벗어난 이상치들을 감지하여 대처하는 시스템도 지원하고 있다.
  • 프로젝트 주요 개발 내용

1) 데이터 및 변수 소개

분석은 8개의 input데이터와 1개의 output 데이터를 가지고 30분 간격(하루 = 48개의 데이터)으로 관측한 데이터로 예측 값을 구했다.

 

Hour 시간
Minute
DHI 수평면 산란일사량(Diffuse Horizontal Irradiance (W/m2))
DNI 직달일사량(Direct Normal Irradiance (W/m2))
WS 풍속(Wind Speed (m/s))
RH 상대습도(Relative Humidity (%))
T 기온(Temperature (Degree C))
Target 태양광 발전량 (kW)

2) 활용 라이브러리 소개

  • Tensorflow
  • Keras
  • Pandas
  • Scikit-learn

3) 데이터 전처리

  • Train, Test set 나누기
from sklearn.model_selection import train_test_split

x_train, x_valid, y_train, y_valid = train_test_split(train_x, train_y, test_size=0.2)



x_train.shape, x_valid.shape

 

  • 정규화 처리
    정규화 과정은 숫자 데이터의 상대적인 크기 차이를 제거해주는 과정이다. 데이터의 범위가 각 column마다 다른 상태로 데이터를 분석하면, 상대적 크기의 차이로 인해 분석결과가 달라질 수 있다.
sc = MinMaxScaler() #정규화

test_data1=sc.fit_transform(test_data)

test_data=pd.DataFrame(test_data1,columns=test_data.columns)

  • 슬라이딩 윈도우
  • 시계열 데이터를 활용한 예측 모델을 만들 때 방법 중 하나인 슬라이딩 윈도우(Sliding Window)이다.
    위 그림을 참고하여 설명하면, 빨간색 네모칸이 ‘윈도우’, 그리고 옆으로 이동하는 칸의 수가 ‘스텝’이다.이 기법을 활용하여 예측 모델을 만들면, 모델에 학습에 들어가게 되는 data set의 수가 늘어나고 더 정교한 예측을 할 수 있어 정확도가 높아지는 효과가 있다.
  • 윈도우(Window)의 크기와 스텝(Step)의 크기를 정하면, 윈도우 사이즈 만큼 데이터가 묶이고 스텝의 크기만큼 데이터가 이동한다.
def make_dataset(data, label, window_size):

feature_list = []

label_list = []

for i in range(len(data) - window_size-96):

        feature_list.append(np.array(data.iloc[i:i+window_size]))

        label_list.append(np.array(label.iloc[i+window_size :i+window_size+96 ]))

return np.array(feature_list), np.array(label_list)

 

이번 프로젝트에서 과거 7일의 데이터로 미래 2일을 예측하고자 했기 때문에 윈도우 사이즈는 336(7일* 48개/일), 스텝 크기는 1으로 지정했다.

  • 변수 선택과정

독립변수를 통계분석을 통해 결정하기 위해 회귀분석의 최조제곱추정법과 다중공선성을 확인하였다.

 

-다중공선성

a_data.corr() # 다중공선성 확인

cmap = sns.light_palette("darkgray", as_cmap = True)

sns.heatmap(a_data.corr(), annot = True, cmap = cmap)

plt.show()



vif=pd.DataFrame() # VIF지표 

vif["VIF Factor"]=[variance_inflation_factor(a_data.values, i) for i in range(a_data.shape[1])]

vif['features'] = a_data.columns

독립변수들은 종속변수하고만 상관 관계가 있어야 선형적인 관계가 있는데, 만약 독립변수끼리 상관관계가 있다면 부정적인 결과가 도출이 된다. 독립변수 간 상관관계를 보이는 것을 다중공선성(Multicollinearity)라고 한다.

다중공선성을 확인하기 위해 Vif와 Correlation 지표를 사용하였다.
처음에는 과거에 태양광 발전량 수치가 다음날의 발전량을 예측하는 것에 좋은 변수가 될 것 같아 과거에 Target값도 변수로서의 값어치가 있는지 함께 측정해보았다.

 

VIF 수치 10이상 또는 Correlation 값이 0.8이상이면 다중공선성이 있다고 판단되는데, 그림에서 TARGET 변수의 VIF 값과 Correlation 값이 모두 기준보다 큰 값들이 도출됨을 알 수 있다.

 

이 말은, 과거의 Target값이 다른 변수인 풍속(WS)이나 일사량(DNI)과의 관계에 있어 좋게 작용하기 때문에 미래의 발전량이 과대적합이 되어 프로젝트에서 원하는 정확한 예측값보다 무조건 적으로 좋은 값이 나오게 된다. 그래서 TARGET 변수를 제외한 5개의 변수를 독립변수로 우선 결정했다.

 

-변수선택법, 최소제곱추정법(회귀분석)

 

회귀분석에 변수선택법과 최소제곱추정법을 이용하여 각 변수가 종속변수인 Target 변수에 유의미한 것이 있는지 확인하는 절차이다.

R_squared는 '결정계수'라고 하며 회귀선형모형이 얼마나 오차가 적고 정확도가 높은지 나타내주는 숫자이다.
0에 가까울수록 회귀식의 정확도는 매우 낮고 1에 가까울수록 회귀식의 정확도는 매우 높다.

또한, 통계학에서 p-value(유의확률)이 유의수준보다 작으면 '통계적으로 유의미하다'라고 표현할 수 있다. 보통 모델링이나 논문을 작성할 때 0.05를 기준으로 비교한다.

 

lm = sm.OLS(a_label, a_data )

results = lm.fit()

results.summary()



from IPython.core.interactiveshell import InteractiveShell

def linear_reg(X,y):

model = linear_model.LinearRegression(fit_intercept = True) # 단순선형회귀

model.fit(X,y)

RSS = mean_squared_error(y,model.predict(X)) * len(y)

R_squared = model.score(X,y)

return RSS, R_squared

#X변수 개수

m = len(a_label)

k = 8

RSS_list, R_squared_list, feature_list = [],[], []



numb_features = [] #1 ~ 5까지 모든 조합에 대한 성능 테스트(RSS, R_Squared)

for k in tnrange(1,len(a_data.columns) + 1):

    for combo in itertools.combinations(a_data.columns,k):

        tmp_result = linear_reg(a_data[list(combo)],a_label)

        RSS_list.append(tmp_result[0])

        R_squared_list.append(tmp_result[1])

        feature_list.append(combo)

        numb_features.append(len(combo))



#결과

df = pd.DataFrame({'numb_features': numb_features,'RSS': RSS_list, 'R_squared':R_squared_list,'features':feature_list})

print(df)

for i in range(len(R_squared_list)):

    if R_squared_list[i]==max(R_squared_list) :

        print(' 변수중요도가 높은값 : ', feature_list[i])

for j in range(len(RSS_list)):

    if RSS_list[j]==max(RSS_list) :

        print(' 오차가 큰 변수 : ' , feature_list[j])

InteractiveShell.ast_node_interactivity = "all"

Adj_R_squared를 사용하는 이유는 R_squared를 사용할 경우 타겟변수를 설명할 수 있는 변수가 추가될수록 값이 좋아진다. 즉, 무조건적으로 더 좋은 모형이 나타난다. 그래서 변수가 여러개인 다중회귀분석을 실시할때는 Adj_R_squared를 사용하여 모형의 적합도를 확인하는 것이 좋다.

좌측 그림를 통해 5개 변수일 때 수정된 결정계수(Adj_R_squared) 값이 가장 높게 나타나는 것을 알 수 있었고, 우측 그림의 결과를 통해서 5개의 변수가 유의수준 0.05보다 작기 때문에 모두 유의한 것을 알 수 있었다. 따라서 우리는 통계분석의 결과로 5개의 변수를 독립변수로 사용하기로 결정했다.

4) 모델구축

  • RNN vs LSTM
    시계열 데이터를 사용한 예측모델을 만들 때, 딥러닝에서 주로 사용하는 구조는 RNN과, LSTM이다.
    이 두 구조를 비교해 본 후, 어떤 구조를 사용할 것인지 결정하고자 했다.또한, RNN은 긴 길이의 시퀀스 때문에 기울기 소실이나 폭발과 같은 문제가 발생할 수 있는 문제가 있다. 두 구조를 비교한 결과, 이번 프로젝트 예측 모델에는 LSTM이 더 적합할 것으로 판단하여 LSTM을 사용하여 모델을 구축하였다.
    위 그림은 실제 데이터, 그리고 LSTM과 RNN 구조를 사용해 예측한 예측값을 비교한 그래프이다. 그림을 통해 LSTM이 RNN보다 더 좋은 예측결과를 도출하는 것을 확인할 수 있다.
  • RNN(Recurrent Neural Network)은 단기기억을 사용하기 때문에, 바로 직전 타임스텝의 정보만을 다음 셀로 전달한다는 특징이 있다. 하지만 LSTM(Long-Short Term Memory)은 이름에서도 알 수 있듯이 장기기억과 단기기억이 모두 존재한다. 그래서 보통은 LSTM의 구조가 RNN보다 더욱 정교하고, 시계열 데이터나 순차적인 데이터를 처리할 때엔 LSTM을 사용한다.
  • LSTM 모델
reduceLR = ReduceLROnPlateau(

monitor='val_loss', # 검증 손실을 기준으로 callback이 호출됩니다

factor=0.5, # callback 호출시 학습률을 1/2로 줄입니다

patience=10, # epoch 10 동안 개선되지 않으면 callback이 호출됩니다 )

model = Sequential()

model.add(LSTM(48, activation='relu',input_shape=(336,5)))

model.add(Dense(96 ,activation='relu'))

model.compile(loss='mse', optimizer='adam')

model.summary()

history=model.fit(x_train, y_train , epochs=100, batch_size=32, validation_split=0.2, callbacks=[reduceLR], verbose=1)
  • Activation Function, Optimizer
    예측 모델의 활성화 함수는 총 4가지를 적용해보았다. 4가지는 relu, sigmoid, softmax, tanh이다. 이 중에서 relu를 적용했을 때, loss 값이 가장 작았기 때문에 최종적으로 relu를 적용하기로 결정했다.
    Optimizer를 결정하기 위해서도 SGD, ADAGRAD, ADAM 총 3개의 함수를 적용해보았다. 적용해본 결과 ADAM이 가장 좋은 결과를 도출하였고, LSTM 모델에는 ADAM이 가장 적합하다는 논문이 있어 ADAM으로 결정하였다.

5) 예측 결과

위 [그림]과 같이 앞의 LSTM모델을 사용해 예측한 결과, 과거 7일치 데이터를 이용해 미래 2일치를 예측해볼 수 있었다.

  • 리뷰

아쉬웠던점은 LSTM모델이 아닌 다른 머신러닝모델을 사용하였다면 어떤 차이가 있었을지 궁금하였고 다른 column들을 추가로 넣어봤다면 좋은 모형이 나왔을 것 같다.

  • 참고문헌

[1] 학위논문(석사)-- 부산대학교 대학원 : 전기전자컴퓨터공학과 2020. 2
[2] 2012 한국에너지기술평가원—태양광 발전 기술 전망
3 --http://www.kea.kr/elec_journal/2015_7/12.pdf
[4][해줌]–https://corp.haezoom.com/tech/
[5] <Can Solar Power Compete With Coal? In India, It’s Gaining Ground> 2020 Phred Dvorak--
www.wsj.com/articles/solar-power-is-beginning-to-eclipse-fossil-fuels-11581964338
[6] 정규화
https://soo-jjeong.tistory.com/122
[7] 슬라이딩 윈도우
https://twinparadox.tistory.com/595
[8] RNN vs LSTM
https://davinci-ai.tistory.com/30
[9] Optimizer
https://velog.io/@jooh95/%EA%B0%9C%EB%85%90-%EB%94%A5%EB%9F%AC%EB%8B%9D-optimizer-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%A0%95%EB%A6%AC
[10] 활성화 함수--모두의 딥러닝 개정2판