[Machine Learning] 03. 사이킷런(2)

Nina·2021년 2월 12일
0
post-thumbnail

「권철민(2020).파이썬 머신러닝 완벽가이드(개정판).위키북스」 책으로 공부한 뒤 정리한 내용.

5. 데이터 전처리

머신러닝 알고리즘은 데이터에 기반하고 있기 때문에 입력값으로 가지는 데이터가 중요하다. 따라서 알고리즘을 적용하기 전에 결손값(NaN, Null)을 처리하는 과정이 필요하다. 이러한 Null값은 고정된 다른 값으로 변환해야 하는데, 피처 값 중 Null값이 얼마 되지 않으면 평균값 등으로 대체 가능하나, Null값의 비율이 높다면 피처를 드롭하는 것이 낫다.
사이킷런의 머신러닝 알고리즘은 문자열 값을 입력값으로 허용하지 않기 때문에 모든 문자열 값은 숫자 형태로 인코딩되어야 한다. 문자열 피처는 일반적으로 카테고리형 피처와 텍스트형 피처를 의미한다. 식별차 피처는 단순히 데이터 로우를 식별하는 용도로 사용되기 때문에 예측에 중요한 요소가 될 수 없으므로 삭제하는게 좋다.

(1) 데이터 인코딩

레이블 인코딩

레이블 인코딩은 카테고리 피처를 코드형 숫자 값으로 변환한다.

>>> import sklearn
>>> from sklearn.preprocessing import LabelEncoder
>>> fruits = ['사과','배','귤','복숭아','메론','복숭아','참외','메론','자두']
>>> encoder = LabelEncoder()
>>> encoder.fit(fruits)
LabelEncoder()
>>> labels = encoder.transform(fruits)
>>> print(labels)
[4 2 0 3 1 3 6 1 5]
>>> encoder.classes_
array(['귤', '메론', '배', '복숭아', '사과', '자두', '참외'], dtype='<U3')
>>> encoder.inverse_transform([0,1,2,3,4,5,6])
array(['귤', '메론', '배', '복숭아', '사과', '자두', '참외'], dtype='<U3')
>>> encoder.inverse_transform([1,4,3,0])
array(['메론', '사과', '복숭아', '귤'], dtype='<U3')

귤, 메론, 배, 복숭아, 사과, 자두, 참외가 0부터 6까지의 코드로 변환되었다. fit()은 데이터 변환을 위한 기준 정보 설정(zb. 데이터 세트의 최댓값/최솟값 설정)을 적용하며 transform()은 이렇게 설정된 정보를 이용해 데이터를 변환한다.

원-핫 인코딩

레이블 인코딩을 통해 간단하게 문자열 값을 숫자형 카테고리 값으로 변환할 수 있으나, 숫자 값의 크고 작음에 따른 특성이 작용함으로 인해 예측 성능이 떨어질 수 있다. 예를들어, 귤은 0이고 참외는 6이기 때문에 참외에 더 많은 가중치가 부여되는 식이다.
이러한 한계를 극복하기 위해 원-핫 인코딩을 사용한다.

>>> from sklearn.preprocessing import OneHotEncoder
>>> import numpy as np
>>> fruits = ['사과','배','귤','복숭아','메론','복숭아','참외','메론','자두']
# 먼저 숫자 값으로 변환을 해야함
>>> encoder = LabelEncoder()
>>> encoder.fit(fruits)
LabelEncoder()
>>> labels = encoder.transform(fruits)
# 2차원 데이터로 변환해야함
>>> labels = labels.reshape(-1,1)
>>> oh_encoder = OneHotEncoder()
>>> oh_encoder.fit(labels)
OneHotEncoder()
>>> oh_labels = oh_encoder.transform(labels)
>>> oh_labels.toarray()
array([[0., 0., 0., 0., 1., 0., 0.],
       [0., 0., 1., 0., 0., 0., 0.],
       [1., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 1., 0., 0., 0.],
       [0., 1., 0., 0., 0., 0., 0.],
       [0., 0., 0., 1., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 1.],
       [0., 1., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 1., 0.]])
