TigerCow.Door

3_Regression


안녕하세요. 문범우입니다.

이번 포스팅은 텐서플로우의 튜토리얼 세번째 내용, Regression에 대한 내용입니다.


In [2]:
# TensorFlow and tf.keras
# 텐서플로우와 keras를 import한다. 이떄 tensorflow는 tf라는 별칭으로 사용할 것임.
import tensorflow as tf
from tensorflow import keras

# Helper libraries
# numpy와 matplotlib을 사용한다.
import numpy as np
import matplotlib.pyplot as plt
# jupyter notebook에서 matplotlib을 사용하기 위한 매직커맨드
%matplotlib inline

print("사용되는 tensorflow의 버전:",tf.__version__)
사용되는 tensorflow의 버전: 1.9.0

Regression 이란?

Regression(회귀분석)이란, 관찰되는 연속형 변수들에 대해서 두 변수 사이의 모형을 구한뒤 그 적합도를 측정하는 분석 방식이다.

ㄱ. 데이터 준비

tensorflow를 이용하여 데이터를 다운 받고 데이터를 섞어준다.(shuffle)

이후 데이터를 확인해보는데 이전과 다른점은, 그전보다 데이터의 개수가 훨씬 적다.

실제로 확인해보면 이번 실습에서 사용되는 데이터의 개수는 전체 506개이다.

In [8]:
boston_housing = keras.datasets.boston_housing

(train_data, train_labels), (test_data, test_labels) = boston_housing.load_data()

# Shuffle the training set
order = np.argsort(np.random.random(train_labels.shape))
train_data = train_data[order]
train_labels = train_labels[order]
In [9]:
print("Training set: {}".format(train_data.shape))  # 404 examples, 13 features
print("Testing set:  {}".format(test_data.shape))   # 102 examples, 13 features
Training set: (404, 13)
Testing set:  (102, 13)
In [10]:
train_data[0]
Out[10]:
array([7.8750e-02, 4.5000e+01, 3.4400e+00, 0.0000e+00, 4.3700e-01,
       6.7820e+00, 4.1100e+01, 3.7886e+00, 5.0000e+00, 3.9800e+02,
       1.5200e+01, 3.9387e+02, 6.6800e+00])

위와 같이 하나의 데이터는 총 13개의 특징을 가지고 있다.

각 특징이 나타내는 의미는 다음과 같다.

  1. Per capita crime rate.(1인당 범죄율)

  2. The proportion of residential land zoned for lots over 25,000 square feet.(25,000 평방 피트가 넘는 지역에 거주하는 토지의 비율.)

  3. The proportion of non-retail business acres per town.(마을 당 비 소매 사업 에이커의 비율.)

  4. Charles River dummy variable (= 1 if tract bounds river; 0 otherwise).(Charles River 더미 변수 (강이 경계에 있으면 1, 그렇지 않으면 0).)

  5. Nitric oxides concentration (parts per 10 million).(질소 산화물 농도 (1000 만 분당).)

  6. The average number of rooms per dwelling.(주거 당 평균 객실 수.)

  7. The proportion of owner-occupied units built before 1940.(1940 년 이전에 건설 된 소유 점령 단위의 비율.)

  8. Weighted distances to five Boston employment centers.(5 개의 보스턴 고용 센터에 가중치 적용.)

  9. Index of accessibility to radial highways.(방사형 고속도로 접근성 지수.)

  10. Full-value property-tax rate per $10,000.($ 10,000 당 부당한 재산세 비율.)

  11. Pupil-teacher ratio by town.(마을 별 학생 - 교사 비율.)

  12. 1000 (Bk - 0.63) ** 2 where Bk is the proportion of Black people by town.(1000 (Bk - 0.63) ** 2 여기서 Bk는 도시 별 흑인 비율입니다.)

  13. Percentage lower status of the population.(인구의 낮은 지위의 백분율.)

위와 같은 데이터들은 서로 다른 범위를 가지고 있다.

어떤 데이터는 0,1 의 범위를, 어떤 데이터는 1~12의 범위를, 어떤 데이터는 0~100의 범위를 가지고 있다.

실제 데이터들은 위와 같이 서로 다른 범주를 갖는 경우가 많은데, 이를 잘 분석하고 탐색하는 것은 중요한 기술이다.

먼저 pandas를 이용해서 입력데이터를 column name과 함께 살펴본다.

In [11]:
import pandas as pd

column_names = ['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD',
                'TAX', 'PTRATIO', 'B', 'LSTAT']

df = pd.DataFrame(train_data, columns=column_names)
df.head()
Out[11]:
CRIM ZN INDUS CHAS NOX RM AGE DIS RAD TAX PTRATIO B LSTAT
0 0.07875 45.0 3.44 0.0 0.437 6.782 41.1 3.7886 5.0 398.0 15.2 393.87 6.68
1 4.55587 0.0 18.10 0.0 0.718 3.561 87.9 1.6132 24.0 666.0 20.2 354.70 7.12
2 0.09604 40.0 6.41 0.0 0.447 6.854 42.8 4.2673 4.0 254.0 17.6 396.90 2.98
3 0.01870 85.0 4.15 0.0 0.429 6.516 27.7 8.5353 4.0 351.0 17.9 392.43 6.36
4 0.52693 0.0 6.20 0.0 0.504 8.725 83.0 2.8944 8.0 307.0 17.4 382.00 4.63

