NVIDIA NCA-GENL

NVIDIA NCA-GENL 시험 노트개념 정리17 MIN

데이터 전처리와 피처 엔지니어링

결측치 대치, 표준화와 정규화, 원-핫·레이블 인코딩, 텍스트 정제와 중복 제거, 파생 변수, 클래스 불균형과 샘플링, 학습·검증·테스트 분할을 누수 없이 처리하는 순서로 정리합니다.

07편에서 데이터를 보고 문제를 찾았다면, 이번에는 고칩니다. 전처리(preprocessing)는 원시 데이터를 모델이 받을 수 있는 모양으로 다듬는 일이고, 피처 엔지니어링(feature engineering)은 그 과정에서 모델이 쓰기 좋은 입력 변수를 새로 만드는 일입니다. 둘을 하나로 묶는 원칙이 있습니다 — 전처리에 쓰는 통계값은 학습 데이터에서만 구한다는 것입니다. 이 원칙을 어기는 것이 데이터 누수(data leakage), 곧 평가할 때 써야 할 정보가 학습에 새어 들어가 성능이 부풀려지는 현상이고, 이 노트의 모든 절이 그 원칙 위에 섭니다.

결측치 대치

단순 대치

대치(imputation)는 빈칸을 그럴듯한 값으로 채우는 일입니다. 가장 흔한 것이 열의 대표값으로 채우는 단순 대치입니다.

방법 맞는 데이터 주의점
평균 대칭에 가까운 수치형 이상치에 끌려간다
중앙값 꼬리가 긴 수치형 분산이 줄어든다
최빈값 범주형 한 범주가 과하게 늘어난다
상수 「없음」 자체가 뜻이 있을 때 새 범주가 생긴다

어느 방법이든 채운 값은 모두 같으므로 그 열의 분산이 실제보다 작아집니다. 결측 비율이 크면 이 왜곡도 커져서, 절반 넘게 빈 열은 채우기보다 버리는 쪽을 먼저 검토합니다. 결측이 있는 행을 통째로 지우는 방법도 있지만, 결측이 특정 집단에 몰려 있으면 그 집단이 데이터에서 사라집니다.

결측 표시와 모델 기반 대치

빈칸이었다는 사실 자체가 정보일 때가 있습니다. 소득을 적지 않은 고객이 따로 모인 집단이라면, 대치와 함께 income_missing 같은 0·1 열을 더해 그 사실을 모델에 넘깁니다. 이것을 결측 표시 변수라 합니다. 더 정교하게는 다른 열로 빈 값을 예측하는 모델 기반 대치(k-최근접 이웃 대치, 반복 대치)를 씁니다. 어느 방법이든 대치에 쓰는 평균·모델은 학습 데이터에서만 적합하고, 검증·테스트 데이터에는 그 값을 그대로 적용합니다.

스케일링

피처마다 단위와 범위가 다르면 거리 기반 모델(k-NN, SVM)과 경사하강법으로 학습하는 모델이 큰 범위의 피처에 휘둘립니다. 연봉(수천만)과 나이(수십)를 그대로 넣으면 거리 계산이 사실상 연봉만 보게 됩니다. 범위를 맞추는 두 방법이 있습니다.

표준화

표준화(standardization)는 평균을 빼고 표준편차로 나눠 평균 0, 표준편차 1로 옮기는 변환입니다.

z=x−μσz = \frac{x - \mu}{\sigma}

[10,20,30,40,50][10, 20, 30, 40, 50] 이면 평균이 30이고, 편차 제곱의 평균이 200이라 표준편차가 200≈14.14\sqrt{200} \approx 14.14 입니다. 50은 20/14.14≈1.4120 / 14.14 \approx 1.41 이 됩니다. scikit-learn의 StandardScaler는 nn 으로 나눈 표준편차를 씁니다. 값의 범위를 한정하지 않으므로 이상치가 있어도 다른 값들이 한쪽으로 짓눌리지 않습니다.

정규화

정규화(normalization)는 여기서는 최소·최대를 써서 값을 0~1 사이로 옮기는 min-max 스케일링을 말합니다. 01편의 정규화(L1·L2·드롭아웃)는 과적합을 막는 기법이라 이름만 같고 전혀 다른 것입니다.

x′=x−xmin⁡xmax⁡−xmin⁡x' = \frac{x - x_{\min}}{x_{\max} - x_{\min}}

같은 데이터에서 40은 (40−10)/40=0.75(40 - 10) / 40 = 0.75 입니다. 범위가 정해져 있어 이미지 픽셀처럼 경계가 분명한 값에 잘 맞지만, 최댓값 자리에 이상치가 하나 있으면 나머지가 모두 0 근처로 몰립니다. 결정 트리 계열은 값의 순서만 보므로 두 스케일링 모두 결과에 거의 영향을 주지 않습니다.

범주형 인코딩

원-핫 인코딩

