#!/usr/bin/env python3


LASSO and Ridge Regression


이전 포스팅 보기

[1]Ridge, [2]Lasso


LASSO Ridge는 모두 출력 값에 미치는 regularization을 적용합니다.

tensorflow에서는 기울기A값에 의존하는 항을 cost function에 추가하면 이런 효과를 얻을 수 있습니다.


LASSO의 경우 기울기A가 특정 값 이상이 되면 cost를 크게 증가시키는 항을 추가해야합니다.

tensorflow의 논리 연산을 사용할 수도 있지만, 이렇게 하면 경사도를 계산할 수 없습니다. 대신에 step function을 연속 함수로 근사한 continuous heavyside step 함수를 조절해서 사용하여 문제를 해결 할 수 있습니다.


step function은 step이 중요합니다. step이 너무 높으면 수렴하지 않는 경우가 발생할 수 있습니다.


iris데이터셋으로 LASSO를 적용해보겠습니다. 


먼저 data를 로딩하고 placeholder를 생성하겠습니다.

import tensorflow as tf

from tensorflow.python.framework import ops

import numpy as np

from sklearn.datasets import load_iris


ops.reset_default_graph()


iris = load_iris()

# iris.keys(): dict_keys(['data', 'target', 'target_names', 'DESCR', 'feature_names'])

# iris.feature_names: ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']


regression_type = 'LASSO' # LASSO, Ridge


x_vals = iris.data[:, 3] # petal width

y_vals = iris.data[:, 0] # sepal length


x_data = tf.placeholder(shape=[None, 1], dtype=tf.float32)

y_target = tf.placeholder(shape=[None, 1], dtype=tf.float32)


A = tf.Variable(tf.random_normal(shape=[1, 1]))

b = tf.Variable(tf.random_normal(shape=[1, 1]))


연속함수로 근사한 LASSO의 cost function인 heavyside step function은 다음과 같이 쓸 수 있습니다.$$y = \frac {1}{e^{ \left( x-\theta \right) \cdot (-\delta) }+1}$$


Ridge의 cost function은 다음과 같습니다.

$$mean\left(\sum { \left( y-\overset { \wedge  }{ y }  \right) ^{ 2 } }\right) + mean \left(\theta \sum {A^{ 2 } } \right)$$

여기서 $\theta$는 critical value임계값을 말하며 $\delta$는 step의 sensitivity민감도를 나타냅니다.


activate function인 continuous heavyside step함수는 다음 코드로 시각화 할 수 있습니다.

deltas = [0.1, 1, 5, 50]

_, axes = plt.subplots(2, 2)


for ax, delta in zip(axes.ravel(), deltas):

    line = np.linspace(-5, 5)

    theta = 0.9

    step = 1

    y = 1/(np.exp((line-theta)*(-delta)) + 1) * step

    ax.plot(line, y)

    ax.set_title('$\delta$={}'.format(delta))

plt.show()

$\delta$값에 따른 heavyside step function



따라서 LASSO와 Ridge의 cost function을 고려한 연산과정은 다음과 같습니다

with tf.Session() as sess:

    fomula = tf.add(tf.matmul(x_data, A), b)


    if regression_type == 'LASSO':

        lasso_params = tf.constant(0.9, dtype=tf.float32) # limit slope

        heavyside_step = tf.truediv(1., tf.add(tf.exp(tf.multiply(tf.subtract(A, lasso_params), -50)), 1))

        regularization = tf.multiply(99., heavyside_step)

        loss = tf.add(tf.reduce_mean(tf.square(y_target-fomula)), regularization)


    elif regression_type == 'Ridge':

        ridge_params = tf.constant(1., dtype=tf.float32)

        ridge_loss = tf.reduce_mean(tf.square(A))


