본문 바로가기

AI/빅데이터

범주형 데이터 다루기

순서가 없는 범주형 특성 인코딩하기

import numpy as np
from sklearn.preprocessing import LabelBinarizer, MultiLabelBinarizer

# 특성 생성
feature = np.array([["Texas"], ["California"], ["Texas"], ["Delaware"], ["Texas"]])

# 원-핫 인코더 생성
one_hot = LabelBinarizer()

# 특성을 원-핫 인코딩
print(one_hot.fit_transform(feature))

# 결과
[[0 0 1]
 [1 0 0]
 [0 0 1]
 [0 1 0]
 [0 0 1]]
 
 # 특성의 클래스 확인
print(one_hot.classes_)

# 결과
['California' 'Delaware' 'Texas']

# 원-핫 인코딩 되돌리기
print(one_hot.inverse_transform(one_hot.transform(feature)))

# 결과
['Texas' 'California' 'Texas' 'Delaware' 'Texas']

# 판다스를 이용하여 원-핫 인코딩
import pandas as pd

# 특성으로 더미 변수 생성
print(pd.get_dummies(feature[:, 0]))

# 결과
   California  Delaware  Texas
0           0         0      1
1           1         0      0
2           0         0      1
3           0         1      0
4           0         0      1

# 다중 클래스 특성 생성
features = [("Texas", "Florida"), ("California", "Alabama"), ("Texas", "Florida"), ("Delware", "Florida"), ("Texas", "Alabama")]

# 다중 클래스 원-핫 인코더 생성
multi_one_hot = MultiLabelBinarizer()

# 다중 클래스 특성을 원-핫 인코딩
print(multi_one_hot.fit_transform(features))

# 결과
[[0 0 0 1 1]
 [1 1 0 0 0]
 [0 0 0 1 1]
 [0 0 1 1 0]
 [1 0 0 0 1]]
 
 
 # 밀집 배열 얻기
 from sklearn.preprocessing import OneHotEncoder

# 특성 생성
feature = np.array([["Texas", 1], ["Califonia", 1], ["Texas", 3], ["Delware", 1], ["Texas", 1]])

# sparse = False 로 지정하면 밀집 배열을 얻음
one_hot_enc = OneHotEncoder(sparse=False)
print(one_hot_enc.fit_transform(feature))

# 결과
[[0. 0. 1. 1. 0.]
 [1. 0. 0. 1. 0.]
 [0. 0. 1. 0. 1.]
 [0. 1. 0. 1. 0.]
 [0. 0. 1. 1. 0.]]

 

순서가 있는 범주형 특성 인코딩하기

import pandas as pd

# 특성 생성
df = pd.DataFrame({"Score" : ["Low", "Low", "Medium", "Medium", "High"]})

# 딕셔너리 생성
scale_mapper = {"Low":1, "Medium":2, "High":3}

# 특성을 정수로 변환
print(df["Score"].replace(scale_mapper))

# 결과
0    1
1    1
2    2
3    2
4    3
Name: Score, dtype: int64

 

# 특성 딕셔너리를 인코딩하기

from sklearn.feature_extraction import DictVectorizer

# 딕셔너리 생성
data = [{"Red":2, "Blue":4}, {"Red":4, "Blue":3}, {"Red":1, "Yellow":2}, {"Red":2, "Yellow":2}]

# DictVectorizer 객체 생성
vector = DictVectorizer(sparse=False)

# 특성을 행렬로 변환
features = vector.fit_transform(data)

# 특성 행렬 확인
print(features)

# 결과
[[4. 2. 0.]
 [3. 4. 0.]
 [0. 1. 2.]
 [0. 2. 2.]]
 
 # 특성을 데이터프레임으로 만들기
import pandas as pd

# 특성 이름 얻기
names = vector.get_feature_names()
# 데이터 프레임으로 변환
print(pd.DataFrame(features, columns=names))

# 결과
   Blue  Red  Yellow
0   4.0  2.0     0.0
1   3.0  4.0     0.0
2   0.0  1.0     2.0
3   0.0  2.0     2.0

 

누락된 클래스 값 대체하기

# KNN 이용하기
import numpy as np
from sklearn.neighbors import KNeighborsClassifier

