Python의 선형 회귀 III

2024. 1. 27. 14:30python/intermediate

scikit-learn을 사용한 다중 선형 회귀

단순 회귀와 동일한 단계에 따라 다중 선형 회귀를 구현할 수 있습니다. 주요 차이점은 배열에 𝑥²와 같은 비선형 용어가 포함하도록 변환할 필요가 있다는 것입니다.

1단계 및 2단계: 패키지 및 클래스 가져오기 및 데이터 제공

numpy와 sklearn.linear_model.LinearRegression외에, 또한 sklearn.preprocessing에서 class PolynomialFeatures를 가져 와야 합니다.

In [ ]:
import numpy as np
from sklearn.linear_model import LinearRegression

x = [
  [0, 1], [5, 1], [15, 2], [25, 5], [35, 11], [45, 15], [55, 34], [60, 35]
]
y = [4, 5, 20, 14, 32, 22, 38, 43]
x, y = np.array(x), np.array(y)

이는 입력 x와 출력 y을 정의하는 간단한 방법입니다. 인쇄하여 지금 x와 y가 어떻게 보이는지 확인할 수 있습니다.

In [ ]:
x
In [ ]:
y

다중 선형 회귀 분석에서는 x는 2개 이상의 열이 있는 2차원 배열인 반면, y는 일반적으로 1차원 배열입니다. 이는 다중 선형 회귀의 간단한 예이며 x는 정확히 두 개의 열이 있습니다.

3단계: 모델 생성 및 피팅

다음 단계는 회귀 모델을 LinearRegression의 인스턴스로 생성하고 이를 .fit()으로 피팅하는 것입니다.

In [ ]:
model = LinearRegression().fit(x, y)

이 명령문의 결과는 model유형의 LinearRegression 객체를 참조하는 변수입니다. 기존 데이터에 맞는 회귀 모델을 나타냅니다.

4단계: 결과 얻기

단순 선형 회귀의 경우와 동일한 방식으로 모델의 속성을 얻을 수 있습니다.

In [ ]:
r_sq = model.score(x, y)
print(f"coefficient of determination: {r_sq}")
In [ ]:
print(f"intercept: {model.intercept_}")
In [ ]:
print(f"coefficients: {model.coef_}")

.score() 및 intercept_와 .coef_를 가진 회귀 계수 추정기 값을 사용하여 𝑅² 값을 얻습니다 . 다시, .intercept_는 편향 𝑏₀을 유지하는 반면, .coef_는 𝑏₁ 및 𝑏₂를 포함하는 배열 입니다.

이 예에서 절편은 약 5.52이며 이는 𝑥₁ = 𝑥₂ = 0일 때 예측 반응의 값입니다. 𝑥₁가 1 증가하면 예측 반응이 0.45만큼 증가합니다. 마찬가지로 𝑥₂가 1만큼 커지면 응답은 0.26만큼 증가합니다.

5단계: 반응 예측

예측은 단순 선형 회귀의 경우와 동일한 방식으로 작동합니다.

In [ ]:
y_pred = model.predict(x)
print(f"predicted response:\n{y_pred}")

예측된 응답은 .predict()이며, 결과는 다음과 같습니다.

In [ ]:
y_pred = model.intercept_ + np.sum(model.coef_ * x, axis=1)
print(f"predicted response:\n{y_pred}")

입력의 각 열에 적절한 가중치를 곱하고, 결과를 합산하고, 그 합에 절편을 추가하여 출력 값을 예측할 수 있습니다.

이 모델을 새 데이터에도 적용할 수 있습니다.

In [ ]:
x_new = np.arange(10).reshape((-1, 2))
x_new
In [ ]:
y_new = model.predict(x_new)
y_new

이것이 선형 회귀 모델을 사용한 예측입니다.

scikit-learn을 사용한 다항식 회귀

scikit-learn을 사용하여 다항식 회귀를 구현하는 것은 선형 회귀와 매우 유사합니다. 추가 단계는 한 가지뿐입니다. 𝑥²와 같은 비선형 항을 포함하도록 입력 배열을 변환해야 합니다.

1단계: 패키지 및 클래스 가져오기

numpy및 sklearn.linear_model.LinearRegression 외에도 sklearn.preprocessing 에서 .PolynomialFeatures 클래스를 가져와야 합니다

