01 회귀 적합 과제
-01 선형 회귀
-02 기타 회귀
02 선형회귀 모형의 패널티 모형
-01 릿지
-02 라쏘
-03 엘라스틱넷
03 타겟변수 변환에 따른 회귀분석 성능 비교
04 부스팅 이론
01 회귀 적합 과제
-01 선형 회귀
> 변수 선택 중요
> 종속변수 분포에 따라 변수 변환 필수
> 이상치 민감
> 모형 가정 확인 필수
> 유의성 검정 결과 확인 가능 (여러 변수가 같이 학습될 때 각 회귀계수의 유의성 정도)
-02 기타 회귀
> 모델에 따라 변수 선택이 불필요할 수 있음 (트리기반)
> 대체로 종속변수 분포에 따라 변환 필수 (트리기반은 효과가 거의 없음)
> 모델에 따라 이상치 민감 여부 다름
> 통계적 모형 가정 불필요
> 유의성 검정 결과 확인 불가
02 선형회귀 모형의 패널티 모형
-01 릿지
> L2 규제 (정규화)
> 회귀계수의 제곱의 합이 최소화 시키는 방식으로 패널티 부여
> 회귀계수를 0에 가깝게 작게 만드는 기법 (0으로 만들지는 않는다.)
-02 라쏘
> L1 규제 (정규화)
> 회귀계수의 절댓값을 최소화 시키는 방식으로 패널티 부여
> 회귀계수를 0으로 만들기도 함 -> 중요하지 않은 변수 제거 효과
-03 엘라스틱넷
> 릿지 + 라쏘 혼합 모형 (혼합정도의 기본은 0.5, 조절 가능)
[ 예제 - 보스턴 가격셋의 패널티 회귀 모형 적용 ]
# 1. 데이터 로딩
import pandas as pd
df = pd.read_csv('boston.csv')
y = df['medv']
X = df.drop(columns = 'medv')
# 2. 데이터 분리
from sklearn.model_selection import train_test_split
train_x, test_x, train_y, test_y = train_test_split(X, y, random_state = 0)
# 3. 모델링
# 1) 기본 회귀
from sklearn.linear_model import LinearRegression, Lasso, Ridge, ElasticNet
m_lr = LinearRegression()
m_lr.fit(train_x, train_y)
m_lr.score(train_x, train_y)
m_lr.score(train_x, train_y)
Out[10]: 0.7697699488741149
m_lr.score(test_x, test_y)
m_lr.score(test_x, test_y)
Out[11]: 0.6354638433202121
m_lr.coef_
m_lr.coef_
Out[12]:
array([-1.17735289e-01, 4.40174969e-02, -5.76814314e-03, 2.39341594e+00,
-1.55894211e+01, 3.76896770e+00, -7.03517828e-03, -1.43495641e+00,
2.40081086e-01, -1.12972810e-02, -9.85546732e-01, 8.44443453e-03,
-4.99116797e-01])
# 2) 릿지
m_rid1 = Ridge(alpha = 1)
m_rid1.fit(train_x, train_y)
m_rid1.score(train_x, train_y)
m_rid1.score(train_x, train_y)
Out[15]: 0.7678858330771392
m_rid1.score(test_x, test_y)
m_rid1.score(test_x, test_y)
Out[16]: 0.6266182204613864
m_rid1.coef_
m_rid1.coef_
Out[17]:
array([-0.11478591, 0.04541838, -0.03540308, 2.30329133, -8.12744537,
3.80634143, -0.01428219, -1.33693873, 0.21674809, -0.01175498,
-0.90393728, 0.00881273, -0.50742473])
m_rid10 = Ridge(alpha = 10)
m_rid10.fit(train_x, train_y)
m_rid10.score(train_x, train_y)
m_rid10.score(train_x, train_y)
Out[25]: 0.7623745182677772
m_rid10.score(test_x, test_y)
m_rid10.score(test_x, test_y)
Out[26]: 0.6132773047207001
m_rid10.coef_
m_rid10.coef_
Out[27]:
array([-0.11235372, 0.04795757, -0.06100708, 1.6862423 , -1.53962161,
3.5557743 , -0.0182528 , -1.25334748, 0.20721315, -0.01262432,
-0.84731899, 0.00908357, -0.53553959])
m_rid100 = Ridge(alpha = 100)
m_rid100.fit(train_x, train_y)
m_rid100.score(train_x, train_y)
m_rid100.score(train_x, train_y)
Out[30]: 0.7472099719179607
m_rid100.score(test_x, test_y)
m_rid100.score(test_x, test_y)
Out[31]: 0.5927292801276112
m_rid100.coef_
m_rid100.coef_
Out[32]:
array([-0.10640308, 0.05390958, -0.06802258, 0.48186878, -0.16308604,
1.98502636, -0.00434631, -1.15482636, 0.24447914, -0.01437744,
-0.87914571, 0.00835041, -0.64793963])
# alpha 변화에 따른 회귀계수 크기 비교
import matplotlib.pyplot as plt
plt.scatter(range(1,X.shape[1]+1), m_rid1.coef_, marker = '^', label = 'alpha:1')
plt.scatter(range(1,X.shape[1]+1), m_rid10.coef_, marker = 'v', label = 'alpha:10')
plt.scatter(range(1,X.shape[1]+1), m_rid100.coef_, marker = '*',label = 'alpha:100')
plt.legend()
plt.title('Lasso')