# 범주형 특성을 가진 행렬 생성
x = np.array([[0, 2.10, 1.45], [1, 1.18, 1.33], [1, -0.21, -1.19]])

# 범주형 특성에 누락된 값이 있는 특성 행렬 생성
x_nan = np.array([[np.nan, 0.87, 1.31], [np.nan, -0.67, -0.22]])

# KNN 학습
clf = KNeighborsClassifier(3, weights='distance')
trained_model = clf.fit(x[:, 1:], x[:,0])

# 누락된 값2의 클래스 예측
values = trained_model.predict(x_nan[:, 1:])

# 예측된 클래스와 원본 특성을 열로 합침
x_imputed = np.hstack((values.reshape(-1, 1), x_nan[:, 1:]))

# 두 특성 행렬을 연결
print(np.vstack((x_imputed, x)))

# 결과
[[ 1.    0.87  1.31]
 [ 1.   -0.67 -0.22]
 [ 0.    2.1   1.45]
 [ 1.    1.18  1.33]
 [ 1.   -0.21 -1.19]]
 

 

불균형한 클래스 다루기

import numpy as np
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris

# 데이터 적재
iris = load_iris()

# 특성 핼렬 생성
feature = iris.data

# 타깃 벡터 생성
target = iris.target

# 처음 40개 샘플 데이터 삭제
feature = feature[40:, :]
target = target[40:]

# 클래스 0을 음성 클래스로 하는 이진 타깃 벡터 생성
target = np.where((target == 0), 0, 1)

# 불균형한 타깃 벡터 확인
print(target)

# 결과
[0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
 
 # 가중치 생성
weights = {0: .9, 1: 0.1}

# 가중치를 부여한 랜덤 포레스트 분류기 생성
RandomForestClassifier(class_weight=weights)

# 균형잡힌 클래스 가중치로 랜덤 포레스트 모델 훈련
RandomForestClassifier(class_weight="balance")

# 각 클래스의 샘플 인덱스 추출
i_class0 = np.where(target == 0)[0]
i_class1 = np.where(target == 1)[0]

# 각 클래스의 샘플 개수
n_class0 = len(i_class0)
n_class1 = len(i_class1)

# 클래스 0의 샘플만큼 클래스 1에서 중복을 허용하지 않고 랜덤하게 샘플 추출
i_class1_downsampled = np.random.choice(i_class1, size=n_class0, replace=False)

# 클래스 0의 타깃 벡터와 다운 샘플링된 클래스 1의 타깃 벡터를 합침
print(np.hstack((target[i_class0], target[i_class1_downsampled])))

# 결과
[0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1]

# 클래스 0의 특성 행렬과 다운샘플링된 클래스 1의 특성 행렬을 합치기
print(np.vstack((feature[i_class0, :], feature[i_class1_downsampled, :]))[0:5])

# 결과
[[5.  3.5 1.3 0.3]
 [4.5 2.3 1.3 0.3]
 [4.4 3.2 1.3 0.2]
 [5.  3.5 1.6 0.6]
 [5.1 3.8 1.9 0.4]]
 
 
 # 클래스 1의 샘플 개수만큼 클래스 0에서 중복을 허용하여 랜덤하게 샘플을 선택하는 방법
i_class0_upsampled = np.random.choice(i_class0, size = n_class1, replace = True)

# 클래스 0의 업샘플링된 타깃 벡터와 클래스 1의 타깃 벡터를 합치기
print(np.concatenate((target[i_class0_upsampled], target[i_class1])))

# 결과
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]

# 클래스 0의 업샘플링된 특성 행렬과 클래스 1의 특성 행렬 합치기
print(np.vstack((feature[i_class0_upsampled, :], feature[i_class1, :]))[0:5])

# 결과
[[4.6 3.2 1.4 0.2]
 [5.1 3.8 1.9 0.4]
 [4.4 3.2 1.3 0.2]
 [5.1 3.8 1.6 0.2]
 [4.4 3.2 1.3 0.2]]

 

'AI > 빅데이터' 카테고리의 다른 글

텍스트 다루기  (0) 2021.06.24
수치형 데이터 다루기  (0) 2021.06.22
3.하둡-YARN  (0) 2021.02.18
3.하둡-맵리듀스  (0) 2021.02.18
3.하둡-2  (0) 2021.02.18