In [ ]:
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures

이제 가져오기가 완료되었으며 작업에 필요한 모든 것이 준비되었습니다.

2a단계: 데이터 제공

이 단계에서 입력과 출력을 정의하며 선형 회귀의 경우와 동일합니다.

In [ ]:
x = np.array([5, 15, 25, 35, 45, 55]).reshape((-1, 1))
y = np.array([15, 11, 2, 8, 25, 32])

이제 적절한 형식의 입력과 출력이 생겼습니다. 입력이 2차원 배열 이어야 한다는 점을 명심하세요 . 왜 .reshape()를 사용하는 이유입니다.

2b단계: 입력 데이터 변환

이것은 다항식 회귀를 위해 구현해야 하는 새로운 단계 입니다!

앞서 배운 것처럼 다항식 회귀를 구현할 때 추가 기능으로 𝑥² 및 기타 용어를 포함해야 합니다. 이러한 이유로 𝑥² 값이 있는 추가 열을 포함한 입력 배열 x 를 변환해야 합니다.

numpy로 부터 insert()을 사용하는 등 여러 가지 방법으로 입력 배열을 변환할 수 있습니다 . 하지만 이 클래스 PolynomialFeatures은 이런 목적을 위해 매우 편리합니다. 계속해서 이 클래스의 인스턴스를 생성하십시오.

In [ ]:
transformer = PolynomialFeatures(degree=2, include_bias=False)

transformer 변수는 입력을 변환하는 데 사용할 수 있는 PolynomialFeaturesx 인스턴스를 나타냅니다.

다음과 같은 여러 선택적 매개변수를 PolynomialFeatures에 제공할 수 있습니다.

  • degree는 다항식 회귀 함수의 정도를 나타내는 정수( 2기본값)입니다.
  • interaction_only는 상호 작용 기능만 포함할지(True) 또는 모든 기능을 포함할지(False) 결정하는 부울(기본값은 False) 입니다.
  • include_bias는 편향 또는 절편, 값 1 열에 포함할지(True) 포함하지 않을지(False) 여부를 결정하는 부울(기본값은 True)입니다.

이 예에서는 include_bias 를 제외한 모든 매개변수의 기본값을 사용합니다. 때로는 함수의 수준을 실험하고 싶을 수도 있으며 어쨌든 이 인수를 제공하는 것이 가독성에 도움이 될 수 있습니다.

transformer를 신청하기 전에 .fit()으로 맞추어줘야 합니다.

In [ ]:
transformer.fit(x)

일단 transformer가 맞추어지면 새로운 수정된 입력 배열을 생성할 준비가 된 것입니다. 당신은 그렇게 하기 위해 .transform()를 신청합니다.

In [ ]:
x_ = transformer.transform(x)

이는 .transform()를 사용한 입력 배열의 변환입니다. 입력 배열을 인수로 사용하고 수정된 배열을 반환합니다.

.fit_transform()을 사용하여 이전 세 개의 문을 하나로 바꿀 수도 있습니다 .

In [ ]:
x_ = PolynomialFeatures(degree=2, include_bias=False).fit_transform(x)

.fit_transform()를 사용하면 하나의 명령문으로 입력 배열을 맞추고 변환할 수 있습니다. 이 메서드는 또한 입력 배열을 사용하여 효과적으로 .fit()과 동일한 작업을 수행 하고 .transform()가 해당 순서로 호출됩니다. 또한 수정된 배열을 반환하여 줍니다. 새로운 입력 배열은 다음과 같습니다.

In [ ]:
x, x_

수정된 입력 배열에는 두 개의 열이 포함되어 있습니다. 하나는 원래 입력이 있고 다른 하나는 사각형이 있습니다. 자세한 내용은 공식 문서 페이지에서 PolynomialFeatures를 확인할 수 있습니다 .

3단계: 모델 생성 및 피팅

이 단계 역시 선형회귀의 경우와 동일합니다. 모델을 생성하고 피팅합니다.

In [ ]:
model = LinearRegression().fit(x_, y)

