Linear Regression - Polynomial Regression

·2025년 8월 1일

just공부

목록 보기
36/41

Sklearn lr

1. Linear Regression w/ Normal equation

# linear_model에서 LinearRegression 부르기
# parameter 설정할 것 없이 그냥 부르면 됨
from sklearn.linear_model import LinearRegression
lr_ne = LinearRegression(fit_intercept=True)

# 이렇게 불러서 사용하면 됨
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.33, random_state=42)

2. Linear Regression w/ SGD

SGD에 대한 모듈 설명을 보게 되면 아래와 같다.

SGDRegressor (loss='squared_loss', penalty='l2', alpha=0.0001, l1_ratio=0.15, fit_intercept=True, max_iter=None, tol=None, shuffle=True, verbose=0, epsilon=0.1, random_state=None, learning_rate='invscaling', eta0=0.01, power_t=0.25, warm_start=False, averate=False, n_iter=None)

  • loss : 기본적으로 squred_loss 사용하면 된다.
  • penalty : Regularization 방법
  • alpha : L2의 앞에 λ\lambda 값 얼마로 설정할 지
    • 이 값이 커질 수록, Regularization이 많이 된다.
    • 학습하는 weight값이 줄어들게 된다.
  • max_iter : epoch을 몇 번 돌 것이냐
  • tol : 멈추는 기준이 되는 값
    • cost function이 이 기준보다 적어지면 멈춰라.
  • shuffle : True로 하면 섞는 것이고, False로 설정하면 섞지 않는 것으로 batch gradient가 될 것이다.
  • learning_rate : 돌아갈 때마다 일정량이 줄어들게 된다. 줄어들게 되는 이 전략이 3가지가 있다.
    • constant, optimal, invascaling
  • eta0 : learning_rate을 지정해주는 것
    • 학습 속도를 빠르게 하기 위해서는 learning_rate을 올려주면 된다.
  • warm_start : 초기값을 지정해주는 것
    • 예측을 할 때 초기값을 기반으로 하게 된다.
# 여러가지 hyperparameter를 직접 입력해주어야 함

from sklearn.linear_model import SGDRegressor
lr_SGD = SGDRegressor(n_iter=10000, eta0=0.00001, learning_rate="constant")

# 특정 값(X)을 정규화하기 위해 표준화 도구 불러오기
from sklearn.preprocessing import StandardScaler
std_scaler = StandardScaler()

# 데이터 X에 대해 평균=0, 표준편차 1이 되도록 스케일러 학습
std_scaler.fit(X)

# 학습된 스케일러로 X를 정규화
X_scaled = std_scaler.transform(X)

# 데이터셋을 학습용과 테스트용으로 나누기
# test_size : 전체의 33%를 테스트용으로 사용
# random_state : 결과 재현을 위해 난수 시드를 사용
from sklearn.model_selection import train_test_split
X_train, X_test, y_train = train_test_split(X, y, test_size=0.33, random_state=42)

# 선형 회귀 모델 학습, 학습된 X_train과 y_train을 사용
lr_SGD.fit(X_train, y_train)

# 테스트 데이터로 예측을 수행
# 실제값을 y_true로 설정
y_hat = lr_SGD.predict(X_test)
y_true = y_test

# 평균제곱오차(MSE), 평균제곱근오차(RMSE) 계산
mse = sklearn.metrics.mean_squared_error(y_hat, y_true)
rmse = np.sqrt((((y_hat - y_true) **2).sum() / len(y_true)))
rmse, mse

# 예측값(y_hat)과 실제값(y_true)을 시각화
plt.scatter(y_true, y_hat, s=10)
plt.xlabel("~~")
plt.ylabel("--")
plt.title("...")
  • n_iter : 반복 횟수로, 현재는 max_iter로 대체되었다.

3. Linear Regression w/ Ridge & Lasso regression

from sklearn.linear_model import Lasso, Ridge

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=42)

ridge = Ridge(fit_intercept=True, alpha=0.5)
ridge.fit(X_train, y_train)
#lasso = Lasso(fit_intercept=True, alpha=0.5)

