본문 바로가기
포트폴리오/딥러닝 프로젝트

검색어 빈도 데이터를 반영한 코로나19 확진자 수 예측 딥러닝 모델

by 유스베리이 2024. 2. 17.

 

구글 트렌드를 확용해서 딥러닝 모델(DNN & LSTM) 을 사용한 탐색적 데이터 분석 실시 

검색어 빈도 데이터 (‘코로나 증상’) + 과거 코로나 19 확진자 수 데이터 -> 미래 코로나 확진자 수 예측 

 

확진자수 예측을 위한 입력 데이터 

  • 긴 기간의 시계열 데이터를 사용할수록 변동성 파악 용이 ( 전염병에 대처하고 관리하기 위해 1년정도의 시계열 데이터만 사용) -> 서울을 포함한 6개의 도시에서 2020년 1월 30일 ~ 2021년 2월 28일의 입력 데이터
  • 입력 데이터 : 확진자 수( 특정일 기준으로 특정일 포함 과거 7일 데이터 사용-> 5일 후 예측), 검색어 빈도수 

      - 훈련 데이터 : 2020년 1월 30일 ~ 2021년 1월 20일

      - 테스트 데이터 : 2021년 1월 21일 ~ 2021년 2월 28일 

  • 배치 사이즈( batch size ) : 데이터를 묶음 단위로 나눔

- 미니 배치 (Mini- batch) : 8X7=56 데이터를 하나의 묶음으로 10개씩 묶은 데이터 하나가 미니 배치 

- 독립변수 : 8개 ( 더미 변수 (6개) 포함) 

- 타입스텝 : 7일

- 배치 사이즈가 클 경우 : 학습 속도 상승 , 정확도 하락

- 배치 사이즈가 작을 경우 : 학습 속도 하락, 정확도 상승

- 너무 많은 데이터에 배치 사이즈를 작게 설정하면 과적합 발생 , 정확도 하락

 

-> “ 본 연구에서는 배치사이즈를 2에서 2씩 증가해 18까지 튜닝 “

 

확진자수 예측 모델 구성

DNN(심층신경망): 입력층과 출력층 사이에 많은 은닉층을 포함해 비선형적 관계 학습

RNN(순환 신경망) : 시계열 데이터 처리에 적합

 

심층신경망 모델 (Deep Neural Network)

# 모델 구성

  • 순차적 방법 + 6개의 dense 층 (출력층 1개, 은닉층 5개 )
  • 은닉층 활성화 함수 : ReLU 함수
  •  - 입력이 양수인 경우 그대로 출력, 음수인 경우 0으로 출력
  • 출력층 활성화 함수 : Linear(선형) 함수

- 확진자수 예측은 선형 회귀 문제 ( 주어진 데이터기반 모델 학습,독립변수들이 주어졌을 때 종속변수 예측)

 

-14개의 입력값(x) 에 가중치(w)를 곱하고 바이러스(b)를  더한 가중합(z)

-활성화 함수(linear)를 거치면 64개의 결과값(A) 산출

-이 결과값이 다음 은닉층의 입력값으로 사용 

 

 

# 학습 과정

  • 컴파일 함수 호출 ( 손실함수, 최적화알고리즘, 평가 지표 지정)

- 손실 함수 : 평균제곱오차 (MSE) 적용 ( 예측값과 실제값 간의 차이를 제곱한 후 평균 )

- 최적화 알고리즘 : 아담 (Adam) 사용 (학습률을 각 파라미터에 대해 자동 조정해 최적화 )

- 평가 지표: 학습 과정이 잘 진행되고 있는지 모니터링하는 지표

  • Early stopping : 과적합이 발생하기 직전에 학습 중단

- Epochs(학습을 총 400번 반복) -> 모델 성능이 추가 40번 동안 반복해도 개선되지 않으면 400번 전 중단

# 정확성 평가

  • MAPE (Mean Absolute Percent Error) 사용 - 오차의 정도를 백분율 값으로 나타냄(직관적 이해)

 

 

 

 

 

