외부의 영향을 처리하는 방법
1.제거 -> 잘 안씀
2. 상쇄, 완화 = Randomization (무작위화)
-> 독립변수, 입력변수
-속성에 따라
범주형
수치형
-인과관계에 따라
독립변수 : 다른 변수에 영향을 받지 않고 종속변수에 영향을 줌
종속변수 : 독립변수로부터 영향을 받음
-머신러닝에서
입력 : 변수(Feature), 속성(Attribute), 예측변수(Predictor), 차원(Dimension), 관측치(Observation), 독립변수(Independent Variable)
출력 : 라벨(Label), 클래스(Class), 목푯값(Target), 반응(Response), 종속변수(Dependent Variable)
※ 독립변수 종속변수 간
X -> Y : 인과 관계
X <-> Y : 상관 관계
인과관계가 되기위한 조건
1. X,Y가 상관 관계이어야 함
2. 시간적 선후관계가 있어야함
3. 비허위적(non-spurious) 관계 (= 중간에 낀 다른 변수가 있어서 영향을 주지 않는 관계, ex)연봉과 혈압의 관계 : 실질적으로 연관이 없지만 상관관계가 있는것으로 보임)
피쳐들 사이에 내재한 특성이나 관계를 분석하여 이들을 잘 표현할 수 있는 새로운 선형 혹은 비선형 결합 변수를 만들어 데이터를 줄이는 방법
고차원의 원본 피쳐 공간을 저차원의 새로운 피쳐 공간으로 투영
PCA(주성분 분석), LDA(선형 판별 분석) 등
피쳐 중 타겟에 가장 관련성이 높은 피쳐만을 선정하여 피쳐 수를 줄임
관련없거나 중복되는 피쳐들을 필터링하고 간결한 subset을 생성
모델 단순화, 훈련 시간 축소, 차원의 저주 방지, 과적합(Over-fitting)을 줄여 일반화해주는 장점이 있음
ilter, Wrapper, Embedded 메서드
차원의 저주?
일상 경험의 3차원 물리적 공간과 같은 저차원 환경에서는 발생하지 않는 고차원 공간에서 데이터를 분석하고 정리할 때 발생하는 다양한 현상
변수들 사이에 내재한 특성이나 관계를 분석하여 이들을 잘 표현할 수 있는 새로운 선형 혹은 비선형 결합 변수를 만들어 데이터를 줄이는 방법
변수들의 공분산 행렬이나 상관행렬을 이용
원래 데이터 특징을 잘 설명해주는 성분을 추출하기 이하여 고차원 공간의 표본들을 선형 연관성이 없는 저차원 공간으로 변환하는 기법
행의 수와 열의 수가 같은 정방행렬에서만 사용
from sklearn import datasets
from sklearn.decomposition import PCA
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
iris = datasets.load_iris()
X = iris.data
y = iris.target
target_names = list(iris.target_names)
print(f'{X.shape = }, {y.shape = }')
print(f'{target_names = }')
# PCA의 객체를 생성, 차원은 2차원으로 설정(현재는 4차원)
pca = PCA(n_components=2)
# PCA를 수행. PCA는 비지도 학습이므로 y값을 넣지 않음
pca_fitted = pca.fit(X)
print(f'{pca_fitted.components_ = }') # 주성분 벡터
print(f'{pca_fitted.explained_variance_ratio_ = }') # 주성분 벡터의 설명할 수 있는 분산 비율
X_pca = pca_fitted.transform(X) # 주성분 벡터로 데이터를 변환
print(f'{X_pca.shape = }') # 4차원 데이터가 2차원 데이터로 변환됨
# LDA의 객체를 생성. 차원은 2차원으로 설정(현재는 4차원)
lda = LinearDiscriminantAnalysis(n_components=2)
lda_fitted = lda.fit(X, y)
print(f'{lda_fitted.coef_=}') # LDA의 계수
print(f'{lda_fitted.explained_variance_ratio_=}') # LDA의 분산에 대한 설명력
X_lda = lda_fitted.transform(X)
print(f'{X_lda.shape = }') # 4차원 데이터가 2차원 데이터로 변환됨