y_hat = ridge.predict(X_test)
y_true = y_test
mse = sklearn.metrics.mean_squared_error(y_hat, y_true)
rmse = np,sqrt((((y_hat - y_true)**2).sum() / len(y_true)))
rmse, mse
  • solver : 데이터를 보고 어떤 알고리즘으로 적합화할 건지, auto 로 설정하게 되면 데이터를 보고 알아서 찾아준다.

Polynomial Regression

집의 넓이와 집세의 상관관계

집의 높이와 크기를 반영하게 된다면 아래와 같은 식이 나오게 된다.

hθ(x)=θ0+θ1x1+θ2x2+θ3x3θ0+θ1(depth)+θ2(frontag)+θ3(depth×frontag)h_\theta (x) = \theta_0 + \theta_1 x_1 + \theta_2 x_2 + \theta_3 x_3 \\ \theta_0 + \theta_1 (depth) + \theta_2 (frontag) + \theta_3 (depth × frontag)

1차 방정식을 고차다항식으로 변경하는 기법

x1+x2x1+x2+x1x2+x12+x22x_1 + x_2 → x_1 + x_2 + x_1 x_2 + x_1^2 + x_2^2
  • sklearn.preprocessing.PolynomialFeatures 사용
X = np.arange(6).reshape(3, 2)
X
poly = PolynomialFeatures(2)
poly.fit_transform(X)
poly = PolynormialFeatures(interaction_only=True)
poly.fit_transform(X)

Dataset

def f(size):
	x = np,linspace(0, 5, size)
    y = x * np.sin(x ** 2) + 1
    return (x, y)

def sample(size):
	x = np.linspace(0, 5, size)
    y = x * np.sin(x ** 2) +1 + pl.randn(x.size)*0.5
  • x값을 생성해주는 코드

Linear regression

from sklearn.linear_model import LinearRegression

lr = LinearRegression()
lr.fit(X, y)

f_x, f_y = f(1000)
plt.plot(f_x, f_y)
plt.scatter(X.flatten(), y.flatten(), s=3, c="black")
plt.plot(X.flatten(), lr.predict(X).flatten())
plt.show()

Polynomial Regression

from sklearn.preprocessing import PolynomialFeatures

# poly_features를 사용하게 되면 절편항이 추가됨
poly_features = PolynomialFeatures(degree=2)
X_poly = poly_features.fit_transform(X)
X_poly[:10]

degree를 바꿔주는 것을 parameter search라고 한다. 실험적으로 접근하는 방법이다.

모델을 fitting해주기 위해서는 우리가 무슨 값을 최소화시켜야 할지 알아볼 수 있다.

  • rmse를 만들어주는 방법
def rmse(predictions, targets):
	return np.sqrt(((predictions - targets) ** 2).mean())
 
# grid search 방법
poly_range = list(range (10, 50)) # feature 몇 개 만들건지
rmse_lr_list = []
rmse_lasso_list = []
rmse_ridge_list = []

from sklearn.linear_model import Lasso
from sklearn.linear_model import Ridge

for poly_value in poly_range:
	poly_features = PolynomialFeatures(degree=poly_value)
    X_poly = poly_features.fit_transform(X)
    lr = LinearRegression(fit_intercept=False)
    lr.fit(X_poly, y)
    
    rmse_lr_list.append(rmse(lr.predict(X_poly), y))
    
    lasso = Lasso()
    lasso.fit(X_poly, y)
    rmse_lasso_list.append(rmse(lasso.predict(X_poly), y))
    
    ridge = Ridge()
    ridge.fit(X_poly, y)
    rmse_ridge_list.append(rmse(ridge.predict(X_poly), y))
    
# Dataframe형태로 정리해서 결과 보기
import pandas as pd
from pandas import DataFrame
data = {"poly_range":poly_range, "lr_rmse":rmse_lr_list, "lasso_rmse":rmse_lasso_list, "ridge_rmse":rmse_ridge_list}
df = DataFrame(data).set_index("poly_range")
df

How to optimize

  • RMSE의 최소값을 찾자
    • df.min()
    • df["ridge_rmse"].sort_values().head()
      → ridge값에서 sorting하기
  • Ridge, Lasso, LR 다 써보기
  • Degree를 10~50까지 사용
  • 결과 정리하기
    .

