오늘은 그동안 과제하느라 못한 수업 정리를 해보려 한다.
* 예시 코드 및 자료의 출처는 오즈코딩스쿨로 부터...
1. 결측치 처리
통계적 방식 + 의료 도메인 지식이 동시에 중요
1.1. 결측치가 왜 문제인가?
결측치(NA, Null, NaN)는 단순히 “비어 있는 값”이 아니다.
모델 입장에서는 다음과 같은 문제를 만든다.
- 평균, 분산, 상관계수 같은 통계량이 왜곡됨
- 거리 기반 모델(KNN, SVM)에서 거리 계산 자체가 불가능해짐
- 선형 모델, 트리 모델 모두 입력 품질이 낮아져 성능이 저하됨
즉, 결측치는 모델 학습을 방해하는 직접적인 원인이다.
1.2. 의료 데이터에서 특히 중요한 이유: “0이 결측치일 수 있음”
의료 데이터에서는 숫자 0이 실제 값이 아니라 측정 누락을 의미하는 경우가 많다.
대표적인 예:
- Glucose(혈당) = 0 → 현실적으로 불가능 → 결측 가능성 매우 높음
- BloodPressure(혈압) = 0 → 불가능 → 측정 누락 가능성
- BMI = 0 → 불가능 → 키/몸무게 정보 누락 가능성
- SkinThickness, Insulin도 0이 “미측정”을 의미하는 경우가 많음
이 지점이 중요하다.
isna().sum()가 0이더라도 min 값을 활용하여 실질적으로 결측치가 존재하는지 확인을 해야 한다.
1.3. 결측치 처리 흐름(실습 내용 기반)
- “0이 결측일 가능성이 있는 컬럼만 선택”
- 0을 NaN으로 변환
- Imputer로 대치
# 0이 될 수 없는 Feature 목록
feature_columns = ['glucose', 'blood_pressure', 'skin_thickness', 'insulin', 'bmi']
# 1. '0' 값을 NaN으로 변환
print(f"변환 전 '0' 개수:\n{ (df[feature_columns] == 0).sum() }")
df[feature_columns] = df[feature_columns].replace(0, np.nan)
# 2. 평균값으로 NaN 대치 (Imputation) - 이건 특성에 따라 다르게 대치할 것
imputer = SimpleImputer(strategy='mean')
df[feature_columns] = imputer.fit_transform(df[feature_columns])
print(f"\n대치(Imputation) 후 결측치 개수:\n{df[feature_columns].isnull().sum()}")
여기서 반드시 기억할 점:
모든 0을 결측치로 처리하면 안 된다.
예를 들어, Pregnancies = 0은 정상 값일 수 있음
어떤 값이 비정상인지는 의료 도메인 지식이 결정한다
2. 데이터 스케일링
2.1. 스케일링을 해주는 이유
변수의 단위와 범위가 너무 차이나면, 모델은 값이 큰 변수에 끌려가기 때문.
2.1.1. 스케일링 종류(모델에 따라, 상황에 따라 선택)
0과 1의 확률로 변환?
→ 시그모이드 함수
(큰 숫자 to 작은 숫자) or (작은 숫자 범위 to 넓은 범위) or 왜도가 큰 경우
→ 로그 함수
2.2. 표준화 (Standardization)
모든 변수를 “평균 0, 표준편차 1” 기준으로 변환
sklearn.preprocessing.StandardScaler
변수 간 상대적 분포 형태는 유지하면서 스케일만 맞춤
특징:
- Min-Max 방식보다 극단값에 덜 민감
- 하지만 이상치가 많으면 여전히 영향 받음
- 데이터가 정규 분포를 따를 때 효과적
특히 필요한 모델:
- SVM
- KNN
- 로지스틱 회귀, 선형 회귀 (특히 규제 사용 시)
- 신경망
2.3. 정규화 (Normalization, Min-Max Scaling)
모든 값을 0과 1 사이로 압축
sklearn.preprocessing.MinmaxScaler
장점:
- 모든 변수 범위를 강제로 통일
- 데이터의 최소/최대를 명확하게 알 때 유용
단점:
- 극단값 하나가 있으면 대부분의 값이 매우 좁은 구간으로 몰림
2.4. 강건한 스케일링(Robust Scalng)
중앙값과 사분위 범위(IQR)를 사용
sklearn.preprocessing.RobustScaler
특징:
- 이상치의 영향을 최소화
- 데이터에 이상치가 많을 때 효과적
3. 라벨 인코딩
머신러닝 모델은 문자열을 직접 계산할 수 없다.
따라서 범주형 데이터는 반드시 숫자로 변환해야 한다.
3.1. Label Encoding
범주를 0, 1, 2 같은 숫자로 치환
위험한 이유:
- 모델이 숫자의 크기에 따라 의미를 잘못 부여할 수 있음(서열이 생겨버림)
- 따라서 순서가 없는 명목형 데이터에는 사용하면 위험.
언제 사용 가능한가?
- 실제로 순서가 있는 범주형 데이터
예: 만족도(낮음/보통/높음), 등급(S/A/B/C)
3.2. One-Hot Encoding
범주 개수만큼 새로운 열을 만들고, 해당 범주에 속하는 경우만 1로 채움
순서가 없는 범주형 데이터에 가장 안전
cf) 데이터 전처리 워크플로우 정리
- 1단계. 데이터 탐색 및 문제 진단(EDA 계획 수립)
- 2단계. 결측치 처리(SimpleImputer)
- 3단계. 스케일 조정(StandardScaler, MinMaxScaler)
- 4단계. 범주형 인코딩(숫자나 다른 포맷의 문자로 변환.
sklearn.preprocessing.OneHotEncoder, pandas.get_dummies
(이로 인해 만들어진 것을 더미 변수) ↔ 디코딩)
- 5단계. 이상치 처리(IQR, 도메인 지식 활용)
- 6단계. 분포 변환(로그 변환)
4. 모델 학습
cf) 모델 학습 플로우
- 1단계. 기획
- 2단계. 문제 정의
- 3단계. 데이터 수집
- 4단계. 데이터 전처리
- 5단계. 모델 선정 및 학습
- 6단계. 평가
- 7단계. 서비스 적용(피드백 생성)
- 8단계. 재학습(파이프라인 구축 → *자동화 설정하여 모델 재학습)
cf) *자동화
4.1. 주요 메서드
4.1.1 fit()
데이터로부터 기준이나 규칙을 학습
ex:
- Scaler: 평균과 표준편차를 계산
- Imputer: 대치에 사용할 평균값 계산
- Model: 가중치(weight)를 학습
👉 fit은 기준을 만드는 단계
fit으로 만든 기준을 실제 데이터에 적용
ex:
- 같은 평균/표준편차로 스케일 변환
- 같은 값으로 결측치 대치
👉 transform은 적용하는 단계
fit과 transform을 한 번에 수행
학습 데이터(train)에서만 사용
4.1.4. predict()
학습된 모델로 예측 결과 생성
4.2. 가중치(weight)는 어떻게 만들어지는가?
모델 학습의 본질은 다음 한 문장이다.
오차를 최소화하도록 각 변수의 가중치를 조정하는 과정
4.2.1. 가중치는 손실(loss)을 줄이면서 업데이트된다
- 1) 현재 가중치로 예측
- 2) 실제 값과 비교해 손실 계산
- 3) 손실이 줄어드는 방향으로 가중치 수정
이 과정이 반복되며 모델이 학습된다.
이때 사용되는 대표적인 방식이 "경사하강법"이다.
4.2.2. 스케일링이 가중치에 영향을 주는 이유
- 입력값 스케일이 크면 손실 변화도 커짐
→ 그 변수의 가중치가 과도하게 커질 수 있음
4.3 Regularization(규제)가 필요한 이유
※ 여기서 말하는 정규화는 스케일링이 아니라 규제다.
4.3.1. 가중치가 커지면 왜 위험한가?
- 모델의 과적합(overfitting) 유발 가능.
- 작은 입력 변화에도 예측이 크게 흔들림
- 새로운 데이터에서 성능 급락
4.3.2. 규제의 핵심 아이디어 및 대표적인 규제 방법
- 손실 함수에 “가중치가 커질수록 불리해지는 벌점”을 추가
→ 결과적으로 가중치가 과도하게 커지지 않도록 제어
L2 규제 (Ridge)
- 큰 가중치를 부드럽게 줄임
- 대부분의 가중치를 0에 가깝게 만들지만 완전히 0은 안 됨
- 안정적이고 기본값처럼 많이 사용
L1 규제 (Lasso)
- 일부 가중치를 정확히 0으로 만듦
- 자동 변수 선택 효과가 있음
Elastic Net
cf) “임계점을 넘지 않게 한다”의 정확한 의미
가중치를 강제로 잘라내는 것이 아님
최적화 과정에서 큰 가중치가 손해가 되도록 설계하는 것
5. 모델 성능 평가 방법
5.1. Confusion Matrix

