과적합(Overfitting) : 훈련에 사용한 데이터에 진행된 학습이 지나치게 진행된 것을 의미. 이는 일반화 오류를 크게 할 수 있으며 복잡도가 오히려 증가할 수 있다.
1) 층이 너무 많을 때 발생
2) 변수가 복잡할 때 발생
3) 테스트와 학습 데이터의 중복일때 발생
과적합(Overfitting) 방지 방법 : 학습을 할 때 사용할 데이터셋과 테스트 전용 데이터셋을 구분. 주로 학습셋과 테스트셋을 분리하기 위해 사이킷런을 사용하고 여기서 train_test_split() 함수를 적용한다.
from sklearn.model_selection import train_test_split
# 학습셋과 테스트셋을 각각 구분, 0.3은 전체 데이터의 30%를 테스트셋으로, 나머지 70(0.7)은 학습셋으로 나눔
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, shuffle=True)
암석과 광물 구분하기
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from sklearn.model_selection import train_test_split
import pandas as pd
# 깃허브 데이터 import
!git clone https://github.com/taehojo/data.git
# 광물 데이터 import
df = pd.read_csv('./data/sonar3.csv', header=None)
# X = 음파 관련 속성, Y = 광물의 종류
X = df.iloc[:,0:60]
y = df.iloc[:,60]
# 학습셋과 테스트셋을 사이킷런의 train_test_split() 함수 사용해 분리
# 전체 데이터의 30%는 테스트셋, 나머지 70%는 학습셋 데이터로 지정
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, shuffle=True)
# 모델 설정(Sequential())
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'])
# 모델 실행(model.fit())
# 시행횟수는 200회, 각 반복 회당 배치 사이즈 크기는 10 단위로 시행
history = model.fit(X_train, y_train, epochs=200, batch_size=10)
# 모델을 테스트셋 적용후 결과 값 출력
score = model.evaluate(X_test, y_test)
print('Test accuracy:', score[1])
모델 성능 향상 방법 : 데이터 보강과 알고리즘 최적화 방식
데이터 보강 방법 | 알고리즘 최적화 방법 |
데이터가 많이 필요. 샘플 수가 많아질 수록 성능이 좋아짐 * 데이터의 크기가 크거나 추가가 어려울 경우 가진 데이터를 적절히 보완하는 방법 사용(시그모이드 함수를 사용해 0~1 사이의 값으로 변환하여 낮은 이상치 배제 혹은 사진 데이터의 경우 사진 크기 축소확대한 것으로도 데이터 인식 대체. 또는 교차 검증 방법이 있음) | 다른 구조로 모델을 변경하며 가장 맞는 최적 구조를 찾는 방법. |
K겹 교차 검증 : 데이터셋을 여러개로 나눈 뒤 하나씩 테스트셋으로 사용하고 나머지를 모두 합한 뒤 학습셋으로 사용
* 주어진 데이터의 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
# 깃허브 데이터 import
!git clone https://github.com/taehojo/data.git
# 광물 데이터 import
df = pd.read_csv('./data/sonar3.csv', header=None)
# X = 음파 관련 속성, Y = 광물의 종류
X = df.iloc[:,0:60]
y = df.iloc[:,60]
# K겹 교차 검증 수 설정
# 5겹인 경우 4개를 학습셋, 나머지 하나를 테스트셋으로 나누어 반복 실시
k = 5
# KFold 함수설정
# 데이터를 원하는 수 만큼 나누어 테스트와 학습셋으로 나누는 사이킷런 제공함수 => 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번의 학습을 실행
# split()함수로 학습셋, 테스트셋으로 분리
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=1)
# verbose 옵션은 학습 과정 출력을 생략(0) 할 것인지 말 것인지(1) 결정
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번 시행에 따라 각각 산출된 정확도가 각 리스트에 저장되고, 저장된 5개의 최종 정확도의 평균이 83% 정도로 나온 것을 알 수 있다.
K겹 교차 검증은 기존에 학습셋 30%, 테스트셋 70%로 나눴을 때보다 모든 데이터를 한 번씩 학습셋과 테스트셋으로 데이터를 활용함으로써 미사용될 데이터 세트에 대한 문제를 해결하고, 보다 더 정확한 정확도를 검출할 수 있다는 장점이 있다.
와인 종류 예측하기
학습셋과 테스트셋을 나누고 여기에 검증셋 데이터를 추가하는 방법 : model.fit() 함수 내에 validation_split 옵션을 추가해 만들 수 있음.
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from sklearn.model_selection import train_test_split
# 깃허브에 준비된 데이터 import
!git clone https://github.com/taehojo/data.git
# 와인 데이터 불러와 df 라는 변수에 저장
df = pd.read_csv('./data/wine.csv', header=None)
# X = 와인의 속성, Y = 와인의 분류 저장
X = df.iloc[:,0:12]
y = df.iloc[:,12]
# 학습셋과 테스트셋으로 분리
# shuffle 옵션 True 설정
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=True)
# 모델 구조 설정
model = Sequential()
# 3개의 은닉층 설정. 30, 12, 8개의 노드 생성. 활성화 함수 Relu
model.add(Dense(30, input_dim=12, activation='relu'))
model.add(Dense(12, activation='relu'))
model.add(Dense(8, activation='relu'))
# 1개의 출력층 설정. 활성화 함수 시그모이드
model.add(Dense(1, activation='sigmoid'))
model.summary()
# 모델 컴파일
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
# 모델 실행
history = model.fit(X_train, y_train, epochs=50, batch_size=500,
validation_split=0.25) # 0.8 x 0.25 = 0.2
# 테스트 결과 출력
score = model.evaluate(X_test, y_test)
print('Test accuracy:', score[1])
에포크(epochs) : 흔히 수행하는 학습 단위를 말하지만, 에포크를 항상 많이 한다해서 이것이 정확도와 비례하지는 않는다.
에포크 실행도중 중간에 가장 높은 정확도가 산출되고 이때의 모델을 중간저장하고 싶다면 케라스에서 제공하는 ModelCheckpoint() 함수를 통해 저장할 수 있다. 이때 verbose 옵션을 True(1) 값을 설정해서 저장되는 현황을 출력할 수 있다.
학습 자동중단 : 학습 도중 테스트셋의 오차가 커지는 경우, 줄어들지 않는 경우 임의로 학습을 자동중단해서 멈추게 할 수 있다.
케라스에서 제공하는 EarlyStopping() 함수를 통해서 수행한다.
자동중단을 사용해 전체 2000회의 에포크 시행 도중 394번째까지만 학습 후 중단된 결과를 확인할 수 있다.
주택 가격 예측하기
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.callbacks import EarlyStopping
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np
# 깃허브 데이터 import
!git clone https://github.com/taehojo/data.git
# 집 값 데이터를 불러와 df 변수에 저장
df = pd.read_csv("./data/house_train.csv")
# 카테고리형 변수를 0과 1로 이루어진 변수로 변환
df = pd.get_dummies(df)
# 결측치를 전체 칼럼의 평균으로 대체
df = df.fillna(df.mean())
# 데이터 사이의 상관관계(correlation 저장)
df_corr = df.corr()
# 집 값과 관련이 큰 것부터 나열
df_corr_sort = df_corr.sort_values('SalePrice', ascending=False)
# 집 값을 제외한 나머지 열을 저장
cols_train = ['OverallQual','GrLivArea','GarageCars','GarageArea','TotalBsmtSF']
X_train_pre = df[cols_train]
# 집 값을 저장
y = df['SalePrice'].values
# 전체의 80%를 학습셋으로, 20%를 테스트셋으로 분리
X_train, X_test, y_train, y_test = train_test_split(X_train_pre, y, test_size=0.2)
# 모델 구조 설정
model = Sequential()
model.add(Dense(10, input_dim=X_train.shape[1], activation='relu'))
model.add(Dense(30, activation='relu'))
model.add(Dense(40, activation='relu'))
model.add(Dense(1))
model.summary()
# 모델 실행
# 손실함수 mean_squared_error(이하 MSE)사용 -> 선형회귀이므로 평균 제곱 오차 손실함수 사용
model.compile(optimizer='adam', loss='mean_squared_error')
# 20번 이상 결과가 향상되지 않으면 자동중단 설정
early_stopping_callback = EarlyStopping(monitor='val_loss', patience=20)
# 모델의 이름설정
modelpath = "./data/model/Ch15-house.hdf5"
# 최적화 모델을 업데이트후 저장
checkpointer = ModelCheckpoint(filepath=modelpath, monitor='val_loss', verbose=0, save_best_only=True)
# 전체의 20%를 검증셋으로 설정
history = model.fit(X_train, y_train, validation_split=0.25, epochs=2000, batch_size=32, callbacks=[early_stopping_callback,checkpointer])
훈련 도중 145번째에서 학습을 중단했으며 이를 바탕으로 상관관계 도출 가능
real_prices = [] # 실제가격 리스트
pred_prices = [] # 예상가격 리스트
X_num = []
n_iter = 0
Y_prediction = model.predict(X_test).flatten()
for i in range(25):
real = y_test[i]
prediction = Y_prediction[i]
print("실제가격: {:.2f}, 예상가격: {:.2f}".format(real, prediction))
real_prices.append(real)
pred_prices.append(prediction)
n_iter = n_iter + 1
X_num.append(n_iter)
실제가격과 예상가격의 결과를 바탕으로 그래프로 시각화(plot() 사용)
plt.plot(X_num, pred_prices, label='predicted price')
plt.plot(X_num, real_prices, label='real price')
plt.legend() # 범례표시
plt.show()
집 값이 추정치와 실제값이 유사한 것을 확인 가능
'통계데이터과학과 및 컴퓨터과학 독서' 카테고리의 다른 글
10. 딥러닝 19-21장 (0) | 2023.12.25 |
---|---|
09. 딥러닝 16-18장 (1) | 2023.12.18 |
07. 딥러닝 10-12장 (0) | 2023.12.04 |
06. 딥러닝 7-9장 (0) | 2023.11.27 |
05. 딥러닝 6장 (0) | 2023.11.20 |