Theory/Deep Learning

07 모델 성능 검증하기 실습

Orangetasteboy 2023. 7. 11. 00:16

초음파 광물 예측하기

colab에서 실습

 

[데이터의 확인과 예측 실행]

# pandas 라이브러리를 불러옵니다.
import pandas as pd

# 깃허브에 준비된 데이터를 가져옵니다.
!git clone https://github.com/taehojo/data.git

# 광물 데이터를 불러옵니다.
df = pd.read_csv('./data/sonar3.csv', header=None)

df.head() # 첫 다섯 줄을 봅니다.

전체가 61개의 열로 구성

마지막 열은 광물의 종류 표시

일반 암석은 0, 광석은 1로 표시

첫 번째 열부터 60번째 열까지는 음파 주파수의 에너지를 0에서 1 사이의 숫자로 표시

 

df[60].value_counts()

광석이 111개, 일반 암석이 97개

총 208개의 샘플

 

X = df.iloc[:,0:60]
y = df.iloc[:,60]

1~60번째 열을 x변수에 저장

광물의 종류는 y변수에 저장

 

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense

# 모델을 설정합니다.
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='binary_crossentropy', optimizer='adam', 
metrics=['accuracy'])

# 모델을 실행합니다.
history = model.fit(X, y, epochs=200, batch_size=10)

딥러닝을 실행하여 200번 반복하니 정확도가 100%  출력

 

[과적합 이해하기]

 

과적합(Overfitting)

  • 모델이 학습 데이터셋 안에서는 일정 수준 이상의 예측 정확도를 보이지만, 새로운 데이터에 적용하면 잘 맞지 않는 것
  • 층이 너무 많거나 변수가 복잡하거나 테스트셋과 학습셋이 중복될 때 발생
  • 딥러닝은 학습 단계에서 입력층, 은닉층, 출력층의 노드들에 상당히 많은 변수가 투입되기 때문에 과적합에 주의

 

과적합 방지법

  • 학습을 하는 데이터셋과 이를 테스트할 데이터셋을 완전히 구분한 후 학습과 동시에 테스트를 병행하며 진행

 

from sklearn.model_selection import train_test_split

# 학습셋과 테스트셋을 구분합니다.
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, shuffle=True)

사이킷런의 train_test_split() 함수를 사용하여 학습셋을 70%, 테스트셋을 30%로 설정

test_size는 테스트셋의 비율

 

score = model.evaluate(X_test, y_test)
print('Test accuracy:', score[1])

model.evaluate() 함수를 사용하여 기존에 만들어진 모델을 테스트셋에 적용

model.evaluate() 함수는 loss와 accuracy, 두 가지를 계산해 출력하고 이것을 score로 저장하고 accuracy로 출력하도록 범위 설정

 

[학습셋과 테스트셋을 구분하여 재실행]

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from sklearn.model_selection import train_test_split

import pandas as pd

# 깃허브에 준비된 데이터를 가져옵니다.
!git clone https://github.com/taehojo/data.git

# 광물 데이터를 불러옵니다.
df = pd.read_csv('./data/sonar3.csv', header=None)

# 음파 관련 속성을 X로, 광물의 종류를 y로 저장합니다.
X = df.iloc[:,0:60]
y = df.iloc[:,60]

# 학습셋과 테스트셋을 구분합니다.
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, shuffle=True)

# 모델을 설정합니다.
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='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

# 모델을 실행합니다.
history = model.fit(X_train, y_train, epochs=200, batch_size=10)

# 모델을 테스트셋에 적용해 정확도를 구합니다.
score = model.evaluate(X_test, y_test)
print('Test accuracy:', score[1])

학습셋을 이용해 200번 학습했을 때 정확도는 82.54%

따로 저장해 둔 테스트셋에 이 모델을 적용하면 정확도는 82.53%

 

[모델 성능을 향상시키는 방법]

  1. 데이터를 보강하는 방법
    • 데이터 추가가 어렵거나 추가만으로 성능에 한계가 있을 수 있으므로 가지고 있는 데이터를 적절히 보완해주는 방법 사용
    • ex) 사진 크기를 확대/축소한 것을 더하거나 위아래로 조금씩 움직어 넣는 방법
  2. 알고리즘을 최적화하는 방법
    • 먼저 다른 구조로 모델을 바꾸어가며 최적의 구조를 찾음.
    • ex) 은닉층의 개수나 안에 들어갈 노드의 수, 최적화 함수 종류 변경 등

 

[모델 저장과 재사용]

학습이 끝나면 만든 모델을 저장하여 이를 불러와 재사용 가능

 

# 모델 이름과 저장할 위치를 함께 지정합니다.
model.save('./data/model/my_model.hdf5')

