본문 바로가기
[KT AIBLE SCHOOL]에이블스쿨

[KT에이블스쿨] 04.11 딥러닝

by 오동일지 2025. 4. 11.

지난 글에 이어서...


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 - 예측값과 예측 오차 간의 관계를 시각화한 것

- 모델의 품질과 오차 패턴 분석에 유용

- 오차가 특정 방향에 쏠려있다면 모델이 잘못 학습했을 가능성 있음, 오차가 무작위로 분포하면 좋은 모델

 

오차 그래프 작성

  1. 잔차(residuals) = 실제값 - 예측값, 모델이 예측을 얼마나 틀렸는지 계산
  2. 잔차 산점도(Resicual Plot): x축=모델이 예측한 값(y_pred) / y축=예측오차(residuals)
  3. 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. 데이터 전처리

  1. 객체형 데이터의  수치형 변환 및 데이터 결측치 처리
  2. 타켓 변수 변환
  3. 범주형 변수의 원핫 인코딩
  4. 입력(x), 정답(y) 분리
  5. 입력값의 수치형 변수 정규화
  6. 훈련 / 테스트 데이터 분리

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)

- 예측 결과를 분류별로 정리한 혼동 행렬 생성

TN, FP, FN, TP

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))