이 방법을 언제쓰나?

  • 한개 변수가 Y값과 비선형적인 관계가 있다고 의심될 때
  • 주기적인 패턴을 보이는 Series 데이터
  • 모델 자체가 복잡해지면 해결가능한 부분이 많음
    • SVM, Tree-based models

L1

  • Unstable solution
  • Always on solution
  • Sparse solution
  • Feature selection

L2

  • Stable solution
  • Only one solution
  • Non-sparse solution

Performance measure techniques

Holdout Method (Sampling)

데이터를 Training과 Test와 나눠서 모델을 생성하고 테스트하는 기법이다.
가장 일반적인 모델 생성을 위한 데이터 랜덤 샘플링 기법으로, Training과 Test를 나누는 비율은 데이터의 크기에 따라 다르다.

import numpy as np
from sklearn.model_selection import train_test_split

X, y = np.arrange(10).reshape((5, 2)), range(5)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=42)

Training - Validation - Test

TrainingValidationTest
Model BuildingModel CheckModel Evaluation

Validation Set

  • Test set은 Model이 생성 시 절대 Training Set에 포함되지 않아야 한다.
  • Test Set과 달리 Model 생성 시 Model에 성능을 평가하기 위해 사용한다.
  • Hyper Parameter Turning 시 성능 평가를 위해 Overfitting을 방지한다.
  • Training 중간에 Model의 성능을 점검한다.

K-fold cross validation

  • 학습 데이터를 K번 나눠서 Test와 Train을 실시 → Test의 평균값을 사용
  • 모델의 Parameter 튜닝, 간단한 모델의 최종 성능 측정 등 사용
from sklearn.model_selection import KFold

# 몇 번 데이터를 나눌지, shuffle을 할 지 여부
kf = KFold(s_splits=10, shuffle=True)

# index값만 넣어주게 됨
for train_index, test_index in kf.split(x):
	print("TRAIN - ", train_index[:10])
    print("TEST - ", test_index[:10])
from sklearn.model_selection import cross_validate
from sklearn.linear_model import Lasso, Ridge
from sklearn.metrics import mean_squared_error
kf = KFold(n_splits=10, shuffle=True)
lasso_regressor = Lasso(wram_start=False)
ridge_regressor = Ridge()

lasso_mse = []
ridge_mse = []

for train_index, test_index in kf.split(X):
	lasso_regressor.fit(X[train_index], y[train_index])
    ridge_regressor.fit(X[train_index], y[train_index])
    
    lasso_mse.append(mean_squared_error(y[test_index], lasso_regressor.predict(X[test_index])))
    ridge_mse.append(mean_squared_error(y[test_index], ridge_regressor.predict(X[test_index])))
    
sum(lasso_mse) / 10, sum(ridge_mse) / 10
  • cross_val_score 함수로 한번에 해결할 수 있다
  • sklearn은 pipeline 등을 위해 "High is better"로 처리하자
    • → MSE를 Negative로 변환
  • 이로 인해 RMSE를 지원하지 않는다.
from sklearn.model_selection import cross_val_score
import numpy as np

lasso_regressor = Lasso(warm_start=False)
ridge_regressor = Ridge()

lasso_scores = cross_val_score(lasso_regressor, X, y, cv=10, scoring='neg_mean_squared_error')
ridge_scores = cross_val_score(ridge_regressor, X, y, cv=10, scoring='neg_mean_squared_error')

lasso_scores

scikit learn의 정책 - 큰값일수록 정확도도 높고, rmse도 훨씬 좋다.
가장 좋은 파라미터를 자동으로 찾아주기도 한다.

  • negative로 뜨기 떄문에, 큰 값이 더 좋은 것임

Leave One Out (LOO)

잘 안쓰는 방법이기는 하다.

  • Simple cross validation -> k = data size
  • 한 번에 한 개의 데이터만 Test set으로 사용한다
    • 총 k번 iteration
from sklearn.model_selection import LeaveOneOut

