지난 글에 이어서...
7. 모델 평가
회귀 모델은 수치 예측
테스트 데이터로 모델의 예측값과 실제값이 얼마나 가까운지 평가
loss, mae = model.evaluate(X_test, y_test)
print(f"테스트 손실 (MSE): {loss:.2f}")
print(f"테스트 평균 절대 오차 (MAE): {mae:.2f}")
- model.evaluate() : 학습된 모델에 대해 테스트셋 성능 평가
8. 예측 수행
학습에 사용하지 않은 새로운 입력 데이터 전달
y_pred = model.predict(X_test).flatten() # 결과는 (N, 1) 형태의 2차원 배열
#10개의 테스트 데이터의 실제 정답과 예측값 출력
for i in range(10):
print(f"실제값: {y_test[i]:.1f}, 예측값: {y_pred[i]:.1f}")
- predict() 함수는 (샘플 수, 1)형태의 2차원 배열로 나옴
-그래프 시각화나 반복문 출력시 1차원으로 바꾸면 더 편리함 -> .flatten()으로 출력 형태 만들기
- 예측값과 실제값을 출력했을 때, 값이 비슷할수록 성능 good
.flatten(): 1차원 배열(N,)로 변환
9. 시각화
예측 결과 시각화
오차 그래프: Residual Plot - 예측값과 예측 오차 간의 관계를 시각화한 것
- 모델의 품질과 오차 패턴 분석에 유용
- 오차가 특정 방향에 쏠려있다면 모델이 잘못 학습했을 가능성 있음, 오차가 무작위로 분포하면 좋은 모델
오차 그래프 작성
- 잔차(residuals) = 실제값 - 예측값, 모델이 예측을 얼마나 틀렸는지 계산
- 잔차 산점도(Resicual Plot): x축=모델이 예측한 값(y_pred) / y축=예측오차(residuals)
- y=0인 수평선을 기준으로 표시: 모든 점이 선에 가까우면 예측이 정확, 멀어질수록 오차가 큼
import matplotlib.pyplot as plt
residuals = y_test - y_pred
plt.scatter(y_pred, residuals)
plt.axhline(0, color='red', linestyle='--')
학습중 손실의 변화 추이 시각화
모델학습 중 손실(loss)의 변화 추이를 그래프로 그려 확인
학습데이터에 대한 손실값 변화를 에폭별로 선 그래프를 그림
왼쪽은 초기 학습, 오른쪽으로 갈 수록 후반 학습 상태
import matplotlib.pyplot as plt
plt.plot(history.history['loss'], label='Train Loss')
plt.plot(history.history['val_loss'], label='Val Loss')
plt.title('Training Loss Curve')
plt.xlabel('Epoch')
plt.ylabel('Loss (MSE)')
plt.legend()
plt.grid()
plt.show()
- history.history['loss']는 model.fit()이 자동으로 저장해준 값
- history.history[‘val_loss'] 검증 데이터(validation set)에 대한 손실값
- 파랑색선 : 에포크(epoch)별 훈련 데이터 손실 (MSE 기준)
- 주황색선 : 에포크별 검증 데이터 손실 (MSE 기준)
평가 결과 해석
- Train Loss와 Val Loss가 모두 감소하고 있다면 모델이 잘 학습됨
- Val Loss가 오히려 증가하고 있다면 과적합 가능성 있음
- Loss가 진동하거나 급증한다면 학습률 조정 필요
통신사 고객 이탈 예측 실습
1. 라이브러리 가져오기
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
2. 데이터 로딩
url = "파일 이름"
df = pd.read_csv(url)
df.head()
1) 데이터 구조 살피기
df.shape
2) 데이터 요약정보 확인
df.info()
3) 범주형 변수와 수치형 변수 구분
df.describe()
df.describe(include='object')
4) 범주형 컬럼들의 고유값 확인(label 확인용)
for col in df.columns:
if df[col].dtype == 'object':
print(f"[{col}] 고유값: {df[col].unique()}")
5) 이탈 여부(목표 변수) 분포 확인
df['Churn'].value_counts(normalize=True) #normalize 비율로 보기
3. 데이터 전처리
- 객체형 데이터의 수치형 변환 및 데이터 결측치 처리
- 타켓 변수 변환
- 범주형 변수의 원핫 인코딩
- 입력(x), 정답(y) 분리
- 입력값의 수치형 변수 정규화
- 훈련 / 테스트 데이터 분리
4. 모델 구조 정의
model = Sequential([
Dense(128, activation='relu', input_shape=(x_train.shape[1],)),
Dense(62, activation='relu'),
Dense(1, activation='sigmoid')
])
5. 모델 컴파일
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
학습방법 - adam
손실 함수 - 이진분류용
평가지표 - 전체 샘플 중 정확히 예측한 비율 평가지표
6. 모델 학습
실제 데이터로 가중치를 조정하며 모델을 학습.
모델 학습 시 조기종료(EarlyStopping)를 적용하여 과적합 방지
가장 성능이 좋은 모델만 저장하기 위한 콜백(callback)함수 설정
1) 클래스 가져오기
from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint
2) ModelCheckpoint 콜백 설정
checkpoint = ModelCheckpoint('model.keras', monitor='val_loss', save_best_only=True, verbose=1)
model.keras : 모델 가중치를 저장할 파일 이름
monitor='val_loss' : 검증 손실을 기준으로 가장 작을 때를 저장해서 성능 추적
save_best_only=True : 검증 손실이 개선된 경우만 저장
3) EarlyStopping 콜백 설정
early_stop = EarlyStopping(monitor='val_loss', patience=10, restore_best_weights=True)
patience=10 : 10에폭 연속으로 개선이 없으면 학습 중단
restore_best_weights=True : 가장 성능이 좋았던 가중치로 복원
4)콜백 적용
history = model.fit(X_train, y_train,
epochs=100, batch_size=32,
validation_split=0.2,
callbacks=[early_stop, checkpoint],
verbose=1)
7. 모델 평가
loss, acc = model.evaluate(X_test, y_test)
print(f"Test Accuracy: {acc:.2%}")
학습된 모델에 대해 테스트 셋 성능 평가
(입력 데이터, 실제 정답 라벨)
평가지표 : 정확도
8. 예측 수행
from tensorflow.keras.models import load_model
model = load_model('model.keras')
- 저장된 최적 이진 분류 모델 불러오기
from sklearn.metrics import classification_report, confusion_matrix
y_pred_prob = model.predict(X_test)
y_pred = (y_pred_prob > 0.5).astype(int)
- 테스트 데이터에 대해 예측 수행
- 확률값 기준으로 이진 분류 : 0.5보다 크면 1, 작으면 0
from sklearn.metrics import confusion_matrix, classification_report
confusion_matrix(y_test, y_pred)
- 예측 결과를 분류별로 정리한 혼동 행렬 생성
print(classification_report(y_test, y_pred))
- 분류 성능 리포트: 정밀도, 재현율 등 출력
전체 정확도 : 79%
정밀도: 62%
재현율: 55%
9. 시각화
print(history.history.keys())
딕셔너리 형태로 각 key에 대한 에폭별 값을 리스트로 저장
1) 손실 곡선 시각화
import matplotlib.pyplot as plt
plt.plot(history.history['loss'], label='Train Loss')
plt.plot(history.history['val_loss'], label='Val Loss')
plt.title('Loss Curve')
plt.xlabel('Epochs')
plt.ylabel('Binary Crossentropy')
plt.legend()
2) 정확도 곡선 시각화
import matplotlib.pyplot as plt
plt.plot(history.history['accuracy'], label='Accuracy')
plt.plot(history.history['val_accuracy'], label='Val Accuracy')
plt.title('Model Accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend(['Train', 'Validation'], loc='lower right')
10. 모델의 성능 개선
재현율 개선 방법 : threshold 조정, class_weight, 모델 구조 개선 등
오버피팅 해소 방법 : 일반화 성능 개선을 위해 EarlyStopping, Dropout, 정규화 등
예측 임계값(Threshold) 조정
모델은 기본적으로 0.5를 기준으로 예측 확률을 0, 1로 나눔
- 더 많은 데이터이탈(1)을 예측하게 되어 재현율이 증가할 수 있음
- 임계값이 너무 낮으면 정밀도 하락 가능성 o
class_weight 사용 : 이탈 클래스 가중치 부여
학습데이터에서 이탈(1)이 적은 불균형 데이터인 경우, 모델은 잔류(0)를 더 많이 예측하려는 경향임
- 이탈 클래스에 더 높은 가중치를 주면, 모델이 이탈자를 더 중요하게 학습하게 됨
- 가중치를 너무 높이면 비이탈을 이탈로 잘못 예측할 수 있음
모델 구조 개선 : 복잡도와 일반화 향상
- Dropout: 과적합 방지
- BatchNormalization : 학습 안정화
- Layer 추가 : 더 깊은 표현력 확보
구조가 너무 복잡하면 오히려 학습이 어려워질 수 있으므로 성능 확인 후 조정
<모델 구조 개선 실습>
model = Sequential([
Dense(128, activation='relu', input_shape=(X_train.shape[1],), kernel_regularizer=l2(0.001)),
BatchNormalization(),
Dropout(0.5),
Dense(64, activation='relu', kernel_regularizer=l2(0.001)),
Dropout(0.3),
Dense(1, activation='sigmoid')
])
층(layer) | 뉴런 수 | 활성화 함수 | 설명 |
입력층 + Dense | 128 | ReLU | 입력 특성 정의, 첫 번째 은닉층 정의, L2정규화를 통해 복잡도 감소 |
BatchNormalization | - | - | 은닉층 출력값을 정규화하여 학습 안정화 및 속도 향상 |
Dropout | - | - | 50%의 뉴런을 무작위로 제거하여 과적합 방지 |
Dense | 64 | ReLU | 두 번째 은닉층 정의, 추가적인 특성 학습, L2정규화를 통해 복잡도 감소 |
Dropout | - | - | 30%의 뉴런 드롭아웃 적용 |
출력층 (Dense) | 1 | Sigmoid | 확률(0~1)을 출력하는 이진 분류용 출력층 |
#컴파일
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
콜백 설정
early_stop = EarlyStopping(monitor='val_loss',
patience=5, restore_best_weights=True)
checkpoint = ModelCheckpoint(
'best_model.keras', monitor='val_loss', save_best_only=True, verbose=1
)
조기 종료 , 최적 모델 저장 설정
모델 학습
history = model.fit(
X_train, y_train,
validation_split=0.2,
epochs=100,
batch_size=32,
callbacks=[early_stop, checkpoint],
verbose=1
)
검증데이터 설정, 반복횟수 설정, 콜백함수 설정 등
모델 평가
loss, acc = model.evaluate(X_test, y_test)
print(f"Test Accuracy: {acc:.2%}")
시각화
손실 곡선 시각화
import matplotlib.pyplot as plt
plt.plot(history.history['loss'], label='Train Loss')
plt.plot(history.history['val_loss'], label='Val Loss')
plt.title('Loss Curve')
plt.xlabel('Epoch')
plt.ylabel('Binary Crossentropy')
plt.legend()
plt.grid()
plt.show()
정확도 곡선 시각화
import matplotlib.pyplot as plt
plt.plot(history.history['accuracy'], label='Accuracy')
plt.plot(history.history['val_accuracy'], label='Val Accuracy')
plt.title('Model Accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend(['Train', 'Validation'], loc='lower right')
결과 예측
from sklearn.metrics import classification_report, confusion_matrix
y_pred_prob = model.predict(X_test)
y_pred = (y_pred_prob > 0.5).astype(int)
#혼동 행렬
print(confusion_matrix(y_test, y_pred))
print(classification_report(y_test, y_pred))
'[KT AIBLE SCHOOL]에이블스쿨' 카테고리의 다른 글
[KT에이블스쿨 기자단] DX 7기 미니 프로젝트 1차 후기 (1) | 2025.04.15 |
---|---|
[미니프로젝트 1차] 산출물 (2) | 2025.04.15 |
[KT에이블스쿨] 04.10 딥러닝 (0) | 2025.04.10 |
[KT에이블스쿨] 04.09 머신러닝 회귀 (1) | 2025.04.09 |
[KT에이블스쿨] 04.08 전처리, 머신러닝 (1) | 2025.04.08 |