RBF 신경망을 이용한 패턴 인식 기술의 활용과 최적화

1. 패턴 인식에서 RBF 네트워크의 역할

패턴 인식은 이미지, 음성, 생체 정보 등 다양한 데이터에서 의미 있는 구조를 추출하고 분류하는 핵심적인 머신러닝 작업이다. 이 과정에서 RBF(Radial Basis Function) 신경망은 비선형 문제에 강한 일반화 능력과 빠른 수렴 속도 덕분에 주목받는 모델 중 하나다. 본 문서에서는 RBF 신경망의 작동 원리와 실제 패턴 인식 과제에 적용하는 방법을 설명하며, 파이썬 기반의 구현 예제를 통해 실무 적용 가능성을 탐구한다.

2. RBF 신경망의 구조와 동작 방식

RBF 네트워크는 세 개의 계층으로 구성된다: 입력층, 은닉층, 출력층.

  • 입력층: 전처리된 특징 벡터를 수신한다.
  • 은닉층: 각 노드는 중심점(center)을 가지며, 입력과 중심 간 거리에 따라 활성화 값을 계산한다. 가장 흔히 사용되는 활성화 함수는 가우시안 함수로 다음과 같다:
    \( \phi(\mathbf{x}) = \exp\left(-\frac{\|\mathbf{x} - \mathbf{c}_i\|^2}{2\gamma_i^2}\right) \)
    여기서 \( \mathbf{c}_i \)는 i번째 은닉 노드의 중심이며, \( \gamma_i \)는 확산 정도를 조절하는 스케일 파라미터다.
  • 출력층: 은닉층의 출력에 선형 가중치를 적용하여 최종 클래스 점수를 생성한다. 다중 클래스 분류에서는 소프트맥스 또는 argmax 연산을 통해 예측 라벨을 결정한다.

3. 구현 프레임워크 및 전처리

모델 성능은 데이터 전처리 단계에 크게 의존한다. 표준화, 정규화, 차원 축소 등의 기법은 학습 안정성과 정확도를 높이는 데 필수적이다. 아래 코드는 대표적인 전처리 절차를 보여준다.

import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split

# 샘플 데이터 로드 및 전처리
X_raw, y_raw = load_iris(return_X_y=True)
scaler = StandardScaler()
X_norm = scaler.fit_transform(X_raw)
X_train, X_val, y_train, y_val = train_test_split(X_norm, y_raw, test_size=0.25, stratify=y_raw)

4. 기본 RBF 모델 구현

다음은 K-평균 클러스터링 기반 중심 선택과 의사역행렬(pseudo-inverse)을 통한 가중치 학습을 수행하는 RBF 네트워크 클래스다.

class SimpleRBF:
    def __init__(self, n_centers, gamma=1.0):
        self.n_centers = n_centers
        self.gamma = gamma
        self.centers = None
        self.W = None  # 가중치 행렬
        self.bias = None

    def _gaussian(self, x, c):
        return np.exp(-np.linalg.norm(x - c)**2 / (2 * self.gamma**2))

    def _hidden_output(self, X):
        H = np.zeros((X.shape[0], self.n_centers))
        for idx, center in enumerate(self.centers):
            dists = np.linalg.norm(X - center, axis=1)
            H[:, idx] = np.exp(-dists**2 / (2 * self.gamma**2))
        return H

    def fit(self, X, y):
        from sklearn.cluster import KMeans
        kmeans = KMeans(n_clusters=self.n_centers, n_init=10).fit(X)
        self.centers = kmeans.cluster_centers_
        
        H = self._hidden_output(X)
        H_bias = np.column_stack([H, np.ones(H.shape[0])])
        
        # 원-핫 인코딩
        n_classes = len(np.unique(y))
        Y_onehot = np.eye(n_classes)[y]
        
        # 최소 자승 해법으로 파라미터 추정
        params = np.linalg.pinv(H_bias) @ Y_onehot
        self.W = params[:-1].T
        self.bias = params[-1]

    def predict(self, X):
        H = self._hidden_output(X)
        logits = H @ self.W.T + self.bias
        return np.argmax(logits, axis=1)

5. 실제 데이터셋에서의 성능 평가

손글씨 숫자 인식 (MNIST)

from sklearn.datasets import fetch_openml

mnist = fetch_openml('mnist_784', version=1, as_frame=False)
X_mnist, y_mnist = mnist.data / 255.0, mnist.target.astype(int)

X_tr, X_ts, y_tr, y_ts = train_test_split(X_mnist, y_mnist, test_size=0.2)

rbf_mnist = SimpleRBF(n_centers=150, gamma=1.0)
rbf_mnist.fit(X_tr[:5000], y_tr[:5000])  # 일부 데이터로 제한
preds = rbf_mnist.predict(X_ts[:1000])

acc = np.mean(preds == y_ts[:1000])
print(f"MNIST Test Accuracy: {acc:.3f}")

얼굴 인식 (Olivetti Faces)

from sklearn.datasets import fetch_olivetti_faces

faces = fetch_olivetti_faces(shuffle=True, random_state=42)
X_face, y_face = faces.data, faces.target

