본문 바로가기
기본소양/CODE

1. Linear Regression CODE [3] How to select Variables

by EXUPERY 2021. 2. 3.
반응형

How to select Variables

Linear Regression CODE 

 

 


 

0. EDA

항상 EDA와 도메인지식을 통해서 이상치와 결측을 제거하고 Feature Engineering을 통해 특성을 잘 조정해야한다. 모델의 성능을 높이는 데 가장 중요한 것은 다른데 있지 않다.

 

1. KBest

## K Best 
from sklearn.feature_selection import SelectKBest, f_regression
selector = SelectKBest(score_func=f_regression, k=20) # Instance 생성
X_train_K = selector.fit_transform(X_train, y_train) # train 적용
X_test_K = selector.transform(X_test) # test 적용
print(X_train_K.shape, X_test_K.shape) # 결과

## 선택된 feature확인
all_names = X_train.columns 
selected_mask = selector.get_support()

selected_names = all_names[selected_mask]
unselected_names = all_names[~selected_mask] 

print('Selected names: ', selected_names)
print('Unselected names: ', unselected_names)

## K에 따른 RMSE, R2, R2 adj
feature_com = []
for i in range(1,30):
  # feature개수 적용
  selector = SelectKBest(score_func=f_regression, k=i)
  X_train_BEST = selector.fit_transform(X_train, y_train)
  X_test_BEST = selector.transform(X_test)
  # Poly의 degree적용
  poly_features = PolynomialFeatures(degree=3)
  X_train_BEST = poly_features.fit_transform(X_train_BEST)
  X_test_BEST = poly_features.fit_transform(X_test_BEST)
  # Lambda값 적용
  ridge = Ridge(alpha=0.1)
  ridge.fit(X_train_BEST,y_train)
  # 오차값산출
  y_test_pred = ridge.predict(X_test_BEST)
  mse = mean_squared_error(y_test, y_test_pred)
  rmse = np.sqrt(mse)
  mae = mean_absolute_error(y_test, y_test_pred)
  r2 = r2_score(y_test, y_test_pred)
  r2_adj = 1 - (1-r2)*(len(y_test)-1)/(len(y_test)-X_test_BEST.shape[1]-1)
  # 리스트에 저장
  feature_com.append([i, rmse, r2, r2_adj])
  
# in DataFrame
df_feature = pd.DataFrame(feature_com)
df_feature.columns = ['Num of K', "RMSE", "R2","R2_adj"]
df_feature.sort_values('R2_adj',ascending=False).head()

## Visualization
# K에 따른 RMSE
plt.figure(figsize=(15,5))
sns.barplot(x='Num of K',y='RMSE',data=df_feature)
plt.grid()

# K에 따른 R2, R2adj
plt.figure(figsize=(15,5))
sns.lineplot(x='Num of K',y='R2',data=df_feature,label='R2')
sns.lineplot(x='Num of K',y='R2_adj',data=df_feature, label='R2_adj')
plt.grid()
plt.show()
plt.show()

 

 

2. 전진선택법

## 전진선택법 알고리즘
import statsmodels.api as sm
df_2 = df_1.drop(columns='date').copy()
y = df_2['price'] # 타겟
df_2 = df_2.drop(columns='price').copy()
variables = df_2.columns[:].tolist() # 변수 리스트

selected_variables = [] ## 선택된 변수들
sl_enter = 0.01 # 유의수준
 
sv_per_step = [] # 각 스텝별로 선택된 변수들
adjusted_r_squared = [] # 각 스텝별 수정된 결정계수
steps = [] # 스텝
step = 0
while len(variables) > 0:
    remainder = list(set(variables) - set(selected_variables))
    pval = pd.Series(index=remainder) ## 변수의 p-value
    # 기존에 포함된 변수와 새로운 변수 하나씩 돌아가면서 만들고 비교합니다.
    for col in remainder: 
        X = df_2[selected_variables+[col]]
        X = sm.add_constant(X)
        model_OLS = sm.OLS(y,X.astype(float)).fit()
        pval[col] = model_OLS.pvalues[col]
 
    min_pval = pval.min()
    if min_pval < sl_enter: # 최소 p-value 값이 기준 값보다 작으면 포함시킵니다.
        selected_variables.append(pval.idxmin())
        
        step += 1
        steps.append(step)
        adj_r_squared = sm.OLS(y,sm.add_constant(df_2[selected_variables].astype(float))).fit().rsquared_adj
        adjusted_r_squared.append(adj_r_squared)
        sv_per_step.append(selected_variables.copy())
    else:
        break
        
print(selected_variables) # 선택된 변수보기

## 시각화
fig = plt.figure(figsize=(25,5))
fig.set_facecolor('white')
 
