move84

머신러닝: 특징 선택에 유전자 알고리즘 활용하기 본문

머신러닝

머신러닝: 특징 선택에 유전자 알고리즘 활용하기

move84 2025. 3. 5. 00:54
반응형

머신러닝 모델의 성능을 향상시키는 데 있어, 관련 없는 특징들을 제거하는 특징 선택(Feature Selection)은 매우 중요한 과정입니다. 이 글에서는 특징 선택을 위한 강력한 방법 중 하나인 유전자 알고리즘(Genetic Algorithm, GA)을 소개하고, Python 코드를 통해 실제로 어떻게 구현할 수 있는지 살펴보겠습니다.

유전자 알고리즘(Genetic Algorithm)이란?
유전자 알고리즘은 생물학적 진화 과정을 모방한 최적화 알고리즘입니다. 자연 선택, 유전, 교차(crossover), 돌연변이(mutation) 등의 과정을 통해 최적의 해를 찾아나가는 방식입니다. 특징 선택에서는 각 특징의 조합을 하나의 개체(chromosome)로 보고, 모델의 성능을 개체의 적합도(fitness)로 평가합니다. 유전자 알고리즘은 다양한 특징 조합을 탐색하며 가장 좋은 성능을 내는 특징의 집합을 찾아냅니다.

--- 구분선 ---

💡 특징 선택에 유전자 알고리즘을 사용하는 이유
특징 선택은 모델의 정확성을 높이고, 과적합(overfitting)을 방지하며, 모델의 해석 가능성을 향상시키는 데 기여합니다. 유전자 알고리즘은 다음과 같은 장점을 가지고 있어 특징 선택에 효과적으로 활용될 수 있습니다.

  • 전역 탐색 능력: 유전자 알고리즘은 무작위적인 탐색을 통해 전역 최적해를 찾을 가능성이 높습니다. 다른 탐색 방법들에 비해 지역 최적해에 갇힐 위험이 적습니다.
  • 유연성: 다양한 문제에 적용 가능하며, 문제의 특성에 맞게 유전자 알고리즘의 매개변수를 조정할 수 있습니다.
  • 병렬 처리: 여러 개체를 동시에 평가할 수 있어 계산 속도를 향상시킬 수 있습니다.

--- 구분선 ---

💻 Python을 이용한 유전자 알고리즘 기반 특징 선택 구현
다음은 Python의 DEAP 라이브러리를 사용하여 유전자 알고리즘을 구현하는 예시 코드입니다. DEAP는 유전자 알고리즘을 쉽게 구현할 수 있도록 다양한 도구를 제공합니다.

import random
from deap import base, creator, tools
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