test = [1, 2, 3, 4]
loo = LeaveOneOut()
for train, test in loo.split(test):
	print("%s %s % (train, test))
    
# 결과
[1 2 3] [0]
[0 2 3] [1]
[0 1 3] [2]
[0 1 2] [3]
loo = LeaveOneOut()
lasso_scores = cross_val_score(lasso_regressor, X, y, cv=loo, scoring='neg_mean_squared_error')
ridge_scores = cross_val_score(ridge_regressor, X, y, cv=loo, scoring='neg_mean_squared_error')
np.mean(lasso_scores), np.mean(ridge_scores)
  • cv : KFold, loo 등의 값을 넣어주기도 한다.

Check variation of cross validation

import matplotlib.pyplot as plt
labels=["Lasso", "RIDGE"]
plt.boxplot((lasso_scores, ridge_scores), labels=labels)
plt.grid(linestyle="--")
plt.show()

validation set for parameter turning

  • Validation set의 많은 이유 중 하나가 Hyper parameter turning
  • Number of iterations (SGD), Number of branch (Tree-based) etc.
  • Validation set의 성능으로 최적의 parameter를 찾음
    • Training Iteration을 돌릴 때도, Training Set을 먼저 돌리고, Validation Set의 차이가 벌어지기 시작하면, stop을 해준다.
  • Validation set 결과와 Training set 결과의 차이가 벌어지면 overfitting
from sklearn.linear_model import SGDRegressor
from sklearn.preprocessing import StandardScaler

std = StandardScaler()
std.fit(X)
X_scaled = std.transform(X)

eta0 = 0.01
max_iter = 100

from sklearn.model_selection import train_test_split

# test_size를 0.2로 설정함으로써
# training set은 0.8이 됨
X_train_dataset, X_test, y_train_dataset, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)

# warm_start : 초기값이 주어지는 것
# cold_start : 초기값을 아무것도 주지 않는 것
sgd_regressor = SGDRegressor(eta0=eta0, max_iter=max_iter, warm_start=True, learning_rate="constant")

rmse_val_score = []
rmse_train_score = []
model_list = []

X_train, X_val, y_train, y_val = train_test_split(X_train_dataset, y_train_dataset, test_size=0.2, random_state=42)

# kf = KFold(n_splits=100, shuffle=True)
# for train_index, test_index in kf.split(X_train_dataset):

for i in range(300):
	y_pred = sgd_regressor.predict(X_train)
    y_true = y_train
    rmse_train_score.append(rmse(y_pred, y_true))
    
    y_pred = sgd_regressor.predict(X_val)
    y_true = y_val
    rmse_val_score.append(rmse(y_pred, y_true))
    model_list.append(sgd_regressor) # 현재 상태의 모델 instance를 저장, weight 값이 저장되어 있음 
    # 여러 개의 w값을 가진 식들이 만들어짐
    # 이게 model_list에 저장되는 것
    
    # copy해서 coef에 넣음
    coef = sgd_regressor.coef_.copy()
    intercept = sgd_regressor.intercept_.copy()
    
    # 새로운 모델을 만들어줌
    # 기존에 있는 값으로 start를 함
    sgd_regressor = SGDRegressor(eta0=eta0, max_iter=max_iter, warm_start=True, learning_rate="constant")
    
    # w_0값을 init을 백 번을 돌린 값을 넣어라
    # fitting을 해라
    sgd_regressor.fit(X_train, y_train, coef_init=coef, intercept_init=intercept)
    

plt.plot(range(len)rmse_val_score)), rmse_val_score, c="G", lavel="VAL")
plt.plot(range(len(rmse_train_score)), rmse_train_score, c="r", label="TRAINING")
plt.scatter(99, rmse(y_test, sgd_regressor.predict(X_test)), s=1, label="TEST")
plt.legend()
plt.show()

Etc..

  • RepatedKFold : 중복이 포함된 K-Fold 생성
  • LeavePOut : 한 번에 P개를 뽑음( Not LOO for one data)
  • ShuffleSplit : 독립적인(중복되는) 데이터 Sampling
  • StratifiedKFold: Y값 비율에 따라 뽑음
  • GroupKFold : 그룹별로 데이터를 Sampling
    • ex. Y값에 상관없이 지역별로 데이터를 뽑는 방법
profile
Whatever I want | Interested in DFIR, Security, Infra, Cloud

0개의 댓글