순환신경망 모델 (Recurrent Neural Network)

순서가 있는 데이터 학습에 사용하면 좋음 (순환구조가 들어있음)

 

RNN(결과값이 출력층으로 전달되는 동시에 순환 구조를 통해 현재 층의 다음 계산을 위헤 사용)

- 은닉상태 ( 과거의 모든 정보 기억) , hs( 실수 벡터) 를 사용

- 은닉 상태와 현재 입력데이터를 고려해 출력값을 발생시키며 

- 은닉상태는 새로운 입력데이터가 처리될 때 마다 업데이트

  # 학습과정

-  입력층을 따로 만들어서 입력층과 출력층 사이에 5개의 은닉층

- 첫번째 은닉층 ( 순환층 ) + 나머지 은닉층 & 출력층 (Dense층/feed-forward층)

  • 기간이 긴 시계열 데이터를 학습할 때는 기울기 소실 문제가 발생 -> RNN + LSTM/GRU 사용 
  • 컴파일 함수 

- 손실함수 : 평균제곱오차(MSE)

- 최적화 알고리즘 : Adam

- 평가 지표 : 평균절대오차(MAE)

  • 하이퍼 파라미터- 에폭(Epochs), 배치 사이즈, early stopping 은 DNN 과 동일

# 정확성 평가

  •  MAPE로 계산

모델 생성 과정

과거 7일간의 확진자 수와 검색어 빈도수 데이터를 결합하여 딥러닝을 적 용해 5일 후의 코로나 19 확진자수를 선제적으로 예측하는데 중점

 

코로나 환자와 접촉했거나 코로나 환자가 발생한 장소에 있었던 사람이 코로나에 전염됐을 것을 걱정한다면 반드시 검색해야 할 단어인 ‘ 코로나 증상’ 이 하나의 검색어만 사용하여 매일의 검색 빈도수를 확보해서 사용

여기서 논문은 구글 트렌드를 통해 검색 빈도수를 구했으나 저희는 대한민국 국민의 검색어 빈도 수를 위해 점유율이 더 많고 많이 사용하는 네이버 트렌드를 사용해서 검색어 빈도수의 값을 구함.
이 논문에서는  LSTM 모델과 DNN모델을 모두 적용해 예측 능력 을 비교하였으나  DNN만 사용하여 예측.

또한 논문은 서울을 포함한 6개의 도시에서의 데이터를 입력데이터로 사용하였으나

전체적인 데이터를 확인하기 위해 전 지역을 통합해 전국의 데이터를 입력데이터로 사용.

 

<입력데이터>
논문에서와 동일하게 2020년 1월 30일 부터 2021년 2월 28일까지의 데이터를 사용해

훈련데이터는 2020년 1월30일부터 21년 1월 20일까지의 데이터를 사용했고 테스트 데이터는 21년 1월 21에서 2월 28일 데이터를 사용.


입력 데이터는 두개의 변수 확진자수, 검색어 빈도수로 구성. 확진자 수는 공공데이 터 포털에서 데이터를 요청 승인 받아서 확진자수를 얻었고, 검색어 빈도수는 네이버 트렌드에서 제공을 받았고, 지정한 기간과 코로나 증상이라는 검색어를 입력하면

그 기간동안 해당 검색어가 네이버에 입력된 빈도수를 기반으로 점수를 산정.

 

<모델 구성> 

모델 구성할 , 위의 코드처 층을 차례대로 는 순 방법을 사용하였고, 1개의 예측값을 발생시는 출력층과 5개의 은닉층으로 이져 총 6개의 dense 층을 가지는 DNN 모델을 계함.

 은닉층의  함수로 입력이 양수인 경 입력값을 그대로 반환하고 아  0 으로 반환하는

계산이 단순한 relu 함수를 사용하였고, 최종 출력값은 이 모델은 종속변수와 두개의 독립변수간의 관계이로 선형 회귀 문제로 출력층은 선형 함수를 사용.

 

<모델 학습>

 여기서 파일 함수 출 에 손실함수, 화 알고리, 가 지표 3가지 요소를 지정.