[이미지 출처: Understanding the Confusion Matrix]
예를 들어 Positive: 암환자, Negative: 정상이라고 가정하자
- TP: 실제로 암환자인데 암환자라고 맞힘
- FN: 실제로 암환자인데 정상이라고 잘못 맞힘(매우 위험!!)
- FP: 실제로는 정상인데 암환자라고 오진(생배째기)
- TN: 실제로 정상인데 정상으로 맞힘
의료에서는 FN이 특히 치명적이다.
여기서 중요한건
sklearn의 confusion_matrix는 [[TN, FP], [FN, TP]] 순서로 반환하기 때문에 해석에 유의해야 한다.
5.2. 지표 선택의 기준
5.2.1. Accuracy: 전체 중 맞춘 비율
→ 클래스 불균형에서는 거의 의미 없음
5.2.2. Precision: 환자라고 예측한 것 중 진짜 환자
→ 오진(FP)을 줄이는 관점
5.2.3. Recall(민감도): 실제 환자 중에서 찾아낸 비율
→ 놓침(FN)을 줄이는 관점
→ 의료에서 매우 중요
5.2.4. F1-score: Precision과 Recall의 균형
5.2.5. ROC-AUC: 임계값을 바꿔가며 성능을 종합 평가
5.3. 임계값(Threshold) 관점
-
임계값을 낮추면:
- Recall 증가 (환자 더 많이 발견)
- FP 증가
-
임계값을 높이면:
의료 문제에서는 종종 Recall 우선 전략을 선택한다.