#!/usr/bin/env python3


polynomial analysis with boston house price


1. 실제 데이터로 polynomial 분석



Ridge 참조


Random Forest 참조


### load library

from sklearn.datasets import load_boston

from sklearn.model_selection import train_test_split

from sklearn.preprocessing import MinMaxScaler, OneHotEncoder, PolynomialFeatures

from sklearn.linear_model import Ridge

from sklearn.ensemble import RandomForestRegressor


### data load

boston = load_boston() 

# print(boston.keys())

x_train, x_test, y_train, y_test = \

  train_test_split(boston.data, boston.target,

                   test_size=0.3, random_state=0)


### scale 조정

scaler_mms = MinMaxScaler().fit(x_train) # scaler 호출

x_train_scaled = scaler_mms.transform(x_train) # scaler를 x_train에 적용

x_test_scaled = scaler_mms.transform(x_test) # scaler를 x_test를 적용


### model

randfor = RandomForestRegressor(n_estimators=100, random_state=0, n_jobs=-1) # n_jobs = 코어의 수(-1 : all)

ridge = Ridge()

models = [randfor, ridge]


### model 적용 및 성능 테스트

for degree in range(1, 6):

    poly = PolynomialFeatures(degree=degree, include_bias=False).fit(x_train_scaled)# include_bias = True: x_train_scaled 맨 왼쪽에 상수항 추가. 

    x_train_poly = poly.transform(x_train_scaled)

    x_test_poly = poly.transform(x_test_scaled)

    print('degree={}'.format(degree))

    print('x_train.shape={}'.format(x_train.shape))

    print('x_train_poly.shape={}\n'.format(x_train_poly.shape))

    print('원래 특성과 polynomial 한 특성의 수 \n==> origin:{}, poly:{}\n'.format(

        boston.data.shape[1], len(poly.get_feature_names())))


    for model in models:

        conf = model.fit(x_train_scaled, y_train)

        print('교차항이 없을 때 {} 점수: {:.3f}'.format(

            model.__class__.__name__, model.score(x_test_scaled, y_test))) # __class__.__name__ : class이름 호출

        conf = model.fit(x_train_poly, y_train)

        print('degree={}, 교차항이 있을 때 {} 점수{:.3f}\n'.format(

            degree, model.__class__.__name__, model.score(x_test_poly, y_test)))

    ptrint('----------------------------------------------')


모델 성능 테스트 평가의 일부분

교차항이 있을 때 Ridge모델은 성능이 상승하지만

복잡한 모델인 RandomForestRegressor경우에는 정확도가 큰차이가 나지 않음

degree=3의 경우

중복조합을 이용

원래 특성 13개 + x0 ~ x12 중 중복을 허락하여 2개를 조합(91개) + x0 ~ x12 중 중복을 허락하여 3개를 조합(455개)를 다합친 559개가 특성으로 사용됨


'데이터 표현과 특성 > interaction과 polynomial' 카테고리의 다른 글

interaction과 polynomial  (0) 2018.03.28

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