데이터 한 그릇

11) 시계열 CNN 본문

시계열 분석/Practical TIme Series Analysis

11) 시계열 CNN

장사이언스 2022. 11. 4. 10:13

가전제품의 전기 사용량을 CNN을 활용하여 예측해볼 예정이다

 


df=pd.read_csv('energydata_complete.csv')
df.head()

 

 

Appliances 칼럼을 활용하여 시계열 예측 작업을 수행할 예정

 

from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler(feature_range=(0, 1))
df['scaled_App'] = scaler.fit_transform(np.array(df['Appliances']).reshape(-1, 1))
df.head()

 

0과 1사이로 Appliances 를 스케일링한다

 

from datetime import datetime
split_date = datetime(year=2016, month=5, day=1, hour=0)
df_train = df.loc[df['date']<split_date]
df_test = df.loc[df['date']>=split_date]
print('Shape of train:', df_train.shape)
print('Shape of test:', df_test.shape)

 

이전 ANN 과 마찬가지로 기준이 되는 날짜를 설정하고 train 데이터와 test 데이터로 나눈다

 

df_test.reset_index(drop=True, inplace=True)
df_test.head()

 

인덱스를 맞춰주기 위해서 test 데이터셋을 reset index 해준다

 

def makeXy(ts, nb_timesteps):
    X = []
    y = []
    for i in range(nb_timesteps, ts.shape[0]):
        X.append(list(ts.loc[i-nb_timesteps:i-1]))
        y.append(ts.loc[i])
    X, y = np.array(X), np.array(y)
    return X, y

 

ANN 과 마찬가지로 X,y 로 나뉘어 담는다

 

X_train, y_train = makeXy(df_train['scaled_App'], 10)
print('Shape of train arrays:', X_train.shape, y_train.shape)
print(X_train[0])
print(y_train[0])

X_test, y_test = makeXy(df_test['scaled_App'], 10)
print('Shape of Test arrays:', X_test.shape, y_test.shape)
print(X_test[0])
print(y_test[0])

 

train 데이터와 test 셋에 동일하게 적용한다

 

# Keras import
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import Flatten
from keras.layers.convolutional import Conv1D
from keras.layers.pooling import AveragePooling1D
from keras.models import Sequential


#X_train and X_val are reshaped to 3D arrays
X_train, X_test = X_train.reshape((X_train.shape[0], X_train.shape[1], 1)),\
                 X_test.reshape((X_test.shape[0], X_test.shape[1], 1))
print('Shape of arrays after reshaping:', X_train.shape, X_test.shape)


model=Sequential()
model.add(Conv1D(64, 3, strides=1, use_bias=True, input_shape=(10,1),padding='same'))
model.add(AveragePooling1D(pool_size=3, strides=1))
model.add(Flatten())
model.add(Dropout(0.2))
model.add(Dense(1, activation='linear'))

 

tensorflow 가 요구하는 데이터 shape 이 존재하기 때문에 위에서 makeXy를 통해서 만든 데이터 셋은 2차원이지만 3차원으로 reshape 을 해준다

모델의 input 구조는 Conv1D 에 담길 수 있다 Conv1D 의 64 는 합성곱 layer 를 64개 쌓는다는 것과 같고 3은 filter 크기를 3으로 둔다는 것과 같다. strides 는 window 사이즈에서 얼마나 움직일지를 나타내고 이는 한 칸씩 움직이겠다는 것과 같다

 

보통 이미지에서는 pooling 을 max 풀링을 사용하지만 시계열에서는 일반적으로 Averagepooling 을 사용한다, 풀링사이즈도 마찬가지로 3 으로 두고 window 에서 1칸씩 움직이는 것으로 설정한다

 

model.compile(loss='mean_squared_error', optimizer='adam')
model.summary()

 

손실함수는 mse, 최적화는 adam 을 사용한다

 

history=model.fit(X_train, y_train, batch_size=16, epochs=10,shuffle=True)

preds = model.predict(X_test)
pred_App = scaler.inverse_transform(preds)
pred_App = np.squeeze(pred_App)

from sklearn.metrics import r2_score
r2 = r2_score(df_test['Appliances'].loc[10:], pred_App)
print('R-squared for the test set:', round(r2,4))

 

모델 예측 후에 min max scaler 로 변환한 값을 다시 본래의 값으로 바뀐다

성능을 확인해보니 r^2 값이 0.5123 을 기록하고 있다

 

plt.plot(range(50), df_test['Appliances'].loc[10:59], linestyle='-', marker='*', color='r')
plt.plot(range(50), pred_App[:50], linestyle='-', marker='.', color='b')
plt.legend(['Actual','Predicted'], loc=2)
plt.title('Actual vs Predicted Appliances')
plt.ylabel('Appliances')
plt.xlabel('Index')

 

실제값과 예측값을 plot 을 그려보면 위와 같다

Comments