Xf_tr, Xf_ts, yf_tr, yf_ts = train_test_split(X_face, y_face, test_size=0.2)

rbf_face = SimpleRBF(n_centers=40, gamma=0.8)
rbf_face.fit(Xf_tr, yf_tr)
pred_face = rbf_face.predict(Xf_ts)

face_acc = np.mean(pred_face == yf_ts)
print(f"Face Recognition Accuracy: {face_acc:.3f}")

6. 고급 튜닝 및 개선 전략

중심 선택 방식 변경

K-평균 외에도 무작위 샘플링이나 밀도 기반 클러스터링을 사용할 수 있다.

class RandomCenterRBF(SimpleRBF):
    def fit(self, X, y):
        indices = np.random.choice(X.shape[0], self.n_centers, replace=False)
        self.centers = X[indices]
        H = self._hidden_output(X)
        H_ext = np.column_stack([H, np.ones(H.shape[0])])
        Y_enc = np.eye(len(np.unique(y)))[y]
        theta = np.linalg.pinv(H_ext) @ Y_enc
        self.W = theta[:-1].T
        self.bias = theta[-1]

그라디언트 기반 학습 도입

대규모 데이터셋에서는 의사역행렬보다 경사하강법이 더 효율적일 수 있다.

class GradientRBF(SimpleRBF):
    def __init__(self, n_centers, gamma=1.0, lr=0.001, epochs=300):
        super().__init__(n_centers, gamma)
        self.lr = lr
        self.epochs = epochs

    def fit(self, X, y):
        self.centers = X[np.random.choice(X.shape[0], self.n_centers, replace=False)]
        n_classes = len(np.unique(y))
        self.W = np.random.randn(n_classes, self.n_centers) * 0.1
        self.bias = np.zeros(n_classes)
        Y_hot = np.eye(n_classes)[y]

        for _ in range(self.epochs):
            H = self._hidden_output(X)
            logits = H @ self.W.T + self.bias
            prob = softmax(logits)
            error = Y_hot - prob
            grad_W = self.lr * (error.T @ H)
            grad_b = self.lr * np.sum(error, axis=0)
            self.W += grad_W
            self.bias += grad_b

def softmax(z):
    z_stable = z - np.max(z, axis=1, keepdims=True)
    exp_z = np.exp(z_stable)
    return exp_z / np.sum(exp_z, axis=1, keepdims=True)

하이퍼파라미터 탐색

GridSearchCV를 활용해 최적의 중심 수와 감마 값을 탐색할 수 있다.

from sklearn.model_selection import ParameterGrid

best_score = 0
best_params = {}

for params in ParameterGrid({'n_centers': [50, 100], 'gamma': [0.5, 1.0]}):
    model = SimpleRBF(**params)
    model.fit(X_train, y_train)
    acc = np.mean(model.predict(X_val) == y_val)
    if acc > best_score:
        best_score = acc
        best_params = params

print("Best:", best_params, "Accuracy:", best_score)

7. 복잡한 시나리오에서의 확장

차원 축소와 결합 (PCA)

고차원 데이터에는 PCA를 사전 처리로 적용해 차원을 줄이고 노이즈를 제거할 수 있다.

from sklearn.decomposition import PCA

pca = PCA(n_components=64)
X_train_pca = pca.fit_transform(X_train)
X_val_pca = pca.transform(X_val)

rbf_pca = SimpleRBF(n_centers=80)
rbf_pca.fit(X_train_pca, y_train)

온라인 학습 지원

스트리밍 데이터 환경에서는 새로운 샘플이 들어올 때마다 모델을 업데이트해야 한다.

class OnlineRBF(SimpleRBF):
    def partial_fit(self, x, y):
        x = x.reshape(1, -1)
        H = self._hidden_output(x)
        logit = H @ self.W.T + self.bias
        target = np.eye(self.W.shape[0])[y]
        error = (target - logit) * self.lr
        self.W += error.T @ H
        self.bias += error.flatten()

다중 모달리티 데이터 처리

이미지와 텍스트 같은 복합 입력은 특징 벡터를 연결(concatenate)하여 통합 입력으로 사용할 수 있다.

# 예: 이미지 피처 + 텍스트 임베딩
image_features = extract_cnn_features(img_batch)
text_embeddings = get_sentence_embedding(text_batch)
combined = np.hstack([image_features, text_embeddings])

model = SimpleRBF(n_centers=100)
model.fit(combined, labels)

8. 해석 가능성 및 모델 진단

RBF 네트워크는 중심점이 실제 데이터 샘플과 유사한 의미를 갖기 때문에 해석이 비교적 용이하다. 중심 벡터를 시각화하거나 가중치 분포를 분석함으로써 어떤 패턴이 중요하게 작용했는지를 추론할 수 있다.

def inspect_model(rbf_model):
    print("Number of Centers:", rbf_model.centers.shape[0])
    print("Weight Matrix Shape:", rbf_model.W.shape)
    # 중심 벡터 시각화 (예: 이미지 기반 태스크)
    if rbf_model.centers.shape[1] == 4096:
        show_as_image(rbf_model.centers[0])

태그: RBF 신경망 패턴 인식 머신러닝 파이썬 scikit-learn

7월 30일 07:21에 게시됨