일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 데이터분석
- DataFrame
- linux
- 씨본
- numpy
- seaborn
- 선형회귀
- pandas
- OR게이트
- 데이터크롤링
- AND게이트
- 달의조각
- Perceptron
- 퍼셉트론
- ubuntu
- python
- NAND게이트
- 리눅스
- 머신러닝
- 데이터프레임
- 데이터시각화
- 딥러닝
- 로지스틱회귀
- 파이썬
- Deeplearning
- XOR게이트
- 우분투
- 판다스
- 비지도학습
- 크롤링
- Today
- Total
Charming ['ㅡ'] Ham !
선형 회귀와 로지스틱회귀 본문
선형 회귀와 로지스틱 회귀¶
회귀 (Regression), 회귀분석 (Regression Analysis) 란 ?¶
회귀분석 (Regression Analysis) 란 통계학에서 주로 사용되는 방법으로 수집된 여러 데이터를 통해 각 연속형 변수간의 상관관계를 모델링하고, 적합도를 측정하는 분석 방법이다.
회귀 분석은 특정 조건 x 가 변하면 y 도 함께 변하는 형태의 문제
를 분석하는데 주로 활용되며, 예를 들면 부모님의 키와 자식의 키 사이의 관계, 위치와 집 값의 관계 등이 있다.
즉, 독립변수 (independent variable)
와 종속변수 (dependent variable)
사이의 상관을 설명하는 문제들이다. 독립변수는 설명변수 (explanatory variable)
, 종속변수는 반응변수 (response variable)
이라고도 한다.
회귀분석은 처음에 아버지의 키 x 와 자식의 키 y 사이의 직선 형태의 기울기가 1보다 작다는 것에 주목하게 했다. 세대를 거듭할 수록 아버지의 키과 무관하게 평균에 수렴하게 된다는 것을 알게되었다. 즉, 평균으로 회귀한다는 것이다.
하지만 요즘에는 평균으로 수렴하는 것 뿐만아니라, 두 개 이상의 변수 사이의 함수관계를 추구하는 통계적 방법을 의미
힌다.
두 변수 사이의 관계를 직선 형태로 가정하고 분석하는 것을 선형 회귀분석 (Linear Regression)
이라고 한다.
만약 회귀분석을 통해 예측하고자 하는 종속변수가 독립변수 데이터와의 명확한 관계가 있는 것으로 나타난다면 새로운 종속변수 데이터에 대한 예측이 가능하다.
선형 회귀분석 (Linear Regression)¶
선형 회귀분석은 위에서 간단히 말했듯이 두 변수 사이의 관계를 직선 형태로 가정하는 회귀 분석의 대표적인 방법이다.
종속변수 y 와 한개 이상의 독립변수 x 의 선형관계를 모델링하는 회귀분석 기법
으로 독립변수의 개수가 1개하면 단순 선형회귀
2개 이상이라면 다중 선형회귀
라고 한다.
선형 회귀 모델링¶
선형회귀식은 다음과 같다.
$$y = \beta x + \epsilon$$$\beta$ 는 회귀계수 라고하며, $\epsilon$ 은 종속변수와 독립변수 사이에 오차 를 의미한다. 이 오차는 데이터로부터 추정해야하는 파라미터 가 된다. 즉, x 와 y 에 해당하는 데이터가 있을 때, 데이터로부터 $\beta$ 와 $\epsilon$ 을 추정한 후 추정한 값들을 바탕으로 모델링을 수행한다. 그리고 모델을 기반으로 새로운 데이터의 x 값들을 입력으로 넣어주면, 그에 해당하는 y 값을 추론하게 된다.
즉, 선현회귀 모델을 찾는 것은 주어진 데이터에 우리의 선형 식이 잘 맞도록 회귀계수 및 오차를 구하는 것 이다.
머신러닝에서의 선형회귀모델 표기법¶
머신러닝에서 선형회귀 표기법은 통계적 선형회귀 식과는 조금 다르다.
$$H = Wx + b$$로 사용되며 H 는 가정 (Hypothesis), W 는 가중치 (Weight), b 는 편향 (bias) 를 뜻한다. 즉, 주어진 데이터를 이용하여 W 와 b 를 구하는 것이다.
위 통계적 선형회귀에서 $\beta$ 값이 W, 에러 값이 b 에 해당하는 것이다. 대부분의 W, b 는 단순 스칼라 값이 아닌 고차원의 행렬 (matrix) 형태를 띄고 있는 경우가 많고, 이 파라미터의 개수가 많을 수록 모델의 크기가 커지고 학습하는 것도 어려워진다.
선형회귀모델의 용어¶
-
잔차 (Residuals)
:회귀모델을 이용해 추정한 값과 실제 데이터의 차이
를 의미한다. 즉, x 값이 되며, (종속 변수 y) - (실제 데이터의 x 값을 모델에 대입했을 때 추론된 y 값) 이된다. -
최소제곱법
: 잔차를 이용하여 주어진 점 데이터들을 가장 잘 설명하는 회귀모델을 찾는 가장 대표적인 방법 중 하나로 다음과 같은 식을 사용한다. $$argmin_W,b (\sum_{i=1}^n residuals^2)$$
즉, n 개의 점 데이터에 대하여 잔차의 제곱의 합을 최소화하는 W, b 를 구하는 방법이다.
-
손실함수 (Loss function) : 머신러닝에서는 최소제곱법과 같은 회귀계수를 구하는 과정에 쓰는 함수로, 여러가지 종류의 손실함수가 있지만 최소제곱법을 이용해보기로 한다.
-
결정계수 (R-squared, R2 score 등) : 회귀모델이 잘 결정되었는지 확인할 때 참고하는 지표로 0~1 사이의 값을 나타내며, 1에 가까울 수록 해당 회귀모델이 데이터를 잘 표현한다.
머신러닝에서 선형회귀를 위한 데이터셋 준비하기¶
Bosthon house prices dataset 을 이용하여 선형회귀 모델을 만들어보자. sklearn
라이브러리에서 제공하는 기본 데이터셋으로 보스턴 집 값 데이터이다.
총 506 row, 13 가지 attribut (columns)로 구성되어 있고, 각 row 에 대응되는 가격 값이 price
에 저장되어 있다.
# boston house prices dataset에 대한 정보
from sklearn.datasets import load_boston
from sklearn import model_selection
import pandas as pd
import numpy as np
# 데이터 로드
boston = load_boston()
data, price = boston['data'], boston['target']
x_train, x_test, y_train, y_test = model_selection.train_test_split(data, price, test_size=0.2)
df = pd.DataFrame(x_train, columns=boston['feature_names'])
print("boston dataset의 차원: ", data.shape)
print("price의 차원", price.shape)
print("boston train dataset의 차원: ", x_train.shape)
print("boston test dataset의 차원: ", x_test.shape)
print("Boston dataset의 예시")
df.head() # data 요약
boston dataset의 차원: (506, 13)
price의 차원 (506,)
boston train dataset의 차원: (404, 13)
boston test dataset의 차원: (102, 13)
Boston dataset의 예시
CRIM | ZN | INDUS | CHAS | NOX | RM | AGE | DIS | RAD | TAX | PTRATIO | B | LSTAT | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0.37578 | 0.0 | 10.59 | 1.0 | 0.489 | 5.404 | 88.6 | 3.6650 | 4.0 | 277.0 | 18.6 | 395.24 | 23.98 |
1 | 0.06466 | 70.0 | 2.24 | 0.0 | 0.400 | 6.345 | 20.1 | 7.8278 | 5.0 | 358.0 | 14.8 | 368.24 | 4.97 |
2 | 0.07022 | 0.0 | 4.05 | 0.0 | 0.510 | 6.020 | 47.2 | 3.5549 | 5.0 | 296.0 | 16.6 | 393.23 | 10.11 |
3 | 0.12650 | 25.0 | 5.13 | 0.0 | 0.453 | 6.762 | 43.4 | 7.9809 | 8.0 | 284.0 | 19.7 | 395.58 | 9.50 |
4 | 5.70818 | 0.0 | 18.10 | 0.0 | 0.532 | 6.750 | 74.9 | 3.3317 | 24.0 | 666.0 | 20.2 | 393.07 | 7.74 |
# 각 특성에 대한 요약
print(boston["DESCR"])
.. _boston_dataset:
Boston house prices dataset
---------------------------
**Data Set Characteristics:**
:Number of Instances: 506
:Number of Attributes: 13 numeric/categorical predictive. Median Value (attribute 14) is usually the target.
:Attribute Information (in order):
- CRIM per capita crime rate by town
- ZN proportion of residential land zoned for lots over 25,000 sq.ft.
- INDUS proportion of non-retail business acres per town
- CHAS Charles River dummy variable (= 1 if tract bounds river; 0 otherwise)
- NOX nitric oxides concentration (parts per 10 million)
- RM average number of rooms per dwelling
- AGE proportion of owner-occupied units built prior to 1940
- DIS weighted distances to five Boston employment centres
- RAD index of accessibility to radial highways
- TAX full-value property-tax rate per $10,000
- PTRATIO pupil-teacher ratio by town
- B 1000(Bk - 0.63)^2 where Bk is the proportion of blacks by town
- LSTAT % lower status of the population
- MEDV Median value of owner-occupied homes in $1000's
:Missing Attribute Values: None
:Creator: Harrison, D. and Rubinfeld, D.L.
This is a copy of UCI ML housing dataset.
https://archive.ics.uci.edu/ml/machine-learning-databases/housing/
This dataset was taken from the StatLib library which is maintained at Carnegie Mellon University.
The Boston house-price data of Harrison, D. and Rubinfeld, D.L. 'Hedonic
prices and the demand for clean air', J. Environ. Economics & Management,
vol.5, 81-102, 1978. Used in Belsley, Kuh & Welsch, 'Regression diagnostics
...', Wiley, 1980. N.B. Various transformations are used in the table on
pages 244-261 of the latter.
The Boston house-price data has been used in many machine learning papers that address regression
problems.
.. topic:: References
- Belsley, Kuh & Welsch, 'Regression diagnostics: Identifying Influential Data and Sources of Collinearity', Wiley, 1980. 244-261.
- Quinlan,R. (1993). Combining Instance-Based and Model-Based Learning. In Proceedings on the Tenth International Conference of Machine Learning, 236-243, University of Massachusetts, Amherst. Morgan Kaufmann.
Boston Dataset 에 Linear Regression 적용하기¶
import pandas as pd
from sklearn import datasets
from sklearn import model_selection
from sklearn.linear_model import LinearRegression
from sklearn import metrics
from sklearn import datasets
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(10,35))
fig.suptitle('Boston dataset - (X:Y = each attr: price) with R2', fontsize=16, y=0.9)
# boston dataset에서 i번째 attribute(column)을 살펴보자.
for i in range(data.shape[1]):
# i번째 attribute에 대한 data 및 이름
single_attr, attr_name = data[:, i].reshape(-1, 1), boston['feature_names'][i]
# 선형 회귀 모델.
estimator = LinearRegression()
# x에는 single_attr, y에는 price에 해당하는 데이터를 대입해서
# 최소제곱법을 이용하여 모델 내에서 W, b를 구하는 과정.
estimator.fit(single_attr, price)
# 위 fit() 과정을 통해 구한 회귀계수를 기반으로
# 회귀모델에 X값을 대입했을 때의 예측 Y 값.
pred_price = estimator.predict(single_attr)
# 결정계수를 구하는 함수.
score = metrics.r2_score(price, pred_price)
# 캔버스 생성
ax = fig.add_subplot(7, 2, i+1)
# 실제 데이터에 대한 산포도
ax.scatter(single_attr, price)
# 선형회귀모델의 추세선
ax.plot(single_attr, pred_price, color='red')
#subplot의 제목.
ax.set_title("{} x price, R2 score={:.3f}".format(attr_name ,score))
# x축
ax.set_xlabel(attr_name)
# y축
ax.set_ylabel('price')
R2 score 가 높은 편에 속하는 LSTAT (R2 = 0.544) 과 RM (R2 = 0.484) 을 이용하여 그린 선형회귀 모델이 그나마 데이터를 잘 설명한다고 할 수 있다. 회귀선을 따라 두 데이터가 잘 모여있는 것을 보면 알 수 있다.
경사 하강법 (Gradient Descent Algorithm)¶
적절한 회귀모델의 회귀계수를 찾기 위해서 손실함수를 잘 설정하는 것이 중요하다.
데이터에 대해 손실함수를 최소화하는 W 와 b 를 구하는 것이 핵심이기 때문이다.
손실함수의 형태가 주어진 데이터의 분포를 잘 반영하는 것이 중요하다. 하지만 데이터의 분포가 어떠한지 항상 알 수 없기 때문에 머신러닝에서 가중치의 그래디언트 (미분값) 가 최소가 되는 지점이 손실함수를 최소로하는 지점일 것이라는 가정을 해야한다. 보통 가중치 함수는 아래로 볼록한 형태이기 때문이다.
J(W) 를 최소로 하는 가중치 값을 가지려면, 기울기 (그래디언트) 값이 가장 작은 중앙에 있는 것이 좋다. 손실함수를 최소로 하는 가중치를 한번에 알아낼 수 있으면 가장 좋지만, 가중치 파라미터의 개수가 많을 경우에는 엄청난 시간이 소요된다. 또한 최적의 가중치를 무조건 찾아낼 수 있는 것도 아니다. 하지만 최소 손실함수를 가지는 지점으로 가기위한 방법으로 다음과 같은 식을 사용한다.
$$ W : W -\alpha{\partial \over \partial W} J(W)$$$\alpha$ 는 learning rate 를 의미하며, 값이 커질수록 화살표의 길이가 더 길어지게 되고, 최저점으로 빠른 수렴이 가능하다. 하지만 이 값이 너무 크게되면 최적의 W 값을 건너뛸 경우가 발생한다. 따라서 적절한 learning rate 를 선정하는 것이 중요하다.
로지스틱 회귀분석 (Logistic Regression)¶
데이터가 어떤 범주에 속할 확률을 0~1 사이 값으로 예측하고 그 확률에 따라 가능성이 더 높은 범주에 속하는 것으로 분류해주는 지도학습 알고리즘 이다.
선형회귀와 같이 y 값이 확률로 나오기 때문에 상한이 [0, 1] 로 정해져있다. 또한 특정 threshold 값을 기준으로 삼아 예측될 확률 값이 threshold 이상인 것과 미만인 적으로 분류한다.
즉, 1개 이상의 독립변수가 있을 때 이를 이용하여 데이터가 2개의 범주 중 하나에 속하도록 결정한느 이진분류 (binary classification) 문제를 풀 때 사용된다.
정의 및 용어 설명¶
로지스틱 회귀식은 다음과 같다.
$$LogOdds = {log{{P(y=0|x)} \over {(1-P(y=0|x)}} = {\beta_0 + \sum_{j=1}^p \beta_j} x_j}$$- Odds : 사건이 발생할 확률을 발생하지 않을 확률로 나눈 값으로 사건이 발생할 확률을 1, 발생하지 않을 확률을 0이라고 한다면,
와 같이 Odds 를 계산할 수 있다.
-
Log-odds : 위 Odds 값에 로그를 취한 값을 말하며, log-odds 값을 선형회귀 분석의 종속변수처럼 구하면 된다.
$$log(\frac{P(Y=0|x)}{1-P(Y=0|x)}) = log(0.25) = \beta_0 + \sum_{j=1}^{p}\beta_j x_j$$ 위 식에 데이터를 이용하면 주어진 데이터를 잘 설명하는 회귀계시 ($\beta$) 값을 구할 수 있다.
위 과정을 통해 로지스틱 회귀모델이 구성되는데, 수식적으로 볼 때 Log-odds 의 선형 회귀모델이라고 할 수 있다.
하지만 실제로 원하는 값은 종속변수가 0일 확률, 1일 확률 자체를 원한다. 따라서 log-Odds 의 식을 $P(Y=0|x)$ 에 대해 다시 정리를 해야할 필요가 있다.
정리된 식은 다음과 같다.
$$P(y=0|x) = \frac{exp({\beta}_0 + \sum_{j=1}^{p}{\beta}_{j}x_j)}{1+exp({\beta}_0 + \sum_{j=1}^{p}{\beta}_{j}x_j)}$$$z = exp({\beta}_0 + \sum_{j=1}^{p}{\beta}_{j}x_j)$ 라고 한다면 식은 다음과 같다.
$$P(y=0|x) = \frac{1}{1+exp(-z)}$$이것이 바로 sigmoid function 의 형태이다. 즉, log-odds 값을 구한 다음 sigmoid function 에 넣어서 0과 1사이의 값으로 변환해주어야 한다.
이 함수는 확률모델을 선형 회귀모델로 표현한 것이 아닌, $z=0$ 인 지점을 중심으로 하여 두 범주간 경계가 불명확해지는 $x$ 의 구간을 최소화해주기 때문에 분류모델의 분류 성능을 향상시켜준다.
- 로지스틱스 회귀 요약
-
실제 데이터를 대입하여 Odds 및 회귀계수를 구한다.
-
Log-odds 를 계산, 이를 sigmoid function 의 입력 값으로 사용하여 특정 범주에 속할 확률값을 계산한다.
-
설정한 threshold 에 맞춰 설정값 이상이면 1, 이하면 0 으로 이진분류를 수행한다.
# 로지스틱 회귀분석 예제: 유방암 데이터셋
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
# 데이터 로드
cancer=load_breast_cancer()
# y = 0(Malignant - 악성 종양), y=1(Benign - 양성 종양)
cancer_X, cancer_y= cancer.data, cancer['target']
train_X, test_X, train_y, test_y = train_test_split(cancer_X, cancer_y, test_size=0.1, random_state=10) # train 데이터셋과 test 데이터셋으로 나눔
print("전체 검사자 수: {}".format(len(cancer_X)))
print("Attribute 수: {}".format(len(cancer_X[0])))
print("Train dataset에 사용되는 검사자 수: {}".format(len(train_X)))
print("Test dataset에 사용되는 검사자 수: {}".format(len(test_X)))
cancer_df = pd.DataFrame(cancer_X, columns=cancer['feature_names'])
cancer_df.head()
전체 검사자 수: 569
Attribute 수: 30
Train dataset에 사용되는 검사자 수: 512
Test dataset에 사용되는 검사자 수: 57
mean radius | mean texture | mean perimeter | mean area | mean smoothness | mean compactness | mean concavity | mean concave points | mean symmetry | mean fractal dimension | ... | worst radius | worst texture | worst perimeter | worst area | worst smoothness | worst compactness | worst concavity | worst concave points | worst symmetry | worst fractal dimension | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 17.99 | 10.38 | 122.80 | 1001.0 | 0.11840 | 0.27760 | 0.3001 | 0.14710 | 0.2419 | 0.07871 | ... | 25.38 | 17.33 | 184.60 | 2019.0 | 0.1622 | 0.6656 | 0.7119 | 0.2654 | 0.4601 | 0.11890 |
1 | 20.57 | 17.77 | 132.90 | 1326.0 | 0.08474 | 0.07864 | 0.0869 | 0.07017 | 0.1812 | 0.05667 | ... | 24.99 | 23.41 | 158.80 | 1956.0 | 0.1238 | 0.1866 | 0.2416 | 0.1860 | 0.2750 | 0.08902 |
2 | 19.69 | 21.25 | 130.00 | 1203.0 | 0.10960 | 0.15990 | 0.1974 | 0.12790 | 0.2069 | 0.05999 | ... | 23.57 | 25.53 | 152.50 | 1709.0 | 0.1444 | 0.4245 | 0.4504 | 0.2430 | 0.3613 | 0.08758 |
3 | 11.42 | 20.38 | 77.58 | 386.1 | 0.14250 | 0.28390 | 0.2414 | 0.10520 | 0.2597 | 0.09744 | ... | 14.91 | 26.50 | 98.87 | 567.7 | 0.2098 | 0.8663 | 0.6869 | 0.2575 | 0.6638 | 0.17300 |
4 | 20.29 | 14.34 | 135.10 | 1297.0 | 0.10030 | 0.13280 | 0.1980 | 0.10430 | 0.1809 | 0.05883 | ... | 22.54 | 16.67 | 152.20 | 1575.0 | 0.1374 | 0.2050 | 0.4000 | 0.1625 | 0.2364 | 0.07678 |
5 rows × 30 columns
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report
#로지스틱 회귀분석
LR = LogisticRegression()
# 유방암 train data를 이용하여 로지스틱 회귀분석 모델 학습
LR.fit(train_X, train_y)
# 학습된 로지스틱 회귀분석 모델을 이용한 예측값 출력
pred = LR.predict(test_X)
# 로지스틱 회귀분석 모델의 예측값과 실제값 비교결과를 나타낸 통계표
print(classification_report(test_y, pred))
precision recall f1-score support
0 0.91 0.95 0.93 21
1 0.97 0.94 0.96 36
accuracy 0.95 57
macro avg 0.94 0.95 0.94 57
weighted avg 0.95 0.95 0.95 57
/home/aiffel/anaconda3/envs/aiffel/lib/python3.7/site-packages/sklearn/linear_model/_logistic.py:762: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
extra_warning_msg=_LOGISTIC_SOLVER_CONVERGENCE_MSG)
로지스틱스 회귀는 모델이 리턴하는 값이 연속적인 변수라는 점에서 분명히 회귀
모델이다. 하지만 선형 회귀모델이 종속변수 $y$ 의 추정치 자체를 리턴하는 반면에 로지스틱 회귀모델은 데이터 $x$ 가 어떤 범주에 속할 확률을 나타낸다는 점이 가장 큰 차이점이다.
이러한 점에서 로지스틱 회귀를 $x$ 가 속할 범주별 확률값을 계산하는데 까지만 사용한다. 이후 $argmax$ 등을 이용해 이 확률값이 최대가 되는 범주를 골라 $x$ 가 어떤 범주에 속하는지 예측하는 것은 로지스틱 회귀모델을 응용한 것이다. 로지스틱 회귀는 분류문제를 확률적으로 접근하는 것이다.
Softmax 함수¶
위에서 살펴보았던 로지스틱 회귀는 선형 회귀가 다중 선형 회귀로 사용될 수 있는 것처럼 다중 로지스틱 회귀 (Multinomial Logistic Regression) 로 확장이 가능하다.
다중 로지스틱 회귀 모델에서는 다중 선형 회귀에서의 sigmoid function 가 softmax function
으로 확장되어야 한다.
Softmax function 는 2가지가 아닌 여러 범주로 분류하는 함수 이다. Multi class classification 에 적합한 함수로, 다음과 같이 표현할 수 있다.
$$softmax(x) = \frac{x_i}{\sum_{j=0}^{k}e^{x_j}}(i=0,1,… k)$$함수식은 각 범주의 확률값이 0~1 사이의 값이며, 모든 범주에 해당하는 softmax 의 값을 합하면 1 이 된다. softmax 함수는 큰 log-odds 와 작은 log-odds 의 차이를 극대화한다. 그래서 마지막에 softmax 함수에 모든 범주의 log-odds 를 통과시키면 해당 데이터가 어떤 범주로 분류되었는지 확실히 알 수 있다. 이때 가장 큰 값을 1, 그 외의 값들을 0 으로 인코딩하는 one-hot encoding 을 통해 표현
한다.
Cross Entropy¶
Cross Entropy 는 softmax 함수의 손실함수로 사용되며, 다음과 같이 쓰인다.
$$H(p, q) = -\sum_{x}p(x)logq(x)$$Cross Entropy 역시 손실함수이기 때문에 가중치가 최적화될수록 M(p,q)
의 값이 감소하게되는 방향으로 가중치 학습이 이루어진다. 또한 p(x)
는 실제 데이터의 범주 값 q(x)
는 softmax 의 결과값을 대입하게 된다.
손실함수는 거리를 측정하기 적절한 형태여야하는데, 선형회귀에서는 잔차 제곱의 합으로 L2 distance 와는 다르지만, 모델의 추정치와 실제 값의 종속변수 좌표축 방향으로의 차이를 가지고 있어 거리를 측정하기 적절하다.
로지스틱 회귀에서는 종속변수 방향이 바로 확률변수의 방향이다. 하지만 선형 회귀에서처럼 제곱을 사용하지 않는다. 개념적으로 말하자면 Cross Entropy 는 로지스틱 회귀모델이 추론한 확률 분포 $q(x)$ 와 실제 데이터의 분포 $p(x)$ 의 차이를 계산한 것으로 이 차이가 적을수록 Cross entropy 가 작아지게된다.
유방암 데이터셋을 이용한 softmax 및 cross entropy 예제¶
sklearn 에서 제공하는 유방암 데이터셋을 이용해, 로지스틱 회귀를 tensorflow API 를 활용해서 구현해보자.
# 실제로 multi-class classification 문제를 풀 때 자주 사용하는 방법
# Tensorflow V2가 아닌 V1 기준으로 작성.
# V2 코드에서 일반적으로 사용하는 model.fit() 함수를 사용해서 학습을 진행하면
# 실제로 gradient descent가 진행되는 과정을 보다 면밀히 관찰하기 어렵기 때문이다.
# 아래 코드에 나오는 train_X, train_y, test_X, test_y 데이터는
# 이전 스텝에서 생성한 것을 그대로 사용
import tensorflow.compat.v1 as tf
import numpy as np
tf.compat.v1.disable_eager_execution()
# 30개의 attribute를 가진 유방암 데이터셋
x = tf.placeholder(tf.float32, [None, 30])
# 악성, 양성 label에 one-hot encoding을 적용하여 2차원이 될 예정
y = tf.placeholder(tf.float32, [None, 2])
num_classes = 2 # 악성, 양성
lr = 0.0003 # learning rate
W = tf.Variable(tf.random_normal([30, num_classes]), name='weight') # 가중치
b = tf.Variable(tf.random_normal([num_classes]), name='bias') # bias
# log-odds에 해당되는 값
logits = tf.matmul(x, W) + b
# log-odds에 softmax 적용한 값
hypothesis = tf.nn.softmax(logits)
loss_i = tf.nn.softmax_cross_entropy_with_logits(
# i번째 변수의 p(x)*log(q(x))
logits=logits, labels=y)
# 이를 모두 summation한 최종 loss function
loss = tf.reduce_mean(loss_i)
#최적화함수로 gradient descent method 사용
optimizer = tf.train.GradientDescentOptimizer(learning_rate=lr).minimize(loss)
# hypothesis의 결과 큰 값을 1, 작은 값을 0으로 매핑
pred = tf.argmax(hypothesis, 1)
# 예측값과 ground truth 값을 비교해서 같으면 True, 다르면 False
correct_pred = tf.equal(pred, tf.argmax(y, 1))
# True는 1, False는 0이 되기 때문에 전체 평균값이 결국 accuracy가 된다.
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
with tf.Session() as sess:
# Tensorflow의 전역 변수 초기화
sess.run(tf.global_variables_initializer())
# one-hot encoding을 수행한 train data 라벨
one_hot_train_y = np.eye(num_classes)[train_y]
# one-hot encoding을 수행한 test data 라벨
one_hot_test_y = np.eye(num_classes)[test_y]
# 전체 train data를 1000번 iteration
for step in range(1000):
# train data로 학습
sess.run(optimizer, feed_dict={x: train_X, y: one_hot_train_y})
#학습된 모델을 통해 측정한 test data의 loss 값 및 정확도
test_loss, test_acc= sess.run([loss, accuracy], feed_dict={x: test_X, y: one_hot_test_y})
# 10번째 step마다 print 수행
if step % 10 == 0:
print("Step {}, loss: {:.3f} accuracy: {:.3f}".format(
step,
test_loss,
test_acc
))
WARNING:tensorflow:From /home/aiffel/anaconda3/envs/aiffel/lib/python3.7/site-packages/tensorflow/python/ops/resource_variable_ops.py:1666: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version.
Instructions for updating:
If using Keras pass *_constraint arguments to layers.
WARNING:tensorflow:From <ipython-input-7-09bfd8bd0ee0>:32: softmax_cross_entropy_with_logits (from tensorflow.python.ops.nn_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Future major versions of TensorFlow will allow gradients to flow
into the labels input on backprop by default.
See `tf.nn.softmax_cross_entropy_with_logits_v2`.
Step 0, loss: 763.116 accuracy: 0.632
Step 10, loss: 119.154 accuracy: 0.368
Step 20, loss: 125.972 accuracy: 0.368
Step 30, loss: 119.669 accuracy: 0.368
Step 40, loss: 128.805 accuracy: 0.368
Step 50, loss: 89.856 accuracy: 0.368
Step 60, loss: 118.758 accuracy: 0.368
Step 70, loss: 87.781 accuracy: 0.368
Step 80, loss: 110.656 accuracy: 0.368
Step 90, loss: 66.143 accuracy: 0.368
Step 100, loss: 96.349 accuracy: 0.368
Step 110, loss: 66.728 accuracy: 0.368
Step 120, loss: 75.612 accuracy: 0.368
Step 130, loss: 65.885 accuracy: 0.368
Step 140, loss: 61.830 accuracy: 0.368
Step 150, loss: 53.775 accuracy: 0.368
Step 160, loss: 48.856 accuracy: 0.368
Step 170, loss: 42.722 accuracy: 0.368
Step 180, loss: 36.270 accuracy: 0.386
Step 190, loss: 34.123 accuracy: 0.404
Step 200, loss: 30.348 accuracy: 0.439
Step 210, loss: 25.735 accuracy: 0.491
Step 220, loss: 18.609 accuracy: 0.596
Step 230, loss: 18.242 accuracy: 0.596
Step 240, loss: 13.062 accuracy: 0.772
Step 250, loss: 7.900 accuracy: 0.842
Step 260, loss: 7.716 accuracy: 0.842
Step 270, loss: 7.532 accuracy: 0.860
Step 280, loss: 6.998 accuracy: 0.895
Step 290, loss: 6.889 accuracy: 0.895
Step 300, loss: 6.780 accuracy: 0.895
Step 310, loss: 6.668 accuracy: 0.895
Step 320, loss: 6.556 accuracy: 0.895
Step 330, loss: 6.449 accuracy: 0.895
Step 340, loss: 6.343 accuracy: 0.895
Step 350, loss: 6.237 accuracy: 0.895
Step 360, loss: 6.132 accuracy: 0.895
Step 370, loss: 6.027 accuracy: 0.895
Step 380, loss: 5.926 accuracy: 0.895
Step 390, loss: 5.830 accuracy: 0.895
Step 400, loss: 5.738 accuracy: 0.912
Step 410, loss: 5.654 accuracy: 0.912
Step 420, loss: 5.581 accuracy: 0.895
Step 430, loss: 5.520 accuracy: 0.895
Step 440, loss: 5.465 accuracy: 0.895
Step 450, loss: 5.412 accuracy: 0.895
Step 460, loss: 5.360 accuracy: 0.895
Step 470, loss: 5.307 accuracy: 0.895
Step 480, loss: 5.357 accuracy: 0.912
Step 490, loss: 5.399 accuracy: 0.895
Step 500, loss: 5.404 accuracy: 0.895
Step 510, loss: 5.432 accuracy: 0.895
Step 520, loss: 5.488 accuracy: 0.895
Step 530, loss: 5.504 accuracy: 0.895
Step 540, loss: 5.504 accuracy: 0.877
Step 550, loss: 5.518 accuracy: 0.877
Step 560, loss: 5.532 accuracy: 0.877
Step 570, loss: 5.522 accuracy: 0.877
Step 580, loss: 5.528 accuracy: 0.877
Step 590, loss: 5.556 accuracy: 0.877
Step 600, loss: 5.575 accuracy: 0.860
Step 610, loss: 5.597 accuracy: 0.860
Step 620, loss: 6.465 accuracy: 0.825
Step 630, loss: 33.386 accuracy: 0.421
Step 640, loss: 29.766 accuracy: 0.439
Step 650, loss: 23.331 accuracy: 0.491
Step 660, loss: 11.298 accuracy: 0.754
Step 670, loss: 6.014 accuracy: 0.842
Step 680, loss: 5.713 accuracy: 0.877
Step 690, loss: 5.692 accuracy: 0.877
Step 700, loss: 5.673 accuracy: 0.877
Step 710, loss: 5.654 accuracy: 0.877
Step 720, loss: 5.621 accuracy: 0.877
Step 730, loss: 5.535 accuracy: 0.895
Step 740, loss: 5.496 accuracy: 0.895
Step 750, loss: 5.480 accuracy: 0.895
Step 760, loss: 5.468 accuracy: 0.895
Step 770, loss: 5.460 accuracy: 0.895
Step 780, loss: 5.448 accuracy: 0.895
Step 790, loss: 5.442 accuracy: 0.895
Step 800, loss: 5.437 accuracy: 0.895
Step 810, loss: 5.441 accuracy: 0.895
Step 820, loss: 6.031 accuracy: 0.825
Step 830, loss: 6.318 accuracy: 0.825
Step 840, loss: 6.758 accuracy: 0.807
Step 850, loss: 7.688 accuracy: 0.807
Step 860, loss: 7.605 accuracy: 0.807
Step 870, loss: 7.591 accuracy: 0.807
Step 880, loss: 7.579 accuracy: 0.807
Step 890, loss: 7.577 accuracy: 0.807
Step 900, loss: 7.578 accuracy: 0.807
Step 910, loss: 7.583 accuracy: 0.807
Step 920, loss: 7.585 accuracy: 0.807
Step 930, loss: 7.578 accuracy: 0.807
Step 940, loss: 7.552 accuracy: 0.807
Step 950, loss: 7.529 accuracy: 0.807
Step 960, loss: 7.523 accuracy: 0.807
Step 970, loss: 7.522 accuracy: 0.807
Step 980, loss: 7.517 accuracy: 0.807
Step 990, loss: 7.496 accuracy: 0.807
step 을 거치루록 가중치와 편향이 최정화되어 loss 값이 감소함을 확인할 수 있다. 또한 정확도 역시 높아진다. 이를 위해서는 learning rate 등 하이퍼파라미터 사용에 주의해야한다.
Tensorflow V1에서는 with tf.Session()
위쪽에 있는 모델 선언부와 with tf.Session()
문 안에 있는 실행부로 코드가 크게 나뉩니다. 그래서 모든 코드의 실제 수행은 sess.run()
안에서만 진행된다는 특징이 있다.
import tensorflow as tf
from tensorflow import keras
n_dense=30
n_train_epoch=20
num_classes = 2 # 악성, 양성
model=keras.models.Sequential()
model.add(keras.layers.Dense(num_classes, use_bias=True, activation='softmax', input_shape=(30,)))
model.summary()
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
# 모델 훈련
model.fit(train_X, train_y, epochs=n_train_epoch)
# 모델 시험
test_loss, test_accuracy = model.evaluate(test_X, test_y, verbose=2)
print("test_loss: {} ".format(test_loss))
print("test_accuracy: {}".format(test_accuracy))
Model: "sequential_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense_4 (Dense) (None, 2) 62
=================================================================
Total params: 62
Trainable params: 62
Non-trainable params: 0
_________________________________________________________________
Train on 512 samples
Epoch 1/20
512/512 [==============================] - 0s 33us/sample - loss: 182.6403 - accuracy: 0.3730
Epoch 2/20
512/512 [==============================] - 0s 39us/sample - loss: 157.4377 - accuracy: 0.3730
Epoch 3/20
512/512 [==============================] - 0s 35us/sample - loss: 132.0265 - accuracy: 0.3730
Epoch 4/20
512/512 [==============================] - 0s 38us/sample - loss: 106.4679 - accuracy: 0.3730
Epoch 5/20
512/512 [==============================] - 0s 36us/sample - loss: 81.3977 - accuracy: 0.3711
Epoch 6/20
512/512 [==============================] - 0s 38us/sample - loss: 56.6313 - accuracy: 0.3633
Epoch 7/20
512/512 [==============================] - 0s 36us/sample - loss: 36.9335 - accuracy: 0.3125
Epoch 8/20
512/512 [==============================] - 0s 37us/sample - loss: 27.8734 - accuracy: 0.2070
Epoch 9/20
512/512 [==============================] - 0s 37us/sample - loss: 26.8210 - accuracy: 0.1875
Epoch 10/20
512/512 [==============================] - 0s 36us/sample - loss: 25.5480 - accuracy: 0.1973
Epoch 11/20
512/512 [==============================] - 0s 35us/sample - loss: 24.3977 - accuracy: 0.2129
Epoch 12/20
512/512 [==============================] - 0s 40us/sample - loss: 23.2327 - accuracy: 0.2129
Epoch 13/20
512/512 [==============================] - 0s 35us/sample - loss: 22.0832 - accuracy: 0.2285
Epoch 14/20
512/512 [==============================] - 0s 38us/sample - loss: 20.9586 - accuracy: 0.2383
Epoch 15/20
512/512 [==============================] - 0s 42us/sample - loss: 19.7648 - accuracy: 0.2598
Epoch 16/20
512/512 [==============================] - 0s 39us/sample - loss: 18.6884 - accuracy: 0.2773
Epoch 17/20
512/512 [==============================] - 0s 33us/sample - loss: 17.6249 - accuracy: 0.2891
Epoch 18/20
512/512 [==============================] - 0s 34us/sample - loss: 16.6442 - accuracy: 0.3164
Epoch 19/20
512/512 [==============================] - 0s 32us/sample - loss: 15.5840 - accuracy: 0.3359
Epoch 20/20
512/512 [==============================] - 0s 34us/sample - loss: 14.7177 - accuracy: 0.3633
test_loss: 15.431968889738384
test_accuracy: 0.3333333432674408
위 코드를 보면 딥러닝과 매우 유사한데, 로지스틱 회귀 처럼 분류모델이 softmax 를 통해 범주별 확률 예측값을 만들게하고 이를 최대로 만드는 범주를 선택하는 방법을 썼었다. 하지만 분류모델을 설계할 때 Dense 레이어 하나만을 사용하는 것이 아니고 여러 레이어를 사용하여 깊게 쌓는 방법을 썼다.
위 모델을 조금 변형하여 딥러닝 모델로 변형해보자.
import tensorflow as tf
from tensorflow import keras
n_dense=30
n_train_epoch=20
num_classes = 2 # 악성, 양성
model=keras.models.Sequential()
#레이어 3장을 추가
model.add(keras.layers.Dense(n_dense, input_shape=(30,), use_bias=True))
model.add(keras.layers.Dense(n_dense, use_bias=True))
model.add(keras.layers.Dense(n_dense, use_bias=True))
model.add(keras.layers.Dense(num_classes, use_bias=True, activation='softmax'))
model.summary()
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
# 모델 훈련
model.fit(train_X, train_y, epochs=n_train_epoch)
# 모델 시험
test_loss, test_accuracy = model.evaluate(test_X, test_y, verbose=2)
print("test_loss: {} ".format(test_loss))
print("test_accuracy: {}".format(test_accuracy))
Model: "sequential_2"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense_5 (Dense) (None, 30) 930
_________________________________________________________________
dense_6 (Dense) (None, 30) 930
_________________________________________________________________
dense_7 (Dense) (None, 30) 930
_________________________________________________________________
dense_8 (Dense) (None, 2) 62
=================================================================
Total params: 2,852
Trainable params: 2,852
Non-trainable params: 0
_________________________________________________________________
Train on 512 samples
Epoch 1/20
512/512 [==============================] - 0s 42us/sample - loss: 33.5748 - accuracy: 0.5527
Epoch 2/20
512/512 [==============================] - 0s 49us/sample - loss: 5.7182 - accuracy: 0.7305
Epoch 3/20
512/512 [==============================] - 0s 51us/sample - loss: 1.7365 - accuracy: 0.8691
Epoch 4/20
512/512 [==============================] - 0s 50us/sample - loss: 1.0447 - accuracy: 0.8789
Epoch 5/20
512/512 [==============================] - 0s 51us/sample - loss: 1.0521 - accuracy: 0.8926
Epoch 6/20
512/512 [==============================] - 0s 45us/sample - loss: 0.9953 - accuracy: 0.9043
Epoch 7/20
512/512 [==============================] - 0s 43us/sample - loss: 0.9803 - accuracy: 0.8984
Epoch 8/20
512/512 [==============================] - 0s 49us/sample - loss: 0.9128 - accuracy: 0.9023
Epoch 9/20
512/512 [==============================] - 0s 37us/sample - loss: 1.0032 - accuracy: 0.8984
Epoch 10/20
512/512 [==============================] - 0s 39us/sample - loss: 0.8904 - accuracy: 0.8984
Epoch 11/20
512/512 [==============================] - 0s 45us/sample - loss: 1.0656 - accuracy: 0.8887
Epoch 12/20
512/512 [==============================] - 0s 43us/sample - loss: 0.7908 - accuracy: 0.9160
Epoch 13/20
512/512 [==============================] - 0s 42us/sample - loss: 0.9420 - accuracy: 0.8770
Epoch 14/20
512/512 [==============================] - 0s 45us/sample - loss: 0.8728 - accuracy: 0.8867
Epoch 15/20
512/512 [==============================] - 0s 50us/sample - loss: 1.0388 - accuracy: 0.8750
Epoch 16/20
512/512 [==============================] - 0s 51us/sample - loss: 0.8391 - accuracy: 0.8945
Epoch 17/20
512/512 [==============================] - 0s 43us/sample - loss: 0.7719 - accuracy: 0.8965
Epoch 18/20
512/512 [==============================] - 0s 41us/sample - loss: 0.6476 - accuracy: 0.8945
Epoch 19/20
512/512 [==============================] - 0s 55us/sample - loss: 0.6456 - accuracy: 0.9121
Epoch 20/20
512/512 [==============================] - 0s 48us/sample - loss: 0.6186 - accuracy: 0.9043
test_loss: 1.1407956669205113
test_accuracy: 0.9122806787490845
일반 로지스틱 회귀 모델과 딥러닝의 모델의 성능에 큰 차이가 있지는 않은 것을 볼수 있다. 하지만 로지스틱 회귀모델 원리를 통해 딥러닝으로 확률 모델을 구현하는 것이 분류 문제 해결에 사용되는지 기본 원리를 파악하는데 도움을 준다.
'지식 정보 공유 > 딥러닝, 머신 러닝 : Deep, Machine Learning' 카테고리의 다른 글
퍼셉트론에 관하여 - 파이썬 코드 (0) | 2021.02.26 |
---|---|
퍼셉트론 (Perceptron) 에 관하여 (0) | 2021.02.26 |
비지도 학습 (Unsupervised Learning) | 클러스터링 (Clustering) , 차원축소 (Demension reduction) - K-means, PCA, T-SNE (0) | 2021.01.30 |
탐색적 데이터분석 (EDA) | 전설의 포켓몬 분류기 (0) | 2021.01.28 |
사이킷런을 통한 머신러닝 (0) | 2021.01.25 |