데이터 과학을 위한 파이썬 머신러닝 : 6. 데이터 전처리(1)

데이터 전처리 개념과 유형

  • 데이터 전처리(data preprocessing) : 머신러닝 모델에 훈련 데이터를 입력하기 전에 데이터를 가공
  • 머신러닝 기초 수식 : y=f(X)
    • 데이터 X는 훈련 데이터(train data)와 테스트 데이터(test data)가 모두 같은 구조를 갖는 피쳐(feature)이고, X값을 넣으면 y값이 나옴
  • 연속형 데이터 : 최댓값과 최솟값 차이가 피쳐보다 더 많이 나는 경우, 학습에 영향을 최소화 하기 위해 데이터의 스케일(scale)을 맞춰줌
  • 기수형 데이터와 서수형 데이터 : 일반적으로 숫자로 표현되지 않기 때문에 컴퓨터가 이해할 수 있는 숫자 형태의 정보로 변형
  • 결측치(missing data) : 실제로 존재하지만 데이터베이스 등에 기록되지 않는 데이터
    • 해당 데이터를 빼고 모델을 돌릴 수 없기 때문에 결측치 처리 전략을 세워 데이터를 채워 넣음
  • 이상치(outlier) : 극단적으로 크거나 작은 값
    • 단순히 데이터 분포의 차이와는 다르며, 데이터 오기입이나 특이 현상 때문에 나타남

데이터 전처리 전략

isnull() : NaN 값이 존재할 경우 True, 그렇지 않을 경우 False 출력

df.isnull().sum() / len(df)  # 결측치 비율
출력 결과 :

first_name 0.2
last_name 0.2
age 0.2
sex 0.2
preTestScore 0.4
postTestScore 0.4
dtype: float64

결측치 처리하기 : 드롭

  • dropna() : 드롭(drop), 결측치, NaN이 나온 열이나 행을 삭제
  • 매개변수 inplace=True를 사용하거나 다른 변수에 재할당하는 것이 좋음
df_no_missing = df.dropna()
df_no_missing

  • 매개변수 how로 조건에 따라 결측치가 있는 행 또는 열 제거
    • ‘all’ 행에 있는 모든 값이 NaN일 때 해당 행을 삭제
    • ‘any’ 하나의 NaN만 있어도 삭제
  • 매개변수 thresh로 결측치 아닌 데이터의 개수 조건에 따라 결측치가 있는 행 또는 열 제거
df_cleaned = df.dropna(how='all')
df_cleaned
df.dropna(axis=0, thresh=1)

결측치 처리하기 : 채우기

  • fillna() : 채우기(fill), 비어있는 값을 채움
  • 일반적으로 드롭한 후에 남은 값들을 채우기 처리
  • 평균, 최빈값 등 데이터의 분포를 고려해서 채움
df.fillna(0)

# 열 단위 평균값을 계산해 해당 열에만 결측값에 채우는 방식
df["preTestScore"].fillna(df["preTestScore"].mean(), inplace=True)
df

# 성별에 따라 빈칸을 채우는 방식
df["postTestScore"].fillna(
    df.groupby("sex")["postTestScore"].transform("mean"),
    inplace=True)
df

범주형 데이터 처리 : 원핫인코딩

  • get_dummies() : 원핫인코딩(one-hot encoding), 범주형 데이터의 개수만큼 가변수(dummy variable)를 생성하여 존재 유무를 1 또는 0으로 표현
edges.dtypes
출력 결과 : 

source int64
target int64
weight int64
color object
dtype: object
pd.get_dummies(edges)

# 열 이름으로 되어있는 접두어가 없는 가변수 생성
pd.get_dummies(edges["color"])

# 열 이름으로 되어있는 접두어가 있는 가변수 생성
pd.get_dummies(edges[["color"]])
# pd.get_dummies(edges).iloc[:, 3:]
# pd.get_dummies(edges[["color"]])
# pd.get_dummies(edges["color"], prefix="color")

  • 필요에 따라 정수형을 객체로 변경해서 처리
weight_dict = {3: "M", 4: "L", 5: "XL"}
edges["weight_sign"] = edges["weight"].map(weight_dict)
weight_sign = pd.get_dummies(edges["weight_sign"])
weight_sign

pd.concat([edges, weight_sign], axis=1)

범주형 데이터로 변환 : 바인딩

  • cut() : 바인딩(binding), 연속형 데이터를 범주형 데이터로 변환
# postTestScore에 대한 학점을 측정하는 코드를 작성
bins = [0, 25, 50, 75, 100]  # bins 정의(0-25, 25-50, 60-75, 75-100)
group_names = ['Low', 'Okay', 'Good', 'Great']

# cut : 나눌 시리즈 객체와 구간, 구간의 이름을 넣어주면 해당 값을 바인딩하여 표시해줌
categories = pd.cut(df['postTestScore'], bins, labels=group_names)
categories
출력 결과 : 

0 Low
1 Great
2 Good
3 Good
4 Good
5 Low
6 Great
7 Good
8 Good
9 Good
10 Good
11 Good
Name: postTestScore, dtype: category
Categories (4, object): ['Low' < 'Okay' < 'Good' < 'Great']

피쳐 스케일링

  • 스케일링(scaling) : 데이터 간 범위를 맞춤
  • 최솟값-최댓값 정규화(min-max normalization) : 최솟값과 최댓값을 기준으로 0에서 1, 또는 0에서 지정 값까지로 값의 크기를 변화시킴
    • x는 처리하고자하는 열, x_i는 열 하나의 값
    • max(x)는 해당 열의 최댓값, min(x)는 해당 열의 최솟값
    • new_{max}와 new_{min}은 새롭게 지정되는 값의 최댓값 또는 최솟값
  • z-스코어 정규화(z-score normalization) : 기존 값을 표준 정규분포값으로 변환하여 처리
    • μ는 x열의 평균값이고 σ는 표준편차
# 스케일링은 브로드캐스팅 개념으로 스칼라 값(평균값, 최댓값, 최솟값)과 벡터(열) 값 간 연산
df["A"] - df["A"].min()
출력 결과 :

0 0.00
1 76.20
2 76.95
3 82.27
4 77.21
Name: A, dtype: float64
# 최솟값-최댓값 정규화 방법에서 최댓값과 최솟값을 따로 구하지 않고 코드로 수식을 나타낼 수 있음
(df["A"] - df["A"].min()) / (df["A"].max() - df["A"].min())
출력 결과 :

0    0.000000
1    0.926219
2    0.935335
3    1.000000
4    0.938495
Name: A, dtype: float64
# z-스코어 정규화 수식 역시 코드로 나타낼 수 있음
(df["B"] - df["B"].mean()) / (df["B"].std())
출력 결과 :

0   -1.405250
1   -0.540230
2    0.090174
3    0.881749
4    0.973556
Name: B, dtype: float64

머신러닝 프로세스와 데이터 전처리

  1. 데이터를 확보한 후 데이터를 정제 및 전처리
  2. 학습용과 테스트 데이터를 나눠 학습용 데이터로 학습을 실시
  3. 학습 결과를 평가 지표와 비교하여 하이퍼 매개변수 변환
  4. 최종적인 모델 생성하여 테스트 데이터셋으로 성능을 측정
  5. 모델을 시스템에 배치하여 모델을 작동시킴

참고문헌

최성철, 『데이터 과학을 위한 파이썬 머신러닝』, 초판, 한빛아카데미, 2022

이 글이 도움이 되었나요?

신고하기
0분 전
작성된 댓글이 없습니다. 첫 댓글을 달아보세요!
    댓글을 작성하려면 로그인이 필요합니다.