AI/모두의 딥러닝

[딥러닝 : Deep Learning] 과적합 해결하기 Solutions for Overfitting

LiDARian 2021. 10. 5. 13:00
반응형


# 데이터 입력
from google.colab import files
uploaded = files.upload()
my_data = 'sonar.csv'

from keras.models import Sequential
from keras.layers.core import Dense
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split

import pandas as pd
import numpy
import tensorflow as tf

# seed 값 설정
seed = 0
numpy.random.seed(seed)
tf.compat.v1.set_random_seed(3)

#데이터 적용
df = pd.read_csv(my_data, header=None)

'''
print(df.info())
print(df.head())
'''

dataset = df.values
X = dataset[:,0:60]
Y_obj = dataset[:,60]

e = LabelEncoder()
e.fit(Y_obj)
Y = e.transform(Y_obj)

 

sklearn 라이브러리의 train_test_split()함수를 통해서 학습셋과 테스트셋을 쉽게 나눌 수 있다.

처음 보는 함수니까 레퍼런스를 살펴보자.

https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html

train_test_split(X, Y, test_size=0.3, random_state=seed)

에서 X는 속성, Y는 클래스를 넣고, test_size로 테스트셋의 비율을 정한다. 그리고 테스트셋을 랜덤으로 정하는데 사용하는 seed값을 random_state에 넣는다.

random_state를 그대로 두면 받아둔 데이터셋의 뒷부분을 테스트셋으로 사용한다.

그리고 test_size만 정의하면 나머지는 다 train_size가 된다.

 

그리고 반환값은 리스트로 반환되기에, ` X_train, X_test, y_train, y_test = train_test_split(...)`형태로 반환값을 받을 수 있다. 외워두자.

이렇게 데이터를 나눠놨으면 딥러닝 모델의 학습도 `model.fit(X_train, Y_train, epochs=130, batch_size=5)`와 같이 학습셋으로 한정하자.

 

# 학습 셋과 테스트 셋의 구분
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.3, random_state=seed)

model = Sequential()
model.add(Dense(24,  input_dim=60, activation='relu'))
model.add(Dense(10, activation='relu'))
model.add(Dense(1, activation='sigmoid'))

model.compile(loss='mean_squared_error',
            optimizer='adam',
            metrics=['accuracy'])

# 학습셋을 이용해서 딥러닝 모델을 학습한다.
model.fit(X_train, Y_train, epochs=130, batch_size=5)

# 테스트셋에 모델 적용
print("\n Test Accuracy: %.4f" % (model.evaluate(X_test, Y_test)[1]))

결과는 다음과 같이 나온다. 과적합 문제가 어느 정도 해결된다. 다만 정확도가 너무 낮다...

 

 


다음과 같이 data set을 k개로 분할해서 학습하면 과적합 문제를 해결할 수 있을 뿐만아니라 정확도가 상승한다.

 

 


또한, 알고리즘에 대한 데이터가 충분하지 않으면 좋은 결과를 낼 수 없다. 이 경우에도 data set을 k개로 분할하는 방법을 사용한다. 이를 k-fold cross validation(k겹 교차 검증)이라 한다.

k-fold cross validation은 data set을 여러 개로 나누어 하나씩 테스트셋으로 사용하고 나머지를 모두 학습셋으로 사용하는 방법이다.

이런 식으로 각 epoch마다 차례로 테스트셋을 변경한다. 

sklearn.model_selection.StratifiedKFold를 이용하면 k겹 교차 검증을 이용할 수 있다.
레퍼런스는 아래 링크를 참고하자.

https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.StratifiedKFold.html

skf = StratifiedKFold(n_splits=10, shuffle=True, random_state=seed)


n_split은 데이터셋을 나누는 회수
shuffle은 데이터셋을 나누기 전에 섞을지 말지를 결정한다.
random_state에 일정한 seed를 주면 일정한 shuffle이 나온다.

실행 예시를 보자

import numpy as np

from sklearn.model_selection import StratifiedKFold

X = np.array([[1, 2], [3, 4], [1, 2], [3, 4]])

y = np.array([0, 0, 1, 1])

skf = StratifiedKFold(n_splits=2)



print(skf)

StratifiedKFold(n_splits=2, random_state=None, shuffle=False)

for train_index, test_index in skf.split(X, y):

# X와 y를 trainset, testset으로 나눈다.

  print("TRAIN:", train_index, "TEST:", test_index)

  X_train, X_test = X[train_index], X[test_index]

  y_train, y_test = y[train_index], y[test_index]

######################

출력 :

TRAIN: [1 3] TEST: [0 2]

TRAIN: [0 2] TEST: [1 3]

 

K Fold를 이용해 학습한 결과는 다음과 같다.

 

# 데이터 입력
from google.colab import files
uploaded = files.upload()
my_data = 'sonar.csv'

!pip install -q tensorflow-gpu==1.15.0
%tensorflow_version 1.x
import tensorflow as tf
import pandas as pd
import numpy

from keras.models import Sequential
from keras.layers.core import Dense
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import StratifiedKFold

# seed 값 설정
seed = 0
numpy.random.seed(seed)
tf.compat.v1.set_random_seed(3)

# 데이터 적용
df = pd.read_csv(my_data, header=None)

dataset = df.values
X = dataset[:,0:60]
Y_obj = dataset[:,60]

e = LabelEncoder()
e.fit(Y_obj)
Y = e.transform(Y_obj)

# 10개의 파일로 쪼갬
n_fold = 10
skf = StratifiedKFold(n_splits=n_fold, shuffle=True, random_state=seed)

# accuracy를 리스트로 선언해서 여러 fold에 대하여 accuracy를 모은다.
accuracy = []

# 모델의 설정, 컴파일, 실행
# 각각의 fold에 대하여 100회 씩 학습을 진행한다.
for train, test in skf.split(X, Y):
    model = Sequential()
    model.add(Dense(24, input_dim=60, activation='relu'))
    model.add(Dense(10, activation='relu'))
    model.add(Dense(1, activation='sigmoid'))
    model.compile(loss='mean_squared_error',
                  optimizer='adam',
                  metrics=['accuracy'])
    model.fit(X[train], Y[train], epochs=100, batch_size=5)
    # accuracy를 리스트로 선언해서 여러 fold에 대하여 accuracy를 모은다.
    k_accuracy = "%.4f" % (model.evaluate(X[test], Y[test])[1])
    accuracy.append(k_accuracy)

# 결과 출력
print("\n %.f fold accuracy:" % n_fold, accuracy)

반응형