#!/usr/bin/env python3


univariate analysis(단변량 분석)


0.살펴보기

univariate analysis단변량 통계에서는

1. 개개의 특성target 사이에 중요한 통계적 관계가 있는지를 계산

2. 깊게 관련되어 있다고 판단되는 특성을 선택


분산분석 : 데이터를 클래스별로 나누어 평균을 비교하는 방법

분산분석으로 계산한 어떤 특성의 F-통계량이 높으면 그 특성은 클래스별 평균이 서로 다르다는 뜻

분류에서는 ANOVA, analysis of variance분산분석


사용하는 분포는 F-distribution

0. 기본적인 형태는 group(1) / group(2), 큰 값을 분자로 사용하여 최솟값을 1이 되게함

1. H0 = 클래스들의 평균과 분산이 같다

2. H0상태에서의 F-distribution 그래프를 그림

3. F-통계량이 1(좌측)에 가까운 수가 나올수록 두 집단은 비슷한 평균과 분산을 갖음

4. F-통계량이 1에 가까울수록 p-value의 값은 커짐 ==> target에 미치는 영향이 적다고 판단

5. p-value는 pvalues_에 저장됨

6. scikit-learn의 SelectBest, SelectPercentile에서 특성을 선택하는 기준은 F-통계값

7. F-통계값은 scores_에 저장됨


이 방법의 핵심 요소는 univariate, 즉 각 특성이 독립적으로 평가됨

==> 따라서 다른 특성과 깊게 연관된 특성은 선택되지 않을 것으로 예상 가능


이 방법의 특징은

1. 계산이 매우 빠르고 평가를 위해 모델을 만들 필요가 없음

2. 특성을 선택한 후 적용하려는 모델에 상관없이 사용 가능


scikit-learn에서 univariate로 특성을 선택하려면 

1. 분류에는 f_classif(default)를, 회귀에서는 f_regression을  선택하여 테스트

2. 계산한 p-value에 기초하여 특성을 제외하는 방식을 선택. 


이런 방식들은 매우 높은 p-value를 가진(target값과 연관성이 적은) 특성을 제외할 수 있도록 critical value를 조정하는 parameter를 사용

critical value를 계산하는 방법중 하나인 SelectKBest는 고정된 k개의 특성을 선택하고 SelectPercentile은 지정된 비율만큼 특성을 선택



1. cancer data에서 univariate analysis(단변량 분석)하기

### library import

from sklearn.datasets import load_breast_cancer

from sklearn.feature_selection import SelectPercentile

from sklearn.model_selection import train_test_split

import numpy as np

import matplotlib

import matplotlib.pyplot as plt


### matplotlib 한글출력, 축- 설정

matplotlib.rc('font', family='AppleGothic')

plt.rcParams['axes.unicode_minus'] = False


### dataload

cancer = load_breast_cancer()


### preprocessing

rng = np.random.RandomState(seed=0) # random seed

noise = rng.normal(size=(cancer.data.shape[0], 50)) # normal분포에서 cancer.data.shape[0]x50의 데이터추출

cancer_data_noise = np.hstack([cancer.data, noise]) # data 병합

print('cancer_data_noise.shape \n{}'.format(cancer_data_noise.shape)) # (569, 80)


### data 분할

x_train, x_test, y_train, y_test = \

  train_test_split(cancer_data_noise, cancer.target,

                   test_size=0.5, random_state=0)


### preprocessing 메소드 호출 및 적용

select = SelectPercentile(percentile=50).fit(x_train, y_train) # percentile: 50%만 선택

x_train_select = select.transform(x_train) # 적용

x_test_selected = select.transform(x_test)


print('x_train.shape \n{}'.format(x_train.shape))

print('x_train_select.shape \n{}'.format(x_train_select.shape))

합친 데이터와 선택된 데이터의 형태

>>  특성의 갯수가 80에서 40개로 줄음



2. 어떤 특성이 선택되었는지 확인


idx = select.get_support()[각주:1]

print('idx \n{}'.format(idx))

논리값으로 만들어진 idx


plt.matshow(idx.reshape(1, -1), cmap='gray_r')

plt.yticks([]) # 축눈금없애기

plt.xlabel('feature number')

plt.show()


SelectPercentile이 선택한 특성


>> 마스킹된 그래프에서 볼 수 있듯이 선택된 특성은 대부분 원본특성이며, 노이즈 특성은 거의 제거됨을 볼 수 있음




3. 전체 특성을 이용했을 때와 선택된 특성만 사용했을 때 로지스틱 회귀 성능 비교


Logistic Regression 링크 참조

[1]Logistic Regression[1], [2]Logistic Regression[2]


### library import

from sklearn.linear_model import LogisticRegression


### model 호출

lr = LogisticRegression()


### 전체특성을 사용했을 때 정확도

lr.fit(x_train, y_train)

print('전체 특성을 사용한 점수: \n{:.3f}'.format(lr.score(x_test, y_test))) # 0.937


### 일부특성을 사용했을 때 정확도

lr.fit(x_train_select, y_train)

print('선택된 특성을 사용한 점수 \n{:.3f}'.format(lr.score(x_test_selected, y_test))) # 0.951


>> 이 경우에는 일부 원본 특성이 없더라도 노이즈 특성을 제거한 쪽의 성능이 더 높음

이 예는 인위적으로 간단하게 만들었고 실제 데이터에서는 엇갈리는 경우도 많음

너무 많은 특성 때문에 모델을 만들기가 현실적으로 어려울 때 univariate를 사용하거나,

많은 특성들이 확실히 도움이 안된다고 생각할 때 사용

  1. get_support(): 선택된 특성을 논리값으로 표시 [본문으로]

+ Recent posts