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

+ Recent posts