[AI] day5. 로지스틱 회귀 (Logistic Regression) - 1



1. 분류 분석 (Classification Analysis)

미리 정의되어 있는 클래스의 라벨(종류) 중 하나를 예측하는 것이다. 두 개로 분류하는 이진 분류 (Binary Classification)과 다중 분류 (Multiclass Classification)이 있다. 





1) 이진 분류 로지스틱 회귀 분석 (Binary Classification Logistic Regression)

선형 회귀 분석과 같이 독립변수와 종속변수 간의 관계를 구체적인 함수로 나타내고 예측한다. 2가지 종류 중 하나를 택하는 방식으로 0 또는 1, true 또는 false 중에 하나를 고르는 것이다. 즉 이진 분류 로지스틱 회귀 분석은 이진 분류를 이용하여 독립변수와 종속변수 간의 관계를 파악하는 것이다. 머신러닝에서는 보통 0과 1로서 관계를 나타낸다.

Linear Regression
Logistic Regression


각 그래프에서 가는 선이 y = 1일 때, 테스트케이스가 0과 1로만 이루어진다면 (즉, y = 0, y = 1에 대해 몰려있다면), 선형 회귀는 테스트케이스에 대해 오차가 상당히 크지만, 로지스틱 회귀의 경우 그래프가 x축과 평행한 부분이 상당 부분 존재하기 때문에 선형 회귀보다 상대적으로 테스트케이스에 대한 오차가 적은 편이다.
예제를 통해 자세히 알아보자.


import tensorflow as tf
import numpy as np
from numpy.random import multivariate_normal, permutation
import pandas as pd
from pandas import DataFrame
from matplotlib import pyplot as plt

# <step 1>

Y_0 = 20
Y_1 = 15
learningRate = 0.01
totalStep = 20001

np.random.seed(321)
dataNumber_y0 = Y_0
mu_y0 = [10, 11]
variance_y0 = 20

data_y0 = multivariate_normal(mu_y0, np.eye(2) * variance_y0, dataNumber_y0)
df_y0 = DataFrame(data_y0, columns=['x1', 'x2'])
df_y0['y'] = 0

dataNumber_y1 = Y_1
mu_y1 = [18, 20]
variance_y1 = 22

data1 = multivariate_normal(mu_y1, np.eye(2) * variance_y1, dataNumber_y1)
df_y1 = DataFrame(data1, columns=['x1', 'x2'])
df_y1['y'] = 1


Pandas를 이용하여 행렬로 이루어진 데이터를 처리할 수 있다. Pandas는
https://pandas.pydata.org/
여기서 다운로드 받도록 하자.

mu_y0, mu_y1은 데이터의 평균 값을, variance_y0, variance_y1은 데이터의 분산을 나타낸다. 이 때 난수를 생성하기 위해 multivariate_normal()이라는 함수를 사용했는데, 이것은 다변수 정규 분포에서 난수를 생성하는 기능으로 1차원 정규분포를 더 높은 차원으로 일반화한 것이다. 기본 형식은 다음과 같다.

np.random.multivariate_normal(mu, cov[ , size, check_valid, tol])
  • mu : 평균
  • cov(shape) : 분포의 공분산 행렬
  • size : 난수의 개수

np.eye()는 1을 대각선 형태로 갖고, 나머지는 0으로 채우는 배열이다.

np.eye(N, M=None, k=0, dtype=<class='float'>, order='C')

  • N : row (행) 의 수
  • M : column (열) 의 수
  • K : 대각선 위치 변경 

([[1, 0, 0, 0, 0],          ([[0, 1, 0, 0, 0],         ([[0, 0, 0, 0, 0],
  [0, 1, 0, 0, 0],            [0, 0, 1, 0, 0],             [1, 0, 0, 0, 0],
  [0, 0, 1, 0, 0],            [0, 0, 0, 1, 0],             [0, 1, 0, 0, 0],
  [0, 0, 0, 1, 0],            [0, 0, 0, 0, 1],             [0, 0, 1, 0, 0],
  [0, 0, 0, 0, 1]])          [0, 0, 0, 0, 0]])           [0, 0, 0, 1, 0]])
         k = 0                          k > 0                            k < 0


즉 위의 코드에서 np.eye(2)는 2차원 배열 ([1, 0], [0, 1]) 을 의미한다. 위의 코드로 생성한 data_y0는 아래와 같은 배열 형태를 보인다.


이 데이터를 Pandas Dataframe을 이용하여 dataframe 형태로 출력해보면 아래와 같이 나온다.


이 처럼 Pandas Dataframe은 배열 데이터를 쉽게 변경하고 다룰 수 있어서 데이터 처리에 많이 쓰는 라이브러리이다.




import tensorflow as tf
import numpy as np
from numpy.random import multivariate_normal, permutation
import pandas as pd
from pandas import DataFrame
from matplotlib import pyplot as plt

# <step 1>

Y_0 = 20
Y_1 = 15
learningRate = 0.01
totalStep = 20001

np.random.seed(321)
dataNumber_y0 = Y_0
mu_y0 = [10, 11]
variance_y0 = 20

data_y0 = multivariate_normal(mu_y0, np.eye(2) * variance_y0, dataNumber_y0)
df_y0 = DataFrame(data_y0, columns=['x1', 'x2'])
df_y0['y'] = 0