원-핫 인코딩(one-hot encoding)은 범주 하나마다 0·1 열을 하나씩 만들고, 해당하는 열에만 1을 적는 방식입니다. 색상이 빨강·파랑·초록이면 열 셋이 생기고 파랑은 [0,1,0][0, 1, 0] 입니다. 범주 사이에 없는 순서를 만들어 내지 않는 것이 장점입니다. 대신 범주 수만큼 열이 늘어서, 우편번호처럼 범주가 수천인 열에는 열이 폭증하고 대부분이 0인 희소 행렬이 됩니다. 학습 때 없던 범주가 추론 때 들어올 수 있으므로 handle_unknown="ignore" 같은 처리를 정해 둡니다.

레이블 인코딩

레이블 인코딩(label encoding)은 범주마다 정수 하나를 붙입니다. 빨강 0, 파랑 1, 초록 2처럼 열이 하나로 끝나지만, 선형 모델과 신경망은 「초록이 빨강의 두 배」라는 없는 관계를 읽어 버립니다. 그래서 레이블 인코딩은 크기 순서가 실제로 있는 순서형 범주(S·M·L, 초급·중급·고급)나, 순서를 크게 신경 쓰지 않는 트리 계열 모델에 씁니다.

import pandas as pd
from sklearn.preprocessing import OneHotEncoder, OrdinalEncoder

df = pd.DataFrame({"color": ["red", "blue", "green"], "size": ["S", "L", "M"]})
onehot = OneHotEncoder(handle_unknown="ignore").fit(df[["color"]])
ordinal = OrdinalEncoder(categories=[["S", "M", "L"]]).fit(df[["size"]])
print(onehot.transform(df[["color"]]).toarray())
print(ordinal.transform(df[["size"]]))   # S → 0, L → 2, M → 1

텍스트 정제

정제 규칙

LLM 학습·RAG 데이터의 품질은 대부분 여기서 정해집니다. 흔한 정제 단계는 HTML 태그와 스크립트 제거, 유니코드 정규화(겉보기엔 같지만 코드가 다른 글자를 한 형태로 맞추기), 제어 문자와 깨진 인코딩 제거, 개인정보 마스킹, 너무 짧거나 기호만 가득한 문서 걸러내기입니다. 옛 NLP에서 하던 불용어 제거와 소문자화는 LLM 데이터에서는 대개 하지 않습니다. 문맥을 읽는 모델에게는 조사와 대소문자도 정보이기 때문입니다.

중복 제거

웹에서 모은 말뭉치에는 같은 문서가 여러 번 들어 있습니다. 중복은 모델이 그 문서를 과하게 외우게 만들고, 학습 데이터와 평가 데이터에 같은 글이 있으면 평가 점수가 부풀려집니다. 방법은 두 층입니다. 정확 중복은 문서를 정규화한 뒤 해시값을 비교해 빠르게 지웁니다. 근사 중복은 날짜나 광고 한 줄만 다른 문서들이라 해시가 달라서, 문서를 짧은 조각의 집합으로 보고 자카드 유사도를 근사하는 MinHash 같은 방법으로 찾아 임계값 넘는 쌍을 지웁니다. NVIDIA NeMo Curator는 이런 정제·중복 제거를 GPU에서 대규모로 돌리는 도구입니다.

파생 변수

조합과 비율

파생 변수는 기존 열을 조합해 만든 새 피처입니다. 총 구매액과 구매 횟수가 있으면 「건당 평균 구매액」을, 키와 몸무게가 있으면 체질량지수를 만듭니다. 모델이 두 열의 나눗셈을 스스로 배울 수도 있지만, 사람이 아는 관계를 직접 넣어 주면 적은 데이터로도 빨리 배웁니다. 꼬리가 긴 금액 열에 로그를 씌우는 것도 흔한 파생입니다.

날짜와 구간화

타임스탬프 한 열에서 요일·시간대·월말 여부·주말 여부를 뽑아낼 수 있습니다. 「금요일 저녁 주문이 많다」는 패턴은 원래 타임스탬프 숫자에서는 모델이 거의 찾지 못합니다. 연속값을 몇 개의 구간으로 나누는 구간화는 나이를 연령대로 묶듯 잡음을 줄이고 해석을 쉽게 합니다. 파생 변수를 만들 때 가장 조심할 것은 예측 시점에 알 수 없는 정보를 쓰는 것입니다. 「해지 여부」를 맞히는 모델에 「해지 처리일」에서 뽑은 피처를 넣으면 검증 점수는 높고 실제로는 쓸모가 없습니다.

불균형과 분할

클래스 불균형과 샘플링

사기 거래가 1%인 데이터에서 모두 「정상」이라고 답하는 모델도 정확도 99%를 얻습니다. 이렇게 한 클래스가 압도적으로 많은 것을 클래스 불균형이라 하고, 세 가지로 다룹니다. 다수 클래스를 줄이는 언더샘플링은 빠르지만 정보를 버리고, 소수 클래스를 복제하는 오버샘플링은 같은 행을 외우게 만들 위험이 있으며, SMOTE는 소수 클래스 이웃 사이에 새 점을 합성해 복제의 단점을 줄입니다. 샘플링 대신 손실 함수에서 소수 클래스에 가중치를 더 주는 방법도 있습니다. 샘플링은 학습 데이터에만 적용합니다. 검증·테스트는 실제 분포 그대로 두어야 점수가 현실을 반영합니다.