# 1. 데이터 생성
X, y = make_classification(n_samples=100, n_features=20, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 2. 유전자 알고리즘 설정
creator.create("FitnessMax", base.Fitness, weights=(1.0,))
creator.create("Individual", list, fitness=creator.FitnessMax)

toolbox = base.Toolbox()
toolbox.register("attr_bool", random.randint, 0, 1) # 특징 선택 여부 (0: 선택 안 함, 1: 선택 함)
toolbox.register("individual", tools.initRepeat, creator.Individual, toolbox.attr_bool, n=X.shape[1])
toolbox.register("population", tools.initRepeat, list, toolbox.individual)

# 3. 적합도 함수 정의
def evaluate_individual(individual, X_train, y_train, X_test, y_test):
    selected_features = [index for index, value in enumerate(individual) if value == 1]
    if not selected_features: # 특징을 하나도 선택하지 않은 경우,
        return 0.0,

    X_train_subset = X_train[:, selected_features]
X_test_subset = X_test[:, selected_features]
    model = LogisticRegression(solver='liblinear', random_state=42)
    model.fit(X_train_subset, y_train)
    y_pred = model.predict(X_test_subset)
    accuracy = accuracy_score(y_test, y_pred)
    return accuracy,

toolbox.register("evaluate", evaluate_individual, X_train=X_train, y_train=y_train, X_test=X_test, y_test=y_test)

# 4. 유전자 알고리즘 연산자 등록
toolbox.register("mate", tools.cxTwoPoint)
toolbox.register("mutate", tools.mutFlipBit, indpb=0.05)
toolbox.register("select", tools.selTournament, tournsize=3)

# 5. 알고리즘 실행
population = toolbox.population(n=50) # 개체수
generations = 50 # 세대수

for gen in range(generations):
    offspring = toolbox.select(population, len(population))
    offspring = [toolbox.clone(ind) for ind in offspring]

    for ind1, ind2 in zip(offspring[::2], offspring[1::2]):
        if random.random() < 0.5:
            toolbox.mate(ind1, ind2)

        toolbox.mutate(ind1)
        toolbox.mutate(ind2)

    fitnesses = map(toolbox.evaluate, offspring)
    for ind, fit in zip(offspring, fitnesses):
        ind.fitness.values = fit

    population[:] = offspring

    # 각 세대별 최적 개체와 정확도 출력
    best_ind = tools.selBest(population, 1)[0]
    best_fit = best_ind.fitness.values[0]
    print(f"세대 {gen+1}: 정확도 = {best_fit:.4f}")

# 최종 결과 출력
best_ind = tools.selBest(population, 1)[0]
selected_features = [index for index, value in enumerate(best_ind) if value == 1]
print("선택된 특징 인덱스:", selected_features)

위 코드의 각 단계를 자세히 살펴보겠습니다.

  1. 데이터 생성 및 분할: make_classification 함수를 사용하여 예시 데이터를 생성하고, 훈련 세트와 테스트 세트로 분할합니다.
  2. 유전자 알고리즘 설정: DEAP 라이브러리를 사용하여 개체와 적합도 함수를 정의합니다. 각 개체는 선택된 특징의 집합을 나타내는 바이너리 리스트입니다(1: 선택, 0: 미선택). toolbox를 사용하여 유전자 알고리즘의 연산자(예: 교차, 돌연변이, 선택)를 등록합니다.
  3. 적합도 함수 정의: evaluate_individual 함수는 주어진 특징 조합(개체)으로 모델을 훈련하고, 테스트 데이터에 대한 정확도를 계산하여 적합도를 반환합니다. 특징을 하나도 선택하지 않은 경우를 처리합니다.
  4. 유전자 알고리즘 연산자 등록: 교차(cxTwoPoint), 돌연변이(mutFlipBit), 선택(selTournament) 연산자를 등록합니다. 이러한 연산자들은 개체들을 진화시키는 데 사용됩니다.
  5. 알고리즘 실행: 초기 개체 집단을 생성하고, 지정된 세대 수만큼 유전자 알고리즘을 실행합니다. 각 세대마다 교차, 돌연변이, 선택 연산을 수행하고, 각 개체의 적합도를 평가합니다. 최적의 개체를 찾으면, 선택된 특징 인덱스를 출력합니다.

--- 구분선 ---

📝 코드 실행 결과 분석
위 코드를 실행하면 각 세대별로 모델의 정확도가 출력되고, 마지막에는 최적의 특징 조합이 출력됩니다. 예를 들어, 50세대 동안 실행했을 때 다음과 같은 결과를 얻을 수 있습니다.

세대 1: 정확도 = 0.4500
세대 2: 정확도 = 0.5500
...
세대 50: 정확도 = 0.8500
선택된 특징 인덱스: [0, 2, 4, 7, 9, 12, 15, 18]

이 결과는 유전자 알고리즘이 특징 선택을 통해 모델의 정확도를 향상시켰음을 보여줍니다. 선택된 특징 인덱스를 통해 어떤 특징들이 모델의 예측에 가장 중요한 영향을 미치는지 확인할 수 있습니다.

--- 구분선 ---

🔑 핵심 용어 정리

  • 유전자 알고리즘 (Genetic Algorithm): 생물학적 진화 과정을 모방한 최적화 알고리즘.
  • 특징 선택 (Feature Selection): 모델의 성능 향상을 위해 관련 없는 특징을 제거하는 과정.
  • 개체 (Chromosome): 유전자 알고리즘에서 문제의 해를 나타내는 단위. 특징 선택에서는 특징의 조합을 의미.
  • 적합도 (Fitness): 개체의 성능을 평가하는 지표. 특징 선택에서는 모델의 정확도, 정밀도 등을 사용.
  • 교차 (Crossover): 두 개체의 유전자를 섞어 새로운 개체를 생성하는 연산.
  • 돌연변이 (Mutation): 개체의 유전자를 무작위로 변경하는 연산.
  • DEAP: Python에서 유전자 알고리즘을 구현하기 위한 라이브러리.

--- 구분선 ---

🚀 결론
유전자 알고리즘은 특징 선택 문제에 효과적으로 적용될 수 있는 강력한 방법입니다. Python과 DEAP 라이브러리를 사용하여 유전자 알고리즘을 구현하는 것은 비교적 간단하며, 이를 통해 모델의 성능을 향상시키고 더 나은 해석 가능성을 확보할 수 있습니다. 유전자 알고리즘의 원리를 이해하고 실제로 코드를 작성해보면서 머신러닝 모델의 성능을 최적화하는 데 활용해 보시기 바랍니다.

반응형