특성공학은 과제에 적합한 특성을 만들어 내는 과정입니다. 이 프로세스는 실무 현장에서 가장 많은 시간이 소요되는 작업 중 하나입니다. 이제 사이킷런의 SelectKBest를 사용해서 회귀모델에 중요한 특성을 선택해 보겠습니다.
1. Feature Engineering을 통해 1차적으로 데이터 정리
def engineer_features(X):
# pandas.DataFrame.copy()
X = X.copy()
## 욕실 갯수을 정수형으로 처리합니다.
X['bathrooms'] = X['bathrooms'].round(0).astype(int)
## 총 방 수를 합하여 rooms로 합쳐 봅시다.
X['rooms'] = X['bedrooms'] + X['bathrooms']
## 사용하지 않을 특성을 삭제합니다.
X = X.drop(['id', 'date', 'waterfront'],axis=1)
return X
train = engineer_features(train)
test = engineer_features(test)
2. 선택 가능한 특성들의 가지수를 계산
from math import factorial
n = len(train.columns)
def n_choose_k(n, k):
return factorial(n)/(factorial(k)*factorial(n-k))
combinations = sum(n_choose_k(n,k) for k in range(1,n+1))
combinations
# print(f'{combinations:,.0f}')
524287.0
3. SelectKBest를 사용해 가장 효과적인 특성 K개를 고르기
# target(Price)와 가장 correlated 된 features 를 k개 고르는 것이 목표입니다.
## f_regresison, SelectKBest
from sklearn.feature_selection import f_regression, SelectKBest
## selctor 정의합니다.
selector = SelectKBest(score_func=f_regression, k=10)
## 학습데이터에 fit_transform
X_train_selected = selector.fit_transform(X_train, y_train)
## 테스트 데이터는 transform
X_test_selected = selector.transform(X_test)
X_train_selected.shape, X_test_selected.shape
4. 선택된 특성 확인
all_names = X_train.columns
## selector.get_support() 선택된 feature들을 mask처리 해주기
selected_mask = selector.get_support()
## 선택된 특성들
selected_names = all_names[selected_mask]
## 선택되지 않은 특성들 (~ 표시는 not임)
unselected_names = all_names[~selected_mask]
print('Selected names: ', selected_names)
print('Unselected names: ', unselected_names)
Selected names: Index(['bedrooms', 'bathrooms', 'sqft_living', 'view', 'grade', 'sqft_above',
'sqft_basement', 'lat', 'sqft_living15', 'rooms'],
dtype='object')
Unselected names: Index(['sqft_lot', 'floors', 'condition', 'yr_built', 'yr_renovated',
'zipcode', 'long', 'sqft_lot15'],
dtype='object')
5. 특성의 수 k 를 어떻게 결정하는게 좋을지 위의 내용을 하나의 함수에 정의하고 시각화까지
# features를 몇 개 선책하는 것이 좋은지 알아 봅시다.
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error, r2_score
training = []
testing = []
ks = range(1, len(X_train.columns)+1) # 0부터 시작하기 때문에 +1을 해준다
# 1 부터 특성 수 만큼 사용한 모델을 만들어서 MAE 값을 비교 합니다.
for k in range(1, len(X_train.columns)+ 1):
print(f'{k} features')
selector = SelectKBest(score_func=f_regression, k=k)
X_train_selected = selector.fit_transform(X_train, y_train)
X_test_selected = selector.transform(X_test)
all_names = X_train.columns
selected_mask = selector.get_support()
selected_names = all_names[selected_mask]
print('Selected names: ', selected_names)
model = LinearRegression()
model.fit(X_train_selected, y_train)
y_pred = model.predict(X_train_selected)
mae = mean_absolute_error(y_train, y_pred)
training.append(mae)
y_pred = model.predict(X_test_selected)
mae = mean_absolute_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
testing.append(mae)
print(f'Test MAE: ${mae:,.0f}')
print(f'Test R2: {r2} \n')
plt.plot(ks, training, label='Training Score', color='b')
plt.plot(ks, testing, label='Testing Score', color='g')
plt.ylabel("MAE ($)")
plt.xlabel("Number of Features")
plt.title('Validation Curve')
plt.legend()
plt.show()