관리 메뉴

FU11M00N

[ Numpy ] 회귀분석 , 선형 회귀분석 , sklearn.linear_model , 결정계수 본문

AI/Numpy

[ Numpy ] 회귀분석 , 선형 회귀분석 , sklearn.linear_model , 결정계수

호IT 2021. 4. 5. 11:30

- 회귀분석

회귀 분석은 데이터 간의 상관관계 모형을 구해서 데이터를 해석하거나 예측하는 기법을 의미합니다.

 

간단한 예로는 들어 다음과 같은 데이터를 통과하는 직선을 찾는 기법이 있습니다.

a = np.array([1,3,5,7,9])

물론 점들이 정확히 직선에 위치되어있다면 이는 매우 쉬운 문제일 것입니다.

 

하지만 실제 데이터는 노이즈를 포함하여 복잡한 형태를 띠고 있기 때문에 이러한 데이터의 경향성을 파악하는 것은 결코 쉬운 일이 아닙니다.

 

아래의 데이터를 봐보겠습니다.

b = a + np.random.normal(0,1,5)

위의 데이터에 정규분포 평균0, 편차 1의 노이즈를 포함한 데이터를 포함한 경우입니다.

위에서 다룬 직선은 분명 이번 데이터의 경향성도 어느 정도 잘 다루고 있습니다.

하지만 이것이 잘 표현되었는지 알수없습니다.

 

 

 

 

 

위의 경우는 직선을 통해 표현된 모델과 실제 데이터의 오차를 통해 측정합니다.

특히 이와 같이 데이터 간의 상관관계를 연속된 선형 관계로 해석하는 기법을 "선형 회귀분석"이라고 합니다

a = np.array([1,3,5,7,9])
b = a + np.random.normal(0,1,5)
plt.plot(b,'o')
plt.plot(a)
plt.show()

 

 

 

 

- 선형 회귀분석

 

앞선 예제의 경우는 가장 오차가 적은 직선을 찾은 경우로서 이러한 직선은 x의 1차 항 만을 ( x 제곱 이상은 무시 ) 포함한 모델을 의미합니다.(2차 항이 끼면 구부러지기 시작)

 

 

이러한 경우를 선형 단순 회귀분석이라 칭합니다.

먼저 회귀분석을 위한 가장 단순한 형태의 데이터를 생성해보겠습니다.

import numpy as np
import matplotlib.pyplot as plt

x = np.array([1,2,3])
y = np.array([2,4,6])
plt.ylim(0,10)
plt.xlim(0,5)
plt.plot(x,y,'o')
plt.show()

이는 y = x * 2의 가장 단순한 형태의 데이터 배치이며 이때 오차를 최소화하는 직선 모델은 y = x * 2입니다.

 

 

 

 

이를 얻기 위해서 여기서는 sklearn 라이브러리의 linear_model을 사용해보겠습니다.

 - sklearn.linear_model

from sklearn import linear_model 
regr = linear_model.LinearRegression()

regr.fit(x,y)

위의 모델은 regr 은 선형 회귀분석을 수행할 수 있는 객체이며 fit이라는 메서드를 통해 회귀분석을 수행합니다.

그러면 이것을 수행해보겠습니다.

 

 

 

 

 

 

 

 

하지만 에러가 출력됩니다.

 

 

 

회귀분석에서 x는 하나이상의 변수를 가정합니다.

변수가 하나인 [1,2,3]이라면 이 형태로도 괜찮겠지만 [3,4,5]가 포함될 경우 [[1,2], [2,4], [3,5]] 이런 식으로

입력되는 경우를 가정해서 설계되어있습니다.

 

그러므로 [1,2.3] 이 아니라

 

아래와 같은 형태가 되어야 합니다.

이것은 (1,3)의 배열을 (3,1)로 바꾸어주어야만 함을 의미합니다.

이 경우 reshape를 사용하면 쉽게 변환이 가능합니다.

regr.fit(x.reshape(3,1),y)

 

 

 

 

 

이제 regr.coef_ 값을 통해 상관 계수 2를 추출할 수 있습니다!

coef_ : 상관계수

print(regr.coef_)

 

 

 

 

이것을 그래프로 표현하면 아래와 같습니다.

plt.ylim(0,10)
plt.xlim(0,5)
plt.plot(x,y, 'o')
plt.plot(x, x * regr.coef_)

 

 

- 회귀분석 예제

