#!/usr/bin/env python3


interaction과 polynomial


특별히 특성을 다양하게 나타내는 방법은 원본 데이터interactionpolynomial을 추가하는 것

이런 방법은 머신러닝에도 많이 적용


구간별 선형 모델은 인위적인 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[각주:1](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다항 회귀모델이 됨


SVR 은 아래 링크 참조

Kernelized Support Vector Machines


### 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



  1. np.digitize: 각 데이터 포인트가 어느 구간에 속하는지 계산 후 인덱스로 리턴 [본문으로]

+ Recent posts