모든 피쳐 배정 -> 최적의 subset 선택 -> 학습 알고리즘 -> 성능평가
분산 기반 선택(Variance-based Selection)
from sklearn import datasets
from sklearn.feature_selection import VarianceThreshold
# iris 데이터셋을 로드
iris = datasets.load_iris()
X = iris.data # iris 데이터셋의 피쳐들
y = iris.target # iris 데이터셋의 타겟
X_names = iris.feature_names # iris 데이터셋의 피쳐 이름
y_names = iris.target_names # iris 데이터셋의 타겟 이름
# 분산이 0.2 이상인 피쳐들만 선택하도록 학습
sel = VarianceThreshold(threshold=0.2).fit(X)
print(f'{sel.variances_ = }') # 각 피쳐의 분산 확인
# 분산이 0.2 이상인 피쳐들만 선택 적용
X_selected = sel.transform(X) # 분산이 0.2 이상인 피쳐들만 선택
X_selected_names = [X_names[i] for i in sel.get_support(indices=True)] # 선택된 피쳐들의 이름
print(f'{X_selected_names = }')
print(f'{X_selected[:5] = }')

정보 소득(Information Gain)
카이제곱 검정(Chi-Square Test)
피셔 스코어(Fisher Score)
상관계수(Correlation Coefficient)
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import f_classif, f_regression, chi2
# k개의 베스트 피쳐를 선택
sel_fc = SelectKBest(f_classif, k=2).fit(X, y)
print('f_classif: ')
print(f'{sel_fc.scores_ = }')
print(f'{sel_fc.pvalues_ = }')
print(f'{sel_fc.get_support() = }')
print('Selected features: ', [X_names[i] for i in sel_fc.get_support(indices=True)]) # 선택된 피쳐들의 이름
sel_fr = SelectKBest(f_regression, k=2).fit(X, y)
print('\nf_regression: ')
print(f'{sel_fr.scores_ = }')
print(f'{sel_fr.pvalues_ = }')
print(f'{sel_fr.get_support() = }')
print('Selected features: ', [X_names[i] for i in sel_fr.get_support(indices=True)]) # 선택된 피쳐들의 이름
sel_chi2 = SelectKBest(chi2, k=2).fit(X, y)
print('\nchi2: ')
print(f'{sel_chi2.scores_ = }')
print(f'{sel_chi2.pvalues_ = }')
print(f'{sel_chi2.get_support() = }')
print('Selected features: ', [X_names[i] for i in sel_chi2.get_support(indices=True)]) # 선택된 피쳐들의 이름

모든 피쳐 배정 -> 최적의 subset 선택(subset 생성 -> 학습 알고리즘 -> 성능평가)
전진 선택법(Forward Selection)
RFE(Recursive Feature Elimination)
# RFE(Recursive Feature Elimination) 적용
from sklearn.datasets import load_iris
from sklearn.feature_selection import RFE, RFECV, SelectFromModel, SequentialFeatureSelector
from sklearn.svm import SVC, SVR
# iris 데이터셋 로드
X, y = load_iris(return_X_y=True)
# 분류기 SVC 객체 생성, 선형분류, 3개의 클래스
svc = SVR(kernel="linear", C=3)
# RFE 객체 생성, 2개의 피쳐 선택, 1개씩 제거
rfe = RFE(estimator=svc, n_features_to_select=2, step=1)
# RFE+CV(Cross Validation), 5개의 폴드, 1개씩 제거
rfe_cv = RFECV(estimator=svc, step=1, cv=5)
# 데이터셋에 RFE 적용
rfe.fit(X, y)
print('RFE Rank: ', rfe.ranking_)
# rank가 1인 피쳐들만 선택
X_selected = rfe.transform(X)
X_selected_names = [X_names[i] for i in rfe.get_support(indices=True)] # 선택된 피쳐들의 이름
print(f'{X_selected_names = }')
print(f'{X_selected[:5] = }')
# 데이터셋에 RFECV 적용
rfe_cv.fit(X, y)
print('RFECV Rank: ', rfe_cv.ranking_)
# rank가 1인 피쳐들만 선택
X_selected = rfe_cv.transform(X)
X_selected_names = [X_names[i] for i in rfe_cv.get_support(indices=True)] # 선택된 피쳐들의 이름
print(f'{X_selected_names = }')
print(f'{X_selected[:5] = }')
SelectFromModel
-의사결정나무 기반 알고리즘에서 변수를 선택하는 기법
from sklearn.feature_selection import SelectFromModel
from sklearn import tree
from sklearn.datasets import load_iris
# 데이터를 로드하고, 분류기를 초기화한 후 SFS를 적용
X, y = load_iris(return_X_y=True)
clf = tree.DecisionTreeClassifier()
sfm = SelectFromModel(estimator=clf)
# 모형 구조 확인 및 출력을 pandas로 설정
sfm.set_output(transform='pandas')
# 모형 학습
sfm.fit(X, y)
print('SFM threshold: ', sfm.threshold_)
# 선택된 피쳐들만 선택
X_selected = sfm.transform(X)
X_selected.columns = [X_names[i] for i in sfm.get_support(indices=True)] # 선택된 피쳐들의 이름
X_selected.head()
