Backpropagation 없이 XOR 풀기: Genetic Algorithm 접근법 🧬

발행: (2026년 1월 7일 오전 03:08 GMT+9)
5 min read
원문: Dev.to

Source: Dev.to

소개

우리는 신경망을 훈련시킬 때 보통 역전파와 경사 하강법에 대해 듣습니다. 이것들은 업계 표준이며, “미적분학”적인 학습 방법입니다.
하지만 한 걸음 물러서서 자연이 어떻게 학습하는지를 살펴본다면 어떨까요? 이 글에서는 유전 알고리즘(GA)을 사용하여 고전적인 XOR 문제(단일 뉴런으로는 해결할 수 없는 문제)를 해결합니다. 기울기는 계산되지 않으며, 우리는 “생존자 경쟁”을 시뮬레이션합니다.

XOR 문제

XOR (exclusive OR) 게이트는 비선형 문제입니다. 단순한 선형 선으로는 그 출력들을 구분할 수 없으므로 신경망이 필요합니다.

Genetic Algorithm Overview

In a GA we treat neural networks as individuals in a population.

  • Fitness – How well the network solves XOR (inverse of error).
  • Selection – The best networks reproduce.
  • Crossover – We mix the weights of two parents.
  • Mutation – Random noise is added to maintain genetic diversity.

파이썬 구현

Note: 이 코드는 기본 NeuralNetwork 클래스와 .forward() 메서드 및 가중치 행렬 W1, W2 등을 가지고 있다고 가정합니다.

적합도 계산

import numpy as np
from basic_neural_network import NeuralNetwork

def calculate_fitness(nn):
    """
    Measures the XOR performance of the network.
    The lower the error, the higher the fitness (score).
    """
    X_xor = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
    y_target = np.array([[0], [1], [1], [0]])

    predictions = nn.forward(X_xor)
    mse = np.mean((y_target - predictions) ** 2)  # Mean Squared Error

    # Add a tiny constant to avoid division by zero
    return 1 / (mse + 1e-9)

변이

def mutate(nn, mutation_rate=0.1, strength=0.5):
    """
    Adds random noise to the network's weights.
    """
    parameters = [nn.W1, nn.b1, nn.W2, nn.b2, nn.W3, nn.b3]

    for param in parameters:
        if np.random.rand() < mutation_rate:
            # Add random Gaussian noise
            noise = np.random.randn(*param.shape) * strength
            param += noise

교차

def crossover(parent1, parent2):
    """
    Produces a child by averaging two parents' weights.
    """
    child = NeuralNetwork()
    child.W1 = (parent1.W1 + parent2.W1) / 2
    child.b1 = (parent1.b1 + parent2.b1) / 2
    child.W2 = (parent1.W2 + parent2.W2) / 2
    child.b2 = (parent1.b2 + parent2.b2) / 2
    child.W3 = (parent1.W3 + parent2.W3) / 2
    child.b3 = (parent1.b3 + parent2.b3) / 2
    return child

메인 진화 루프

# --- MAIN LOOP ---

population_size = 50
population = [NeuralNetwork() for _ in range(population_size)]
generation_count = 1000

print("Evolution starting...")

for gen in range(generation_count):
    # Evaluate fitness and sort (highest score first)
    population = sorted(population, key=lambda x: calculate_fitness(x), reverse=True)

    best_individual = population[0]
    best_error = 1 / calculate_fitness(best_individual)

    if gen % 100 == 0:
        print(f"Gen {gen}: Lowest Error (MSE): {best_error:.5f}")
        if best_error < 0.001:
            print("Solution found!")
            break

    # Create new generation (elitism + crossover)
    new_population = []

    # Keep top 5 individuals unchanged (elitism)
    new_population.extend(population[:5])

    # Fill the rest by breeding top performers
    while len(new_population) < population_size:
        parent1 = population[np.random.randint(0, 10)]  # top 20%
        parent2 = population[np.random.randint(0, 10)]

        child = crossover(parent1, parent2)
        mutate(child, mutation_rate=0.3, strength=0.2)
        new_population.append(child)

    population = new_population

최종 테스트

print("\n--- Training Complete ---")
X_test = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
result = population[0].forward(X_test)

print("XOR Inputs:")
print(X_test)
print("Trained Network Predictions:")
print(np.round(result, 3))

백프로파게이션보다 유전 알고리즘을 사용하는 이유

  • 희소 보상: 많은 문제에서 결과를 마지막에만 알 수 있습니다 (예: 게임 승리).
  • 비미분 가능 영역: 이산 논리나 복잡한 물리 시뮬레이션은 사용 가능한 그래디언트를 제공하지 않을 수 있습니다.

결론

진화적 접근법은 gradient‑based 방법이 어려워하는 문제들을 해결할 수 있습니다. 진화적 코드를 실험해 본 적이 있나요? 댓글에 여러분의 경험을 공유해주세요! 즐거운 코딩 되세요! 🚀

Back to Blog

관련 글

더 보기 »

기술은 구원자가 아니라 촉진자다

왜 사고의 명확성이 사용하는 도구보다 더 중요한가? Technology는 종종 마법 스위치처럼 취급된다—켜기만 하면 모든 것이 개선된다. 새로운 software, ...

에이전틱 코딩에 입문하기

Copilot Agent와의 경험 나는 주로 GitHub Copilot을 사용해 인라인 편집과 PR 리뷰를 수행했으며, 대부분의 사고는 내 머리로 했습니다. 최근 나는 t...