>>> oh_labels.shape
(9, 7)

판다스의 get_dummies()를 사용하면 더 쉽게 원-핫 인코딩을 할 수 있다.

>>> import pandas as pd
>>> df = pd.DataFrame({'fruit': ['사과','배','귤','복숭아','메론','복숭아','참외','메론','자두']})
>>> pd.get_dummies(df)
   fruit_귤  fruit_메론  fruit_배  fruit_복숭아  fruit_사과  fruit_자두  fruit_참외
0        0         0        0          0         1         0         0
1        0         0        1          0         0         0         0
2        1         0        0          0         0         0         0
3        0         0        0          1         0         0         0
4        0         1        0          0         0         0         0
5        0         0        0          1         0         0         0
6        0         0        0          0         0         0         1
7        0         1        0          0         0         0         0
8        0         0        0          0         0         1         0

(2) 피처 스케일링과 정규화

서로 다른 변수의 값 범위를 일정한 수준으로 맞추는 작업을 feature scaling이라 하는데, 대표적인 방법으로는 표준화(standardization)과 정규화(normalization)가 있다. 이 포스트에서 피처 스케일링과 표준화, 정규화에 대해 자세히 설명한다.
표준화는 데이터 피처를 평균이 0이고 분산이 1인 가우시안 정규 분포를 가진 값으로 변환하는 것을 말한다. 정규화는 서로 다른 피처의 크기를 동일하게 해주기 위해 최솟값을 0, 최댓값을 1로 변환하는 과정을 의미한다.

StandardScaler

StandardScaler는 표준화를 지원하기 위한 클래스이다.

>>> from sklearn.datasets import load_iris
>>> import pandas as pd
>>> iris = load_iris()
>>> iris_data = iris.data
>>> iris_df = pd.DataFrame(data=iris_data, columns=iris.feature_names)
>>> iris_df.mean()
sepal length (cm)    5.843333
sepal width (cm)     3.057333
petal length (cm)    3.758000
petal width (cm)     1.199333
dtype: float64
>>> iris_df.var()
sepal length (cm)    0.685694
sepal width (cm)     0.189979
petal length (cm)    3.116278
petal width (cm)     0.581006
dtype: float64

표준화 전, feature들의 평균값과 분산값은 모두 상이하다.

>>> from sklearn.preprocessing import StandardScaler
>>> scaler = StandardScaler()
>>> scaler.fit(iris_df)
StandardScaler()
>>> iris_scaled = scaler.transform(iris_df)
>>> iris_df_scaled = pd.DataFrame(data=iris_scaled, columns=iris.feature_names)
>>> iris_df_scaled.mean()
sepal length (cm)   -1.690315e-15
sepal width (cm)    -1.842970e-15
petal length (cm)   -1.698641e-15
petal width (cm)    -1.409243e-15
dtype: float64
>>> iris_df_scaled.var()
sepal length (cm)    1.006711
sepal width (cm)     1.006711
petal length (cm)    1.006711
petal width (cm)     1.006711
dtype: float64

StandardScale로 표준화를 한 이후, 평균은 모두 0에 아주 가까운 값으로, 분산은 1에 아주 가까운 값으로 변환되었다.

MinMaxScaler

MinMaxScaler는 데이터를 0과 1 사이의 값으로 변환한다.

>>> from sklearn.preprocessing import MinMaxScaler
>>> scaler = MinMaxScaler()
>>> scaler.fit(iris_df)
MinMaxScaler()
>>> iris_scaled = scaler.transform(iris_df)
>>> iris_df_scaled = pd.DataFrame(data=iris_scaled, columns=iris.feature_names)
>>> iris_df_scaled.min()
sepal length (cm)    0.0
sepal width (cm)     0.0
petal length (cm)    0.0
petal width (cm)     0.0
dtype: float64
>>> iris_df_scaled.max()
sepal length (cm)    1.0
sepal width (cm)     1.0
petal length (cm)    1.0
petal width (cm)     1.0
dtype: float64
profile
https://dev.to/ninahwang

0개의 댓글