1. 모델의 복잡도
- 너무 단순한 모델 -> train, val 성능이 떨어짐
- 적절히 복잡한 모델 -> 적절한 예측력
- 너무 복잡한 모델 -> train 성능이 높고, val 성능이 떨어짐 -> 과적합
- 복잡하다고 무조건 과적합을 일으키진 않음. 하지만 과할 경우 과적합
1-1. 딥러닝에서 모델의 복잡도를 조절하는 방법
- Epoch와 learning_rate
- hidden layer 수, node 수
- Early Stopping
- Dropout
- 가중치 규제
2. Early Stopping
- epoch가 많으면 과적합 될 수 있음
- 반복횟수가 증가할 수록 val error이 줄어들다가 어느 순간 다시 증가 가능
- val error가 더 이상 줄어들지 않을 경우 멈추는 방법으로 과적합 방지
2-1. 코드
- monitor
- min_delta
- 오차의 최소값에서 얼마나 감소해야 감소로 인정하는 지
- default = 0
- patience
- 오차가 더 이상 줄어들지 않은 상황에서 얼마나 더 학습할 것인지
- default = 0
from keras.callbacks import EarlyStopping
es = EarlyStopping(monitor = 'val_loss', min_delta = 0.01, patience = 5)
model.fit(x_train, y_trin, epochs = 100,
validation_split = 0.2, callbacks = [es])
2-2. 문제점
- 오차율이 가장 낮을 때의 가중치가 아닌, 추가 학습을 진행하였을 때(ex) 오차가 5번 학습할 동안 더 이상 감소하지 않을 경우)의 가중치를 사용
2-3. 해결
- 중간 체크 포인트 저장
- ModelCheckPoint
from keras.callbacks import ModelCheckpoint
cp_path = '/content/best_model.keras'
mcp = ModelCheckpoint(cp_path, monitor = 'val_loss', verbose = 1, save_best_only = True)
model.fit(x_train, y_trin, epochs = 100,
validation_split = 0.2, callbacks = [mcp])
from keras,models import load_model
model = load_model('best_model.keras')
3. Dropout
- 과적합을 줄이기 위한 방법
- 훈련 과정에서 신경망의 일부 뉴런을 임의로 비활성화
- 훈련 배치에서 랜덤하게 선택된 일부 뉴런 제거
- 매 epochs 마다 다른 뉴런을 비활성화 -> 앙상블 효과
3-1. 코드
model = Sequential( [Input(shape = (x_train.shape[1],)),
Dense(128, activation= 'relu'),
Dropout(0.4),
Dense(64, activation= 'relu'),
Dropout(0.4),
Dense(32, activation= 'relu'),
Dropout(0.4),
Dense(1, activation= 'sigmoid')] )
- 보통 0.2 ~ 0.5의 범위 지정
- feature가 적을 경우 rate를 낮추고, 많을 경우 rate를 높임
4. 딥러닝 모델 함수
from tensorflow.keras import Sequential, Input, Model
from tensorflow.keras.layers import Dense, Dropout
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint
from tensorflow.keras.models import load_model
from tensorflow.keras.backend import clear_session
from sklearn.metrics import *
import numpy as np
import matplotlib.pyplot as plt
def deep_learning_model(type, Dense_node = [], act = 'relu', drop_rate = 0,learn = 0.01, min_del = 0, pati_num = 0, epochs_size = 50, ver = 0) :
clear_session()
layer_list = [Input(shape = (x_train.shape[1],))]
if len(Dense_node) != 0 :
for i in range(len(Dense_node)) :
layer_list.append(Dense(Dense_node[i] , activation = act))
layer_list.append(Dropout(drop_rate))
if type == 'regg' :
layer_list.append(Dense(1))
loss_method = 'mse'
elif type == 'binary' :
layer_list.append(Dense(1, activation = 'sigmoid'))
loss_method = 'binary_crossentropy'
elif type == 'multi' :
layer_list.append(Dense(len(np.unique(y_train)), activation = 'softmax'))
loss_method = 'sparse_categorical_crossentropy'
else:
raise ValueError("type은 'regg', 'binary', 'multi' 중 하나여야 합니다.")
model = Sequential(layer_list)
print(model.summary())
model.compile(optimizer=Adam(learning_rate = learn), loss = loss_method)
es = EarlyStopping(monitor = 'val_loss', min_delta = min_del, patience = pati_num)
cp_path = '/content/best_model.keras'
mcp = ModelCheckpoint(cp_path, monitor = 'val_loss', verbose = ver, save_best_only = True)
history = model.fit(x_train, y_train, epochs = epochs_size, validation_split= 0.2, verbose = ver, callbacks = [es, mcp]).history
plt.plot('loss', data=history, label = 'train', marker = '.')
plt.plot('val_loss', data=history, label = 'val', marker = '.')
plt.grid()
plt.legend()
plt.show()
model = load_model(cp_path)
pred = model.predict(x_val)
if type == 'regg' :
print(f'RMSE : {root_mean_squared_error(y_val, pred)}')
print(f'MAE : {mean_absolute_error(y_val, pred)}')
print(f'MAPE : {mean_absolute_percentage_error(y_val, pred)}')
elif type == 'binary' :
pred = np.where(pred >= .5, 1, 0)
print(confusion_matrix(y_val, pred))
print(classification_report(y_val, pred))
else :
pred = pred.argmax(axis=1)
print(confusion_matrix(y_val, pred))
print(classification_report(y_val, pred))