데이터가 알고리즘을 이긴다: 모델을 바꾸기 전에 데이터를 바꾸라

발행: (2026년 6월 7일 AM 04:47 GMT+9)
8 분 소요
원문: Dev.to

Source: Dev.to

특성 엔지니어링을 통해 배운 “좋은 데이터가 좋은 알고리즘보다 더 큰 효과를 낸다”는 교훈

머신러닝을 처음 배우기 시작했을 때, 나는 많은 초보자들이 그렇듯 생각했다:
모델 성능이 좋지 않다면, 더 좋은 알고리즘이 필요하다.
그래서 나는 모델을 계속 바꾸었다.
로지스틱 회귀 → 결정 트리 → 랜덤 포레스트 → XGBoost와 신경망까지 읽어 보기 시작했다.
성능이 약간씩은 개선됐지만, 눈에 띄게 크게 향상되지는 않았다.

놀랍게도 가장 큰 개선은 알고리즘을 바꾸는 것이 아니라 데이터를 바꾸는 것에서 나왔다.

나는 결측값, 이상치, 범주형 변수가 섞인 데이터셋을 다루고 있었다.
많은 초보자와 마찬가지로 내 첫 번째 직관은 간단했다:

model.fit(X_train, y_train)
pred = model.predict(X_test)

모델은 정상적으로 학습했고, 정확도도 괜찮아 보였다.
하지만 뭔가 이상했다. 데이터 자체가 엉망이었기 때문이다.

  • 몇몇 컬럼엔 결측값이 존재했고,
  • 일부 수치형 특성엔 극단적인 이상치가 있었으며,
  • 여러 범주형 컬럼은 텍스트 형태로 표현돼 있었다.

그럼에도 나는 모델이 모든 것을 자동으로 학습해 주길 기대했다.

원시 데이터에 로지스틱 회귀 적용 결과

  • 정확도: 72%

그다지 나쁘지도, 인상적이지도 않다.

모델을 바꾸는 대신, 나는 데이터 자체를 조사하기로 방향을 틀었다.
이 결정이 프로젝트 전체에서 가장 중요한 선택이 되었다.

결측값 처리

데이터셋에 결측값이 다수 존재했다. 처음엔 행을 그냥 삭제하려고 했다.

df.dropna(inplace=True)

하지만 이렇게 하면 데이터의 큰 부분을 잃게 된다. 그래서 여러 방법을 시도했다.

from sklearn.impute import SimpleImputer

imputer = SimpleImputer(strategy='mean')
X = imputer.fit_transform(X)

imputer = SimpleImputer(strategy='median')
from sklearn.impute import KNNImputer

imputer = KNNImputer(n_neighbors=5)
X = imputer.fit_transform(X)

KNN 임퓨팅은 단순 평균보다 레코드 간 관계를 더 잘 보존해 주었고, 성능이 눈에 띄게 향상되었다.

이상치 처리

수치형 컬럼을 시각화해 보니 박스플롯이 형편없었다. 몇몇 극단값이 전체 분포를 왜곡하고 있었다.

sns.boxplot(df["experience"])

모델이 몇 개의 특이한 관측치에 과도하게 맞추려는 것을 방지하고 싶었다. 그래서 IQR 기반 방법을 적용했다.

Q1 = df["experience"].quantile(0.25)
Q3 = df["experience"].quantile(0.75)
IQR = Q3 - Q1

lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR

df = df[(df["experience"] >= lower) &
        (df["experience"] <= upper)]

이상치를 제거한 뒤 데이터 분포가 훨씬 깔끔해졌고, 모델은 잡음이 아닌 실제 패턴을 학습하기 시작했다.

범주형 변수 인코딩

머신러닝 알고리즘은 텍스트를 이해하지 못한다. 따라서 다음과 같은 컬럼은 변환이 필요했다.

  • Male / Female
  • Private / Public
  • Graduate / Masters

One‑Hot Encoding을 적용했다.

pd.get_dummies(df,
               columns=["gender",
                        "company_type"])

순서가 중요한 경우에는 Ordinal Encoding을 사용했다.

education_level
# High School → Graduate → Masters → PhD

이렇게 하면 사람이 읽을 수 있는 카테고리를 기계가 이해할 수 있는 형태로 바꿀 수 있다.

스케일링

특성마다 값의 범위가 달라 거리 기반 알고리즘이 큰 값에 편향될 위험이 있었다.

  • 일부 컬럼: 0 ~ 5
  • 다른 컬럼: 0 ~ 100,000

그래서 MinMax Scaling을 적용했다.

from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler()

X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

이제 모든 특성이 공정하게 기여한다.

동일 모델 재학습

데이터만 바꾼 상태에서 로지스틱 회귀 모델을 다시 학습했다.

결과

  • 특성 엔지니어링 전: 72%
  • 특성 엔지니어링 후: 86%

14%p 상승을 기록했다.

  • 알고리즘을 바꾸지 않았다.
  • 딥러닝을 사용하지 않았다.
  • 복잡성을 추가하지 않았다.
    오직 데이터를 개선했을 뿐이다.

교훈

이 프로젝트는 내 머신러닝 사고 방식을 완전히 바꾸어 놓았다.

이전 믿음:

Better Algorithm

Better Results

현재 믿음:

Better Data

Better Features

Better Results

대부분의 실제 머신러닝 문제는 알고리즘 문제가 아니라 데이터 문제다.
품질이 낮은 데이터에 강력한 모델을 적용해도 여전히 한계가 있다.
반대로 깨끗하고 의미 있는 데이터에 단순 모델을 적용하면 복잡한 모델보다 더 좋은 성과를 낼 수 있다.

가장 어려웠던 점

  • 완전 케이스 분석(Complete Case Analysis)으로 인한 행 손실
  • 평균, 중앙값, KNN 임퓨팅 중 선택
  • 변환된 데이터셋 결합
  • One‑Hot Encoding 후 차원 폭증 처리
  • 진짜 이상치와 가치 있는 희귀 사례 구분

이러한 난관들은 모델 학습보다 더 큰 교훈을 주었다.

마무리

특성 엔지니어링은 머신러닝에서 가장 화려한 파트는 아니다.
누구도 결측값 처리 과정을 스크린샷으로 SNS에 올리지는 않는다.
특성 스케일링을 축하하는 사람도 없다.
하지만 실제 성능 향상의 대부분은 바로 여기서 일어난다.

이 프로젝트 이후 나는 더 이상

어떤 모델을 써야 할까?

라는 질문을 하지 않는다. 대신

내 데이터가 무엇을 말하고 있지?

라는 질문을 한다.
이 사고 방식의 전환이 새로운 알고리즘을 배우는 것보다 내 머신러닝 실력을 크게 끌어올렸다.

0 조회
Back to Blog

관련 글

더 보기 »

모바일 한여름 열풍

!Cover image for Mobile Midsommer Madnesshttps://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploa...