박가방
1. 모델링 간단 요약(선형 회귀) 본문
서울 시 따릉이 데이터 → **시계열 데이터 **
- DateTime : year-month-day hh:mi:ss
- Count : 시간대별 수요량
- Temperature : 온도(섭씨)
- Humidity : 습도(%)
- WindSpeed : 풍속(m/s)
- Rainfall - mm
- Snowfall - cm
- Seasons - Winter, Spring, Summer, Autumn
- Holiday - Holiday / No holiday
- FuncDay - Yes / No
1. 환경 설정
1.1 라이브러리
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.metrics import *
from sklearn.preprocessing import MinMaxScaler
from keras.models import Sequential
from keras.layers import Dense
from keras.backend import clear_session
from keras.optimizers import Adam
1.2 학습곡선 함수
# 학습곡선 함수
def dl_history_plot(history):
plt.figure(figsize=(10,6))
plt.plot(history['loss'], label='train_err', marker = '.')
plt.plot(history['val_loss'], label='val_err', marker = '.')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend()
plt.grid()
plt.show()
1.3 파일 불러오기
path = 'https://raw.githubusercontent.com---------교육용-----.csv'
data = pd.read_csv(path)
1.4 DateTime열을 판다스형으로 변환 & 불필요한 열 제거
data['DateTime'] = pd.to_datetime(data['DateTime'])
data.drop(['Visibility','Solar'], axis = 1, inplace = True)
1.5 14일치의 수요량 확인
temp = data[:24*14]
plt.figure(figsize = (20,8))
plt.plot('DateTime', 'Count', data = temp)
plt.grid()
plt.show()
2. 전처리
① 결측치 조회
data.isna().sum()
② (예외) 의도적으로 y 만들어서 예측 - 실제 예측할 수 있는 미래 데이터가 없으므로 따로 y를 만들자.
# 2칸을 앞당겼기 때문에 하위 2행의 y값에 NaN이 표시
data['y'] = data['Count'].shift(-2)
data.tail()
# 하위 2행 제외하여 재 할당
data = data.iloc[:-2]
③ 데이터 정리
target = 'y'
x = data.drop(target, axis = 1)
y = data.loc[:, target]
# 날짜 데이터 제거
x.drop('DateTime', axis = 1, inplace = True)
x.head()
④ 가변수화
cat_cols = ['Seasons','Holiday','FuncDay']
x = pd.get_dummies(x, columns = cat_cols, drop_first = True)
⑤ 데이터 분할
-> 시계열 데이터이므로 시간의 흐름에 맞게 분할 해야함
* 뒤에서 30일 : validaiton * 나머지 : train * 30일 : 시간단위 데이터이므로 24 * 30 |
* train_test_split : shuffle(뒤섞기) 옵션을 False로 하면 저장된 순서대로 자름.
i = 30 * 24
x_train, x_val, y_train, y_val = train_test_split(x, y, test_size = i, shuffle = False)
- 이에 대한 그래프
plt.figure(figsize = (20,8))
plt.plot(y_val)
plt.grid()
plt.show()
y_val에 대한 그래프로, X축은 인덱스 번호(8038~8757), Y축은 열 'Y'의 값
-> 이를보면 test_size와 shuffle의 관계를 알 수 있다. y_train은 당연히 0부터 8037까지
즉, 여기서 아래 식과 train_split~ 식은 같다
# 30일 기준으로 분할
i = 30 * 24
x_train, x_val = x[:-i], x[-i:]
y_train, y_val = y[:-i], y[-i:]
⑥ 스케일링 : DL에서 필수
scaler = MinMaxScaler()
x_train = scaler.fit_transform(x_train)
x_val = scaler.transform(x_val)
3. 모델링
① features 입력
# 모든 X 변수의 개수
# num of columns, 피쳐의 개수를 뽑아서 담아라. 18개
# 1차원은 데이터만 있지 방향은 없습니다. -> (3, ) (개수, )
nfeatures = x_train.shape[1]
nfeatures
-> 여기서, x_train의 모든 변수(열) 개수를 가져왔는데,
만약 다중공선성을 위반하거나 & 영향도가 미미하여 제외시킬 변수가 있다면 여기서 바꾸는게 아니라,
x_train을 다시 그에 맞게 전처리 후 모델링을 시작해줘야한다.
② 구조 설계
Node 4 - 2 - 1 - y^ : 일반적인 레이어 패턴
- Node 수 감소
4 -> 2 : 예측 값의 오차를 최소화, 중요한 정보로 묶는 것
- Node 수 증가
3 -> 5 : 입력된 3개의 정보로 더 많은 5개의 정보로 확장
# 메모리 정리 - 꼭 써줘야하는 건 아니지만, 써주면 좋다.
clear_session()
# Sequential 타입 모델 선언
# Sequential의 뜻은 순차적, 연속적이라는 뜻
# 이것은 MLP(MultiLayer Perceptron) 레이어가 순차적으로 쌓여가는 것을 의미.
# Dense
# Perceptron 설게를 위해 -> 문제를 어떻게 학습할래?라는 알고리즘 설계.
# Sequential 타입 모델 선언(입력은 리스트로!)
model1 = Sequential([Dense(8, input_shape = (nfeatures,), activation = 'relu'),
Dense(4, activation = 'relu'),
Dense(1)]) # dense(1)은 자기가 알아서 연결시켜 줌.
# input_shape에 들어갈 데이터는 -> 1차원 데이터(nfeatures, )
# 모델요약
model1.summary()
③ 컴파일
고급언어 -> 기계언어
- Optimizer : 'Adam' - 가중치를 조절(Learning_rate : 보폭 크기, 증가, 감소)하면서 오차를 최소화 시켜라.
- Loss : 'MSE' - 회귀 , 'Binary_crossentrophy' - 분류
# 컴파일
model1.compile(optimizer=Adam(learning_rate=0.01), loss='mse')
④ 학습
- fit(xtrain,ytrain, epochs = 10 : 10번 반복 학습, validation_split = 0.2 : xtrain의 20 %를 검증용으로 만들어 오차 평가)
- medv = w_1 * istat + w_0
- 몇번 가중치(w)를 조절해서 모델('medv')을 찾아갈 것이냐( ep=5 -> 5번, ep=30 -> 30번),
- 가중치를 파라미터라고도 부름
- 이 코드만 다시돌리면 이전에 학습된 위치에서 시작하므로, 모델링 첫 단계부터 다시 실행시켜줘야 함.
- epochs를 같은 값으로 다시 실행해도 다른 그래프가 생성됨 -> 가중치 초기 값이 랜덤으로 지정되기 때문
#학습
#첫번째 history는 단순히 변수명
#두번째 history는 loss, val_loss에 대한 정보를 저장하는용도
history = model1.fit(x_train, y_train, epochs = 50, validation_split=0.2).history
⑤ 학습 곡선
- 한 번의 epoch는 인공 신경망에서 전체 데이터 셋에 대해 forward pass/backward pass 과정을 거친 것을 말함.
즉, 전체 데이터 셋에 대해 한 번 학습을 완료한 상태.
- train_err와 달리 val_err는 값이 들쑥날쑥이므로 과적합.
dl_history_plot(history)
4. 검증
① 모델의 예측값과 실제값에 대해 MSE, MAE를 확인
pred1 = model1.predict(x_val)
# 스케일링된 데이터 원래대로 돌려놓기
# pred1 = pred1 * (y_train_max - y_train_min) + y_train_min
print(f'RMSE : {mean_squared_error(y_val, pred1, squared=False)}')
print(f'MAE : {mean_absolute_error(y_val, pred1)}')
② 그래프로 예측값과 실제값 비교
#예측값과 실제값 비교 그래프
plt.figure(figsize = (20,8))
plt.plot(y_val.values, label = 'actual') # y_val.values ==> 넘파이 어레이가 되면서 인덱스가 0부터 시작
plt.plot(pred1, label = 'pred1')
plt.grid()
plt.legend()
plt.show()
5. 파라미터 튜닝
- 위와 동일한 모델을, Layer 갯수를 증가시키고, epochs를 늘려보았다.
5.1 Layer 변경
5.1.1 기존
# 메모리 정리
clear_session()
# Sequential 타입 모델 선언
model1 = Sequential([Dense(8, input_shape = (nfeatures,), activation = 'relu'),
Dense(4, activation = 'relu'),
Dense(1)])
# 모델요약
model1.summary()
5.1.2 변경
# 메모리 정리
clear_session()
# Sequential 타입 모델 선언
model2 = Sequential([Dense(10, input_shape = (nfeatures,), activation = 'relu'),
Dense(10, activation = 'relu'),
Dense(5, activation = 'relu'),
Dense(1)])
# 모델요약
model2.summary()
5.2 epochs 변경 - (일단은, learning rate 동일)
5.2.1 기존
#학습
history = model1.fit(x_train, y_train, epochs = 50, validation_split=0.2).history
5.2.2 변경
# 컴파일 후 학습
model2.compile(optimizer=Adam(learning_rate=0.01), loss='mse')
history = model2.fit(x_train, y_train, epochs = 200, validation_split=0.2).his
- learning rate가 동일했음에도 값의 변화가 크지 않음.
기존 변경
5.3 결과
- 미세하게 더 좋아짐
'데이터 마이닝 > 딥러닝' 카테고리의 다른 글
3.1 softmax (0) | 2023.03.22 |
---|---|
2. 모델링 간단 요약 - (이진 분류) (0) | 2023.03.22 |
1.1 활성화 함수 Sigmoid, Relu (0) | 2023.03.22 |
Relu (0) | 2023.03.22 |
AIVLE 복습 1. (0) | 2023.03.06 |