일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 텐서플로2와 머신러닝으로 시작하는 자연어처리
- 밑바닥부터 시작하는 딥러닝
- Django
- 텍스트 분류
- word2vec
- 차원축소
- rnn
- Pandas
- 자연어 처리
- 모두의 딥러닝
- 코사인 유사도
- 밑바닥부터 시작하는 딥러닝2
- 오래간만에 글쓰네
- 결정계수
- 은준아 화이팅
- 감성분석
- 파이썬 pandas
- student t분포
- 가설검정
- F분포
- 기초통계
- 구글 BERT의 정석
- 머신러닝
- 기술통계학
- 최소자승법
- numpy
- 회귀분석
- 군집화
- 다층 퍼셉트론
- 히스토그램
- Today
- Total
데이터 한 그릇
10)시계열 딥러닝 ANN 본문
(한양대학교 BI수업 참조)
날씨 관련 데이터를 활용하여 간단한 전처리부터, ANN모델까지 돌려볼 예정이다.
task 는 날씨 관련 특징을 예측하는 작업을 수행한다
#Read the dataset into a pandas.DataFrame
df = pd.read_csv('PRSA_data_2010.1.1-2014.12.31.csv')
print('Shape of the dataframe:', df.shape)
데이터를 읽은 결과 따로 datetime type 의 칼럼이 존재하는 게 아니라, year, month, day 칼럼으로 날짜 feature 가 나뉘어져 있음을 알 수 있다
시계열적인 분석을 하기 위해서는 datetime 이 필요하기 때문에 year, month, day feature를 활용하여 datetime 타입을 가지는 "datetime" 칼럼을 만들어야한다
# Index creation
df['datetime'] = df[['year', 'month', 'day', 'hour']].\
apply(lambda row: datetime.datetime(year=row['year'], \
month=row['month'], day=row['day'],hour=row['hour']), axis = 1)
df.sort_values('datetime', ascending=True, inplace=True)
df.head()
year, month, day, hour 칼럼에 접근하여 "datetime" 패키지를 활용해서 datetime 칼럼을 만든다.
오름차순으로 sorting 한다
g = sns.boxplot(df['PRES'])
g.set_title('Box plot of Air Pressure')
g = sns.lineplot(x='datetime',y='PRES',data=df)
g.set_title('Time series of Air Pressure')
g.set_xlabel('Year')
g.set_ylabel('Air Pressure readings in hPa')
시계열적으로 'PRES' 를 lineplot 그려보니 계절성을 가지고 있고 정상성을 가지고 있는 데이터임을 확인할 수 있었다.
즉, 평균과 분산이 시점에 상관없이 일정함을 살펴볼 수 있었다
# Minmax scaling PRES variable
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler(feature_range=(0, 1))
df['scaled_PRES2'] = scaler.fit_transform(np.array(df['PRES']).reshape(-1,1))
df.head()
PRES 에 대해서 모든 데이터들을 0 ~ 1 사이로 반환하는 MinMaxScaler 를 활용한다
split_date = datetime.datetime(year=2014, month=1, day=1, hour=0)
df_train = df.loc[df['datetime']<split_date]
df_test = df.loc[df['datetime']>=split_date]
일반적인 데이터를 훈련 데이터와 테스트 데이터로 나눌 때는 사이킷런 model_selection 의 train_test_split을 활용하여 train 과 test 로 나눈다
이 경우에는 할당된 %에 랜덤으로 train, test set을 나누는 작업이지만, 이와 같은 방식으로 시계열 데이터를 나누게 되면 문제가 발생한다
왜냐하면, 시계열 데이터는 연속성의 특징을 가지고 있기 때문이다. 이전 3일의 데이터를 활용하여 현재 데이터를 예측하는 경우 이전 3일의 데이터의 경우 연속성을 유지해야만한다, 하지만 train_test_split 을 활용하게 되면 시계열 데이터가 연속성을 유지할 수 없다
따라서 split_date 변수에 train set과 test set 을 나누는 기준 날짜를 정하고 그 기준으로 train 과 test 를 나눈다
df_test.reset_index(drop=True, inplace=True)
df_test.head()
train과 test셋을 split_date 변수를 활용하여 나누게 되면 index 가 서로 일치하지 않기 때문에 index 를 맞춰준다
g = sns.lineplot(x='datetime',y='scaled_PRES',data=df_train, color='b')
g.set_title('Time series of scaled Air Pressure in train set')
g.set_xlabel('Index')
g.set_ylabel('Scaled Air Pressure readings')
train 데이터의 scaled 된 pres 를 다시 그려보니 아래와 같았다
test 데이터의 scaled 된 pres를 그려보니 아래와 같았다
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
가장 중요한 부분이라고 할 수 있는데, 함수의 ts는 데이터 즉, 타임 시리즈를 의미하고 nb_timesteps는 사용할 lag를 의미한다
만일 timesteps을 7로 보고싶으면 함수에 7을 집어 넣으면 되는데, 밑에 for문을 살펴보면,,
만일 timeseries가 3000건이라고 한다면 range는 range(7, 3000) 이 된다
맨 처음 i는 7이 되고, 따라서 loc[i-nb_timesteps:i-1], loc[7-7:6] => loc[0:6] 가 된다
이 값이 x에 담기게 되는데 결국 이는 0,1,2,3,4,5,6 까지의 7개 학습 데이터가 담겼다고 할 수 있다
y에는 7번째 데이터가 담기게 되어 target데이터가 담기게 된다
즉, for문으로 지속적으로 이전 7개 데이터와 타겟 1개 데이터가 y에 순차적으로 담기게 된다
#train
X_train, y_train = makeXy(df_train['scaled_PRES'], 7)
print('Shape of train arrays:', X_train.shape, y_train.shape)
print(X_train[0])
print(y_train[0])
print(df.shape)
#test
X_test, y_test = makeXy(df_test['scaled_PRES'], 7)
print('Shape of Test arrays:', X_test.shape, y_test.shape)
print(X_test[0])
print(y_test[0])
train 과 test 셋에 대해 makeXy 함수를 돌린다
from keras.layers import Dense, Dropout
from keras.models import Sequential
model = Sequential()
model.add(Dense(32, activation='relu', input_shape=(7,)))
model.add(Dense(16, activation='relu'))
model.add(Dense(16, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(1, activation='linear'))
모델을 생성하는데 해당 모델은 은닉층을 3 layer로 쌓고 각 노드는 32, 16, 16 으로 설정했으며 활성화 함수로는 relu 함수를 사용했다
입력 shape 은 이전 7개의 데이터를 활용하여 학습하기 때문에 shape을 (7,) 로 맞춘다
dropout을 0.2 %를 주어 과적합을 방지하고, 출력층을 linear 모델을 활성화 함수로 두어 설정한다
model.compile(loss='mean_squared_error', optimizer='adam')
model.summary()
손실 함수로는 mse(mean squared error) 를 사용하고 최적화 방식으로는 adam 방식을 사용한다
모델의 구조를 보면 위와 같다
history=model.fit(X_train, y_train, batch_size=16, epochs=20,
verbose=1, validation_split=0.3,
shuffle=True)
batch size를 16, epoch을 20을 주어 돌려본다
from sklearn.metrics import r2_score
r2 = r2_score(df_test['PRES'].loc[7:], pred_PRES)
print('R-squared for the test set:', round(r2,4))
R^2 를 살펴보니 0.9796 이 도출됐다
plt.plot(range(50), df_test['PRES'].loc[7:56], linestyle='-', marker='*', color='r')
plt.plot(range(50), pred_PRES[:50], linestyle='-', marker='.', color='b')
plt.legend(['Actual','Predicted'], loc=2)
plt.title('Actual vs Predicted Air Pressure')
plt.ylabel('Air Pressure')
plt.xlabel('Index')
실제 데이터와 예측한 데이터를 lineplot 을 그려보니 위의 그림과 같았다
지금까지는 간단한 ANN 모델을 짜서 예측을 해봤는데, 다음으로는 CNN 을 활용하여 예측 모델을 짜볼 예정이다
'시계열 분석 > Practical TIme Series Analysis' 카테고리의 다른 글
11) 시계열 CNN (0) | 2022.11.04 |
---|---|
8)시계열을 위한 머신러닝2 (0) | 2022.10.31 |
8)시계열을 위한 머신러닝 (0) | 2022.10.31 |
6)시계열 특징의 생성 및 선택 (0) | 2022.10.26 |
5)시계열의 통계모델3 (0) | 2022.10.26 |