보스톤 집값 예측
패키지로딩
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression, Lasso, Ridge, ElasticNet # LinearRegression: 규제가 적용되지 않은 선형회귀 모델
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error
import numpy as np
import pandas as pd
데이터 로드 및 확인
boston = pd.read_csv('./dataset/HousingData.csv')
print(boston.shape)
display(boston.head())
# MEDV (주택가격): 종속변수
boston.dropna(inplace= True)
# 독립변수와 종속변수 분리
data_x = boston.drop('MEDV', axis= 1)
data_y = boston['MEDV']
결측치가 존재하여 독립변수와 종속변수간의 길이를 맞추기위해 데이터에 있는 결측치를 제거한 후 분리하였다.
data_x.describe() # 실제 학습 전 스케일링 (표준화) 필요
기술통계치를 사용하여 확인 결과 평균값의 폭이 너무 커, 크기를 맞추기 위해 스케일링 작업이 필요한 것을 알 수 있다.
학습, 평가 데이터 분리(전에 스케일링 하기)
scaled_data = StandardScaler().fit_transform(data_x)
x_train, x_test, y_train, y_test = train_test_split(scaled_data, data_y,
test_size= 0.3, random_state= 10)
알파값 변화에 따른 회귀계수 및 상관계수 계산
알파값 = 규제의 강도를 제어하는 상수[0,Inf) 범위의 부동소수점 값을 사용할 수 있다.
alpha = 0 이면 LinearRegression 에서 사용하는 일반적인(규제를 사용하지 않는) 최소제곱법과 같아진다.
회귀계수 = w, 상관계수 = r-squared 값
다양한 알파값에 의한 모델별 회귀계수값, 상관계수값 비교 함수 생성
# 규제 : w 가 계속해서 커지는 걸 방지
def regulation_compare(alpha, model_name):
df = pd.DataFrame()
# 리스트 형태로 넘어오기 때문에
for a in alpha :
print('회귀모형:', model_name)
print('알파값:', a)
if model_name == 'Ridge' :
model = Ridge(alpha= a)
elif model_name == 'Lasso' :
model = Lasso(alpha= a)
elif model_name == 'ElasticNet' :
model = ElasticNet(alpha= a, l1_ratio= 0.5)
# 릿지와 라쏘를 같이 사용하기 때문에 비율을 정해주어야함
# 결정계수 값
model.fit(x_train, y_train)
print(f'결정계수: {model.score(x_test,y_test):.3f}') # 평가
# 추정계수 w값
# 각 컬럼별의 w값을 알아내기 위한 딕셔너리
weight = { f:w for f,w in zip(data_x.columns, model.coef_)} # 독립변수 : w 값
# 평가지표 (예측값, 정답 필요)
y_hat = model.predict(x_test) # 예측값
print(f'RMSE = {np.sqrt(mean_squared_error(y_test, y_hat)):.2f}') # 근의 값 구함
print('='* 20)
df['alpha = ' + str(a)] = pd.Series(weight) # 키값 = index, 값 = weight
return df
Lasso 회귀모델 생성 (L1 규제 적용)
# 알파값이 커질수록 제거되는 항이 많아지기 때문에 결정계수가 낮아진것이다.
# weight 값이 0인 애들이 많아지는 것 = 항이 제거되는 것
# => 13개의 독립변수들이 모두 다 중요한 역할을 하고 있다.
# => 과적합 발생여부 판단 : 교차검증
alpha = [0.07, 0.1, 0.5, 1, 3] # 알파값을 아주 작은 값부터 시작
regulation_compare(alpha,'Lasso')
회귀모형: Lasso
알파값: 0.07
결정계수: 0.796
RMSE = 3.38
====================
회귀모형: Lasso
알파값: 0.1
결정계수: 0.798
RMSE = 3.37
====================
회귀모형: Lasso
알파값: 0.5
결정계수: 0.770
RMSE = 3.59
====================
회귀모형: Lasso
알파값: 1
결정계수: 0.738
RMSE = 3.84
====================
회귀모형: Lasso
알파값: 3
결정계수: 0.585
RMSE = 4.82
====================
Ridge 릿지 회귀모델 사용 (L2 규제 적용)
# 0: 일반적인 비용함수와 동일하다.
# 알파값을 10 -> 결정계수 높, 오차 낮
# 완전히 제외되는 항이 미존재 (w에 각 비례하는 값을 빼기 때문에)
# 독립변수 간에 영향이 있다.
# L1 규제 보다는 더 높은 규제 강도를 조정
alpha = [0, 1, 5, 10, 100]
regulation_compare(alpha,'Ridge')
회귀모형: Ridge
알파값: 0
결정계수: 0.782
RMSE = 3.50
====================
회귀모형: Ridge
알파값: 1
결정계수: 0.784
RMSE = 3.48
====================
회귀모형: Ridge
알파값: 5
결정계수: 0.791
RMSE = 3.42
====================
회귀모형: Ridge
알파값: 10
결정계수: 0.796
RMSE = 3.39
====================
회귀모형: Ridge
알파값: 100
결정계수: 0.776
RMSE = 3.54
====================
ElasticNet 엘라스틱 회귀모델 생성 (L1 + L2 규제)
# 알파값을 키웠을때는 현저히 결정계수가 낮아진다.(제외되는 항이 많아진다.)
alpha = [0, 1, 5, 10, 100]
regulation_compare(alpha, 'ElasticNet')
회귀모형: ElasticNet
알파값: 0
결정계수: 0.782
RMSE = 3.50
====================
회귀모형: ElasticNet
알파값: 1
결정계수: 0.725
RMSE = 3.93
====================
회귀모형: ElasticNet
알파값: 5
결정계수: 0.406
RMSE = 5.77
====================
회귀모형: ElasticNet
알파값: 10
결정계수: 0.108
RMSE = 7.07
====================
회귀모형: ElasticNet
알파값: 100
결정계수: -0.014
RMSE = 7.54
====================
과적합 방지 방법 중에 하나이다.(모든 상황에서 과적합이 발생하는 것은 아님)
과적합 없애기 위한 방법(변수제거, 주성분분석_차원축소, 규제, 정규화.. 등) 과적합이 나오지 않는 모델을 만드는 것이 최종 목적이다.
대한민국 육군 몸무게 예측
필요한 패키지 로드
import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression, Lasso,Ridge
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_absolute_error, r2_score
데이터를 읽어오고, 결측치 있는지 확인
df = pd.read_csv('./dataset/Army-Dataset.csv')
print(df.shape)
df.head()
print(df.isna().sum())
기술통계량으로 확인하며 스케일링 여부 확인한다. (큰 차이가 없기 때문에 스케일링이 필수적이진 않다.)
df.describe() # 스케일링이 필수적이진 않음
독립변수, 종속변수 분리
( 주석 = 내가 작성한 코드 ) 관련 없는 'Seq'와 종속변수인 'Weight'는 제외하고 독립변수 x로 만든다.
# data_x = df.drop(['Seq','Weight'], axis= 1)
x = df.loc[:,'Chest':'Foot']
display(x.head())
# data_y = df['Weight']
y = df['Weight']
독립변수간 상관관계 확인
import seaborn as sns
import matplotlib.pyplot as plt
sns.pairplot(x)
plt.show() # 상관관계가 없음.
체크 한 번 더
x.corr() # 다중공선성 관계를 가지는 변수는 없다.
데이터 스케일링(여기서는 데이터를 표준화한 후 사용)
from sklearn.preprocessing import StandardScaler
# 스케일링한 독립변수 가지고 본다면 새로운 데이터도 스케일링 해야함
scaler = StandardScaler().fit(x) # 스케일링 필요한 데이터를 가져오고 그에 대한 학습을 함
scaled_data = scaler.transform(x) # 데이터 변환
fit_transform 을 동시에 하게 되면 새로운 데이터를 넣을때 변환을 시킬 수 없기 때문에
나중에 새로운 데이터가 들어와도 똑같은 기준으로 fit() 하기 위해 두 함수를 분리시켜 적어놓는다.
학습, 평가 데이터 분리
x_train,x_test,y_train,y_test = train_test_split(scaled_data, y,
train_size= 0.8, random_state= 10) # random_state : 필수 아님
' random_state '는 현재 동일한 데이터를 넣고 결과를 보기위해 작성한 것이므로 필수가 아니다.
모델 생성 및 학습
규제가 없는 방식, L1 규제, L2 규제 3가지 방식으로 진행하여 본다.
ridge_alpha = 10
lasso_alpha = 1
# 모형 생성
linear = LinearRegression()
ridge = Ridge(alpha= ridge_alpha)
lasso = Lasso(alpha=lasso_alpha)
# 학습
linear.fit(x_train,y_train)
ridge.fit(x_train,y_train)
lasso.fit(x_train,y_train)
예측 및 평가
# 예측
linear_y_hat = linear.predict(x_test)
ridge_y_hat = ridge.predict(x_test)
lasso_y_hat = lasso.predict(x_test)
linear_r2 = r2_score(y_test,linear_y_hat) # 정답과 예측값을 넣음 <> model.score() = 평가데이터를 넣음(안에서 예측을 다시 한 번 함)
ridge_r2 = r2_score(y_test,ridge_y_hat)
lasso_r2 = r2_score(y_test,lasso_y_hat)
# 정답은 같음
# 평가 결과값
linear_mae = mean_absolute_error(y_test, linear_y_hat)
ridge_mae = mean_absolute_error(y_test, ridge_y_hat)
lasso_mae = mean_absolute_error(y_test, lasso_y_hat)
print(f'R2 score - Linear : {linear_r2:.2f}, Ridge : {ridge_r2:.2f}, Lasso : {lasso_r2:.2f}')
print(f'MAE score - Linear : {linear_mae:.2f}, Ridge : {ridge_mae:.2f}, Lasso : {lasso_mae:.2f}')
# 규제를 쓰나 안쓰나 차이가 없다.
R2 score - Linear : 0.89, Ridge : 0.89, Lasso : 0.88
MAE score - Linear : 3.54, Ridge : 3.54, Lasso : 3.68
Linear() 와의 비교를 통해 규제 여부는 관계없다는 것을 알았다.
새로운 값 넣어보기
1차원 -> 학습: 2차원으로 들어가야함 (or 이중리스트로 넣어도 된다.)
linear.predict(new_data)
# 학습데이터와는 단위가 다르기 때문에 스케일링 필요 (fit() 과 transform() 을 구분하여 작성한 이유이다.)
x.iloc[0] # 0번째 행 데이터
new_data = np.array([90, 178, 80, 55, 26.5]).reshape(1,5)
# linear.predict(new_data) # 학습데이터와는 단위가 다름 -> 스케일링 필요
linear.predict(scaler.transform(new_data))
'국비 교육 > 머신러닝, 딥러닝' 카테고리의 다른 글
[머신러닝] 지도학습 알고리즘 - 분류분석 : 로지스틱 회귀분석 (0) | 2023.11.20 |
---|---|
[머신러닝] 회귀분석 - 교차검증 (0) | 2023.11.20 |
[머신러닝] 회귀분석 - 다중공선성, L1 규제 ,L2규제 (0) | 2023.11.20 |
[머신러닝] 회귀분석 - 데이터 전처리(원핫 인코딩, 라벨 인코딩, 데이터 스케일링) (0) | 2023.11.20 |