여기서는 단순 선형회귀란 무엇인지,
풀기위한 방법들에는 어떤 것들이 있는지 다뤄본다.
(statsmodel, OLS, OLS 안쓰고 풀기, 경사하강법, 등)
단순 선형 회귀 (simple linear regression) :
추세선이 평균으로의 회귀라고 해서 회귀 분석이라고 한다
독립변수 x, 종속변수 y 의 관계를 알아본다고 하자.
x, y 의 상관관계가
y= a+bx 와 같이 일차식으로 나타날 때, 이를 단순 선형 회귀라고 한다.
이 식의 추세선을 구하는 방법:
1. 방정식, 선형대수(행렬) -> 손으로 계산하는 경우
2. 최소제곱법 -> 완벽히 직선상에 있지 않을 경우 사용.
주어진 점들과의 오차의 제곱이 최소가 되는 추세선을 구한다.
( python에서는 statsmodel 혹은 Scikit Learn을 이용한다. )
1) 샘플 데이터(학습시킬 raw data, 주어진 점들)를 데이터프레임으로 만든다 .
2) 산점도를 그려 추세를 파악 ( plt.scatter(df['x'], df['y']) plt.show() )
3) y = ax +b +e (모든 점들이 한 직선 상에 있지않을 경우 오차가 있음. )라고 놓고 sklearn이나 statsmodel을 사용해 parameter값들을 구한다.
*statsmodels : 추정 및 검정, 회귀분석, 시계열분석 등의 기능을 제공하는 파이썬 패키지.
여기에 최소제곱법을 이용해 추세선을 구하는 코드(OLS)가 내장되어있다. statsmodels에는 아래와 같은 기능들이 있다.
예제 데이터셋
검정 및 모수추정
회귀분석
선형회귀
강건회귀
일반화 선형모형
혼합효과모형
이산종속변수
시계열 분석
SARIMAX 모형
상태공간 모형
벡터 AR 모형
생존분석
요인분석 ...
------------------------------------------------------------------
최소제곱법(OLS)을 이용해서 추세선 구하기
OLS(OLS: Ordinary Least Squares), 최소제곱법, 또는 최소자승법, 최소제곱근사법, 최소자승근사법(method of least squares, least squares approximation)이라고도 하며, 어떤 계의 해방정식을 근사적으로 구하는 방법으로서 근사적으로 구하려는 해와 실제 해의 오차의 제곱의 합이 최소가 되는 해를 구하는 방법이다.
import statsmodels.api as sm
ols('종속변수명 ~ 독립변수명', data=데이터프레임명).fit().summary()
statsmodels를 사용할 때는 feature, target, model을 지정해줘야함.
feature는 입력시켜 줄 학습값 중 독립변수 (x),
target은 종속변수 (y)
model 은 statsmodel 내의 여러가지 방법 중에 어떤 함수를 쓸 것인지. (여기서는 ols)
OLS, 최소제곱법 역시 선형대수를 기반으로 하기 때문에, 행렬의 연산 시 상수항 1을 맨 앞열에 독립변수 데이터에 추가해줘야한다. (상수항 결합).
feature는 input x를 전처리해준거라고 생각하면 된다.
[OLS 를 이용해서 추세선 구하기 코드]
x,y 정의
datas = np.array([[1, 3], [2, 5], [3, 7]])
df = pd.DataFrame(datas, columns=list("xy"))
feature = sm.add_constant(df["x"], has_constant='add')
model = sm.OLS(df["y"], feature).fit()
model.params
sm.add_constant : 상수항 결합을하는 함수.
model = sm.OLS( 종속변수,독립변수).fit() :OLS 모델을 돌린다.
model.params : 돌린 모델에서 나온 결과값. 파라미터값을 출력한다.
const, x가 나오는데 이게 가중치 벡터이다. (구하는 해)
>>
const 3.0 (y절편 상수)
x -1.0
y= -x+3 이라는 뜻. 아래의 f를 구한 셈이다.
input model output
x -> f -> y
이제 어떤 x가 들어왔을 때 y 값이 어떻게 나타날지 예측해보자.
x가 f를 거치는 과정은 벡터의 내적으로 나타낼 수 있다.
백터내적함수 np.dot( x, f) = y
가중치 벡터를 구했으면 x와 내적을 해야 y 값을 구할 수 있다.
predicted_data= a+bx (구한 추세선 함수식) 라고 할 때,
predicted_data= np.dot( feature, model.params)
-------------------------------------------------------------------------------------------
* 참고 ) OLS의 원리
- 모델을 사용해 쉽게 추세선을 구했지만,
이 모델은 어떤 원리인지 알아보자.
OLS 함수 안쓰고 a,b 찾기 1. : 오차제곱법 활용
1) a, b의 범위를 지정해준다.
2) 오차 제곱 합을 구하는 함수를 만든다.
3) 범위 내의 모든 a, b에 대해서 error_func를 돌려 각각 (a,b)에 대한 e를 저장한다.
a, b 를 정해준다.
batch_size = 0.5
a_datas = np.arange(0, 3, batch_size)
b_datas = np.arange(0, 3, batch_size)
batch_size : a,b 값의 resolution. 몇씩 늘려가며 관찰할 것인가.
0~3까지의 a, b, (0, 0.5, 1, 1.5. ... )
오차 제곱 합을 구하는 함수를 만든다.
def error_func(df, a, b):
e = 0
for idx, data in df.iterrows():
e += (data.y - a - b * data.x) ** 2 # feature 데이터 x, y 값과 비교.
return e # 오차들 제곱합 값을 반환한다.
df = (x, y) 형태의 데이터 프레임, (a, b) 는 추세선 함수의 가중치 벡터이다.
아래 식에서
data.y : 실제값
a+b*data.x : 추정치
* 참고) iterrow() : 데이터프레임의 각 행 정보를 담은 객체.
(행 넘버, 해당 행 데이터) .. (마지막 행 넘버, 해당 행 데이터)
범위 내의 모든 a, b에 대해서 error_func를 돌려 각각 (a,b)에 대한 e를 저장한다.
error_datas = []
for a_data in a_datas:
for b_data in b_datas:
error_datas.append({
"a_data": a_data,
"b_data": b_data,
"error": error_func(df, a_data, b_data),
})
# error_datas : a, b, 오차 제곱값 딕셔너리 형태로 반환
error_df = pd.DataFrame(error_datas)
error_df
여기서 가장 작은 오차를 주는 a, b 값이 추세선이 된다.
error_df[error_df.error == np.min(error_df.error)]
--------------------------------------------------------------------------
OLS 함수 안쓰고 a,b 찾기 2.
경사하강법으로 추세선 구하기 : a, b의 미분값으로 기울기 구하기.
위의 오차제곱법은 a, b의 범위를 정해놓고 그 범위 내의 a, b를 전부 입력해서 최소값을 찾는데,
a, b를 각각 다 넣으면 a x b 만큼의 경우의 수가 나오게 된다. (batch 사이즈 고려하면 더 많아짐. )
b 값의 범위만 구해도 구할 수 있다.
1) b 의 범위를 지정해준다.
2) 오차 제곱의 합을 구하는 함수를 만든다.
b_datas = np.arange(0, 5, 0.5)
def error_func(df, b):
e = 0
for idx, data in df.iterrows():
e += (data.y - b * data.x) ** 2
return e # 오차 제곱합값을 반환함.
error_datas = []
# 0 ~ 4.5 까지 에러를 출력
for b_data in b_datas:
e = error_func(df, b_data)
error_datas.append({
"b_data":b_data,
"error": e,
})
# b 값이 2.5일때 가장 오차제곱합이 가장 작다.
error_df = pd.DataFrame(error_datas)
error_df
error_df[error_df.error == np.min(error_df.error)]
---------------------------------------------------
경사하강법2 (일단 b 초기값 아무거나 정하고, 기울기 때려맞히기)
- 함수의 최소값은 기울기가 0이 되는 지점이다.
- 오차의 제곱 = (data.y - (b*data.x+a)) **2
- 오차의 제곱은 b에 대한 2차 방정식으로도 볼 수 있다.
- 오차의 제곱이 가장 작아지는 부분은 함수 기울기가 0일 때, b 값이 양수이면 값을 낮추고, 음수이면 값을 높여 error 가 0에 가장 가까운 b값을 채택한다.
1) b 의 초기값을 정해주고 최소의 기울기를 찾아가본다.
2) epoch : 몇번의 시도를 통해 기울기값을 찾을 지 정한다.
# b의 초기값
b = 50
# 최적값을 찾기위한 실행 횟수
# epoch가 낮으면 정확한 값을 찾기 어려움
epoch = 50
# 한번에 이동하는 크기제어
batch_size = 0.01
log_datas = []
def slope_func(df, b):
slope = 0
for idx, data in df.iterrows():
slope += -2 * (data.y - b * data.x) * data.x
return round(slope, 2)
for _ in range(epoch):
# b 값에 대한 기울기 구하기
slope = slope_func(df, b)
# print(np.round(b, 2), slope)
# 기울기가 0이면 반복문 빠져나가기
if slope == 0:
break
# 기울기가 0 미만이면 b값이 증가 (slope가 음수이므로 b 값이 증가)
# 기울기가 0 초과이면 b값이 증가 (slope가 양수이므로 b 값이 감소)
b -= batch_size * slope
b = np.round(b, 5)
# 에러 구하기
e = error_func(df, b)
# 데이터 저장
log_datas.append({
"b": np.round(b, 2),
"e": e,
"slope": slope,
})
log_df = pd.DataFrame(log_datas)
log_df.head(2)
len(log_df), b
---------------------------------------------------------------------
statsmodel 말고 sklearn을 이용해서 선형회귀분석 해보기.
feature : 독립변수. target : 종속변수 .
feature_gf = df[["gf"]]
feature_ga = df[["ga"]]
target = df["points"]
from sklearn.linear_model import LinearRegression
model_gf = LinearRegression().fit(feature_gf, target) : 실점을 input으로 했을때의 모델.
model_ga = LinearRegression().fit(feature_ga, target) :득점을 input으로 했을때의 모델.
model_gf.intercept_,model_gf.coef_
(statsmodel의 const, x 값으로 출력되는 것들, sklearn에서는 용어가 살짝 다르다. )
intercept : y절편, coef : 기울기.
두개의 모델을 비교해보자.
모델의 성능을 평가하는 척도 : MAE, RMSE, MSE, MAPE 등..
MAE (Model Absolute Error) : 오차의 절댓값을 척도로 삼음.
MAE가 낮을 수록 정확한 모델이라고 볼 수 있다.
sklearn 에 MAE를 구하는 모듈이 이미 있다.
from sklearn.metrics import mean_absolute_error
pred = np.round(model_gf.predict(feature_gf))
mean_absolute_error(target, pred)
: 오차의 절댓값을 구할, 결과값 & 추정값
( target 값은 우리가 알고 있는 결과 값.
pred 값은 target이 나왔던 input 재료값을 모델에 넣었을 때 나온 추정값. )
각 feature를 사용해 모델을 만들었을때 오차값을 구해 모델의 성능을 비교할 수 있다.
MAPE : Mean Absolute Percentage Error : MAE의 percent 화.
MAPE = MAE/ np.sum(target) * 100
f-value : 클수록 유의미하다. ( 05. multiple linear regression 참조 )
'파이썬 > 머신러닝' 카테고리의 다른 글
[분류모델] 02. Decision Tree (0) | 2022.05.30 |
---|---|
[분류모델] 01. 나이브 베이즈 (0) | 2022.05.29 |
[회귀분석] 04. 다항회귀분석 (0) | 2022.05.28 |
[회귀분석] 03. 다중선형회귀 예제 (0) | 2022.05.28 |
[회귀분석] 02. 다중선형회귀: 상관계수, 결정계수, 다중공선성 (0) | 2022.05.28 |