import pandas as pd
!git clone https://github.com/taehojo/data.git
df = pd.read_csv('./data/sonar3.csv', header = None)
df.head()
X = df.iloc[:, 0:60]
y = df.iloc[:, 60]
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)
정확도(accuracy)가 매우 높게 나타나는 것을 확인할 수 있음
과적합
- 모델이 학습 데이터셋 안에서는 일정 수준 이상의 예측 정확도를 보이지만, 새로운 데이터에 적용하면 잘 맞지 않는 것을 의미한다
이미지 출처 : 모두의 딥러닝
- 과적합 방지 방법
우선적으로, 학습을 하는 데이터 셋과 테스트할 데이터셋을 완전히 구분하여 학습과 동시에 테스트를 병행하며 진행한다
이미지 출처 : 모두의 딥러닝
- 머신러닝 혹은 딥러닝의 최종 목적은 과거의 데이터를 토대로 새로운 데이터를 예측하는 것
- 따라서, 새로운 데이터에 사용할 모델을 만드는 것이 최종 목적이므로 테스트셋을 만들어 정확한 평가를 병행하는 것이 매우 중요함
- 학습데이터만 가지고 평가할 때, 층을 더하거나 에포크(epochs) 값을 높여 실행 횟수를 늘리면 정확도가 계속해서 올라갈 수 있음
- (학습이 계속되면서 학습셋 에러는 줄어들지만, 테스트셋 에러에서는 과적합 발생)
- 학습을 진행해도 테스트 결과가 더 이상 좋아지지 않는 지점에서 학습을 멈추어야 함
train_test_split()
: 사이킷런의 함수로, 학습셋과 테스트셋으로 분리시키는 함수이다
from sklearn.model_selection import train_test_split
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
import pandas as pd
df = pd.read_csv('./data/sonar3.csv', header = None)
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)
# model.evaluate() 함수는 loss와 accuracy 두 가지를 계산해 출력한다
# 이를 score에 저장하고 accuracy를 출력하도록 범위 설정
print('Test accuracy : ', score[1])
데이터를 이용해 성능을 향상시키려면 우선 충분한 데이터를 가져와 추가하면 됨
하지만 데이터를 추가하는 것 자체가 어렵거나 데이터 추가만으로는 성능에 한계가 있을 수 있음
따라서 가지고 있는 데이터를 적절히 보완해 주는 방법을 사용
예를 들어 사진의 경우 사진 크기를 확대/축소한 것을 더해 보거나 위아래로 조금씩 움직여 넣어 본다
테이블형 데이터의 경우 너무 크거나 낮은 이상치가 모델에 영향을 줄 수 없도록 크기를 적절히 조절할 수 있음
시그모이드 함수를 사용해 전체를 0~1 사이의 값으로 변환하는 것이 좋은 예임
교차 검증 방법을 사용해 가지고 있는 데이터를 충분히 이용하는 방법도 있음
model.save()
를 사용하여 학습결과를 저장한다
from tensorflow.keras.models import Sequential, load_model
# 모델 이름과 저장할 위치를 함께 지정합니다.
model.save('./data/model/my_model.keras')
# 모델이 저장된 위치와 이름까지 적어 줍니다.
model = load_model('./data/model/my_model.keras')
# 불러온 모델을 테스트셋에 적용해 정확도를 구합니다.
score = model.evaluate(X_test, y_test)
print('Test accuracy:', score[1])
데이터가 많을 수록 모델 성능이 향상된다
30%의 테스트 데이터를 학습에 이용할 수 없는 단점을 해결하기 위하여 k겹 교차 검증
이 고안되었음
k겹 교차 검증(k-fold cross validation)
- 데이터 셋을 여러개로 나누어 하나씩 테스트 세승로 사용하고 나머지를 모두 합해서 학습셋으로 사용하는 방법
- 장점 : 데이터의 100% 를 학습셋으로 사용할 수 있는 동시에 테스트 셋으로 사용할 수 있다.
- 예시 ( 5겹 교차 검증)
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
df = pd.read_csv('./data/sonar3.csv', header = None)
X = df.iloc[:, 0:60]
y = df.iloc[:, 60]
k = 5 # 몇 겹으로 나눌지 결정
# k-fold 함수를 불러오고, 분할 전 샘플이 치우지지 않도록 섞어준다
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)
avg_acc_score = sum(acc_score) / k
print('정확도 : ', acc_score)
print('정확도 평균 : ', avg_acc_score)
verbose = 0
을 넣어주면 결과만 출력가능초기 학습:
처음에는 데이터를 그냥 피처(X)와 타겟(y)으로 나누어 학습시키면서 정확도를 확인했지만, 이 방식은 모든 데이터를 학습에 사용하기 때문에, 새로운 데이터에 대한 성능을 알 수 없다는 문제가 있음
과적합 인지:
학습 데이터에서 높은 정확도를 기록하더라도, 새로운 데이터를 테스트했을 때 성능이 떨어질 수 있다는 점에서 과적합(overfitting) 문제가 발생할 수 있음
Train-Test Split 도입:
과적합을 방지하기 위해 데이터를 학습셋과 테스트셋으로 나누어, 학습셋으로 모델을 학습하고 테스트셋으로 성능을 평가할 수 있게 했음
하지만, 여전히 데이터 부족으로 인한 과적합 가능성이 있음
K겹 교차 검증 적용:
데이터가 부족할 때, K겹 교차 검증(K-fold cross validation) 을 사용하여 데이터를 여러 번 학습셋과 테스트셋으로 나누고 각 모델의 성능을 평가했음
이렇게 함으로써 데이터 부족 문제를 해결하고, 모델의 평균 정확도를 계산해 더 신뢰할 수 있는 평가를 할 수 있음