loss = tf.expand_dims(tf.add(tf.reduce_mean(tf.square(y_target-fomula)),

                                     tf.multiply(ridge_params, ridge_loss)), 0) 


    opt = tf.train.GradientDescentOptimizer(learning_rate=0.001)

    train_step = opt.minimize(loss)


    init = tf.global_variables_initializer()

    init.run()


    loss_vec = []

    for i in range(1500):

        rnd_idx = np.random.choice(len(x_vals), size = batch_size)

        rnd_x = x_vals[rnd_idx].reshape(-1, 1)

        rnd_y = y_vals[rnd_idx].reshape(-1, 1)


        my_dict = {x_data:rnd_x, y_target:rnd_y}

        sess.run(train_step, feed_dict=my_dict)

        temp_loss = sess.run(loss, feed_dict=my_dict)

        loss_vec.append(temp_loss[0])


        if (i+1)%300 == 0:

            print('step={}: A={}, b={}, Loss={}'.format(i+1, A.eval(), b.eval(), temp_loss))

     # step=300: A=[[0.7634046]], b=[[2.8413053]], Loss=[[5.382721]]

     # step=600: A=[[0.75245243]], b=[[3.7877374]], Loss=[[1.4977918]]

     # step=900: A=[[0.7403701]], b=[[4.3101645]], Loss=[[0.6288415]]

     # step=1200: A=[[0.72969586]], b=[[4.60605]], Loss=[[0.40883213]]

     # step=1500: A=[[0.72272784]], b=[[4.7734385]], Loss=[[0.3297159]]

    slope = A.eval()[0]

    cept = b.eval()[0]



더 자세히 알아보기 위해  시각화 하면

best_fit = []    

for i in x_vals.ravel():

    poly = i*slope + cept

    best_fit.append(poly)


_, ax = plt.subplots(1, 2)

ax[0].scatter(x_vals, y_vals, edgecolors='k', label='Data Points')

ax[0].plot(x_vals, best_fit, c='red', label='Best fit line', linewidth=3)

ax[0].legend(loc=2)

ax[0].set_title('Petal Width vs Sepal Length')

ax[0].set_xlabel('Petal Width')

ax[0].set_ylabel('Sepal Length')


ax[1].plot(loss_vec, c='k')

ax[1].set_title(regression_type + ' Loss per Generation')

ax[1].set_xlabel('Generation')

ax[1].set_ylabel('Loss')


plt.show()

LASSO Regression과 Loss함수



위의 코드를 사용자 정의 함수로 만들어 LASSO, Ridge를 살펴보겠습니다



위의 결과는 아래 코드로 확인할 수 있습니다.

my_regression_type(regression_type='LASSO', batch_size=50)

# step=300: A=[[0.764575]], b=[[2.5382898]], Loss=[[5.8621655]]

# step=600: A=[[0.7535565]], b=[[3.618642]], Loss=[[1.8615394]]

# step=900: A=[[0.7427662]], b=[[4.2173624]], Loss=[[0.7045775]]

# step=1200: A=[[0.7338138]], b=[[4.5521526]], Loss=[[0.44136143]]

# step=1500: A=[[0.72335386]], b=[[4.739038]], Loss=[[0.23825285]]

LASSO Linear Regression과 Loss



my_regression_type(regression_type='Ridge', batch_size=50)

# step=300: A=[[1.9796406]], b=[[1.416961]], Loss=[8.540436]

# step=600: A=[[1.7114378]], b=[[2.419876]], Loss=[5.517313]

# step=900: A=[[1.4033114]], b=[[3.132286]], Loss=[3.4445624]

# step=1200: A=[[1.1520133]], b=[[3.6732914]], Loss=[2.298217]

# step=1500: A=[[0.95343864]], b=[[4.086554]], Loss=[1.4839184]

Ridge Linear Regression과 Loss 




참고 자료: 

[1]TensorFlow Machine Learning Cookbook, Nick McClure

[2]https://github.com/nfmcclure/tensorflow_cookbook

'Tensorflow > Linear Regression' 카테고리의 다른 글