font_size = 15
plt.xticks(steps,[f'step {s}\n'+'\n'.join(sv_per_step[i]) for i,s in enumerate(steps)], fontsize=12)
plt.plot(steps,adjusted_r_squared, marker='o')
    
plt.ylabel('Adjusted R Squared',fontsize=font_size)
plt.grid(True)
plt.show()

 

3. 후진선택법

## 후진 제거법. 전진선택법과 코드는 거의 비슷합니다.
import statsmodels.api as sm
df_2 = df_1.drop(columns='date').copy()
y = df_2['price'] # 타겟
df_2 = df_2.drop(columns='price').copy()
variables = df_2.columns[:].tolist() # 변수 리스트
 
selected_variables = variables # 이번에는 변수를 다 넣고 시작합니다.
sl_remove = 0.01
 
sv_per_step = [] # 각 스텝별로 선택된 변수들 넣을 빈 리스트
adjusted_r_squared = [] # 각 스텝별로 수정된 결정계수
steps = [] # 스텝
step = 0
while len(variables) > 0:
    X = sm.add_constant(df[selected_variables])
    p_vals = sm.OLS(y,X).fit().pvalues[1:] # 절편항의 p-value는 의미가 없으니 빼고
    max_pval = p_vals.max() # 최대 p-value
    if max_pval >= sl_remove: # 최대 p-value값이 기준값보다 크거나 같으면 제외합니다
        remove_variable = p_vals.idxmax()
        selected_variables.remove(remove_variable)
 
        step += 1
        steps.append(step)
        adj_r_squared = sm.OLS(y,sm.add_constant(df_2[selected_variables].astype(float))).fit().rsquared_adj
        adjusted_r_squared.append(adj_r_squared)
        sv_per_step.append(selected_variables.copy())
    else:
        break
        
print(selected_variables) # 선택된 변수보기

## 시각화
fig = plt.figure(figsize=(10,3))
fig.set_facecolor('white')
 
font_size = 15
plt.xticks(steps,[f'step {s}\n'+'\n'.join(sv_per_step[i]) for i,s in enumerate(steps)], fontsize=12)
plt.plot(steps,adjusted_r_squared, marker='o')
    
plt.ylabel('Adjusted R Squared',fontsize=font_size)
plt.grid(True)
plt.show()

 

4. 단계별 선택법

## 단계별 선택법
import statsmodels.api as sm
df_2 = df_1.drop(columns='date').copy()
y = df_2['price'] # 타겟
df_2 = df_2.drop(columns='price').copy()
variables = df_2.columns[:].tolist() # 변수 리스트
selected_variables =[]
sl_enter = 0.05
sl_remove = 0.05

sv_per_step = [] # 각 스텝별로 선택된 변수들
adjusted_r_squared = [] # 각 스텝별 수정된 결정계수
steps = [] # 스텝
step = 0
while len(variables) > 0:
    remainder = list(set(variables) - set(selected_variables))
    pval = pd.Series(index=remainder) # 변수의 p-value
    # 기존에 포함된 변수와 새로운 변수 하나씩 돌아가면서 
    # 선형 모형을 적합한다.
    for col in remainder: 
        X = df[selected_variables+[col]]
        X = sm.add_constant(X)
        model_OLS = sm.OLS(y,X).fit()
        pval[col] = model_OLS.pvalues[col]
 
    min_pval = pval.min()
    if min_pval < sl_enter: # 최소 p-value 값이 기준 값보다 작으면 포함
        selected_variables.append(pval.idxmin())
        # 선택된 변수들에대해 어떤 변수를 제거할지 고릅니다.
        while len(selected_variables) > 0:
            selected_X = df[selected_variables]
            selected_X = sm.add_constant(selected_X)
            selected_pval = sm.OLS(y,selected_X).fit().pvalues[1:] ## 절편항의 p-value는 빼고
            max_pval = selected_pval.max()
            if max_pval >= sl_remove: ## 최대 p-value값이 기준값보다 크거나 같으면 제외
                remove_variable = selected_pval.idxmax()
                selected_variables.remove(remove_variable)
            else:
                break
        
        step += 1
        steps.append(step)
        adj_r_squared = sm.OLS(y,sm.add_constant(df[selected_variables])).fit().rsquared_adj
        adjusted_r_squared.append(adj_r_squared)
        sv_per_step.append(selected_variables.copy())
    else:
        break
        

print(selected_variables)

## 시각화
fig = plt.figure(figsize=(20,3))
fig.set_facecolor('white')
 
font_size = 15
plt.xticks(steps,[f'step {s}\n'+'\n'.join(sv_per_step[i]) for i,s in enumerate(steps)], fontsize=12)
plt.plot(steps,adjusted_r_squared, marker='o')
    
plt.ylabel('Adjusted R Squared',fontsize=font_size)
plt.grid(True)
plt.show()

 

 

반응형

댓글