- 초음파 광물 예측 실험을 텐서플로로 재현해보고 정확도를 평가하는 방법과 성능을 향상시키는 기법 수행
1. 데이터 확인과 예측 실행
- 61개의 열과 일반 암석일 경우 0, 광석일 경우 1의 클래스 값을 가짐
import pandas as pd
# 깃허브에 준비된 데이터를 가져옵니다.
!git clone https://github.com/taehojo/data.git
# 광물 데이터를 불러옵니다.
df = pd.read_csv('./data/sonar3.csv', header=None)
# 첫 5줄을 봅니다.
df.head()
- 광석 111개, 암석 97개로 총 208개의 샘플들로 구성
- 1~60번째 열을 X 변수에 저장하고 광물의 종류는 y로 저장
# 일반 암석(0)과 광석(1)이 몇 개 있는지 확인
df[60].value_counts()
# 음파 관련 속성을 X로, 광물의 종류를 y로 저장
X = df.iloc[:,0:60]
y = df.iloc[:,60]
[output]
1 111
0 97
Name: 60, dtype: int64
- 딥러닝 200번 실행 후 정확도가 100%인 과적합된 모델 생성됨
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)
[output]
Epoch 1/200
21/21 [==============================] - 4s 4ms/step - loss: 0.6951 - accuracy: 0.5000
Epoch 2/200
21/21 [==============================] - 0s 3ms/step - loss: 0.6881 - accuracy: 0.5673
Epoch 3/200
21/21 [==============================] - 0s 3ms/step - loss: 0.6827 - accuracy: 0.6058
...
Epoch 199/200
21/21 [==============================] - 0s 2ms/step - loss: 0.0349 - accuracy: 1.0000
Epoch 200/200
21/21 [==============================] - 0s 2ms/step - loss: 0.0327 - accuracy: 1.0000
2. 과적합 이해하기
- 과적합(overfitting)이란 모델이 학습 데이터셋 안에서는 높은 예측 정확도를 보이지만, 새로운 데이터에 적용하면 잘 맞지 않는 현상
- 그림처럼 선은 주어진 샘플에만 최적화 되어있어 새로운 데이터에 적용하면 정확한 분류가 어려워짐
3. 학습셋과 테스트셋
- 과적합을 방지하기 위한 방법 중 하나는 학습,테스트 데이터셋을 구분하여 학습과 동시에 테스트를 병행하며 진행
- 학습 데이터셋으로 학습된 결과 파일을 모델이라고 함
- 나머지 테스트 데이터셋으로 모델에 적용하여 정확도를 살펴보면 학습이 얼마나 잘 되어있는지 알 수 있음
- 머신러닝의 최종목적은 새로운 데이터에 사용할 모델을 만드는 것이므로 테스트셋을 만들어 정확한 평가를 병행해야 함
- 아래의 그래프처럼 학습이 깊어져 학습셋 내부에서 성공률은 높아져도 테스트셋에 효과가 없다면 과적합이 일어나고 있는 것
- 학습을 진행해도 더 이상 테스트 결과가 좋아지지 않는 지점이 학습 정도가 가장 적절한 것
- 사이킷런의 train_test_split()를 이용하여 학습셋과 테스트셋 분리
- 만들어진 모델을 테스트셋에 적용할 때는 model.evaluate() 사용
- loss,accuracy 두 가지를 계산하여 출력해줌
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, shuffle=True)
# 모델을 테스트셋에 적용해 정확도 구하기
score=model.evaluate(X_test, y_test)
print('Test accuracy:', score[1])
[output]
2/2 [==============================] - 0s 2ms/step - loss: 0.4214 - accuracy: 0.8413
Test accuracy: 0.841269850730896
4. 모델 저장과 재사용
- model.save()를 사용하여 학습결과를 저장
- 모델을 다시 불러오려면 케라스 API의 load_model 사용
# 모델 이름과 저장할 위치를 함께 지정
model.save('./data/model/my_model.hdf5')
from tensorflow.keras.models import Sequential, load_model
# 테스트를 위해 조금 전 사용한 모델을 메모리에서 삭제
del model
# 모델 새로 불러오기
model = load_model('./data/model/my_model.hdf5')
# 불러온 모델을 테스트셋에 적용해 정확도 구하기
score=model.evaluate(X_test, y_test)
print('Test accuracy:', score[1])
[output]
2/2 [==============================] - 0s 2ms/step - loss: 0.4214 - accuracy: 0.8413
Test accuracy: 0.841269850730896
5. K겹 교차 검증
- 실무에서는 데이터를 확보하는 것이 쉽지 않거나 많은 비용이 발생하므로 가지고 있는 데이터를 십분 활용해야 함
- K겹 교차검증이란 데이터 셋을 여러개로 나누어 하나씩 테스트 데이터셋, 나머지는 학습셋으로 사용하는 방법
- 이는 가지고있는 데이터 100%를 학습셋으로 사용할 수 있고, 테스트셋으로도 사용할 수 있음
- 사이킷런의 KFold()를 통해 학습셋과 테스트셋으로 나누어 사용
- 몇 개의 파일로 나눌지 k 변수에 저장
- 샘플이 치우치지않게 shuffle 함수는 True 설정
- split()에 의해 k개의 학습셋, 테스트셋으로 분리되며 for문에 의해 k번 반복
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], yiloc[test_index]
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
# 광물 데이터 dataframe 불러오기
df = pd.read_csv('./data/sonar3.csv', header=None)
# 음파 관련 속성을 X로, 광물의 종류를 y로 저장
X = df.iloc[:,0:60]
y = df.iloc[:,60]
# 폴드 수 설정
k=5
# KFold 함수 호출. 분할하기 전에 샘플이 치우치지 않도록 shuffle
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 train_index , test_index in kfold.split(X): # for 문에 의해서 k번 반복합니다. spilt()에 의해 k개의 학습셋, 테스트셋으로 분리됩니다.
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)
[output]
# 몇 겹으로 나눌 것인지를 정합니다.
k=5
# KFold 함수를 불러옵니다. 분할하기 전에 샘플이 치우치지 않도록 섞어 줍니다.
kfold = KFold(n_splits=k, shuffle=True)
# 정확도가 채워질 빈 리스트를 준비합니다.
acc_score = []
def model_fn():
…
# 결과를 출력합니다.
print('정확도:', acc_score)
print('정확도 평균:', avg_acc_score)
2/2 [==============================] - 0s 2ms/step - loss: 1.0080 - accuracy: 0.7381
2/2 [==============================] - 0s 2ms/step - loss: 0.7071 - accuracy: 0.8095
WARNING:tensorflow:5 out of the last 9 calls to <function Model.make_test_function.<locals>.test_function at 0x000001EDE50D60D0> triggered tf.function retracing. Tracing is expensive and the excessive number of tracings could be due to (1) creating @tf.function repeatedly in a loop, (2) passing tensors with different shapes, (3) passing Python objects instead of tensors. For (1), please define your @tf.function outside of the loop. For (2), @tf.function has experimental_relax_shapes=True option that relaxes argument shapes that can avoid unnecessary retracing. For (3), please refer to https://www.tensorflow.org/guide/function#controlling_retracing and https://www.tensorflow.org/api_docs/python/tf/function for more details.
2/2 [==============================] - 0s 2ms/step - loss: 0.3312 - accuracy: 0.8810
WARNING:tensorflow:6 out of the last 11 calls to <function Model.make_test_function.<locals>.test_function at 0x000001EDE5112AF0> triggered tf.function retracing. Tracing is expensive and the excessive number of tracings could be due to (1) creating @tf.function repeatedly in a loop, (2) passing tensors with different shapes, (3) passing Python objects instead of tensors. For (1), please define your @tf.function outside of the loop. For (2), @tf.function has experimental_relax_shapes=True option that relaxes argument shapes that can avoid unnecessary retracing. For (3), please refer to https://www.tensorflow.org/guide/function#controlling_retracing and https://www.tensorflow.org/api_docs/python/tf/function for more details.
2/2 [==============================] - 0s 2ms/step - loss: 0.4377 - accuracy: 0.9024
2/2 [==============================] - 0s 3ms/step - loss: 0.6416 - accuracy: 0.7317
정확도: [0.738095223903656, 0.8095238208770752, 0.8809523582458496, 0.9024389982223511, 0.7317073345184326]
정확도 평균: 0.8125435471534729
'데이터 > 딥러닝' 카테고리의 다른 글
[모두의 딥러닝] Chapter 5 | 딥러닝 활용하기 - 컨볼루션 신경망(CNN) (0) | 2023.02.20 |
---|---|
[모두의 딥러닝] Chapter 4 | 딥러닝 기본기 다지기 - 모델 성능 향상시키기 (0) | 2023.02.14 |
[모두의 딥러닝] Chapter 4 | 딥러닝 기본기 다지기 - 모델 설계, 다중분류 문제 해결 (0) | 2023.02.13 |
[모두의 딥러닝] Chapter 3 | 신경망의 이해 - 오차 역전파 (0) | 2023.02.04 |
[모두의 딥러닝] Chapter 3 | 신경망의 이해 - MLP (0) | 2023.02.04 |