#!/usr/bin/env python3
LASSO and Ridge Regression
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 |