[혼자 공부하는 머신러닝+딥러닝] - 회귀 알고리즘과 모델 규제
03 회귀 알고리즘과 모델 규제
k-최근접 이웃 회귀
k-최근접 이웃 회귀란?
k-최근접 이웃 회귀는 예측할 데이터와 가장 가까운 이웃 데이터의 값을 기반으로 예측하는 회귀 알고리즘이다. 이 알고리즘은 주변 이웃들의 평균값을 사용하여 예측을 수행한다. 예를 들어, k=3으로 설정했을 때, 예측하려는 데이터와 가장 가까운 3개의 이웃 데이터를 선택하고, 이 이웃들의 평균 값을 예측 결과로 사용한다.
지도 학습 알고리즘은 크게 분류와 회귀로 나뉜다.
회귀란?
회귀란, 주어진 데이터에 기반하여 연속적인 값을 예측하는 머신러닝 기법이다. 회귀 분석은 독립 변수와 종속 변수 간의 관계를 모델링하고, 이를 통해 새로운 독립 변수에 대한 종속 변수 값을 예측하는 것을 목표로 한다.
데이터 준비 (농어의 길이와 무게)
import numpy as np
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)
사이킷런에 사용할 훈련 세트는 2차원 배열이어야 하므로 1차원 배열을 1개의 열이 있는 2차원 배열로 바꿔야 한다.
reshape() 메서드란?
reshape() 메서드는 NumPy 배열의 형태를 변경하는 함수이다. 주어진 배열을 새로운 형태로 재구성할 수 있다. 이 메서드를 사용하여 배열의 차원, 행, 열 등을 조정할 수 있다.
예를 들어, reshape(2, 3)는 6개의 요소를 가진 1차원 배열을 2행 3열의 2차원 배열로 변환한다.
test_array = test_array.reshape(2, 2)
print(test_array.shape)
2행의 2열의 2차원 배열로 전환하였다.

넘파이는 배열의 크기를 자동으로 지정하는 기능을 한다.
크기에 -1을 지정하면 나머지 원소 개수로 모두 채우라는 의미이다.
결정계수(R^2)
결정계수란?
결정계수는 각 샘플의 타킷과 예측한 값의 차이를 제곱하여 더한다. 그 다음 타킷과 타깃 평균의 차이를 제곱하여 더한 값으로 나눈다.
결정계수는 회귀 모델의 성능을 평가하는 지표 중 하나로, 입력 데이터에 대한 모델의 예측력을 나타내는 값이다. 결정계수는 0과 1 사이의 값을 가지며, 1에 가까울수록 모델이 입력 데이터를 잘 설명한다는 의미이다.
from sklearn.neighbors import KNeighborsRegressor
knr = KNeighborsRegressor()
# k-최근접 이웃 회귀 모델을 훈련합니다
knr.fit(train_input, train_target)
객체를 생성하고 fit() 메서드로 회귀 모델을 훈련하였다.
fit() 메서드란?
fit() 메서드는 머신러닝 모델을 훈련시키는 메서드이다. 모델에 훈련 데이터를 입력하여 모델이 입력 데이터에 맞게 학습하도록 한다. 이 메서드를 사용하여 회귀 모델을 훈련시킬 수 있다.

테스트 세트의 점수를 확인해보니, 이는 0.99~로 아주 좋은 값이다.

mean_absolute_error() 함수란?
mean_absolute_error() 함수는 실제값과 예측값 사이의 평균 절대 오차를 계산하는 함수이다. 이 함수를 사용하여 회귀 모델의 성능을 평가할 수 있다.
mean_absolute_error() 이 함수를 사용하여 평균 절대 오차를 계산한다.
결과에서 예측이 평균적으로 19g 정도 타킷값과 다르다는 것을 알 수 있다.
.
과대적합 vs 과소적합
과대적합이란?
과대적합이란, 모델이 훈련 데이터에 너무 잘 맞아서 테스트 데이터나 실제 데이터에서는 성능이 좋지 않은 현상을 말한다. 즉, 모델이 훈련 데이터에 지나치게 맞춰져서 새로운 데이터에 대한 일반화 능력이 떨어지는 것이다.
과소적합이란?
과소적합이란, 모델이 훈련 데이터에도 잘 맞지 않는 현상을 말한다. 즉, 모델이 훈련 데이터에 제대로 적합하지 못하여 새로운 데이터에 대한 예측력이 떨어지는 것을 의미한다.

