Py) 전처리 - ML 분류모델용 - 01

Py) 전처리 - ML 분류모델용 - 01

Python으로 머신러닝(ML) 분류모델에 들어갈 데이터를 전처리하는 방법을 알아보자.


※ 본 내용에서 사용하는 machine_failure.csv 파일은 별도로 다운로드 받아야 한다.
machine_failure.csv 다운받기 [클릭]
※ 상기 데이터는 UCI ML 저장소의 데이터를 가공한 데이터이다.

개요

실무에서 주어지는 데이터는 바로 머신러닝 모델에 넣기 곤란한 경우가 많다. 그리고 이러한 데이터를 머신러닝 모델에 넣기 위해서는 전처리가 필요하다. 이번 게시물에서는 머신러닝 분류모델에 들어갈 데이터를 전처리하는 방법을 알아본다.

본 전처리 예제는 다음의 게시물의 내용을 모두 이해하고난 후에 도전하기 바란다.

그리고 다음과 같은 내용을 다룬다.

대분류 소분류 여부
데이터유형 단일 데이터 O
다중 데이터
일반 전처리 문자 데이터 핸들링
숫자 데이터 핸들링
시간 데이터 핸들링
필터링
정렬
피보팅
그룹 연산
축 연산
특정 변수 제거
데이터 병합 조인 연산
이어붙이기 O
이상치 처리 극단치 확인 O
극단치 제거
극단치 대치
결측치 확인 O
결측치 제거
결측치 대치
수치형 데이터 처리 단순 데이터 변환
특수 지표 생성
구간화
표준화 O
범주형 데이터 처리 단순 데이터 변환
특수 지표 생성
레이블 인코딩
원핫 인코딩 O
데이터 분할 단순 분할
단순 표본추출
층화 표본추출 O

데이터 준비

공장의 센서 데이터를 사용하여 데이터 전처리를 실습하려고 하며 제공되는 데이터(ins_charges.csv)의 각 변수명과 설명은 다음과 같다.

변수명 설명
id 고유 식별자
type 공정 유형
temp_air 공기 온도
temp_process 공정 온도
speed 기계의 작동 속도
torque 기계의 토크(회전력)
tool_wear 공구 마모 정도 (사용 시간)
is_failure 공정 실패 여부 (0: 정상, 1: 실패)

이제 “machine_failure.csv” 데이터를 다운받아 불러온다.
machine_failure.csv 다운받기 [클릭]

1
2
3
import pandas as pd
df = pd.read_csv("machine_failure.csv")
df.head(2)
id type temp_air temp_process speed torque tool_wear is_failure
0 14860 M 298.1 308.6 1551 42.8 0 0
1 47181 L 298.2 308.7 1408 46.3 3 0

전처리

이제 본격적인 전처리를 시작해보자. 전처리를 하기 위해 필요한 각종 라이브러리의 함수와 클래스를 호출하자.

1
from sklearn.model_selection import train_test_split # 데이터셋 분할

결측치

우선 각 변수별 결측치를 확인한다.

1
2
3
4
5
6
7
8
9
10
df.isna().sum()
## id 0
## type 0
## temp_air 0
## temp_process 0
## speed 0
## torque 0
## tool_wear 0
## is_failure 0
## dtype: int64

결측치가 없으므로 결측치 처리는 넘어가도록 한다.

극단치

각 변수별 극단치를 확인한다. 먼저 수치형 변수만 추출하여 최소, 평균, 최대값을 확인한다.

1
df.select_dtypes(include = "number").agg(["min", "mean", "max"])
id temp_air temp_process speed torque tool_wear is_failure
min 14860.000000 295.300000 305.700000 1168.000000 3.800000 0.000000 0.00000
mean 40704.791725 300.003556 310.004208 1538.865057 39.980535 107.929473 0.03306
max 57174.000000 304.500000 313.800000 2886.000000 76.600000 253.000000 1.00000

최소값과 최대값을 보았을 때 평균 대비 아주 극단적으로 크거나 작은 값은 확인이 되지 않는다. 물론 이는 각 변수별로 상자수염그래프 같은 것들을 그려서 확인하는 것이 더 정확하겠지만, 여기서는 생략한다.

그리고 범주형 변수를 살펴본다. 범주형 변수의 경우 어떤 범주가 극단적으로 적은 비율로 있거나 많은 비율로 있으면 처리가 필요할 수 있겠다.

1
2
3
4
5
6
df["type"].value_counts()
## type
## L 5988
## M 2995
## H 999
## Name: count, dtype: int64

“type”변수의 각 범주는 약 6:3:1의 비율로 구성되어 있으므로 극단적인 비율이라고 판단하기에는 어렵다. 그러므로 극단치 처리는 넘어가도록 한다.

데이터 분할

학습 데이터와 평가 데이터로 분할하기 위해 train_test_split() 함수를 사용한다. 그리고 stratify 옵션을 사용하여 층화표본추출을 실시하고 “type”변수의 비율을 유지하도록 한다.

1
2
3
4
5
6
df_train, df_test = train_test_split(df, 
train_size = 0.7,
random_state = 123,
stratify = df["type"])
len(df_train), len(df_test)
## (6987, 2995)

상기 층화표본추출이 제대로 이루어졌는지 코드를 통해 “type” 변수의 범주 구성비를 확인해보도록 하자. 우선 기존 “df” 객체의 경우는 다음과 같다.

