#!/usr/bin/env python3


Elastic Net Regression


elastic net regression을 풀기위해서는 아래 방정식을 적용합니다.

$$y = Ax + b$$


#  y = Sepal Length

#  x = Pedal Length, Petal Width, Sepal Width


사용자 정의 형태로 만들어 인자를 변경하며 결과를 확인해보겠습니다.

elastic net regression의 cost function은 다음과 같습니다.

$$cost = mean \left( \sum{\left (y - \overset{\wedge}{y}\right)^{2} }\right) + 1 \cdot mean \left (\sum{\left | x_{i} \right |}\right) +1 \cdot mean \left (\sum {x^{2}_{i}} \right ) $$

import matplotlib.pyplot as plt

import numpy as np

import tensorflow as tf

from sklearn import datasets

from tensorflow.python.framework import ops


def elastic_net_func(idx, batch_size):

    ops.reset_default_graph()


    # iris.data = [(Sepal Length, Sepal Width, Petal Length, Petal Width)]

    iris = datasets.load_iris()

    x_vals = iris.data[:, idx]

    y_vals = iris.data[:, 0]


    # Initialize placeholders

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

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


    # Create variables for linear regression

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

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


    with tf.Session() as sess:

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

        np.random.seed(seed=42)

        tf.set_random_seed(seed=42)


        l1_a_loss = tf.reduce_mean(tf.abs(A))

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

        y_loss = tf.reduce_mean(tf.square(y_target - fomula)) 


        loss = tf.add(tf.add(l1_a_loss, l2_a_loss), y_loss) # cost function


        opt = tf.train.GradientDescentOptimizer(0.001)

        train_step = opt.minimize(loss)


        # Initialize variables

        init = tf.global_variables_initializer()

        init.run()


        loss_vec = []

        for i in range(1000):

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

            rand_x = x_vals[rand_idx].reshape(-1, 1)

            rand_y = y_vals[rand_idx].reshape(-1, 1)


            my_dict = {x_data:rand_x, y_target:rand_y}

            sess.run(train_step, feed_dict=my_dict)

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

            loss_vec.append(temp_loss)

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

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


        [coef] = A.eval()[0]

        [intercept] = b.eval()[0]


        best_params = []

        for i in x_vals:

            poly = i*coef + intercept

            best_params.append(poly)


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

    axe[0].scatter(x_vals, y_vals, edgecolors='k', label='data points')

    axe[0].plot(x_vals, best_params, c='red', label='best pit line')

    axe[0].set_title('index={}\nslope = {:.5f}, intercept = {:.5f}'.format(idx ,coef, intercept))

    axe[0].set_xlabel('{}'.format(iris.feature_names[idx]))

    axe[0].set_ylabel('{}'.format(iris.feature_names[0]))

    axe[0].legend(loc=2)


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

    axe[1].set_xlabel('Generation')

    axe[1].set_ylabel('Loss')

    axe[1].set_title('Loss per Generation')


    plt.show()


사용자 정의 함수를 이용하여 인자에 따른 시각화를 해보겠습니다.

elastic_net_func(idx=1, batch_size=50)

sepal width vs sepal length

# step 200: A=[1.70271], b=[-0.14161193], Loss=6.42409610748291

# step 400: A=[1.6244563], b=[0.16109753], Loss=6.042064189910889

# step 600: A=[1.5415831], b=[0.44974053], Loss=5.765136241912842

# step 800: A=[1.4513652], b=[0.72334766], Loss=4.744622707366943

# step 1000: A=[1.3864329], b=[0.99185705], Loss=5.004234790802002



elastic_net_func(idx=2, batch_size=50)

petal length vs sepal length

# step 200: A=[1.3025422], b=[-0.19726731], Loss=7.4931416511535645

# step 400: A=[1.2043393], b=[0.24439183], Loss=5.619389057159424

# step 600: A=[1.1216723], b=[0.6478416], Loss=4.893489837646484

# step 800: A=[1.0472624], b=[1.0189508], Loss=5.274661540985107

# step 1000: A=[0.9723399], b=[1.3565185], Loss=2.696936845779419



elastic_net_func(idx=3, batch_size=50)

petal width VS sepal length

# step 200: A=[1.3511531], b=[1.0177041], Loss=14.15509033203125

# step 400: A=[1.5765594], b=[2.0053844], Loss=8.151086807250977

# step 600: A=[1.4302077], b=[2.6739304], Loss=5.979291915893555

# step 800: A=[1.2245288], b=[3.1957018], Loss=4.475618362426758

# step 1000: A=[1.0373899], b=[3.6267276], Loss=3.252098560333252




참고 자료: 

[1]TensorFlow Machine Learning Cookbook, Nick McClure

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

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

Logistic Regression  (0) 2018.05.01
LASSO and Ridge Regression  (1) 2018.04.27
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