(들아가기전에->
예시코드를 이용해 시계열 데이터를 비교하며, 커널(필터)이 어떻게 작동되는지 써놓은 글 입니다.)
(많은 예시와 코드들이 있지만 시계열 데이터 와 아닌 것에는 엄연히 코드의 차이가 있다(데이터 가공하는 부분에 있어서 다름 ))
<시계열 데이터X>
1. 모듈 불러옴.
import numpy as np
import pandas as pd
import tensorflow as tf
from keras.models import Sequential
from keras.layers import Dense,Conv1D,Flatten
from tensorflow import keras
from sklearn.datasets import load_iris
2.seed 설정(하이퍼 파라미터 바꿀시 다른 값들 안바뀌도록)
##seed 설정.
seed=42
tf.random.set_seed(seed)
np.random.seed(seed)
3. 데이터 추출(보스턴 집 값 예측).
boston_housing = tf.keras.datasets.boston_housing
(train_data, train_labels), (test_data, test_labels) = boston_housing.load_data()
print("Training set: {}".format(train_data.shape)) # 404 examples, 13 features
print("Testing set: {}".format(test_data.shape)) # 102 examples, 13 features
4.데이터 정규화
mean = train_data.mean(axis=0)
std = train_data.std(axis=0)
train_data = (train_data - mean) / std
test_data = (test_data - mean) / std
5.데이터 가공. (conv1d의 input은 3차원이어야함으로.)
-> 가공형식=(batch_size, time_steps, input_dimension) , time_steps=feature개수 , input_dimension=1
(input_dimension=1 인 이유= 각각의 행을 묶어주기 위해서.
sample_size = train_data.shape[0] # number of samples in train set
time_steps = train_data.shape[1] # number of features in train set
input_dimension = 1 # each feature is represented by 1 number
#Train data 3차원 가공.
train_data_reshaped = train_data.reshape(sample_size,time_steps,input_dimension)
train_data_reshaped.shape # (404,13,1) =(batch_size, time_steps, input_dimension)
# Test data 3차원 가공.
test_data_reshaped = test_data.reshape(test_data.shape[0],test_data.shape[1],input_dimension)
test_data_reshaped.shape #(102,13,1)
6. 모델 설계.
n_features = train_data_reshaped.shape[1] #13
n_input_dimension = train_data_reshaped.shape[2] #1
model = Sequential()
model.add(keras.layers.Conv1D(filters=64, kernel_size=7,
input_shape=(n_features,n_input_dimension),
activation='relu'))
model.add(keras.layers.Dropout(0.5))
model.add(keras.layers.Conv1D(filters=32, kernel_size=3, activation='relu' ))
model.add(keras.layers.Conv1D(filters=16, kernel_size=2, activation='relu'))
model.add(keras.layers.MaxPooling1D(pool_size=2, ))
model.add(keras.layers.Flatten())
model.add(keras.layers.Dense(32, activation='relu'))
model.add(keras.layers.Dense(1))
model.summary()
커널(필터가) 작동방법:
1. 한개의 데이터에 13개의 feature가 존재
2. 필터(커널)사이즈에 맞게 돌아감
3. strides=1 임으로 한칸씩 가면서 특징맵(output한칸씩)을 추출함.
주의) 1. 커널은 feature의 개수보다 클 수가 없다.(여기서는 최대 13까지 가능함.)
<시계열 데이터 일때 >
(상당히 어려웠다.. 진짜 conv1d 와 동시에 시계열 데이터를 찾아내야하는게 어려웠다.....)
(이 글이 상당히 도움이 되었다. 감사해요 글써 주신 분...)
(윗 그림에서 말하는 x,y,z는 feature라고 생각하면 된다.)
(윗 그림에서 오해 하기 쉬운부분이 있다 -> 윗그림은 시간을 4일치로 묶고 커널 사이즈를 4로 설정한것이다.)
1. 모듈 import
import pandas as pd
import numpy as np
import tensorflow as tf
from keras.layers import Conv1D, AveragePooling1D,Dense, Dropout , MaxPooling1D ,LSTM,InputLayer,Flatten,Reshape
from keras.models import Sequential
from keras.callbacks import EarlyStopping, ModelCheckpoint
from sklearn.model_selection import train_test_split
2. seed설정 (안하면 실행할 때 마다 결과값 바뀜..설정 안하면 하이퍼파라미터 못찾습니다..)
#seed설정.
seed=42
tf.random.set_seed(seed)
np.random.seed(seed)
3. 엑셀 데이터 불러오기 (랩실과제라서 이것저것 수정하기 귀찮아서 생략..)
4. 데이터셋을 만드는 함수.
# 데이터 셋을 만드는 함수
def make_dataset(data, label, window_size):
feature_list = []
label_list = []
for i in range(len(data) - window_size):
feature_list.append(np.array(data.iloc[i:i+window_size])) # np.array=values= pd dataframe을 np형식으로 바꿔줌.
label_list.append(np.array(label.iloc[i+window_size]))
return np.array(feature_list), np.array(label_list)
https://put-idea.tistory.com/44 를 클릭하면 데이터셋(window_size)를 만드는 방법을 자세하게 설명해 두었습니다.
# DODI_C_20_5 = Train DATA
#### ' DODI_C_20_5 ' = train DATA
DODI_C_20_5=np.array(DODI_C_20_5) #슬라이싱을 하기위해 np.array 형식으로 바꿈.
DODI_C_20_5_feature=pd.DataFrame(DODI_C_20_5[:,1]) # feature 열 추출
DODI_C_20_5_label=pd.DataFrame(DODI_C_20_5[:,0]) # label 열 추출
DODI_C_20_5_feature, DODI_C_20_5_label=make_dataset(DODI_C_20_5_feature,DODI_C_20_5_label,5) #window_size=5 설정
x_train, x_valid, y_train, y_valid = train_test_split(DODI_C_20_5_feature,DODI_C_20_5_label, test_size=0.2 , random_state=seed)
x_train.shape, x_valid.shape, # ->(2981, 5, 1), (746, 5, 1)
# DODI_C_20_6 = Test DATA
#### ' DODI_C_20_6 ' = TEST DATA
DODI_C_20_6=np.array(DODI_C_20_6) #슬라이싱을 하기위해 np.array 형식으로 바꿈.
DODI_C_20_6_feature = pd.DataFrame(DODI_C_20_6[:,1])
DODI_C_20_6_label = pd.DataFrame(DODI_C_20_6[:,0])
DODI_C_20_6_feature.shape
test_feature, test_label = make_dataset(DODI_C_20_6_feature, DODI_C_20_6_label, 5)
test_feature.shape, test_label.shape # (3727, 5, 1), (3727, 1)
그렇다면 여기서 만들어진 window_size는 LSTM에서와 어떻게 다르게 작동하는것일까라는 궁금함이 생길것이다.
# window_size함수를 적용하면 아래 사진과 같이 짝이 지어지는 모습이다.
# 지정한 window_size에 맞게 리스트화 된 모습(아래사진).
그렇다면 여기서 만들어진 window_size는 LSTM에서와 어떻게 다르게 작동하는것일까라는 궁금함이 생길것이다.
아래와 같이 커널이 window_size에서 돌아가게 된다. 즉 5일치의 값들을 보며 커널이 돌아가며 특징들을 추출하는것이다!!(생겨난 빈네모들= 특징추출된것임, 특징맵 총 2개 =주황색열,초록색열 )
5. 모델 설계.
model = Sequential()
model.add(Conv1D(64,3,strides=1,
input_shape=(DODI_C_20_5_feature.shape[1], DODI_C_20_5_feature.shape[2]), #input shape=(time_step=windowsize,featrue개수)
activation='relu',
)
)
model.add(AveragePooling1D(pool_size=2,strides=1)) #strides 설정 안하면 pool_size랑 동일한 strides 로 잡힘.
model.add(Dropout(0.5))
model.add(Dense(128, activation='relu'))
model.add(Flatten()) # dense layer에 맞춰야 함으로 flatten사용
model.add(Dense(64, activation='relu'))
model.add(Dropout(0.5)) # drop out 50% 함
model.add(Dense(1))
model.summary()
layer설명. conv1D : 커널(필터)개수 =64개 , 커널 사이즈=3 , 커널이 몇칸씩 이동=strides )AveragePooling1D : 위에서 출력된 주황색3칸,초록색 3칸 에서 pool_size=2가 내려(stride만큼)가면서 평균값을 뽑아냄
(※ stride 설정안하면 pool_size로 자동 설정됨 -> 케라스 공식 링크: https://keras.io/api/layers/pooling_layers/)
Dropout :과접합 방지를 위해 노드를 임의로 꺼줌
6. 모델 컴파일.
model.compile(loss='mse',optimizer='adam',metrics="accuracy")
early_stop = EarlyStopping(monitor='val_loss', patience=100)
model.fit(x_train,y_train,validation_data=(x_valid, y_valid), callbacks=[early_stop],epochs=1000,batch_size=100)
7. 그래프
import matplotlib.pyplot as plt
pred=model.predict(test_feature)
plt.figure(figsize=(12, 9))
plt.plot(test_label, label = 'actual')
plt.plot(pred, label = 'prediction')
plt.legend()
plt.show()
(시계열 데이터에서 사용할 CNN과 LSTM을 공부해봣는데.... 어려운데 재밋다... )
(음 근데 CNN이랑 LSTM을 썻을때 그닥 그래프의 큰차이가 없네....CNN+LSTM으로 구현을 해봐야겟다...)
햇갈릴 수 있는 부분 정리: kernal_size는 n일치로 묶은거보다 같거나 작아야 한다.(n일치들의 관계를 보며 특징을
찾아내기 때문)
<결론>
시계열 데이터 일 때) input_shape = (batch_size, time_steps, input_dimension) ,
= (batch_size, feature개수, 1)
시계열 데이터 아닐 때) input_shape = (batch_size, time_steps, feature개수) ,
= (height, time_steps, feature개수)
'인공지능 (기본 딥러닝) > 딥러닝 사이드 Project' 카테고리의 다른 글
[트랜스포머] 트랜스포머 인코더를 이용한 시계열 예측. (2) | 2023.07.13 |
---|---|
[CNN-Tensorflow] 커스텀 데이터 활용 이미지 분류 예제 코드 설명 (5) | 2023.02.26 |
YOLOv5 커스텀 데이터셋으로 학습하기 (27) | 2022.11.04 |
[CNN] 예제 코드 설명 (회귀 예측 ,첫 번째 layer Conv1D사용) (0) | 2022.08.26 |
[LSTM] 예제 코드 설명 (시계열 데이터 예측) (0) | 2022.08.20 |