x = np.array([1,2,3,4])
y = np.array([1.5, 3, 4.5, 6])
# 연습문제의 코드를 작성하세요
regr.fit(x.reshape(4,1),y) # x와 y 관계의 대해 상관관계로 생성
plt.ylim(0,10)# 도표의 표현 범위를 보여주는것
plt.xlim(0,5) # 도표의 표현 범위를 보여주는것
plt.plot(x,y, 'o') # 점 찍기
plt.plot(x, x * regr.coef_) 

 

 

 

 

- intercept_  상수항

x = np.array([1,2,3])
y = np.array([3,5,7])
plt.ylim(0,10)
plt.xlim(0,5)
plt.plot(x,y,'o')

plt.show()

위의 데이터를 앞의 예제와 같이 처리하면 다음과 같은 결과가 나옵니다.

 

 

x = np.array([1,2,3])
y = np.array([3,5,7])
regr.fit(x.reshape(3,1), y)
plt.ylim(0,10)
plt.xlim(0,5)
plt.plot(x, y, 'o')
plt.plot(x, x * regr.coef_)

앞의 예제와 같이 기울기.. 즉 상관계수는 2 지만 3,5,7 은 여기에 다시 1을 더해준 값입니다.

 

 

두 값의 관계는 다음과 같습니다.

y = x * 2 + 1 

2라는 x의 1차 항 계수에 추가로 1이라는 상수항을 지닌 식입니다.

 

 

 

이 상수항의 값은 아래와 같이 저장됩니다.

regr.intercept_

print(regr.intercept_)

 

 

 

 

- score : 결정계수

이번엔 노이즈를 포함한 3 * x + 2 데이터 50개를 생성해서 선형 단순 회귀분석을 수행해보겠습니다.

노이즈는 편차 5의 정규분포로 생성합니다.

 

n = 50
x = np.arange(0,n,1)
y = x * 3 + 2 + np.random.normal(0,5,n)
plt.plot(x,y, 'o')
regr.fit(x.reshape(n,1),y)
plt.plot(x, x * regr.coef_ + regr.intercept_)
plt.show()
print(regr.score(x.reshape(n,1),y))

 

위에서 회귀분석으로 생성된 모델은 최적화된 직선을 만듭니다.

 

하지만 이 직선이 데이터를 표현하는데 충분한 모델이라고 할 수 있을까요?

위처럼 눈으로 분명히 보인다면 문제가 없지만 3,4차원의 복잡한 데이터는 이렇게 시각화시키기가 어렵습니다.

 

 

그러하여 생성된 회귀모델이 얼마나 데이터를 잘 표현하는지지를 알기 위해서는 직선과 실제 데이터의 오차값의 비율을 측정함으로써 이를 확인할 수 있습니다.

 

 

 

 

이러한 수치를 결정계수라고 하며 다음과 같이 계산합니다.

    - ( Y 오차 / Y 편차 ) ^ 2 

Y 오차는 실제 데이터와 모델의 데이터와의 차이 값이고 편차는 Y 평균과 Y값의 차이 값을 의미합니다.

 

 

 

 

편차 값으로 나누는 이유는 무엇일까요?

데이터의 규모를 반영하기 위함입니다.

 

 

다음과 같은 두 경우가 나옵니다.

y값이 평균 1억단위의 편차가 있는데 평균 1000 정도의 오차로 예측
y값이 평균 1000 단위의 편차가 있는데 평균 500 정도의 오차로 예측

이 두 경우 전자의 경우가 평균 오차가 크지만 데이터의 크기와 평균 편차를 생각하면 오히려 후자 쪽의 모델보다 이쪽이 더 정확한 모델임을 알 수 있습니다.

 

그러므로 편차 값을 나눠줌으로써 데이터유 규모를 반영해서 모델의 정확도를 평가하기 위함입니다.

물론 수동으로 이를 작성할 수도 있겠지만 regr 은 자체적으로 이런 메서드를 지원합니다.

score( x, y ) 

x는 x 데이터와 y 데이터이며 반드시 회귀분석을 수행하던 데이터와 일치하지 않아도 됩니다.

즉 테스트용 데이터를 따로 측정할 수도 있습니다.

 

 

 

결정계수를 알기 위해서는 다음과 같이 출력하면 됩니다.

print( regr.score(x.reshape(n,1), y ))

 

 

- 결정계수 구하기

x = np.array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
y = np.array([0.71, 0.79, 1.28, 1.28, 1.24, 1.41, 1.73, 1.88, 2.15, 2.42])


x = np.arange(0,n,1)
y = x * 3 + 2 + np.random.normal(0,5,n)
plt.plot(x,y, 'o')
regr.fit(x.reshape(-1,1),y)
plt.plot(x, x * regr.coef_ + regr.intercept_)
plt.show()
print(regr.score(x.reshape(-1,1),y))

 

 

 

 

 

 

Comments