훈련 세트의 R^2 점수를 확인해보면 0.96~으로, 앞에서 본 테스트 점수인 0.99~에 비해 점수가 낮다.
이는 훈련 세트보다 테스트 세트의 점수가 높은 과소적합이다.
이때 이웃의 개수 k을 줄이면 k-최근접 이웃 알고리즘으로 모델을 더 복잡하게 만들 수 있다.
k-최근접 이웃 알고리즘의 기본 k 값은 5이다. 5를 3으로 낮추면 훈련세트의 R^2 점수가 높아진다.
테스트 세트의 점수는 훈련 세트보다 낮아졌으므로 과소적합 문제를 해결할 수 있다.
선형 회귀
k-최근접 이웃의 한계
농어 데이터 준비>> 훈련 세트와 테스트 세트로 나누기>> 특성 데이터를 2차원 배열로 변환>>
최근접 이웃 개수를 3으로 하는 모델을 훈련>> 길이가 50cm인 농어의 무게 예측
길이가 50cm인 농어의 무게 예측하기 위해 앞서 했던 내용 반복
knr.predict란?
knr.predict는 k-최근접 이웃 회귀 모델에서 새로운 데이터의 타깃값을 예측하는 메서드이다.

50cm 농어의 무게를 1,033g 정도로 예측 >> 하지만 실제 농어의 무게는 훨씬 더 많이 나간다.
해당 오류를 판단하기 위하여 산점도를 그려본다.

길이가 50cm이고 무게가 1,033g인 농어를 초록색, makre=^로 표시하여보니 이는 그 주변의 샘플인 주황색 마름모 꼴의 샘플들 무게를 평균한 것이다.
오류 원인 : k-최근접 이웃 회귀는 가장 가까운 샘플을 찾아 타깃으로 평균하기 때문
이처럼 새로운 샘플이 훈련 세트의 범위를 벗어나면 엉뚱한 값을 예측할 수 있다. 따라서 농어가 길이가 아무리 길어도 무게는 1,033g으로 변하지 않을 것이다.
회귀 알고리즘인 선형 회귀는 해당 오류를 해결할 수 있다.
선형 회귀
선형 회귀란?
선형 회귀는 주어진 데이터에 기반하여 선형적인 관계를 모델링하는 회귀 알고리즘이다. 특성이 하나인 경우 어떤 직선을 학습한다.
LinearRegression 클래스란?
선형 회귀 클래스는 sklearn 라이브러리에서 제공하는 클래스로, 입력 데이터에 대해 선형 관계를 모델링하고 예측값을 생성하는 기능을 제공한다. 이 클래스는 fit() 메서드를 사용해 훈련 데이터를 학습하며, predict() 메서드를 사용해 새로운 데이터에 대한 예측값을 생성한다.

k-최근접 이웃 휘귀를 사용했을 때와 달리 선형 회귀는 농어의 무게를 아주 높게 예측>> 오류 해결
선형 회귀는 직선을 학습하였기 때문이다.
lr.coef_란?
선형 회귀 모델의 계수(coef_)는 입력 특성의 가중치를 나타낸다. 즉, lr.coef_는 선형 회귀 모델에서 각 입력 특성의 가중치를 의미한다.
lr.intercept_란?
lr.intercept_는 선형 회귀 모델에서의 절편(intercept)을 나타낸다. 절편은 회귀 직선의 y절편으로, 입력 변수(x)가 0일 때의 종속 변수(y)의 예측값을 의미한다.
하나의 직선을 y=ax+b라고 쓸 수 있다. 여기에서 x는 농어의 길이, y는 농어의 무게이다.
a와 b는 Ir 객체의 coef_와 intercept_ 속성에 저장
농어의 길이 15에서 50까지 직선으로 그려본다>> print(lr.coef_, lr.intercept_)를 통하여 구한 기울기와 절편을 사용하여 (15, 15x39-709)와 (50, 50x39-709)의 두 점을 이으면 된다.

이 직선은 선형 회귀 알고리즘이 찾은 최적의 직선이며 길이가 50cm인 농어에 대한 예측은 이 직선의 연장선에 있음을 알 수 있다.