이제 회귀 모델이 생성되고 맞춰졌으므로 적용할 준비가 되었습니다. .fit()의 첫 번째 인수는 원본 배열 x가 아니라 수정된 입력 배열 x_ 이라는 점을 명심해야 합니다 .

4단계: 결과 얻기

선형 회귀의 경우와 동일한 방식으로 모델의 속성을 얻을 수 있습니다.

In [ ]:
r_sq = model.score(x_, y)
print(f"coefficient of determination: {r_sq}")
In [ ]:
print(f"intercept: {model.intercept_}")
In [ ]:
print(f"coefficients: {model.coef_}")

다시 .score()는 𝑅²를 반환합니다. 첫 번째 인수도 x가 아닌 수정된 입력 x_입니다. 가중치 값은 .intercept_ 및 .coef_ 와 연관되어 있습니다 . 여기서는 .intercept_가 𝑏₀을 나타내며, .coef_는 𝑏₁ 및 𝑏₂를 포함한 배열을 참조합니다.

다양한 변환 및 회귀 인수를 사용하여 매우 유사한 결과를 얻을 수 있습니다.

In [ ]:
x_ = PolynomialFeatures(degree=2, include_bias=True).fit_transform(x)

include_bias=True를 포함한 기본 매개변수인 PolynomialFeatures를 사용하여 호출하거나 이를 생략하는 경우, 1 값만 포함하는 추가 맨 왼쪽 열이 있는 새 입력 배열 x_를 얻게 됩니다 . 이 열은 절편에 해당합니다. 이 경우 수정된 입력 배열은 다음과 같습니다.

In [ ]:
x_

x_의 첫 번째 열에는 1들이 포함되고, 두 번째 열에는 x의 값이 포함되며, 세 번째 열에는 x의 제곱이 포함됩니다.

절편은 이미 가장 왼쪽 열에 포함되어 있으므로 인스턴스 LinearRegression를 생성할 때 다시 포함할 필요가 없습니다. 따라서 를 fit_intercept=False를 제공할 수 있습니다. 다음 명령문은 다음과 같습니다.

In [ ]:
model = LinearRegression(fit_intercept=False).fit(x_, y)

변수 model은 다시 새 입력 배열 x_에 해당합니다 . 따라서 x_는 x가 아닌 첫 번째 인수로 전달되어야 합니다.

이 접근 방식은 이전 사례와 유사한 다음과 같은 결과를 생성합니다.

In [ ]:
r_sq = model.score(x_, y)
print(f"coefficient of determination: {r_sq}")
In [ ]:
print(f"intercept: {model.intercept_}")
In [ ]:
print(f"coefficients: {model.coef_}")

지금 .intercept_는 0이지만 .coef_는 실제로는 첫 번째 요소로 𝑏₀을 포함하고 있습니다. 다른 모든 것은 동일합니다.

5단계: 반응 예측

예측된 응답을 얻으려면 .predict()을 사용하면 됩니다. 단, 인수는 이전 입력 x 대신 수정된 입력 x_이어야 한다는 점을 기억하세요.

In [ ]:
y_pred = model.predict(x_)
print(f"predicted response:\n{y_pred}")

보시다시피 예측은 선형 회귀의 경우와 거의 동일한 방식으로 작동합니다. 원본 대신 수정된 입력이 필요합니다.

입력 변수가 여러 개인 경우에도 동일한 절차를 적용할 수 있습니다 . 두 개 이상의 열이 포함된 입력 배열이 있지만 다른 모든 것은 동일합니다. 예는 다음과 같습니다.

In [ ]:
# Step 1: Import packages and classes
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures

# Step 2a: Provide data
x = [
  [0, 1], [5, 1], [15, 2], [25, 5], [35, 11], [45, 15], [55, 34], [60, 35]
]
y = [4, 5, 20, 14, 32, 22, 38, 43]
x, y = np.array(x), np.array(y)

# Step 2b: Transform input data
x_ = PolynomialFeatures(degree=2, include_bias=False).fit_transform(x)

# Step 3: Create a model and fit it
model = LinearRegression().fit(x_, y)

# Step 4: Get results
r_sq = model.score(x_, y)
intercept, coefficients = model.intercept_, model.coef_

# Step 5: Predict response
y_pred = model.predict(x_)

이 회귀 예제는 다음과 같은 결과와 예측을 산출합니다.

