#!/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=Falsesparse 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구간분할이 모델 성능을 높이는데 아주 좋은 방법이 될 수 있음

  1. 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

+ Recent posts