#!/usr/bin/env python3
interaction과 polynomial
특별히 특성을 다양하게 나타내는 방법은 원본 데이터에 interaction과 polynomial을 추가하는 것
이런 방법은 머신러닝에도 많이 적용
구간별 선형 모델은 인위적인 wave 데이터셋의 각 구간에 대해 상수값을 학습하지만 linear 모델은 절편뿐만 아니라 기울기도 학습 가능
선형 모델에 기울기를 추가하는 방법은 구간으로 분할된 데이터에 원래특성을 다시 추가
wave 데이터셋의 경우 10개의 구간을 나누면 원래 특성 + 10 = 11차원 데이터셋이 만들어짐
1. wave data(인위적 데이터셋)에 특성 추가하기
### import library
import matplotlib.pyplot as plt
import matplotlib
from sklearn.preprocessing import OneHotEncoder
from mglearn.datasets import make_wave
import numpy as np
### matplotlib 설정
matplotlib.rc('font', family='AppleGothic')
plt.rcParams['axes.unicode_minus'] = False
### datasets
x , y = make_wave(n_samples=100)
# print(x)
# print(y)
### binding
bins = np.linspace(-3, 3, num=11)
# print(bins)
which_bins = np.digitize(x, bins=bins) # bins: 구간
# print(x[:5])
# print(which_bins)
encoder = OneHotEncoder(sparse=False).fit(which_bins) # OneHotEncoder 메소드 호출 후 적용
x_binned = encoder.transform(which_bins)
print('x_binned[:5] \n{}'.format(x_binned[:5]))
wave데이터의 x에서 one-hot-encoding을 적용한 데이터의 일부
### import library
from sklearn.linear_model import LinearRegression
### model 호출 후 OHE(One Hot Encoding)된 데이터 적용
lreg = LinearRegression().fit(x_binned, y)
### 축 생성
line = np.linspace(-3, 3, num=1000, endpoint=False).reshape(-1, 1)
### np.digitize(line, bins=bins) : line의 각 데이터 포인트가 bins의 어디 구간인지 표현 ==> 1~10 까지 숫자
### encoder.transform(np.digitize(line, bins=bins)) : 1 ~ 10까지를 OHE로 표현 ex) 1 => [1, 0, 0, 0, 0, 0, 0, 0, 0, 0] // 3 => [0, 0, 1, 0, 0, 0, 0, 0 ,0 ,0]
line_binned = encoder.transform(np.digitize(line, bins=bins))
### predict
lreg_pred = lreg.predict(line_binned)
### 각 구간에서는 같은 특성(ex)[0, 1, 0, 0, 0 ,0 ,0 ,0 ,0 ,0])을 가지기 때문에 각 구간에서는 일정한 값으로 예측됨
### 구간에서 기울기 값 추가
x_combined = np.hstack([x, x_binned]) # 원래 특성x와 구간별로 OHE된 리스트를 결합
print('x_combined.shape \n{}'.format(x_combined.shape))
line_combined = np.hstack([line, line_binned])
### model 호출 후 결합한 데이터를 적용
lreg_comb = LinearRegression().fit(x_combined, y)
### predict
pred_lreg_comb = lreg_comb.predict(line_combined)
### visualization
plt.scatter(x[:, 0], y, marker='o', c='k') # c = color
plt.plot(line, lreg_pred, label='binding linear Reg', ls='--', lw=3) # ls = linestyles, lw= linewidths
plt.plot(line, pred_lreg_comb, label='plus original feature')
plt.vlines(bins, ymin=-3, ymax=3, lw=1, alpha=0.2, linestyles=':') # lw = linewidths
plt.ylabel('output regression')
plt.xlabel('input feature')
plt.legend(loc=2) # loc = 1, 2, 3, 4 : 오른쪽 위, 왼쪽 위, 왼쪽 아래, 오른쪽 아래
plt.show()
구간으로 분할된 특성과 하나의 기울기를 사용한 linear regression
이 모델은 각 구간의 절편과 기울기를 학습함
학습된 기울기는 음수이고 모든 구간에 걸쳐 동일
x축 특성이 하나이므로 기울기도 하나이며 모든 구간에서 동일
2. wave data(인위적 데이터셋)에 기울기 특성 추가하기(1)
각 구간에서 다른 기울기를 가지게 하기 위해 데이터 포인트가 있는 구간과
x축 사이의 상호작용 특성을 추가 가능(구간 특성과 원본 특성의 곱)하여 기울기를 표현
### data 축 추가
x_product = np.hstack([x_binned, x * x_binned])
line_proudct = np.hstack([line_binned, line*line_binned])
print(x_product.shape) # (100, 20)
### x_binned는 데이터 포인트가 속한 구간의 one-hot-encoding이므로 x를 곱하면 해당 구간이외에는 모두 0
### 모델 호출 후 결합한 데이터 적용
linear_reg = LinearRegression().fit(x_product, y)
pred_linear_reg = linear_reg.predict(line_proudct)
### visualization
plt.plot(line, pred_linear_reg, label='original feature를 곱한 linear regression')
for bin in bins:
plt.plot([bin, bin], [-3, 3], ls=':', c='k', lw=1, alpha=0.4)
plt.scatter(x[:, 0], y, marker='o', c='k')
plt.ylabel('output regression')
plt.xlabel('input feature')
plt.legend(loc=2)
plt.show()
구간별 기울기가 다른 linear regression
3. wave data(인위적 데이터셋)에 기울기 특성 추가하기(2)
### 구간 나누기는 연속형 특성을 확장하는 방법 중 하나
### 특성 x가 주어지면 x**2, x**3, x**4 ... 등을 시도 가능하여 여러차원으로 까지 늘릴 수 있음
### preprocessing의 PolynomialFeatures에 구현되어 있음
from sklearn.preprocessing import PolynomialFeatures
### degree: x**10까지, include_bias=True: 절편을 그리기 위해 값이 1인 특성을 왼쪽에 추가
poly = PolynomialFeatures(degree=10, include_bias=False)
poly.fit(x)
x_poly = poly.transform(x)
# 10차원을 사용했으므로 10개의 특성이 만들어짐
print('x_poly.shape \n{}'.format(x_poly.shape))
print('x[:5] \n{}'.format(x[:5]))
print('x_poly[:5] \n{}'.format(x_poly[:5]))
print('poly.get_feature_names() \n{}'.format(poly.get_feature_names()))
만들어진 특성의 모양
### 다항식 특성을 선형 모델과 함께 사용하면 전형적인 polynomial regression다항 회귀모델이 됨
### viusalization
### 다항식을 결합한 특성을 적용
poly_reg = LinearRegression().fit(x_poly, y)
line_poly = poly.transform(line)
pred_poly_reg = poly_reg.predict(line_poly)
plt.plot(line, pred_poly_reg, label='polynomial linear regression')
plt.scatter(x[:, 0], y, marker='o', c='k')
plt.xlabel('input feature')
plt.ylabel('output regression')
plt.vlines(bins, ymin=-3, ymax=3, linestyles=':', colors='grey', alpha=0.4) # linestyles = ':' ==> dash
from sklearn.svm import SVR
for gamma in [1, 10]:
svr = SVR(gamma=gamma).fit(x, y)
plt.plot(line, svr.predict(line), label='SVR gamma={}'.format(gamma))
plt.legend(loc=(-0.001, 1.01))
plt.show()
RBF 커널 SVM의 gamma parameter 변화와 10차 다항식을 이용한 LinearRegression