03 타겟변수 변환에 따른 회귀분석 성능 비교
- 회귀 적합의 경우 타겟변수가 정규분포를 따르지 않는다면 정확한 타겟값의 예측에 있어 값이 매우 크거나 작은 쪽에 대한 예측이 어려울 수 있음
- 따라서 타겟변수의 분포를 확인하고 그에 맞는 변환을 한 후에 모델링 할 것을 권고
# 타겟변수 변환
1) 로그 변환
> 양의 왜도 (우측 꼬리가 긴)를 갖는 분포
> 가격, 소득, 매출 등
> 가장 범용적
2) 제곱근 변환
> 약한 양의 왜도를 갖는 분포
3) Box - cox 변환
> 왜도 방향 / 크기가 불확실할 때 데이터의 분포를 보고 최적의 변환을 찾아주는 기법
> y > 0 일때만 변환 가능
4) Yeo - johnson 변환
> Box - cox와 유사
> y <= 일때도 변환 가능
[ 예제 - 캘리포니아 주택가격 타겟변수 변환 성능 비교 ]
# 1. 데이터 로딩
df = pd.read_csv('california_housing.csv')
df.head()
Out[84]:
area rooms age distance floor price
0 97.417854 6 4.006200 1.493812 8 209744.212453
1 81.543392 4 10.868704 3.277197 23 148487.351297
2 101.192213 2 32.638232 24.151560 14 46385.295687
3 123.075746 6 15.132624 5.802179 24 254573.690019
4 79.146166 1 3.535879 9.205487 29 64642.473712
y = df['price']
X = df.drop(columns='price')
# 타겟변수 분포 확인
import matplotlib.pyplot as plt
plt.hist(y)

# 왜도
y.skew()
y.skew()
Out[87]: np.float64(1.607332325696819)
# 2. 타겟변수 변환
# 1) 로그 변환
(y <= 0).sum()
import numpy as np
logy = np.log(y)
logy
Out[91]:
0 12.253644
1 11.908255
2 10.744738
3 12.447346
4 11.076627
2995 12.329869
2996 11.208038
2997 11.455558
2998 11.947248
2999 11.499284
Name: price, Length: 3000, dtype: float64
# 2) box - cox 변환
from sklearn.preprocessing import PowerTransformer
pt = PowerTransformer('box-cox')
boxcox_y = pd.Series(pt.fit_transform(y.values.reshape(-1,1)).flatten(), name='price')
boxcox_y
Out[95]:
0 0.996668
1 0.351573
2 -1.651019
3 1.369238
4 -1.105469
2995 1.142342
2996 -0.883938
2997 -0.457944
2998 0.423190
2999 -0.381487
Name: price, Length: 3000, dtype: float64
# 변수변환 전/후 비교
plt, ax = plt.subplots(1,3)
ax[0].hist(y)
ax[0].set_title('price')
ax[1].hist(log_y)
ax[1].set_title('log(price)')
ax[2].hist(boxcox_y)
ax[2].set_title('boxcox')