입력 데이터에 따른 label은 house price(thousands of dollars) 이다.

In [12]:
print(train_labels[0:10])  # Display first 10 entries
[32.  27.5 32.  23.1 50.  20.6 22.6 36.2 21.8 19.5]

ㄴ. 데이터 정규화

위에서 언급한 바와 같이 범위 등이 서로 다른 데이터들은 정규화를 시켜주는 것이 좋다.

각 특징에 대해 특징의 평균을 빼고 표준편차로 나누어준다.

정규화 없이도 모델이 훈련될 수 있지만, 정규화 되지 않은 데이터들은 훈련을 보다 어렵게 할 수 있으며

심지어 모델이 입력되는 데이터의 단위에 의존하게 될 수 있다.

In [15]:
# Test data is *not* used when calculating the mean and std.

mean = train_data.mean(axis=0)
std = train_data.std(axis=0)
train_data = (train_data - mean) / std
test_data = (test_data - mean) / std # test_data도 train_data의 평균과 표준편차를 이용한다.

print(train_data[0])  # First training sample, normalized
[-0.39725269  1.41205707 -1.12664623 -0.25683275 -1.027385    0.72635358
 -1.00016413  0.02383449 -0.51114231 -0.04753316 -1.49067405  0.41584124
 -0.83648691]

ㄷ. 모델 만들기

우리는 sequential 모델을 사용하여 두개의 dense layer를 연결한다.

그리고 최종 출력에서는 하나의 값을 반환하도록 한다.

In [16]:
def build_model():
  model = keras.Sequential([
    keras.layers.Dense(64, activation=tf.nn.relu, 
                       input_shape=(train_data.shape[1],)),
    keras.layers.Dense(64, activation=tf.nn.relu),
    keras.layers.Dense(1)
  ])

  optimizer = tf.train.RMSPropOptimizer(0.001)

  model.compile(loss='mse',
                optimizer=optimizer,
                metrics=['mae'])
  return model

model = build_model()
model.summary()
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense (Dense)                (None, 64)                896       
_________________________________________________________________
dense_1 (Dense)              (None, 64)                4160      
_________________________________________________________________
dense_2 (Dense)              (None, 1)                 65        
=================================================================
Total params: 5,121
Trainable params: 5,121
Non-trainable params: 0
_________________________________________________________________

ㄹ. 모델 훈련하기

총 500epochs를 진행하며 각 epoch마다 dot을 통해 표시하도록 한다.

훈련에 대한 것은 history 개체에 저장한다.

In [17]:
# Display training progress by printing a single dot for each completed epoch.
class PrintDot(keras.callbacks.Callback):
  def on_epoch_end(self,epoch,logs):
    if epoch % 100 == 0: print('')
    print('.', end='')

EPOCHS = 500

# Store training stats
history = model.fit(train_data, train_labels, epochs=EPOCHS,
                    validation_split=0.2, verbose=0,
                    callbacks=[PrintDot()])
....................................................................................................
....................................................................................................
....................................................................................................
....................................................................................................
....................................................................................................

history개체에 저장한 것을 그래프로 살펴본다.

In [18]:
def plot_history(history):
  plt.figure()
  plt.xlabel('Epoch')
  plt.ylabel('Mean Abs Error [1000$]')
  plt.plot(history.epoch, np.array(history.history['mean_absolute_error']), 
           label='Train Loss')
  plt.plot(history.epoch, np.array(history.history['val_mean_absolute_error']),
           label = 'Val loss')
  plt.legend()
  plt.ylim([0,5])

plot_history(history)

위의 그래프를 보면 알수 있듯이 약 200epoch부터는 모델의 성능향상이 거의 없다.

이럴때 모델이 자동적으로 stop을 하도록 수정해보자.

model.fit의 callback 부분에 earyl stop이 추가되었다.

In [19]:
model = build_model()

# The patience parameter is the amount of epochs to check for improvement.
early_stop = keras.callbacks.EarlyStopping(monitor='val_loss', patience=20)

history = model.fit(train_data, train_labels, epochs=EPOCHS,
                    validation_split=0.2, verbose=0,
                    callbacks=[early_stop, PrintDot()])

plot_history(history)
....................................................................................................
..

실제로 test data를 통해 얼마 만큼의 평균오차를 내는지 확인해보자.

In [20]:
[loss, mae] = model.evaluate(test_data, test_labels, verbose=0)

print("Testing set Mean Abs Error: ${:7.2f}".format(mae * 1000))
Testing set Mean Abs Error: $2947.01

ㅁ. 예측하기

In [21]:
test_predictions = model.predict(test_data).flatten()

