순서가 없는 범주형 특성 인코딩하기
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]]