07 모델 성능 검증하기 실습
초음파 광물 예측하기
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%
[모델 성능을 향상시키는 방법]
- 데이터를 보강하는 방법
- 데이터 추가가 어렵거나 추가만으로 성능에 한계가 있을 수 있으므로 가지고 있는 데이터를 적절히 보완해주는 방법 사용
- ex) 사진 크기를 확대/축소한 것을 더하거나 위아래로 조금씩 움직어 넣는 방법
- 알고리즘을 최적화하는 방법
- 먼저 다른 구조로 모델을 바꾸어가며 최적의 구조를 찾음.
- 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겹 교차 검증]
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번의 정확도 측정