In [ ]:
print(f"coefficient of determination: {r_sq}")
In [ ]:
print(f"intercept: {intercept}")
In [ ]:
print(f"coefficients:\n{coefficients}")
In [ ]:
print(f"predicted response:\n{y_pred}")

이 경우 추정 회귀함수 𝑓(𝑥₁, 𝑥₂) = 𝑏₀ + 𝑏₁𝑥₁ + 𝑏₂𝑥₂ + 𝑏₃𝑥₁² + 𝑏₄𝑥₁𝑥₂ + 𝑏₅𝑥²²에서 보는 바와 같이 절편을 포함하여 6개의 회귀계수가 존재합니다.

또한 동일한 문제에 대해 다항식 회귀가 다중 선형 회귀보다 더 높은 결정 계수를 산출했음을 알 수 있습니다. 처음에는 이렇게 큰 𝑅²를 얻는 것이 훌륭한 결과라고 생각할 수 있습니다. 맞습니다.

그러나 실제 상황에서는 복잡한 모델과 𝑅²이 하나에 매우 가까운 것도 과적합의 징후일 수 있습니다. 모델의 성능을 확인하려면 새로운 데이터, 즉 모델을 맞추거나 훈련하는 데 사용되지 않은 관측치를 사용하여 모델을 테스트해야 합니다. 데이터 세트를 훈련 및 테스트 하위 세트로 분할하는 방법을 알아보려면 scikit-learn의 train_test_split()을 사용하여 데이터 세트 분할을 확인하세요 .

통계 모델을 사용한 고급 선형 회귀

statsmodels 패키지를 사용하여 Python에서 선형 회귀를 구현할 수도 있습니다. 일반적으로 이는 보다 자세한 결과가 필요할 때 바람직합니다.

절차는 scikit-learn과 유사합니다.

1단계: 패키지 가져오기

먼저 몇 가지 가져오기를 수행해야 합니다. numpy 외에도 statsmodels.api을 가져와야 합니다.

In [ ]:
import numpy as np
import statsmodels.api as sm

이제 필요한 패키지를 가져 왔습니다.

2단계: 데이터 제공 및 입력 변환

scikit-learn을 사용할 때와 동일한 방식으로 입력과 출력을 제공할 수 있습니다.

In [ ]:
x = [
  [0, 1], [5, 1], [15, 2], [25, 5], [35, 11], [45, 15], [55, 34], [60, 35]
]
y = [4, 5, 20, 14, 32, 22, 38, 43]
x, y = np.array(x), np.array(y)

입력 및 출력 배열이 생성되었지만 작업은 아직 완료되지 않았습니다.

통계 모델이 절편 𝑏₀을 계산하도록 하려면 입력에 1의 열을 추가해야 합니다. 기본적으로 𝑏₀을 고려하지 않습니다. 이것은 단지 하나의 함수 호출입니다.

In [ ]:
x = sm.add_constant(x)

이것이 add_constant()을 포함한 x에 1의 열을 추가하는 방법입니다. 입력 배열 x를 인수로 사용하고 시작 부분에 삽입된 1의 열을 가진 새 배열을 반환합니다. 어떻게 x와 y 처럼 보이는가 하는 것입니다.

In [ ]:
x
In [ ]:
y

수정된 x 열에는 세 개의 열이 있는 것을 볼 수 있습니다. 즉, 𝑏₀에 해당하고 절편을 대체하는 1 의 첫째 열과 원래 기능의 두 열이 있습니다.

3단계: 모델 생성 및 피팅

보통 최소 제곱을 기반으로 하는 회귀 모델은 클래스 statsmodels.regression.linear_model.OLS의 인스턴스입니다. 획득 방법은 다음과 같습니다.

In [ ]:
model = sm.OLS(y, x)

여기서 조심해야 합니다! 첫 번째 인수는 출력이고 그 뒤에 입력이 옵니다. 이는 해당 scikit-learn 함수의 반대 순서입니다.

모델이 생성되면 fit()dmf 적용할 수 있습니다.

In [ ]:
results = model.fit()

.fit()을 호출하면 statsmodels.regression.linear_model.RegressionResultsWrapper의 클래스의 인스턴스인 변수 results를 얻을 수 있습니다. 이 객체는 회귀 모델에 대한 많은 정보를 담고 있습니다.

