데이터 전처리는 데이터들을 분석하고 머신러닝 모델에 적합한 형태로 데이터셋을 변환하거나 조정하는 과정을 말한다. 데이터도 다양하고 좋아야하지만 동일한 데이터로 데이터 전처리를 어떻게 하냐에따라 모델 성능 결과가 크게 달라진다.
데이터 전처리는 결측치 처리 -> 이상치 처리 -> 인코딩 -> 스케일링 순서로 이루어진다.
데이터 중에 결측치(Missing Value)와 이상치(Outlier)가 존재한다. 결측치는 NA, NaN, None, null로 표현되고, 이상치는 잘못된 값이나 극단치를 가지고 있는 값을 말한다.
데이터에서 결측치와 이상치의 존재여부를 확인해서 해당 데이터 행를 삭제하거나 해당 값을 대체해주는 작업을 해줘야한다.
1️⃣ 결측치 검증 + 대체
df.isnull().sum()

각 컬럼별 결측 개수를 확인하는 방법으로 age 칼럼에 결측치 1개, weight 칼럼에 결측치 2개가 존재한다는 것이다.
전체 데이터 개수에 비해 결측치 개수가 너무 많은 비중을 차지하면 해당 칼럼 자체를 삭제하기도 한다.
df.dropna(axis) : axis는 축을 뜻하며, 0이면 행, 1이면 열(칼럼)에서 결측값을 제거한다.
결측치 대체 방법은 평균/중앙값/최빈값으로 대체하는데 전체 데이터에서 대체값을 만들어내거나 K-NN(K-최근접 이웃) 모델링 기반으로 추출된 데이터 기반으로 대체값을 만들어서 사용한다.
💾 전체 데이터 : SimpleImputer / fillna()
from sklearn.impute import SimpleImputer
# 전체 데이터에서 대체값 만들고 대체하기
df['age'].fillna(df['age'].median()) # 중앙값으로 대체
df['age'].fillna(df['age'].mean()) # 평균값으로 대체
df['weight'].fillna(df['weight'].mean()
# 전체 데이터에서 모든 컬럼에 결측치를 평균값으로 대체하기
imputer = SimpleImputer(strategy='mean')
X_filled = imputer.fit_transform(df)
# 중앙값과 평균값을 각각 다른 칼럼에 적용 가능.
imputer_median = SimpleImputer(strategy='median')
X_filled_median = imputer_median.fit_transform(df['age'])
X_filled_mean = imputer_median.fit_transform(df['weight'])
X_filled = np.concatenate([X_filled_median, X_filled_mean], axis=1) # axis=1: 칼럼을 이어서 붙혀줘야하기 때문에.
👭 K-NN(K-최근접 이웃) 모델링 : KNNImputer
K-NN 모델은 해당 행의 다른 칼럼들을 기준으로 유사한 행을 찾아서 가장 유사한 K개의 이웃을 찾아 이웃들 데이터를 찾는 모델.
K가 너무 크면 정확도가 떨어지고, 너무 작으면 이상치 한계점이 생긴다.
from sklearn.impute import KNNImputer
# K-NN 모델링 기반으로 추출된 데이터만 가지고 평균값으로 결측값 대체하기
imputer = KNNImputer(n_neighbors=3)
X_filled = imputer.fit_transform(X)
2️⃣ 이상치 검증 + 대체
데이터가 정규분포(Normal Distribution)를 따른다고 가정할 때, 평균으로부터 일정 수치를 벗어난 데이터를 이상치라고 판단한다.
📈 표준편차(σ)
$ 정상범위 : u-kσ \leq value \leq u+kσ $ 표준편차(σ)에 k 상수를 곱한 값을 평균(u)에서 빼고 더한 값 범위 안에 속하면 정상범위, 해당 범위 밖이면 이상치라고 검증한다. 이상치가 검증되면 결측치와 동일하게 제거하거나 값을 대체한다.
import numpy as np
mean = df['price'].mean()
std = df['price'].std()
k = 3
outliers = df[(df['price'] < mean - k*std) | (df['price'] > mean + k*std)]
🔢 IQR(Inter quantile Range)
데이터가 정규분포가 아닐경우, IQR을 이용해서 이상치를 검증한다.
데이터를 작은값에서 큰값으로 오름차순으로 정렬한 후 전체를 4등분으로 나눈다. $IQR = Q3 - Q1$ 계산을 해줬을 때 결과 값은 중간 50% 퍼진 폭을 의미한다. IQR값이 크면 데이터가 넓게 퍼져있고, 작으면 서로 비슷한 값들이 모여있다는 뜻을 의미한다.

$정상범위 : Q1-k*IQR \leq value \leq Q3+k*IQR$
상수 k는 1.5 고정값으로 많이 사용하며 해당 범위를 벗어나는 값은 이상치로 간주한다.
🖼️ 도메인 기준
일반적인 기준에서 존재할 수 없는 값들을 제거하고 대체하는 것으로 사람 나이가 200살이라던가 온도가 -300$^{\circ}C$거나 하는 말도 안되는 수치들을 구분해내는 것을 말한다.
3️⃣ 인코딩 (Encoding)
데이터의 결측치와 이상치를 모두 해결했다면 세번째로 범주형 데이터를 수치형으로 변환해줘야한다.
수치형으로 변환해야하는 이유❓
머신러닝 모델 대부분은 수학 연산을 기반으로 작동하는데 문자열이나 Date 타입은 수학적으로 연산이 불가능하다. 계산 가능한 형태로 변환해줘서 머신러닝 모델의 성능을 높이기위해 필요한 단계이다.
범주형 데이터를 수치형으로 변환시키는 Encoding은 Label Encoding과 One-Hot Encoding이 있다.
📚 레이블 인코딩 (Label encoding)
범주형 데이터 중에서도 순서가 존재하는 데이터가 있다. 성적, 직급, 만족도 등등 서열이 존재하는 데이터를 오름차순으로 정렬하고 ["A", "B", "C",,,] -> [0, 1, 2,,,]로 변환한다.
import pandas as pd
from sklearn.preprocessing import LabelEncoder
df = pd.DataFrame({
'grade': ['A', 'B', 'A', 'C', 'B', 'A']
})
# LabelEncoder 생성 및 적용
encoder = LabelEncoder()
df['grade_encoded'] = encoder.fit_transform(df['grade'])

[0,1,2,,,] 숫자 차이가 모델에 영향을 주지 않는 트리 계열 모델(의사결정나무, 랜덤포레스트)에 적용한다.
숫자 차이가 모델에 영향을 미치는 선형 계열 모델(로지스틱회귀, SVM, 신경망)에는 사용하지 않는다.
inverse_transform 함수를 통해 encoder된 숫자에서 원래값을 가지고 온다.
df['grade_encoded'].values
# array([0, 1, 0, 2, 1, 0])
encoder.inverse_transform(df['grade_encoded'])
# array(['A', 'B', 'A', 'C', 'B', 'A'], dtype=object)
🔥 원핫 인코딩 (One-Hot encoding)
N개의 클래스를 N 차원의 One-Hot 벡터로 표현되도록 변환한다.
from sklearn.preprocessing import OneHotEncoder
import pandas as pd
df = pd.DataFrame({
'color': ['red', 'green', 'blue', 'green', 'red']
})
# 객체 생성
ohe = OneHotEncoder() # sparse_output : default True -> 희소행렬 객체(csr_matrix)로 반환한다.
# 학습 + 변환
result = ohe.fit_transform(df) # DataFrame → 희소행렬 객체
col = ohe.get_feature_names_out(['color']) # array(['color_blue', 'color_green', 'color_red'], dtype=object)
new_df = pd.DataFrame(result.toarray(), columns=col) # toarray : 희소행렬 객체 -> ndarray
new_df

sparse_output = True하면 희소행렬을 반환하는데, 희소행렬은 0이 대부분인 데이터를 효율적으로 저장하기 위해 0이 아닌 값들과 그 위치(index)만 따로 관리하는 방식이다. False 하면 ndarray를 반환한다.
get_feature_names_out 함수를 사용하면 One-Hot encoding으로 변환된 Feature(칼럼)들의 이름이 반환된다.
4️⃣ 스케일링 (Scaling)
데이터 전처리의 마지막 단계로 수치형 데이터에만 적용되는 스케일링 단계이다. 스케일링은 "숫자의 크기(범위)"를 조정하는 과정이기때문에 수치형에만 적용된다. Label Encoding과 One-Hot Encoding으로 인해 나온 데이터에는 적용되지 않는다.
키 = 70, 몸무게 = 80, 연봉 = 60,000,000 형태의 데이터가 존재할 때 이대로 학습시키면 연봉값이 다른 칼럼 값들에비해 너무 큰 숫자라 모델이 연봉에만 민감하게 반응하게 된다. 이런걸 막기 위해 모든 칼럼의 값들을 비슷한 범위로 맞추는것을 스케일링이라고 한다.
🧮 StandardScaler
데이터를 평균 0, 표준편차를 1로 변환하는 방식으로 0을 기준으로 모든 데이터들이 모여있게 만든다. 회귀, SVM, 로지스틱 모델에서 주로 사용된다.
$ New{x_i} = \cfrac{X_i-\mu}{\sigma} $ ($\mu-평균, \sigma-표준편차$)
import numpy as np
data = np.array([[10], [2], [30]]) # ndarray 생성.
# 평균, 표준편차 계산
m = data.mean() # 평균
s = data.std() # 표준편차
# Standard Scaling
result = (data - m)/s
StandardScaler : 정규분포일 때 사용, 재사용성 + 일관성 + 가독성 좋게 사용할 수 있다.
from sklearn.preprocessing import StandardScaler
s_scaler = StandardScaler()
result = s_scaler.fit_transform(data)
↕️ MinMaxScaler
데이터를 0~1 범위로 정규화 하는 방식으로 비정규분포도 사용 가능하며 데이터의 분포 형태와 관련없이 일정 범위로 맞출 때 사용한다. 이상치가 존재할 때 0~1 범위로 만들면 정확도가 떨어지므로 이상치 처리를 완료한 다음 MinMaxScaler 단계로 들어와야한다.
KNN, 신경망(ANN, CNN)에서 주로 사용된다.
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
result = scaler.fit_transform(X)'AI > AI TECH' 카테고리의 다른 글
| [sklearn.metrics] 분류형 평가지표 자세히 분석하기 (0) | 2025.11.23 |
|---|---|
| [플레이데이터 SK네트웍스 Family AI 캠프 21기] 11월 1주차 회고 (0) | 2025.11.10 |
| [플레이데이터 SK네트웍스 Family AI 캠프 21기] 10월 4주차 회고 - 1차 단위프로젝트 (0) | 2025.10.26 |
| [플레이데이터 SK네트웍스 Family AI 캠프 21기] 2주차 회고 (1) | 2025.10.05 |
| [플레이데이터 SK네트웍스 Family AI 캠프 21기] 1주차 회고 (0) | 2025.09.28 |