데이터 수집 및 전처리 기초

2025-09-22


인공지능 모델링의 성능은 데이터 품질에 결정적으로 좌우됩니다.
잘못된 입력은 아무리 우수한 모델이라도 부정확한 결과를 낳게 되는것을 명심해야 합니다.

정형 데이터 수집 및 탐색 실습

CSV 데이터 활용

# 파일 구조
Workspace
├── process.ipynb
├── public
│   ├── TravelInsurancePrediction.csv
import pandas as pd
data_file = "public/TravelInsurancePrediction.csv"
df = pd.read_csv(data_file)

상위, 하위 n개 확인

n = 10
 
# 상위 n개 확인
df.head(n)
 
# 하위 n개 확인
df.head(n)

정보 확인

# Null값 확인
df.info()
 
# 숫자형 컬럼을 대상으로 기초 통계 정보 확인
df.describe()
df.describe().T # 가로 세로 변경
 
# 데이터 컬럼과 행의 갯수
df.shape
 
# 데이터 사용량 확인
df.memory_usage(deep=False).sum() / 1024

범주형 데이터 값별로 개수 확인

df['GraduateOrNot'].value_counts()

데이터 사이즈 줄이기

df.memory_usage(deep=False).sum() / 1024  # 155.597,,,
 
df['ChronicDiseases'] = df['ChronicDiseases'].astype('int8')
 
df.memory_usage(deep=False).sum() / 1024  # 141.994,,,

저장 포맷 이해

어떤 포맷의 내용으로 되어 있는지 확인

import chardet
 
f = open('test.csv', 'rb')
result = chardet.detect(f.read())
print(result) # {'encoding': 'ascii', 'confidence': 1.0, 'language': ''}

원하는 포맷으로 읽기

pd.read_csv('test.csv', encoding='euc-kr') # default -> 깨질 때 있음
 
pd.read_csv('test.csv', encoding='utf-8') # 안 깨짐

이유: utf-8euc-kr보다 나중에 나와서 더 많은 영역을 포함하기 때문입니다.


기초 전처리

결측치 탐색 및 처리 방법

기존 데이터에서 비어있는 값 혹은 잘못된 값을 수정 또는 삭제 하는 방법을 말합니다.

실습

# 디폴트로 나오는 값 -> 필요 없기 때문에 삭제
data = df.drop(columns='Unnamed: 0')

여기서 질문이 생겼습니다.
df 변수에서 컬럼을 삭제하고 새로운 데이터 집어 넣으면 메모리만 차는 것 아닌가요?!

결론은 NO!

데이터프레임 객체(시리즈)가 같은 값을 갖게 되면 2개가 공유하도록 Pandas 내부적으로 설계 되어 있습니다.

결측치 확인

data.isnull().sum()
 
# 실제 null값이 있는 인덱스 행들만 출력
data.loc[data.isnull().any(axis=1)]

결측치 삭제

data_dropped = data.dropna()
 
data_dropped = data.dropna(axis=0) # 행 삭제(default)
data_dropped = data.dropna(axis=1) # 열 삭제

결측치 대체

# .mode() -> 가장 같은 값이 많은 값부터 리스트로 출력
fill_value = data_dropped['Employment Type'].mode()[0]
 
filled_value = data_dropped['Employment Type'].fillna(fill_value)

이상치 데이터 이해

전체 데이터의 4분위로 나눠서 특정한 구간의 바깥에 있는 값들을 이상치라고 합니다.

실습

# 방법 1
multiplier = 1.5
Q1 = data['AnnualIncome'].quantile(0.25)
Q3 = data['AnnualIncome'].quantile(0.75)
IQR = Q3 - Q1
 
lower_bound = Q1 - multiplier + IQR
upper_bound = Q3 + multiplier + IQR
 
outliers = data[(data['AnnualIncome'] < lower_bound) | (data['AnnualIncome'] > upper_bound)]
 
print(f"정상 범위: {lower_bound:.2f} ~ {upper_bount:.2f}")
print(f"이상치 개수: {len(outliers)}개 ({len(outliers)/len(data)*100:.2f})%")
# 방법 2
import numpy as np
 
threshold = 3
mean = data['AnnualIncome'].mean()
stf = data['AnnualIncome'].std()
z_score = (data['AnnualIncome'] - mean) / std
outliers = data[np.abs(z_score) > threshold]

정규화 & 표준화

머신러닝에서 자주 듣는 질문이 있습니다. “왜 정규화(normalization)와 표준화(standardization)를 해야 하죠?” 이 글에서는 두 기법의 정의/수식/예시를 간단히 정리하고, 언제 무엇을 선택할지 실무 기준을 제시합니다.

정규화와 표준화는 모두 데이터의 스케일(규모)을 변경하여 큰 값이 학습을 지배하지 않도록 하는 전처리입니다.

  • 정규화: 보통 0~1 범위로 압축 (Min-Max 등)
  • 표준화: 평균 0, 표준편차 1의 분포로 변환 (Z-score)

핵심 한눈에 보기

스케일링 선택 가이드
정규화 (Normalization)
  • 범위 고정: 0~1
  • Min-Max, Robust, Power Transform
  • 거리 기반 모델(KNN, K-means), 점수 합산/가중치 결합에 유리
표준화 (Standardization)
  • 평균 0, 표준편차 1
  • Z-score
  • 선형모델/신경망에서 안정적, 가우시안 가정에 적합

왜 스케일을 바꿔야 할까?

서로 단위/크기가 다른 특성(예: 키 170cm, 몸무게 70kg, 손가락 길이 2cm)을 그대로 학습에 넣으면, 손실(loss) 계산과 가중치 업데이트에서 값이 큰 특성모델을 지배합니다. → 결과: 편향된 학습 / 느린 수렴 / 불안정한 최적화

해법: 모든 특성을 비슷한 규모로 맞춰 공정한 학습 환경을 만든다.


정규화 (Normalization)

정의

  • 데이터를 0과 1 사이로 압축해 범위를 고정합니다.
  • 대표: Min-Max Scaling, (이상치 견고) Robust Scaler, (분포 안정화) Power Transform

실습

from sklearn.preprocessing import MinMaxScaler # 정규화
from sklearn.preprocessing import StandardScaler # 표준화
from sklearn.preprocessing import RobustScaler, PowerTransformer

정규화

m = MinMaxScaler()
# 방법 1
m.fit_transform(data['Age'].values.reshape(-1, 1)) # -> 아래 이유[1]과 같은 이유로 reshape해야 함
 
# 방법 2
m.fit_transform(data[['Age']])

이유[1]

data['Age'].shape # (1990,) # -> 1차원 데이터
 
# fit transform을 하기 위해서는 2차원 데이터로 만들어야 됨
data['Age'].reshape(-1, 1) # error -> 'series' object has no attribue 'reshape'
data['Age'].values.reshape(-1, 1).shape # (1990, 1)

표준화

s = StandardScaler()
# 방법 1
s.fit_transform(data['Age'].values.reshape(-1, 1)) # -> 아래 이유[1]과 같은 이유로 reshape해야 함
 
# 방법 2
s.fit_transform(data[['Age']])

댓글

GitHub 계정으로 댓글을 남겨보세요!