print(test_predictions)
[10.710474 18.635462 22.104404 32.81973  27.015018 21.178158 26.611774
 22.564915 19.1268   23.936018 19.752283 17.452827 15.371007 43.447193
 19.94533  21.828798 27.71085  20.554897 20.708773 28.653221 12.816028
 16.259748 21.786507 17.738703 22.114128 26.368296 31.233797 31.095444
 11.65609  21.96858  20.735067 16.558405 35.90579  26.044052 18.955885
  8.80617  16.236498 18.209204 21.766678 27.251543 29.999348 30.49238
 14.658896 44.367027 31.695284 26.308619 28.913197 17.901768 24.071257
 23.236986 35.848755 20.972424 12.508268 16.33727  36.16853  29.573055
 13.147843 50.08273  37.53314  25.052143 27.157457 17.663246 15.22098
 19.24395  24.517494 22.699238 13.476988 23.181868 14.789012  8.453533
 27.990353 30.44094  26.718273 15.372239 26.475368 18.167768 21.319874
 24.394728 36.479847 11.181536 21.34497  39.06884  17.925838 14.414492
 18.226086 19.24096  20.92412  21.49447  21.532913 34.560352 21.857464
 21.240526 25.733452 40.7276   37.847027 20.7775   36.419277 53.005924
 28.091654 47.61222  32.666664 21.303524]


블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc



안녕하세요.

이번 포스팅에서는 TensorFlow를 통해 간단한 Linear Regression을 구현해보도록 하겠습니다.


1. Tensorflow 시작하기


지난 포스팅에서 윈도우 환경에서 tensorflow를 설치해보았습니다.

설치방법은 지난 포스팅을 참고하시면 좋을 것 같습니다.

먼저 다시 한번 tensorflow가 정상적으로 동작하는지 확인하겠습니다.

아나콘다를 실행시키고 아래 명령어를 통해 텐서플로우 가상환경을 실행합니다.


activate tensorflow


그리고 파이썬으로 들어가서 텐서플로우를 임포트합니다.


$ python

>>> import tensorflow as tf




그럼 이제 간단한 Linear Regression을 구현하겠습니다.



2. Linear Regression 구현하기


먼저, 우리는 hypothesis를 아래와 같은 식으로 나타냅니다.


H(x) = Wx + b


그리고 여기서 매우 간단하게 하기 위해 x와 y값을 아래와 같이 설정합니다.


x_train = [1,2,3]

y_train = [1,2,3]


그리고 W와 b를 Variable로 설정합니다.

근데 여기서 Variable은 프로그래밍에서 사용하는 변수와는 조금 다릅니다.

쉽게 생각해서 해당 Variable은 텐서플로우가 사용하는 Variable이다라고 생각하시면 됩니다.

다시 말해, 이를 실행하면 텐서플로우가 설정하게 되는 Variable이라는 것입니다.

우리가 이 Variable을 만들때 그 shape이 어떻게 되는지 함께 선언을 합니다.


그리고 처음 알아 본 것처럼 hypothesis 식을 함께 설정합니다.


또한 cost의 식도 함께 설정해줍니다.


위의 내용을 코드로 작성해보면 아래 사진과 같습니다.



여기서 제일 아래, reduce_mean이라는 것은 어떤 tensor가 주어졌을 떄 그에 대한 평균을 내주는 것입니다.


그럼 이제 cost까지 주어졌는데, 그 다음 작업은 cost를 최소화하는 작업입니다.

이는 일단 아래의 코드로 구현되는 것이라고 생각하시면 되겠습니다.



그럼 여기까지 해서 일단 그래프를 만들었습니다.

그리고 우리가 해줘야하는 것은 session을 만들어서 실행시켜줘야 합니다.



위의 코드처럼 작성합니다.

for문 아래에서 sess.run(train) 을 통해서 세션이 실행되고

총 2000천 반복중에서 20번 마다 우리가 보고 싶은 값을 출력하게 하였습니다.

이렇게 해서 아래와 같은 결과가 출력됩니다.



결과값을 보시면 처음에 나타나는 cost는 점점 작아지고, W값은 우리가 기대한 것과 같이 점점 1로 가까워 집니다.



3. Placeholders 이용하기


지난 시간에 했던 것처럼 처음에 직접 값을 넣지 않고, placeholder를 이용하여 나중에 값을 입력할 수 있습니다.

placeholder를 이용한 코드는 아래와 같습니다.



위의 코드를 보시면, 처음에 x_train, y_train으로 값을 주었던 것 대신에

placeholder를 통한 X, Y를 이용하며 뒤에서 feed_dict에서 값을 주는 것을 볼 수 있습니다.


이러한 코드에 의한 결과 값은 아까와 같이 cost가 점점 작아지고 w 값이 1에 가까워지는 결과와 동일합니다.



이러한 placeholder를 이용하면 우리가 linear regression을 만들고 학습을 할때 학습데이터를 우리가 원하는 값으로 넣어줄 수 있습니다.



전체적으로 정리를해보면

이번 포스팅에서는 tensorflow를 통해 Hypothesis를 만들어보았습니다.

그리고 placeholder를 이용하여 fedd_dict를 통해 우리가 원하는 값을 입력하고 그에 대한 값을 도출해 보았습니다.

다음 포스팅에서는 해당 linaer regression의 cost를 최소화하는 tensorflow를 구현해보도록 하겠습니다.



블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc