Data Science/통계

회귀 알고리즘

AI쟁이J 2022. 10. 4. 01:57

K-최근접 이웃 회귀

K-Nearest Neighbor 로 KNN으로 불리는 알고리즘이다. 주로 Naive-Bayes 분류 알고리즘과 함께 주로 사용되고 소개되어 당연히 분류 알고리즘으로 알고 있었다.

하지만 이를 사용해 회귀 예측 모델링 또한 가능함.

 

분류

▶ 나누어진 클래스 중 어느 클래스에 속할 것인지 '분류' 하는 것

K = 3의 경우, 3개의 데이터 중 Class B에 속하는 데이터가 더 많기 때문에 빨간색 별을 Class B로 분류함

K = 6의 경우, 6개의 데이터 중 Class A에 속하는 데이터가 더 많기 때문에 빨간색 별을 Class A로 분류함

 

 

회귀

▶ 어떤 '숫자'를 예측하는 문제

K = 3의 경우 데이터들의 Class는 상관이 없고 빨간색 별의 '데이터 값' 을 알고 싶음. 주변 데이터의 값 3개의 평균인

(10+9+8)/3 = 9 로 빨간색 별의 값을 예측

K = 6의 경우 주변 데이터들의 값 평균인 (20+5+15+10+8+9)/6 = 11.1667 로 빨간색 별의 값을 예측

 

파이썬으로 구현된 클래스

scikit-learn의 KNeighborsRegressor로 구현 가능

class sklearn.neighbors.KNeighborsRegressor(n_neighbors=5, *, weights='uniform', algorithm='auto', 
leaf_size=30, p=2, metric='minkowski', metric_params=None, n_jobs=None)

각 구성 요소는

 

n_neighbors

이웃의 수인 K를 결정. default = 5

 

weights

예측에 사용되는 가중 방법을 결정. default = uniform

'uniform' : 각각의 이웃이 모두 동일한 가중치를 가짐

'distance' : 거리가 가까울수록 더 높은 가중치를 가져 더 큰 영향을 미침

'callable' = 사용자가 정의한 함수 사용 가능

 

가중 회귀?

위의 그림처럼 단순한 평균을 구하는 것이 아닌 각 이웃이 얼마나 가까이 있는지에 따라 가중치를 부여해 계산을 하는 것. 

다시 해당 그림에서 가중치를 부여하지 않고 평균을 구하면 K = 3인 경우 빨간 별의 값은 약 11.166이 나온다.

이 때 8, 9, 10을 각

○ A = 8, 별과의 거리 = 2.2

○ B =  9, 별과의 거리 = 5.4

○ C = 10, 별과의 거리 = 3.7

라고 두면 해당 거리에 따른 가중치를 주는 것.

해당 식을 통해 구하면 별의 값은 약 8.7975가 나온다. 가장 가까운 8의 영향이 크게 적용되어 8과 근접한 값으로 예측값이 내려간다.

 

algorithm

가장 가까운 이웃들을 계산하는 데 사용하는 알고리즘을 결정함. default = auto

'auto' : 입력된 훈련 데이터에 기반해 알아서 적용해줌

'ball-tree' : Ball-Tree 구조 사용

'kd_tree' : KD-Tree 구조를 사용

'brute' : Brute-Force 탐색 사용

 

leaf_size

Ball-Tree나 KD-Tree의 leaf size를 결정

 

p

민코프스키 미터법의 차수를 결정

p = 1 : 맨해튼 거리

p = 2 : 유클리드 거리

 

K-최근접 이웃 회귀 실습

perch_length = np.array([8.4, 13.7, 15.0, 16.2, 17.4, 18.0, 18.7, 19.0, 19.6, 20.0, 21.0,
       21.0, 21.0, 21.3, 22.0, 22.0, 22.0, 22.0, 22.0, 22.5, 22.5, 22.7,
       23.0, 23.5, 24.0, 24.0, 24.6, 25.0, 25.6, 26.5, 27.3, 27.5, 27.5,
       27.5, 28.0, 28.7, 30.0, 32.8, 34.5, 35.0, 36.5, 36.0, 37.0, 37.0,
       39.0, 39.0, 39.0, 40.0, 40.0, 40.0, 40.0, 42.0, 43.0, 43.0, 43.5,
       44.0])
perch_weight = np.array([5.9, 32.0, 40.0, 51.5, 70.0, 100.0, 78.0, 80.0, 85.0, 85.0, 110.0,
       115.0, 125.0, 130.0, 120.0, 120.0, 130.0, 135.0, 110.0, 130.0,
       150.0, 145.0, 150.0, 170.0, 225.0, 145.0, 188.0, 180.0, 197.0,
       218.0, 300.0, 260.0, 265.0, 250.0, 250.0, 300.0, 320.0, 514.0,
       556.0, 840.0, 685.0, 700.0, 700.0, 690.0, 900.0, 650.0, 820.0,
       850.0, 900.0, 1015.0, 820.0, 1100.0, 1000.0, 1100.0, 1000.0,
       1000.0])

농어의 길이, 무게 데이터

from sklearn.model_selection import train_test_split

train_input, test_input, train_target, test_target = train_test_split(perch_length, perch_weight, random_state = 42)
train_input = train_input.reshape(-1, 1)
test_input = test_input.reshape(-1, 1)

train/test 데이터 분할 후 reshape()를 통해 2차원 데이터로 변경

 

K-최근접 이웃 알고리즘은

from sklearn.neighbors import KNeighborsRegressor

로 클래스 호출을 통해 간단하게 구현 가능하다.

knr = KNeighborsRegressor()
knr.fit(train_input, train_target)

print(knr.score(test_input, test_target))

knr score의 결과로는 0.9928이 나오는데, 이는 일반적인 회귀에서 사용되는 결정계수이며 모형의 설명력을 설명한다. 매우 높은 예측력을 가졌다고 볼 수 있다.

print(knr.score(train_input, train_target))

훈련 데이터의 knr.score는 그런데 약 0.9697로 오히려 테스트 데이터보다 낮게 나왔다.

이처럼 훈련 데이터의 정확도가 테스트 데이터의 정확도보다 낮거나 두 정확도 모두 낮은 경우를 과소적합이라고 하며,

테스트 데이터의 정확도가 훈련 데이터의 정확도에 비해 지나치게 낮은 경우를 과대적합이라고 한다.

 

과대적합

회귀 모델의 과대 적합 (over fitting)

데이터에 대한 적절한 회귀 모델이 빨간색이지만, 지나치게 훈련 데이터에 모든 데이터를 적용해 오차를 최대한으로 줄이려 해 훈련 데이터에 대해서만 정확도가 높고 테스트 데이터에서 정확도가 크게 떨어짐.

 

발생 원인?

○ 데이터 세트 내 데이터가 충분하지 않은 경우

○ 데이터 세트 내 분산이 크거나 노이즈가 심한 경우

○ 모델의 복잡도가 큰 경우

○ 과도하게 큰 epoch로 학습하는 경우

 

해결 방안?

○ 훈련 세트에 데이터를 추가하기

○ 가중치를 제한하는 규제를 적용해 모델의 복잡도를 낮추기 (L1 패널티를 적용하는 Lasso, L2 패널티를 적용하는 Ridge등)

○ 분산이 크거나 노이즈가 심한 경우 데이터를 전처리하여 훈련에 적합한 형태로 바꾸기

○ 모델의 learning curve를 epoch를 찾아내 해당 epoch까지만 훈련하게 제한 (조기 종료)

○ 회귀 모형의 변수 개수를 줄임

 

과소 적합

회귀 모델의 과소 적합 (under fitting)

모델의 복잡도가 낮아 세트 내 모든 데이터 규칙을 제대로 찾아내지 못해 전체적으로 낮은 정확도를 보임

훈련 데이터 세트와 테스트 데이터 세트의 손실 값이 모두 낮게 나와 성능이 전체적으로 매우 낮은 모습을 보임

 

발생 원인?

○ 모델의 복잡도가 낮은 경우

○ 모델에 너무 많은 규제가 적용된 경우

○ 충분하지 못한 epoch로 학습하는 경우

 

해결 방안?

모델의 복잡도가 낮은 경우 더 복잡한 모델을 사용

규제를 제거해 줄이기

더 많은 epoch를 적용

 

K-최근접 이웃 회귀의 단점은?

print(knr.predict([[100]])) #[1033.3333]

길이가 100으로 극단적인 값을 갖는 농어가 있다고 가정할 때, 예측치는 1033g로 나온다.

하지만 이는 길이가 40~44의 농어들의 무게로, 실제로는 훨씬 높아야 한다.

가장 근접한 이웃들의 값을 통해 값을 뽑아내기 때문에, 테스트하고자 하는 샘플에 근접한 훈련 데이터가 없는 경우는 정확한 예측이 어려운 한계가 있다.

 

튜닝의 끝은 순정, 선형회귀

필자가 통계학과 2학년 때 처음 접했던 회귀분석 과목에서 처음 만났으며 가장 기본적으로 다루는 방법으로, 그만큼 대표적이며 기본 근간이 되는 기법이다.

종속변수 y와 하나 이상의 독립 변수 x와의 선형 관계를 모델링하는 기법이며, 독립변수 x가 1개인 경우를 단순 선형 회귀, 2개 이상인 경우를 다중 선형 회귀 혹은 중선형회귀 라고 부른다.

단순 선형 회귀는 $y = Wx + b$의 식으로 나타내며 ML에서는 W값을 가중치(weight), 상수항의 b를 편향(bias)라고 부른다.

다중 선형 회귀에서는 $y = W_1x_1 + W_2x_2+ ... + W_nx_n + b$의 식으로 나타내며 이 독립 변수들의 그래프는 평면으로 나타난다.

 

직선 추정의 방식

최소 제곱법(Least Square Method)

오차를 최소화 시키는 방법으로 회귀계수 ($\beta_0, \beta_1$)를 추정하는 기법.

회귀식 $y_i = \beta_0 + \beta_1x_i +\varepsilon_i$ 가 있을때

이를 이항하면 $\varepsilon_i = y_i - \beta_0 - \beta_1x_i$ 가 된다. 이 때 이 오차의 제곱의 합이 최소가 되는 $b_0, b_1$을 찾는 것, 즉 이 $b_0, b_1$을 넣었을 때, 위 식이 최소가 되어야 한다. 

이 수식을 완성하기 위해 $f'(x) = 0,. f''(x) > 0$을 통해 각 편미분으로

식을 표현할 수 있으며, 이를 정리하면

정규방정식(Normal Equations)이 나온다.

하지만 $f''(x) >0$을 만족하는 조건이 또 필요하기 때문에

이차 편미분 행렬

의 행렬이 양정치 행렬이 되게 만들어야 한다. 이 경우는

의 경우 모두 만족하게 되며, 이 정규 방정식을 $b_0, b_1$에 대해 풀고 위 조건을 만족하게 구하면,

로 $\beta_0, \beta_1$의 추정치 $b_0, b_1$을 추정할 수 있다.

 

선형 회귀에 규제를 주자

위에서 설명했던 과대 적합의 해결 방안 중에서

○ 가중치를 제한하는 규제를 적용해 모델의 복잡도를 낮추기 (L1 패널티를 적용하는 Lasso, L2 패널티를 적용하는 Ridge등) 가 있었다. 

다항 회귀의 차수(degree)가 높아지는 문제가 생기는데, 이 차수가 낮으면 과소적합, 지나치게 높으면 과대적합의 문제가 생긴다. 따라서 선형 모델의 비용함수인 RSS(Residual Sum of Squares) 의 최소화와 다항식의 차수의 밸런스를 맞춰 과소/과대적합을 방지해야 한다.

이 경우 비용 함수의 목표는

가 되는데, $alpha$는 학습 데이터의 정확 정도와 회귀 계수 값 크기를 제어하는 튜닝 파라미터이며, $W$는 회귀 계수이다. 따라서 $alpha$를 0에서부터 지속적으로 값을 증가시켜 회귀 계수 값의 크기를 감소시킬 수 있다. 이처럼 비용 함수에 $alpha$값에 패널티를 부과해 회귀 계수의 크기를 감소시켜 과적합을 개선하는 방식을 규제(Regulation)라고 부른다.

 

L1 규제

$alpha * ||W||_1$와 같이 W의 절대값에 대해 패널티를 부여하는 규제로, 이 규제를 적용하면 영향력이 크지 않은 회귀 계수 값을 0으로 변환함.

 

Lasso Regression

필요하지 않은 변수에 대해 회귀 계수를 급격히 감소시켜 0까지 만들며 이런 규제를 통해 모델에서 아예 변수를 제외시켜 버려 피처 선택의 가능이 가능하다.

 

L2 규제

$alpha * ||W||^2_2$처럼 W의 제곱에 대해 패널티를 부여하는 방식으로, 이 경우는 라쏘와 달리 회귀 계수의 값을 0으로 만들지는 않는다.

Ridge Regression

라쏘 회귀와 마찬가지로 생성 파라미터는 alpha이며, alpha값이 커질수록 회귀 계수의 값을 작게 만든다. 

 

비교

상황마다 다르지만, 일반적으로 릿지 모델의 성능이 라쏘 모델의 성능보다 좋은 경향이 있다.

 

ElasticNet Regression

다다익선. 좋은 건 둘다 쓰는 취지로 L2 규제와 L1규제 모두를 사용하는 결합된 형식의 회귀 모형이다.

따라서 $RSS(W) + alpha_2*||W||^2_2 + alpha_1*||W||_1$ 의 식을 최소화하는 W를 찾는다.

라쏘 회귀에서 회귀 계수를 0으로 만드는 성향으로 인해 변수의 제거가 일어날 수 있어 이를 완화하기 위해 L2 규제를 동시에 사용한다.

하지만 $alpha_2, alpha_1$의 두 파라미터를 사용하기 때문에 상대적으로 수행시간이 오래 걸린다.