1
2
3
4
5
6
df["type"].value_counts(normalize = True)
## type
## L 0.59988
## M 0.30004
## H 0.10008
## Name: proportion, dtype: float64

다음으로 “df_train”, “df_test” 객체의 경우는 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
df_train["type"].value_counts(normalize = True)
## type
## L 0.599828
## M 0.300129
## H 0.100043
## Name: proportion, dtype: float64

df_test["type"].value_counts(normalize = True)
## type
## L 0.600000
## M 0.299833
## H 0.100167
## Name: proportion, dtype: float64

상기 결과를 봤을 때 “df_train”, “df_test” 객체의 “type” 변수의 범주 구성비가 “df” 객체와 거의 동일하게 유지되었음을 확인할 수 있다.

정규화

정규화를 실시하기 위해 StandardScaler() 클래스를 사용한다. 이때 식별자인 “id”변수, 범주형인 “type”변수, 종속변수로 사용될 수 있는 “is_failure” 변수는 제외하고 정규화를 실시한다.

1
2
3
4
5
6
7
8
9
ls_drop_cols = ["id", "type", "is_failure"]
model_nor = StandardScaler().fit(df_train.drop(columns = ls_drop_cols))
arr_train_nor = model_nor.transform(df_train.drop(columns = ls_drop_cols))
arr_test_nor = model_nor.transform(df_test.drop(columns = ls_drop_cols))

df_train_nor = pd.DataFrame(arr_train_nor,
columns = df_train.drop(columns = ls_drop_cols).columns)
df_test_nor = pd.DataFrame(arr_test_nor,
columns = df_test.drop(columns = ls_drop_cols).columns)

상기 코드에서 제외하고자 하는 변수명을 여러번 써야하는 불편함을 줄이기 위해 “ls_drop_cols”라는 리스트 객체를 생성하여 사용하였다.

정규화 결과를 확인해보자.

1
df_train_nor.head(2)
temp_air temp_process speed torque tool_wear
0 0.399154 1.352290 -0.877336 0.926149 1.084815
1 0.001026 -0.266219 -0.482743 0.596147 -0.889909

범주형 변수 처리

이번에는 범주형 변수를 One-Hot Encoding을 실시한다. 이때 “type” 변수만 One-Hot Encoding을 실시하고 “id” 변수는 식별자이므로 작업에서 제외한다.

1
2
3
4
5
6
7
8
model_ohe = OneHotEncoder().fit(df_train[["type"]])
arr_train_ohe = model_ohe.transform(df_train[["type"]]).toarray()
arr_test_ohe = model_ohe.transform(df_test[["type"]]).toarray()

df_train_ohe = pd.DataFrame(arr_train_ohe,
columns = model_ohe.get_feature_names(input_features = ["type"]))
df_test_ohe = pd.DataFrame(arr_test_ohe,
columns = model_ohe.get_feature_names(input_features = ["type"]))

각 결과 객체를 확인해보자.

1
df_train_ohe.head(2)
type_H type_L type_M
0 0.0 1.0 0.0
1 0.0 1.0 0.0
1
df_test_ohe.head(2)
type_H type_L type_M
0 0.0 0.0 1.0
1 0.0 1.0 0.0

데이터 통합

앞에서 생성한 객체를 하나로 통합한다. 정규화된 수치형 변수 데이터, One-Hot Encoding된 범주형 변수 데이터, 그리고 종속변수와 식별자 데이터를 하나로 통합한다. 단, 종속변수와 식별자 데이터 “df_train” 데이터에서 가져오는데 해당 객체의 row index 때문에 데이터 병합 과정에서 문제가 생길 수 있어 .reset_index() 메서드를 사용하여 index를 초기화한다.

1
2
3
4
5
6
7
8
df_train_bind = pd.concat([df_train[["id", "is_failure"]].reset_index(drop = True), 
df_train_ohe,
df_train_nor],
axis = 1)
df_test_bind = pd.concat([df_test[["id", "is_failure"]].reset_index(drop = True),
df_test_ohe,
df_test_nor],
axis = 1)

병합 결과를 확인해보자.

1
df_train_bind.head(2)
id is_failure type_H type_L type_M temp_air temp_process speed torque tool_wear
0 55100 0 0.0 1.0 0.0 0.399154 1.352290 -0.877336 0.926149 1.084815
1 49876 0 0.0 1.0 0.0 0.001026 -0.266219 -0.482743 0.596147 -0.889909

나중에 모델링을 실시할 때 학습 데이터와 평가 데이터를 구분할 수 있도록 “Xgrp” 변수를 생성하고 하나로 통합한다.

1
2
3
4
5
df_train_bind["Xgrp"] = "train"
df_test_bind["Xgrp"] = "test"
df_bind = pd.concat([df_train_bind, df_test_bind])
df_bind = df_bind.reset_index(drop = True)
df_bind.head(2)
id is_failure type_H type_L type_M temp_air temp_process speed torque tool_wear Xgrp
0 55100 0 0.0 1.0 0.0 0.399154 1.352290 -0.877336 0.926149 1.084815 train
1 49876 0 0.0 1.0 0.0 0.001026 -0.266219 -0.482743 0.596147 -0.889909 train

마무리

적당히 저장하면 끝!

1
df_bind.to_csv("data/model_classification_machine_failure.csv", index = False)
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×