Logistic Regression  (0) 2018.05.01
Elastic Net Regression  (0) 2018.04.29
Deming Regression  (0) 2018.04.27
Loss Function in Linear Regressions  (0) 2018.04.26
TensorFlow Way of LinearRegression  (0) 2018.04.26

#!/usr/bin/env python3


Ridge


Ridge는 linear model이므로 OLS(Ordinary Least Square)를 사용합니다.

Ridge Regression에서 가중치(w) 선택은 추가 제약 조건을 생성하여

가중치(w)의 절댓값을 가능학 작게 만드는 것(0으로 만드는 것이 아님)입니다.


기하학적으로 모든 특성의 기울기를 0에 가깝게 만드는 것이고 이 것을 regularization이라 합니다.

즉 model을 overfitting 하지 않도록 강제로 제한하는 것입니다.


Ridge Regression에 사용하는 regularization을 L2 regularization이라고도 합니다.


보스턴 주택가격으로 Ridge Regression과 linear regression을 사용하여 비교해보겠습니다.

from mglearn.datasets import load_extended_boston

from sklearn.linear_model import Ridge, LinearRegression

from sklearn.model_selection import train_test_split


boston_data, boston_target = load_extended_boston()

x_train, x_test, y_train, y_test = \

  train_test_split(boston_data, boston_target,

                   random_state=0, test_size=0.3)


ridge = Ridge()

ridge.fit(x_train, y_train)

lr = LinearRegression()

lr.fit(x_train, y_train)


print('{:.3f}'.format(ridge.score(x_train, y_train)))

# 0.882

print('{:.3f}'.format(lr.score(x_train, y_train)))

# 0.952

print('{:.3f}'.format(ridge.score(x_test, y_test)))

# 0.783

print('{:.3f}'.format(lr.score(x_test, y_test)))

# 0.645

train set정확도는 Ridge Reg. < Linear Reg.

test set정확도는 Ridge Reg. > Linear Reg. 입니다.


Linear Reg는 train set과 test set의 차이가 많이나므로 overfittng이 되지만

Ridge Reg는 regularization이 적용되기 때문에 train set과 test set의 차이가 적습니다.

따라서 model의 complexity가 낮아지게 되고 test set의 정확도는 상승합니다.



다음으로 Ridge의 Regularization에 대해서 알아보겠습니다.

Ridge Reg.는 alpha parameter로 model을 얼마나 단순화할지를 결정합니다.

default 값은 1이며 높을수록 Regularization을 강화하여 계수를 0에 가깝게 만듭니다.


alpha값에 따른 정확도비교는 아래코드로 확인할 수 있습니다.

alpha_train_score = []

alpha_test_score = []

alpha_set = [0.1, 1 ,10]


for i in alpha_set:

    ridge=Ridge(alpha=i)

    ridge.fit(x_train, y_train)


    ridge_tr_score = round(ridge.score(x_train, y_train), 3)

    ridge_te_score = round(ridge.score(x_test, y_test), 3)


    alpha_train_score.append(ridge_tr_score)

    alpha_test_score.append(ridge_te_score)


print(alpha_set)

# [0.1, 1, 10]


print(alpha_train_score)

# [0.927, 0.882, 0.78]


print(alpha_test_score)

# [0.797, 0.783, 0.678]

alpha값이 커질수록(규제가 강화될수록) 정확도는 낮아지는 것을 볼 수 있습니다.



Ridge도 Linear_model이므로 속성(coef_, intercept_)가 존재합니다.

Ridge의 alpha값에 따른 coef_를 조사하면

import numpy as np

import matplotlib.pyplot as plt


n_feature = boston_data.shape[1]

line = np.linspace(0, n_feature, num=n_feature).reshape(-1, 1)


lr = LinearRegression().fit(x_train, y_train)

plt.scatter(line, lr.coef_, marker='s', label='Linear Reg.') # marker = 's'  => square