손실 함수가 을 수  모델의 수행 능력이 상승하, 예측값과 제 값 간의 이를 제한 후 평균  평균 곱오차(MSE)와 예측값과 제값의 이를 하는 가중 편향 합을  평균절오 차(MAE)를 적용해 손실함수를 결정하였고, 화 알고리에는 아, 학습과정이  진행되는지 모니터하기 위해 mae 를 사용. 

학습과정의 과적합을 기 위해 early stopping 로 모델 성능이 40번 반복 학습될 동안 개선되지 으면 학습을 중단시킴.

직접 짠 코드

## 이미 있는 .xlsx 파일 지우기.
#!rm *.xlsx

## 파일 업로드, 여러개 선택 가능.
from google.colab import files
uploaded = files.upload()
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from keras.models import Sequential
from keras.layers import Dense
from keras.optimizers import Adam
from keras.callbacks import EarlyStopping
from sklearn.metrics import mean_absolute_error


train_input = pd.read_excel('data.xlsx')
confirmed_cases = train_input['newconfcase'].tolist()
confirmed5_cases = train_input['newconfcase5dayslater'].tolist()

trainset_list = list(zip(confirmed_cases, confirmed5_cases))

data_array = np.array(trainset_list)

prex_train = data_array[:357, 0]
x_train = np.empty((0,7))
for j in range(351):
  xk = np.array([])
  for i in range(7):
    i = i + j
    xk = np.append(xk, np.array(data_array[i, 0]))
  x_train = np.append(x_train,np.array([xk]),axis = 0)

y_train = data_array[6:357,1]


num_samples = 351
num_features = 1


model = Sequential()
model.add(Dense(units=64, input_dim=7, activation='linear'))

for _ in range(4):
    model.add(Dense(units=32, activation='relu'))

model.add(Dense(units=1, activation='linear'))


model.compile(loss='mean_squared_error',
              optimizer=Adam(),
              metrics=['mae'])

early_stopping = EarlyStopping(monitor='val_loss', patience=40, restore_best_weights=True)


history = model.fit(x_train, y_train,
                    epochs=400,
                    batch_size=10,
                    validation_split=0.2,
                    callbacks=[early_stopping],
                    verbose = 0
)

test_input = pd.read_excel('data.xlsx')
confirmed_cases_test = test_input['newconfcase'].tolist()
confirmed5_cases_test = test_input['newconfcase5dayslater'].tolist()



testset_list = list(zip(confirmed_cases_test, confirmed5_cases_test))

data_array_test = np.array(testset_list)



prex_test = data_array[357:396, 0]
x_test = np.empty((0,7))
for j in range(357,390):
  xk = np.array([])
  for i in range(7):
    i = i + j
    xk = np.append(xk, np.array(data_array[i, 0]))
  x_test = np.append(x_test,np.array([xk]),axis = 0)

y_test = data_array[363:396,1]

predictions = model.predict(x_test)
mape = np.mean(np.abs((y_test - predictions.flatten()) / y_test)) * 100
print(f'MAPE: {mape:.2f}%') #예측 오차 분석

plt.subplot(1, 2, 1)
plt.plot(history.history['loss'], label='Training Loss')
plt.plot(history.history['val_loss'], label='Validation Loss')
plt.title('Training and Validation Loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()

plt.subplot(1, 2, 2)
plt.plot(history.history['mae'], label='Training MAE') #평균 절차 함수
plt.plot(history.history['val_mae'], label='Validation MAE')
plt.title('Training and Validation MAE')
plt.xlabel('Epochs')
plt.ylabel('MAE')
plt.legend()

plt.tight_layout()
plt.show()

y_pred = model.predict(x_test)
plt.plot(y_test, label='Actual Confirmed5 Cases')
plt.plot(y_pred, label='Predicted Confirmed5 Cases')
plt.title('Predicted Confirmed5 Cases')
plt.xlabel('date')
plt.ylabel('Confirmed5 Cases')
plt.legend()
plt.show()

 

 

결과 예측값