dataNumber_y1 = Y_1
mu_y1 = [18, 20]
variance_y1 = 22

data1 = multivariate_normal(mu_y1, np.eye(2) * variance_y1, dataNumber_y1)
df_y1 = DataFrame(data1, columns=['x1', 'x2'])
df_y1['y'] = 1

# for i in data_y0:
#     print(data_y0)

# for i in df_y0:
#     print(df_y0)

# <step 2>
df = pd.concat([df_y0, df_y1], ignore_index=True)
df_totalTrainData = df.reindex(permutation(df.index)).reset_index(drop=True)

print("===== DATA =====>")
print(df_totalTrainData)
print("df_totalTrainData Shape : {}\n".format(df_totalTrainData.shape))
xTrainData = df_totalTrainData[['x1', 'x2']].as_matrix()
yTrainData_temp = df_totalTrainData['y'].as_matrix()

print("xTrainData shape : {}".format(xTrainData.shape))
print("yTrainData shape : {}".format(yTrainData_temp.shape))

yTrainData = yTrainData_temp.reshape([len(df_totalTrainData), 1])
print("yTrainData reshape : {}".format(yTrainData.shape))


Pandas의 concat으로 확률이 0, 1인 데이터를 하나의 Dataframe으로 합쳐준다. 이 때 데이터는 0, 1의 순서에 따라 합쳐지게 되므로 reindex()를 이용해 순서에 상관없이 재정렬되도록 해준다.
이제 df_totalTrainData에 재정렬된 데이터가 들어가게 된다. 이 Dataframe을 리스트 형식으로 변환해주자. Pandas의 as_matrix()를 이용해 x1, x2의 데이터는 xTrainData에, y의 데이터는 yTrainData_temp에 저장해준다. 이 결과 xTrainData는 (35, 2)의 shape를, yTrainData는 (35, )의 shape를 가진다. 뒤에 학습 모델 그래프를 구성할 때 행렬 곱셈을 할 때 shape가 다를 경우 계산 수식에서 오류가 발생할 수 있으므로 yTrainData를 reshape()로 (35, 1)로 변경해준다. 이제 출력해보자.


지긋지긋한 FutureWarning... .as_matrix() 대신 .values를 사용하란다. 바꿔주고 다시 출력해보자.




위 처럼 데이터가 0, 1의 순서에 상관없이 정렬이 되게 출력이 될 것이다. 이제 학습 데이터 준비를 완료했다. 모델 생성을 위한 변수를 초기화하자.

import tensorflow as tf
import numpy as np
from numpy.random import multivariate_normal, permutation
import pandas as pd
from pandas import DataFrame
from matplotlib import pyplot as plt

# <step 1>

Y_0 = 20
Y_1 = 15
learningRate = 0.01
totalStep = 20001

np.random.seed(321)
dataNumber_y0 = Y_0
mu_y0 = [10, 11]
variance_y0 = 20

data_y0 = multivariate_normal(mu_y0, np.eye(2) * variance_y0, dataNumber_y0)
df_y0 = DataFrame(data_y0, columns=['x1', 'x2'])
df_y0['y'] = 0

dataNumber_y1 = Y_1
mu_y1 = [18, 20]
variance_y1 = 22

data1 = multivariate_normal(mu_y1, np.eye(2) * variance_y1, dataNumber_y1)
df_y1 = DataFrame(data1, columns=['x1', 'x2'])
df_y1['y'] = 1

# for i in data_y0:
#     print(data_y0)

# for i in df_y0:
#     print(df_y0)

# <step 2>
df = pd.concat([df_y0, df_y1], ignore_index=True)
df_totalTrainData = df.reindex(permutation(df.index)).reset_index(drop=True)

print("===== DATA =====>")
print(df_totalTrainData)
print("df_totalTrainData Shape : {}\n".format(df_totalTrainData.shape))
xTrainData = df_totalTrainData[['x1', 'x2']].values
yTrainData_temp = df_totalTrainData['y'].values

print("xTrainData shape : {}".format(xTrainData.shape))
print("yTrainData shape : {}".format(yTrainData_temp.shape))

yTrainData = yTrainData_temp.reshape([len(df_totalTrainData), 1])
print("yTrainData reshape : {}".format(yTrainData.shape))

# <step 3>
X = tf.placeholder(tf.float32, shape=[None, 2])
Y = tf.placeholder(tf.float32, shape=[None, 1])

W = tf.Variable(tf.zeros([2,1]), name='weight')
b = tf.Variable(tf.zeros([1]), name='bias')


x1, x2 데이터는 X 플레이스홀더에, y 데이터는 Y 플레이스홀더에 들어갈 것이다. 이 때 shape에 [35, 2] 같이 모양을 정해줄 수도 있지만, 데이터 수를 정확히 모른다면 None으로 지정해야 계산할 때 오류가 발생하지 않는다.
weight와 bias는 각각 tf.zeros()를 이용해서 위와 같은 크기의 배열로 초기화한 변수로 선언해준다.


다음엔 학습 모델 그래프를 만들어줄 차례지만, 설명할 내용이 많기 때문에 다음에 이어서 쓰도록 하겠다.

댓글