model.save() 함수를 이용해 모델 이름을 적어 학습 결과 저장

hdf5 파일 포맷은 주로 과학 기술 데이터 작업에서 사용, 크고 복잡한 데이터 저장에 사용

 

from tensorflow.keras.models import Sequential, load_model

모델을 다시 불러오려면 케라스 API의 load_model 사용

 

del model

테스트를 위해 조금 전 만든 모델을 메모리에서 삭제

 

# 모델이 저장된 위치와 이름까지 적어 줍니다.
model = load_model('./data/model/my_model.hdf5')

load_model() 함수를 사용하여 조금 전 저장한 모델을 불러옴.

 

score = model.evaluate(X_test, y_test)
print('Test accuracy:', score[1])

불러온 모델을 테스트셋에 적용하여 정확도 측정

 

[k겹 교차 검증]

학습셋과 테스트셋을 설정할 경우 테스트셋은 학습에 이용할 수 없다는 단점 발생

 

이를 해결하기 위해 k겹 교차 검증 고안

 

k겹 교차 검증(k-fold Cross Validation)

데이터셋을 여러 개로 나누어 하나씩 테스트셋으로 사용하고 나머지를 모두 합해서 학습셋으로 사용하는 방법

 

가지고 있는 데이터의 100%를 학습셋과 테스트셋으로 사용 가능

 

5겹 교차 검증

 

[5겹 교차 검증]

from sklearn.model_selection import KFold
k = 5
kfold = KFold(n_splits=k, shuffle=True)
acc_score = []

for train_index, test_index in kfold.split(X):
    X_train, X_test = X.iloc[train_index,:], X.iloc[test_index,:]  
    y_train, y_test = y.iloc[train_index], y.iloc[test_index]

사이킷런 라이브러리의 kFold() 함수로 데이터를 원하는 수만큼 나누어 각각 학습셋과 테스트셋으로 사용

변수 k에 몇 개의 파일로 나눌 것인지 설정

샘플이 어느 한쪽에 치우치지 않도록 shuffle 옵션을 True로 설정

acc_score라는 정확도가 채워질 빈 리스트 정의

split()에 의해 k개의 학습셋, 테스트셋으로 분리되며 for 문에 의해 k번 반봅

 

accuracy = model.evaluate(X_test, y_test)[1] # 정확도를 구합니다.
acc_score.append(accuracy)                   # acc_score 리스트에 저장합니다.

k번의 학습이 끝나면 각 정확도들을 취합해 모델 성능 평가

 

[k겹 교차 검증을 적용하여 재실행]

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from sklearn.model_selection import KFold
from sklearn.metrics import accuracy_score

import pandas as pd

# 깃허브에 준비된 데이터를 가져옵니다.
!git clone https://github.com/taehojo/data.git

# 광물 데이터를 불러옵니다.
df = pd.read_csv('./data/sonar3.csv', header=None)

# 음파 관련 속성을 X로, 광물의 종류를 y로 저장합니다.
X = df.iloc[:,0:60]
y = df.iloc[:,60]

# 몇 겹으로 나눌 것인지 정합니다.
k = 5

# KFold 함수를 불러옵니다. 분할하기 전에 샘플이 치우치지 않도록 섞어 줍니다.
kfold = KFold(n_splits=k, shuffle=True)

# 정확도가 채워질 빈 리스트를 준비합니다.
acc_score = []

def model_fn():
    model = Sequential() # 딥러닝 모델의 구조를 시작합니다.
    model.add(Dense(24, input_dim=60, activation='relu'))
    model.add(Dense(10, activation='relu'))
    model.add(Dense(1, activation='sigmoid'))
    return model

# k겹 교차 검증을 이용해 k번의 학습을 실행합니다.
# for 문에 의해 k번 반복합니다.
# split()에 의해 k개의 학습셋, 테스트셋으로 분리됩니다.
for train_index, test_index in kfold.split(X): 
    X_train, X_test = X.iloc[train_index,:], X.iloc[test_index,:]  
    y_train, y_test = y.iloc[train_index], y.iloc[test_index]

    model = model_fn()
    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
    history = model.fit(X_train, y_train, epochs=200, batch_size=10, verbose=0) 
    
    accuracy = model.evaluate(X_test, y_test)[1] # 정확도를 구합니다.
    acc_score.append(accuracy)                   # 정확도 리스트에 저장합니다.

# k번 실시된 정확도의 평균을 구합니다.
avg_acc_score = sum(acc_score) / k

# 결과를 출력합니다.
print('정확도: ', acc_score)
print('정확도 평균: ', avg_acc_score)

5번의 정확도 측정