#!/usr/bin/env python3
One-Hot-Encoding으로 wave 데이터셋 분석
데이터를 가장 잘 표현하는 방법은 데이터가 가진 의미뿐 아니라 어떤 모델을 사용하는지에 따라 다름
아주 폭넓게 사용하는 두 알고리즘인
linear 모델과 tree 기반 모델(decision tree, gradient boosting tree, random forest 등)은
특성의 표현 방식으로 인해 미치는 영향이 매우 다름
1. wave 데이터셋(인위적 데이터)으로 확인하기
이 데이터에는 입력 특성이 하나뿐
이 데이터셋을 이용해 linear regression 과 decision tree regression tree를 비교
# library import
from sklearn.linear_model import LinearRegression
from sklearn.tree import DecisionTreeRegressor
from mglearn.datasets import make_wave
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
# matplotlib 설정
matplotlib.rc('font', family='AppleGothic') # 한글
plt.rcParams['axes.unicode_minus'] = False # 축 -
# dataset
x, y = make_wave(n_samples=100)
line = np.linspace(-3, 3, num=1000, endpoint=False).reshape(-1, 1)
# model fit
# decision tree
decision_tree_reg = DecisionTreeRegressor(min_samples_split=3).fit(x, y) # min_samples_split 1
plt.plot(line, decision_tree_reg.predict(line), label='decision tree')
# linear regression
linear_reg = LinearRegression().fit(x, y)
plt.plot(line, linear_reg.predict(line), ls='--', label='linear regression') # ls = linestyle,
plt.scatter(x[:, 0], y, marker='o', c='k') # c=color
plt.ylabel('output regression')
plt.xlabel('input feature')
plt.legend(loc=2)
plt.show()
wave 데이터셋에 적용한 LinearRegression과 DecisionTreeRegressor
2. binding(구간분할)
linear 모델은 선형으로만 modeling 하므로 특성이 하나일 땐 직선으로 나타남
decision tree는 훨씬 복잡한 modeling을 함
연속형 데이터에 아주 강력한 linear 모델을 만드는 방법중 하나는
한 특성을 여러 특성으로 나누는 구간분할binding(이산화)임
wave 데이터셋이 특성의 입력값 범위(-3, 3)가 나뉘어 여러 구간으로
10개로 되었다고 가정하면 각 데이터 포인트가 어떤 구간에 속하는지로 나타낼 수 있음
### step1. 구간을 먼저 정하고 ==> 같은 간격으로 10개의 구간을 정의
bins = np.linspace(-3, 3, num=11) # num: 쪼갤 갯수
print('구간: \n{}'.format(bins))
print('구간의 수 \n{}'.format(len(bins)-1))
-3, 3 사이의 구간과 구간의 수
### step2. 각 데이터 포인트가 어느 구간에 속하는지 기록
which_bin = np.digitize(x, bins=bins) # 데이터, 구간
print('데이터 포인트 처음 5개 \n{}'.format(x[:5]))
print('데이터 포인트의 소속구간 처음 5개 \n{}'.format(which_bin[:5]))
각 구간에 맵핑한 x 데이터의 일부
이렇게 함으로써 wave 데이터셋에 있는 연속형 특성을 각 데이터 포인트가 어느 구간에 속하는지 인코딩한 범주형 특성으로 변환이 가능
==> 이 데이터에 모델을 적용하기 위해 preprocessing 모듈의 OneHotEncoder로 이산적인 이 특성을 one-hot-encoding으로 변환
OneHotEncoder는 pandas.get_dummies와 같지만 현재는 숫자로된 범주형 변수에만 적용가능
3. OneHotEncoding된 데이터로 Linear Regressor와 Decision Tree Regressor의 비교
# library import
from sklearn.preprocessing import OneHotEncoder
encoder = OneHotEncoder(sparse=False) # sparse matrix: 희소행렬, True면 1이 있는 값의 위치와 값을 나타냄
encoder.fit(which_bin)
x_binned = encoder.transform(which_bin)
print('x_binned[:5] \n{}'.format(x_binned[:5]))
one-hot-encoder된 구간에 맵핑된 x 데이터의 일부
### 구간을 10개로 정의했기 때문에 변환된 데이터셋 x_binned는 10개의 특성으로 구간
print('x_binned.shape \n{}'.format(x_binned.shape)) # (100, 10)
### one-hot-encoding된 데이터로 선형 회귀 모델과 결정트리의 모델을 새로 만들면
line_binned = encoder.transform(np.digitize(line, bins=bins))
plt.scatter(x[:, 0], y, marker='o', c='k') # c = color
lr_reg = LinearRegression().fit(x_binned, y)
plt.plot(line, lr_reg.predict(line_binned), label='binding linear regression', lw=5) # lw = linewidth
tree_reg = DecisionTreeRegressor(min_samples_split=3).fit(x_binned, y)
plt.plot(line, tree_reg.predict(line_binned), ls='--', label='binding decision tree', c='red') # ls = linestyle, c = color
plt.vlines(bins, ymin=-3, ymax=3, lw=1, alpha=0.2) # lw = linewidth
plt.legend(loc=2)
plt.ylabel('output regression')
plt.xlabel('input feature')
plt.show()
구간으로 나뉜 특성에 적용한 Linear Regrssion과 Decision Tree Regressor의 비교
LinearRegression과 DecisionTreeRegressor가 같은 예측을 만들어내서 완전히 겹침
구간별로 이 모델이 예측한 것은 상수값, 각 구간안에서는 특성의 값이 상수이므로 어떤 모델이든 그 구간의 포인트에 대해서는 같은 값을 예측함
구간으로 나누기전과 비교하면 각 구간에서 다른 값을 가지고 있으므로 linear모델이 훨씬 유연해짐, 반면 decision tree는 덜 유연해짐
tree 모델은 데이터를 자유롭게 나눠 학습할 수 있으므로 특성의 값을 구간으로 나누는 것이 아무런 득이 되지 않음
즉 decision tree는 데이터셋에서 예측을 위한 가장 좋은 구간을 학습함
구간나누기는 특성마다 따로 해야 하지만 decision tree는 한 번에 여러 특성을 살필 수 있음
하지만 linear 모델은 이런 변환으로 큰 이득을 얻음
일부 특성과 출력이 비선형 관계이지만, 용량이 매우 크고 고차원 데이터셋이라 선형모델을 사용해야 한다면
binding구간분할이 모델 성능을 높이는데 아주 좋은 방법이 될 수 있음
- min_samples_split: int, float, optional (default=2) The minimum number of samples required to split an internal node: If int, then consider min_samples_split as the minimum number. If float, then min_samples_split is a percentage and ceil(min_samples_split * n_samples) are the minimum number of samples for each split. Changed in version 0.18: Added float values for percentages. [본문으로]
'데이터 표현과 특성 > One-Hot-Encoding(' 카테고리의 다른 글
One-Hot-Encoding(가변수) (0) | 2018.03.27 |
---|