4단계: 결과 얻기

results 변수는 선형회귀 결과에 대한 자세한 정보를 담고 있는 객체를 의미합니다. 이러한 결과를 설명하는 것은 이 튜토리얼의 범위를 훨씬 벗어나지만 여기서는 결과를 추출하는 방법을 배우게 됩니다.

선형 회귀 결과가 포함된 테이블을 얻기 위해 .summary()을 호출할 수 있습니다 .

In [ ]:
print(results.summary())

이 표는 매우 포괄적입니다. 𝑅², 𝑏₀, 𝑏₁ 및 𝑏₂를 포함하여 선형 회귀와 관련된 많은 통계 값을 찾을 수 있습니다.

이 특별한 경우에는 kurtosistest only valid for n>=20 라는 경고가 표시될 수 있습니다. 이는 예제에 제공된 관측값 수가 적기 때문입니다.

위 표에서 원하는 값을 추출할 수 있습니다. 예는 다음과 같습니다.

In [ ]:
print(f"coefficient of determination: {results.rsquared}")
In [ ]:
print(f"adjusted coefficient of determination: {results.rsquared_adj}")
In [ ]:
print(f"regression coefficients: {results.params}")

이것이 선형 회귀의 일부 결과를 얻는 방법입니다.

  1. .rsquared는 𝑅²를 보유하고 있습니다.
  2. .rsquared_adj는 조정된 𝑅², 즉 입력 특성 수에 따라 수정된 𝑅²을 나타냅니다.
  3. .params는 𝑏₀, 𝑏₁, 𝑏₂로 배열을 나타냅니다.

또한 이러한 결과는 동일한 문제에 대해 scikit-learn을 사용하여 얻은 결과와 동일하다는 것을 알 수 있습니다.

5단계: 반응 예측

입력 배열을 인수로 사용하거나 .fittedvalues 혹은 .predict()를 사용하여 모델 생성에 사용된 입력 값에 대한 예측 응답을 얻을 수 있습니다.

In [ ]:
print(f"predicted response:\n{results.fittedvalues}")
In [ ]:
print(f"predicted response:\n{results.predict(x)}")

이는 알려진 입력에 대한 예측된 응답입니다. 새로운 회귀 변수를 사용하여 예측을 원하는 경우 새 데이터를 인수로 .predict()를 적용할 수도 있습니다 .

In [ ]:
x_new = sm.add_constant(np.arange(10).reshape((-1, 2)))
x_new
In [ ]:
y_new = results.predict(x_new)
y_new

동일한 문제에 대해 scikit-learn을 사용하여 얻은 결과와 예측 결과가 동일하다는 것을 알 수 있습니다.

선형 회귀를 넘어

선형 회귀는 때때로 적합하지 않은 경우가 있으며, 특히 복잡성이 높은 비선형 모델의 경우 더욱 그렇습니다.

다행히도 선형 회귀가 제대로 작동하지 않는 경우에 적합한 다른 회귀 기술이 있습니다. 그 중 일부는 지원 벡터 머신, 의사결정 트리, 랜덤 포레스트 및 신경망입니다.

이러한 기술을 사용하는 회귀를 위한 수많은 Python 라이브러리가 있습니다. 대부분은 무료이며 오픈 소스입니다. 이것이 Python이 기계 학습의 주요 프로그래밍 언어 중 하나인 이유 중 하나입니다.

scikit-learn 패키지는 지금까지 본 것과 매우 유사한 방식으로 다른 회귀 기술을 사용하기 위한 수단을 제공합니다. 여기에는 .fit(), .predict(), .score() 등의 메소드와 함께 지원 벡터 머신 , 의사결정 트리 , 랜덤 포레스트 등에 대한 클래스가 포함되어 있습니다 .

'python > intermediate' 카테고리의 다른 글

Python 이름의 단일 및 이중 밑줄 II  (0) 2024.01.29
Python 이름의 단일 및 이중 밑줄 I  (1) 2024.01.28
Python의 선형 회귀 II  (1) 2024.01.26
Python의 선형 회귀 I  (1) 2024.01.25
Python3 중급 주제  (0) 2024.01.24