# 3. 모델링
from sklearn.model_selection import train_test_split
train_x, test_x, train_y, test_y, train_logy, test_logy, train_boxy, test_boxy = train_test_split(X, y, log_y, boxcox_y, random_state=0)
# 선형회귀
from sklearn.linear_model import LinearRegression
print('='*50)
print('선형회귀')
print('='*50)
m_lr = LinearRegression()
m_lr.fit(train_x, train_y)
print('선형회귀 train R2:', m_lr.score(train_x, train_y))
print('선형회귀 test R2:', m_lr.score(test_x, test_y))
m_lr = LinearRegression()
m_lr.fit(train_x, train_logy)
print('선형회귀 로그변환 train R2:', m_lr.score(train_x, train_logy))
print('선형회귀 로그변환 test R2:', m_lr.score(test_x, test_logy))
m_lr = LinearRegression()
m_lr.fit(train_x, train_boxy)
print('선형회귀 박스콕스변환 train R2:', m_lr.score(train_x, train_boxy))
print('선형회귀 박스콕스변환 test R2:', m_lr.score(test_x, test_boxy))
# 랜덤포레스트 회귀
from sklearn.ensemble import RandomForestRegressor
print('='*50)
print('랜덤포레스트 회귀')
print('='*50)
m_rf = RandomForestRegressor(random_state=0)
m_rf.fit(train_x, train_y)
print('랜덤포레스트 train R2:', m_rf.score(train_x, train_y))
print('랜덤포레스트 test R2:', m_rf.score(test_x, test_y))
m_rf = RandomForestRegressor(random_state=0)
m_rf.fit(train_x, train_logy)
print('랜덤포레스트 로그변환 train R2:', m_rf.score(train_x, train_logy))
print('랜덤포레스트 로그변환 test R2:', m_rf.score(test_x, test_logy))
m_rf = RandomForestRegressor(random_state=0)
m_rf.fit(train_x, train_boxy)
print('랜덤포레스트 박스콕스변환 train R2:', m_rf.score(train_x, train_boxy))
print('랜덤포레스트 박스콕스변환 test R2:', m_rf.score(test_x, test_boxy))
==================================================
선형회귀
==================================================
선형회귀 train R2: 0.6008093142803821
선형회귀 test R2: 0.6157862356015968
선형회귀 로그변환 train R2: 0.7032010794298529
선형회귀 로그변환 test R2: 0.7252494003085954
선형회귀 박스콕스변환 train R2: 0.6999664233307044
선형회귀 박스콕스변환 test R2: 0.7230477083996629
==================================================
랜덤포레스트 회귀
==================================================
랜덤포레스트 train R2: 0.9463112279027306
랜덤포레스트 test R2: 0.6257234117755655
랜덤포레스트 로그변환 train R2: 0.9520188441741153
랜덤포레스트 로그변환 test R2: 0.677691874194297
랜덤포레스트 박스콕스변환 train R2: 0.9516487656743826
랜덤포레스트 박스콕스변환 test R2: 0.678159839161238
# 4. 교차검증
from sklearn.model_selection import KFold, StratifiedKFold # 데이터를 나누는 과정
from sklearn.model_selection import cross_val_score, cross_validate # 평가점수를 계산하는 과정
* KFold : 분류, 회귀 모두 가능
* StratifiedKFold : 분류 전용 (클래스별 비율 유지)
* cross_val_score : test score만 확인 가능, 점수 하나만 확인 가능
* cross_validate : train/tests score 둘 다 확인 가능, 여러 평가점수 동시 리턴 가능
CV = KFold(n_splits = 4, shuffle = True, random_state = 0)
m_lr = LinearRegression()
cv_y = cross_validate(m_lr, X, y, cv = CV, scoring = 'r2', return_train_score = True)
cv_logy = cross_validate(m_lr, X, log_y, cv = CV, scoring = 'r2', return_train_score = True)
cv_boxy = cross_validate(m_lr, X, boxcox_y, cv = CV, scoring = 'r2', return_train_score = True)
print('선형회귀 교차검증 train r2(y, log, boxcox) : ', cv_y['train_score'].mean(), cv_logy['train_score'].mean(), cv_boxy['train_score'].mean())
print('선형회귀 교차검증 test r2(y, log, boxcox) : ', cv_y['test_score'].mean(), cv_logy['test_score'].mean(), cv_boxy['test_score'].mean())
print('선형회귀 교차검증 train r2(y, log, boxcox) : ', cv_y['train_score'].mean(), cv_logy['train_score'].mean(), cv_boxy['train_score'].mean())
선형회귀 교차검증 train r2(y, log, boxcox) : 0.6052802979303791 0.709343707840548 0.7063774388437112
print('선형회귀 교차검증 test r2(y, log, boxcox) : ', cv_y['test_score'].mean(), cv_logy['test_score'].mean(), cv_boxy['test_score'].mean())
선형회귀 교차검증 test r2(y, log, boxcox) : 0.6006289412355167 0.7063819706011178 0.7033957435908458
m_rf = RandomForestRegressor(random_state = 0)
cv_y = cross_validate(m_rf, X, y, cv = CV, scoring = 'r2', return_train_score = True)
cv_logy = cross_validate(m_rf, X, log_y, cv = CV, scoring = 'r2', return_train_score = True)
cv_boxy = cross_validate(m_rf, X, boxcox_y, cv = CV, scoring = 'r2', return_train_score = True)
print('RF 교차검증 train r2(y, log, boxcox) : ', cv_y['train_score'].mean(), cv_logy['train_score'].mean(), cv_boxy['train_score'].mean())
print('RF 교차검증 test r2(y, log, boxcox) : ', cv_y['test_score'].mean(), cv_logy['test_score'].mean(), cv_boxy['test_score'].mean())
m_rf = RandomForestRegressor(random_state = 0)
cv_y = cross_validate(m_rf, X, y, cv = CV, scoring = 'r2', return_train_score = True)
cv_logy = cross_validate(m_rf, X, log_y, cv = CV, scoring = 'r2', return_train_score = True)
cv_boxy = cross_validate(m_rf, X, boxcox_y, cv = CV, scoring = 'r2', return_train_score = True)
print('RF 교차검증 train r2(y, log, boxcox) : ', cv_y['train_score'].mean(), cv_logy['train_score'].mean(), cv_boxy['train_score'].mean())
print('RF 교차검증 test r2(y, log, boxcox) : ', cv_y['test_score'].mean(), cv_logy['test_score'].mean(), cv_boxy['test_score'].mean())
RF 교차검증 train r2(y, log, boxcox) : 0.9460365067183593 0.952886534908141 0.9527860473243714
RF 교차검증 test r2(y, log, boxcox) : 0.6250354606127606 0.6628644103455325 0.6605610731283211
# 5. 최종모형 선택
m_lr1 = LinearRegression()
m_lr1.fit(X, log_y)
m_lr2 = LinearRegression()
m_lr2.fit(X, boxcox_y)
# 6. 최종예측 (역변환)
pre1 = m_lr1.predict(X) # 로그변환 후 y값
np.exp(pre1) # 실제 예측값
np.exp(pre1) # 실제 예측값
Out[190]:
array([235577.51007947, 145358.91793 , 43511.53071406, ...,
89998.02651896, 174820.88304467, 114187.90202547], shape=(3000,))
pre2 = m_lr2.predict(X) # 박스콕스 변환 후 y값
pt.inverse_transform(pre2)
ValueError: Expected 2D array, got 1D array instead:
array=[ 1.1959428 0.33732452 -1.78071172 ... -0.52709427 0.66227755
-0.10217748].
Reshape your data either using array.reshape(-1, 1) if your data has a single feature or array.reshape(1, -1) if it contains a single sample.
pt.inverse_transform(pre2.reshape(-1,1)).flatten()
pt.inverse_transform(pre2.reshape(-1,1)).flatten()
Out[191]:
array([232758.66016883, 147336.94821063, 42789.0585501 , ...,
90747.04933018, 175647.54422035, 115528.18675939], shape=(3000,))
# 제출
# <result.csv>
# pred
# 10000.123
# 12232.323
pd.DataFrame({'pred':reslut}).to_csv('result.csv', index = False)
04 부스팅 이론
- 이전 트리를 보완해서 점차 예측력이 강한 모델을 만들어 내는 방식
- 각 트리마다 독립적이지 않고, 1번 트리가 끝날 때까지 기다렸다가 2번 트리가 시작되는 방식
- 따라서 병렬 처리 효과는 없음
-01 Gradient Boosting Tree
> 오차를 최소화 시키는 방향으로 모델을 진화시키는 방식
> 손실함수 (loss) 를 사전에 정의해주어야 하며, 얼마나 손실이 일어났는지를 확인해가며 모델이 진화
> 따라서 오차는 손실함수의 정의에 따라 달라짐
> 손실함수 : MSE(회귀), cross entropy (분류)
-02 Ada Boosting Tree
> 이전 트리의 예측 실패 데이터에 가중치를 부여하여 다음 트리에서 더 잘 분류 / 예측할 수 있도록 진화시키는 방식
> 회귀일때는 오차의 크기에 비례하게 가중치를 조절 (오차가 큰 관측치에 더 큰 가중치 부여)
[ 연습문제 - 캘리포니아 주택가격 예측에 대한 성능 비교 ]
# 1. 데이터 로딩
df = pd.read_csv('boston.csv')
y = df['medv']
X = df.drop(columns = 'medv')
# 2.데이터 나누기
from sklearn.model_selection import train_test_split
train_x, test_x, train_y, test_y = train_test_split(X, y, random_state = 0)
# 3. 모델링
from sklearn.linear_model import LinearRegression
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor, AdaBoostRegressor
# 1) LinearRegression
m1 = LinearRegression()
m1.fit(train_x, train_y)
m1.score(train_x, train_y) # 0.7698
m1.score(test_x, test_y) # 0.6355
# 2) RandomForestRegressor
m2 = RandomForestRegressor(random_state = 0)
m2.fit(train_x, train_y)
m2.score(train_x, train_y) # 0.9824
m2.score(test_x, test_y) # 0.7953
# 3) GradientBoostingRegressor
m3 = GradientBoostingRegressor(random_state = 0)
m3.fit(train_x, train_y)
m3.score(train_x, train_y) # 0.9830
m3.score(test_x, test_y) # 0.8147
# 4) AdaBoostRegressor
m4 = AdaBoostRegressor(random_state = 0)
m4.fit(train_x, train_y)
m4.score(train_x, train_y) # 0.9276
m4.score(test_x, test_y) # 0.6846
'아이티윌_데이터 분석 55기 > 강의내용 필기_분석(Python)' 카테고리의 다른 글
| #13 13일차_웹크롤링 (0) | 2026.07.08 |
|---|---|
| #12 12일차_군집분석, 연관분석 (0) | 2026.06.19 |
| #8 클래스 불균등 처리 (0) | 2026.06.15 |
| #7 7일차_독립성 검정, 적합도 검정, 클래스 불균등 처리 (0) | 2026.06.11 |
| #6 교호작용 및 효과 검증 (0) | 2026.06.09 |