학습·검증·테스트 분할

데이터는 셋으로 나눕니다. 학습 세트로 가중치를 맞추고, 검증 세트로 하이퍼파라미터와 모델을 고르고, 테스트 세트는 마지막에 한 번만 봅니다. 1만 행을 70:15:15로 나누면 7,000·1,500·1,500행입니다. 불균형 데이터는 계층적 분할(stratified split)로 세 세트의 클래스 비율을 같게 맞춥니다 — 양성이 5%라면 세 세트에 각각 350·75·75개가 들어갑니다. 시간 순서가 있는 데이터는 무작위로 섞지 않고 과거로 학습해 미래로 평가합니다.

순서도 규칙입니다. 먼저 나누고, 그다음 학습 세트로 전처리를 적합합니다.

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

X_train, X_tmp, y_train, y_tmp = train_test_split(
    X, y, test_size=0.3, stratify=y, random_state=42)
X_val, X_test, y_val, y_test = train_test_split(
    X_tmp, y_tmp, test_size=0.5, stratify=y_tmp, random_state=42)

scaler = StandardScaler().fit(X_train)   # 학습 세트에서만 평균·표준편차를 구한다
X_train, X_val, X_test = (scaler.transform(a) for a in (X_train, X_val, X_test))

전체 데이터로 스케일러를 적합한 뒤 나누면 테스트 세트의 평균과 표준편차가 학습에 스며듭니다. 결측치 대치·인코딩·샘플링 모두 같은 규칙입니다.

연습 문제

  1. [10,20,30,40,50][10, 20, 30, 40, 50] 에 min-max 정규화를 적용하면 20은 몇이 되는가?
    ① 0.20
    ② 0.25
    ③ 0.40
    ④ 0.50
    ②. (20−10)/(50−10)=10/40=0.25(20 - 10) / (50 - 10) = 10 / 40 = 0.25 입니다.
  2. 같은 데이터를 표준화(모집단 표준편차 사용)하면 10은 약 몇이 되는가?
    ① −2.00-2.00
    ② −1.41-1.41
    ③ −0.71-0.71
    ④ 00
    ②. 평균 30, 표준편차 200≈14.14\sqrt{200} \approx 14.14 이므로 (10−30)/14.14≈−1.41(10 - 30) / 14.14 \approx -1.41 입니다.
  3. 선형 회귀에 「지역」 열(서울·부산·대구·광주)을 넣으려 합니다. 알맞은 인코딩은?
    ① 레이블 인코딩(서울 0 … 광주 3)
    ② 원-핫 인코딩
    ③ min-max 정규화
    ④ 인코딩 없이 문자열 그대로
    ②. 지역 사이에는 크기 순서가 없어, 정수를 붙이면 선형 모델이 없는 순서를 읽습니다.
  4. 양성 비율이 4%인 20,000행을 70:15:15로 계층적 분할하면 검증 세트의 양성 수는?
    ① 60
    ② 120
    ③ 560
    ④ 800
    ②. 검증 세트는 20000×0.15=300020000 \times 0.15 = 3000 행이고 그 4%인 3000×0.04=1203000 \times 0.04 = 120 개가 양성입니다.
  5. 다음 중 데이터 누수에 해당하는 것은?
    ① 학습 세트로 StandardScaler를 적합해 테스트 세트에 적용한다
    ② 전체 데이터로 결측치 평균을 구해 채운 뒤 학습·테스트로 나눈다
    ③ 학습 세트에만 오버샘플링을 적용한다
    ④ 시계열을 과거로 학습하고 미래로 평가한다
    ②. 테스트 세트의 값이 대치에 쓴 평균에 섞여 들어갑니다. 나머지는 모두 올바른 순서입니다.
  6. 웹 말뭉치에서 날짜 한 줄만 다른 기사 사본들을 지우려 합니다. 알맞은 방법은?
    ① 문서 전체의 해시값이 같은 것만 지운다
    ② MinHash로 근사 중복을 찾아 임계값 넘는 쌍을 지운다
    ③ 모든 문서를 소문자로 바꾼다
    ④ 불용어를 제거한다
    ②. 한 줄만 달라도 해시는 완전히 달라지므로 ①로는 못 잡습니다.
  7. 사기 거래가 1%인 데이터에서 모델의 정확도가 99%로 나왔습니다. 가장 먼저 의심할 것은?
    ① 모델이 거의 완벽하다
    ② 모델이 전부 「정상」으로 답하고 있을 수 있다
    ③ 학습률이 너무 작다
    ④ 원-핫 인코딩을 빠뜨렸다
    ②. 모두 다수 클래스로 답해도 99%가 나옵니다. 소수 클래스의 재현율을 따로 봐야 합니다.
NVIDIA NCA-GENL 시험 노트 전체 보기