alpha_set = [0.1, 1 ,10]

marker_set = ['o', '^', 'v']

for i, m in zip(alpha_set, marker_set):

    ridge = Ridge(alpha=i)

    ridge.fit(x_train, y_train)

    plt.scatter(line, ridge.coef_, marker=m, label='alpha={}'.format(i))


plt.ylim(-30, 30)

plt.hlines(y=0, xmin=0, xmax=n_feature)

plt.legend(loc=(0.01, 1.01))

plt.show()

Linar Regression과 몇 가지 alpha 값을 가진 Ridge Regression의 coefficient 비교

x축은 coef_의 원소를 위치대로 나열한 것입니다. 즉 x=0, x=1은 각각 첫번째 특성과 두번째 특성을 나타내는 것입니다.

alpha=10일 때(빨강 역삼각형)은 대부분 y=0에 위치하며

alpha=1(초록 정삼각형)은 alpha=10일 때보다는 약간 퍼진 상태입니다.

alpha=0.1(주황 원)은 매우 크게 확장되었으며

Linear Reg.(파랑 정사각형)은 자유롭게 퍼져있는 것을 확인할 수 있습니다.



이번엔 learning curve(데이터셋의 크기에 따른 모델의 성능 변화)를 알아보겠습니다.

train_ridge_set = []

train_linear_set = []

test_ridge_set = []

test_linear_set = []


for i in test_size_set:

    x_train, x_test, y_train, y_test = \

      train_test_split(boston_data, boston_target,

                       random_state=35, test_size=i)

    ridge = Ridge(alpha=1).fit(x_train, y_train)

    lr = LinearRegression(n_jobs=-1).fit(x_train, y_train) # n_jobs = 사용할 코어의 수, -1은 모든 코어사용


    rid_tr_score = ridge.score(x_train, y_train)

    rid_te_score = ridge.score(x_test, y_test)

    lr_tr_score = lr.score(x_train, y_train)

    lr_te_score = lr.score(x_test, y_test)


    train_ridge_set.append(rid_tr_score)

    train_linear_set.append(lr_tr_score)

    test_ridge_set.append(rid_te_score)

    test_linear_set.append(lr_te_score)


plt.plot(x_ticks, train_ridge_set, c='lightblue', ls='--', label='train ridge'# c = color, ls = linestyle

plt.plot(x_ticks, train_linear_set, c='orange', ls='--',label='train Linear_Reg')

plt.plot(x_ticks, test_ridge_set, c='lightblue', label='test ridge')

plt.plot(x_ticks, test_linear_set, c='orange', label='test Linear_Reg')


plt.legend(loc=(0.01, 1.01))

plt.ylim(0, 1.1)

plt.show()

보스턴 주택가격 데이터셋에 대한 Ridge vs Linear Reg,

train 데이터(점선)가 test 데이터(line)보다 높음을 알 수 있습니다.

Ridge에는 regularization이 적용되므로 Linear Reg보다 낮습니다.


일반화 데이터에서는 Ridge의 점수가 더 높으며, 데이터셋이 작을수록 두드러집니다.

데이터셋의 크기가 작을수록 Linear Reg.는 어떤 것도 학습하지 못합니다.


데이터가 충분히 크면 regularization이 덜 중요해지고(두 모델의 차이가 줄어듭니다.)

Linear_Reg의 경우 데이터셋이 클수록 train 데이터 성능이 감소합니다. 이는 데이터가 많아질수록 overfitting 하기가 어려움을 시사합니다




참고 자료: 

[1]Introduction to Machine Learning with Python, Sarah Guido

'python 머신러닝 -- 지도학습 > Regression' 카테고리의 다른 글

Decision Tree Regressor  (0) 2018.03.14
Lasso  (0) 2018.03.13
LinearRegression  (0) 2018.03.12
k_NN(k-최근접 이웃) Regression  (1) 2018.03.12

+ Recent posts