[변수 선택] Genetic Algorithm를 이용 (Python)

2020. 10. 7. 00:24분석 Python/구현 및 자료

728x90

파이썬에서 변수 선택 시 다양한 알고리즘이 있다. 

sklearn에서 통계적인 방법론들을 사용한 scikit-learn.org/stable/modules/feature_selection.html 여러개의 메서드들도 있고, brouta와 같은 방법론이나, 아니면 feature importance, correlation을 이용한 방법 등 참 다양한 것 같다.

 

하지만 실제로 이러한 방법들이 통계적으로 유의미한 것을 검증해주는데, 결국 단별량적으로 바라보거나 큰 범위에서는 잘 찾기 어려울 수가 있다. 

 

이럴 때 쓰기 좋은 다른 방법론으로는 GA가 있다.

GA는 랜덤으로 여러개를여러 개를 뿌려보면서, 최적의 해를 찾는 과정에서 주로 쓰이는데, 이때 변수 선택도 여러 개를 뿌려고 실제로 해보면서, 좋은 변수들을 찾는 것이다.

 

이렇게 변수 선택을 GA로 할 수 있는 패키지가 존재하는데 바로, 아래에 나와 있는 패키지이다.

 

실제로 GA 같은 경우 아무런 제약 상황이 없이 오로지 시도만으로 좋은 변수 선택을 찾기 때문에 자유도가 높다고? 할 수 있을 것 같기도 하다. 물론 시간은 오래 걸린다...

 

예제를 가져와서 확인해보면, 아주 간단하게 사용 가능한 것을 알 수 있다.

from sklearn.datasets import make_classification
from sklearn import linear_model
from feature_selection_ga import FeatureSelectionGA, FitnessFunction

X, y = make_classification(n_samples=100, n_features=15, n_classes=3,
                           n_informative=4, n_redundant=1, n_repeated=2,
                           random_state=1)

model = linear_model.LogisticRegression(solver='lbfgs', multi_class='auto')
fsga = FeatureSelectionGA(model,X,y, ff_obj = FitnessFunction())
pop = fsga.generate(100)

#print(pop)

아니면 사용자가 customizing 해서 사용할 수도 있다.

calculate_fitness만 잘 커스터마이징하면 어디에서든 사용 가능할 것 같다.

class FitnessFunction:
    def __init__(self,n_total_features,n_splits = 5, alpha=0.01, *args,**kwargs):
        """
            Parameters
            -----------
            n_total_features :int
            	Total number of features N_t.
            n_splits :int, default = 5
                Number of splits for cv
            alpha :float, default = 0.01
                Tradeoff between the classifier performance P and size of
                feature subset N_f with respect to the total number of features
                N_t.

            verbose: 0 or 1
        """
        self.n_splits = n_splits
        self.alpha = alpha
        self.n_total_features = n_total_features
        
    def calculate_fitness(self,model,x,y):
        alpha = self.alpha
        total_features = self.n_total_features

        cv_set = np.repeat(-1.,x.shape[0])
        skf = StratifiedKFold(n_splits = self.n_splits)
        for train_index,test_index in skf.split(x,y):
            x_train,x_test = x[train_index],x[test_index]
            y_train,y_test = y[train_index],y[test_index]
            if x_train.shape[0] != y_train.shape[0]:
                raise Exception()
            model.fit(x_train,y_train)
            predicted_y = model.predict(x_test)
            cv_set[test_index] = predicted_y

        P = accuracy_score(y, cv_set)
        fitness = (alpha*(1.0 - P) + (1.0 - alpha)*(1.0 - (x.shape[1])/total_features))
        return fitness
        
X, y = make_classification(n_samples=100, n_features=15, n_classes=3,
n_informative=4, n_redundant=1, n_repeated=2,
random_state=1)

# Define the model

model = linear_model.LogisticRegression(solver='lbfgs', multi_class='auto')

# Define the fitness function object

ff = FitnessFunction(n_total_features= X.shape[1], n_splits=3, alpha=0.05)
fsga = FeatureSelectionGA(model,X,y, ff_obj = ff)
pop = fsga.generate(100)

여러 가지 변수 선택 방법론에서 확신이 없다면, 하나의 방법론으로 추천한다.

 

github.com/kaushalshetty/FeatureSelectionGA

 

kaushalshetty/FeatureSelectionGA

Feature Selection using Genetic Algorithm (DEAP Framework) - kaushalshetty/FeatureSelectionGA

github.com

 

728x90