훈련 세트와 테스트 세트의 R^2(결정계수)를 확인해보면 훈련 세트는 0.93~, 테스트 세트는 0.82~이다.
훈련 세트와 테스트 세트의 점수가 모두 높지 않은 것으로 보아, 전체적으로 과소적합 되었다고 볼 수 있다.
또한 그래프 왼쪽 아래를 보면, 농어의 무게가 0g 이하로 내려간 부분이 있어 이는 현실에서 있을 수 없는 일이다.
다항 회귀
다항 회귀는 독립 변수의 단항식이 아닌 2차, 3차 등의 고차항식으로 표현되는 회귀 분석 방법이다. 이 방법은 비선형 데이터를 학습하는데 적합하며, 2차 함수 이상의 다항 함수를 사용하여 데이터의 복잡한 패턴을 더 잘 캡처할 수 있다.
농어의 길이와 무게에 대한 산점도를 자세히 보면 일직선이라기보다는 왼쪽 위로 조금 구부러진 곡선에 가깝다.
이런 2차 방정식 그래프를 그리려면 길이를 제곱한 항이 훈련 세트에 추가되어야 한다.
train_poly = np.column_stack((train_input ** 2, train_input))
test_poly = np.column_stack((test_input ** 2, test_input))
앞서 배운 넘파이와 column_stack() 함수를 이용하여 원래 데이터 앞에 새로운 데이터를 붙인다.
넘파이란?
넘파이(Numpy)는 Python에서 수치 데이터를 효과적으로 다루는 라이브러리이다. 배열이나 행렬 같은 다차원 데이터를 효율적으로 처리할 수 있게 해주며, 선형 대수, 통계 연산 등 다양한 수치 연산 기능을 제공한다.
column_stack이란?
column_stack은 넘파이(Numpy) 함수로, 입력 배열을 열 방향으로 쌓아서 하나의 배열을 만드는 함수이다. 이는 주어진 1차원 배열을 2차원 배열의 열로 변환하고, 2차원 이상의 배열은 그대로 유지하는 역할을 한다.

원래 특성인 길이를 제곱하여 왼쪽 열에 추가하였으므로 훈련 세트와 테스트 세트 모두 열이 2개로 늘어난다.
이제 선형 회귀 모델을 다시 훈련한 후 타깃값은 그대로 사용한다.
50cm짜리 농어에 대해 무게를 예측해보면 앞에서 예측한 1,033g과 달리 1,573g으로 더 높은 값을 예측하였다.
또한 훈련한 개수와 절편을 출력해보면 결과적으로
무게 = 1.01x길이^2 - 21.6x길이 + 116.05 의 그래프를 학습한다.
이런 방정식을 다항식이라 부르며 다항식을 사용한 선형 회귀를 다항 회귀라고 부른다.

구해진 값으로 산점도와 그래프를 그려보면 앞선 단순 선형 회귀 모델보다 훨씬 나은 그래프가 그려진다.
또한 훈련 세트와 테스트 세트의 R^2(결정게수) 점수를 평가하면 모두 0.97~로 높아진 것을 볼 수 있다.
하지만 아직도 전체적으로 과소적합이 남아있다.
특성 공학과 규제
다중회귀
다중회귀란?
다중 회귀는 독립 변수가 2개 이상인 경우에 사용하는 회귀 분석 방법이다. 이 방법은 여러 개의 독립 변수가 종속 변수에 어떠한 영향을 미치는지 분석하기 위해 사용되며, 각 독립 변수의 계수를 추정하여 종속 변수와의 관계를 모델링한다. 이렇게 다중 회귀를 통해 복수의 독립 변수와 종속 변수 사이의 관계를 더 정확하게 이해하고 예측할 수 있다.
특성이 2개면 선형 회귀는 평면을 학습한다>> 평면 : 타킷 = a x 특성1 + b x 특성2 + 절편
특성 공학이란?
특성 공학은 기존의 특성을 사용해 새로운 특성을 뽑아내는 작업을 말한다. 머신러닝 모델의 성능을 향상시키기 위해 데이터의 특성을 선택하고, 변환하고, 생성한다.
판다스와 판다스의 핵심 데이터 구조인 데이터프레임을 이용한다.
import pandas as pd
df = pd.read_csv('<https://bit.ly/perch_csv_data>')
perch_full = df.to_numpy()
print(perch_full)
타깃 데이터는 이전과 동일한 방식으로 준비한다.
