Oja's Rule 시뮬레이션 (260405)

WonTerry·2026년 4월 5일

Deep Learning

목록 보기
4/26

Oja's Rule

Oja’s Rule을 이용한 Hebbian Feature Learning의 가장 대표적인 예제는 “입력 데이터의 첫 번째 주성분(Principal Component)을 뉴런이 스스로 학습하는 것”이다.
즉, 비지도 학습으로 가장 분산이 큰 방향(feature axis)을 찾는 단일 뉴런 PCA 예제이다.

시뮬레이션 코드의 내용은 다음과 같다.

데이터 수: 1000개
100개 학습마다 weight 방향 저장
화살표가 순차적으로 회전하며 PC1 방향으로 수렴
현재 몇 개 샘플을 학습했는지 텍스트 표시
반복 재생되는 matplotlib animation

Oja’s Rule이 Hebbian feature 를 점점 안정된 주성분 방향으로 학습하는 과정을 직관적으로 확인할 수 있다.


Oja's Rule 시뮬레이션 코드

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

# =========================
# 1. 데이터 생성 (총 1000개)
# =========================
np.random.seed(42)

mean = [0, 0]
cov = [[3, 2],
       [2, 1.5]]

X = np.random.multivariate_normal(mean, cov, 1000)

# =========================
# 2. Oja's Rule 초기화
# =========================
w = np.random.randn(2)
w = w / np.linalg.norm(w)

lr = 0.01
history = [w.copy()]

# =========================
# 3. 100개 단위로 학습 방향 저장
# =========================
for i, x in enumerate(X, start=1):
    y = np.dot(w, x)
    dw = lr * y * (x - y * w)
    w += dw
    w /= np.linalg.norm(w)

    # 100개 단위로 화살표 기록
    if i % 100 == 0:
        history.append(w.copy())

history = np.array(history)

# =========================
# 4. 애니메이션 시각화
# =========================
fig, ax = plt.subplots(figsize=(8, 8))
scatter = ax.scatter([], [], alpha=0.25)
ax.set_xlim(X[:, 0].min() - 1, X[:, 0].max() + 1)
ax.set_ylim(X[:, 1].min() - 1, X[:, 1].max() + 1)
ax.set_aspect('equal')
ax.grid(True)
ax.set_title("Oja's Rule Feature Learning Animation")

arrow = [None]
text = ax.text(0.02, 0.95, '', transform=ax.transAxes, fontsize=12)


def update(frame):
    global arrow

    if arrow[0] is not None:
        arrow[0].remove()

    # 100개씩 점 추가
    current_points = X[: max(1, frame * 100)]
    scatter.set_offsets(current_points)

    w = history[frame]

    arrow[0] = ax.arrow(
        0, 0,
        w[0] * 4,
        w[1] * 4,
        width=0.05,
        head_width=0.25,
        length_includes_head=True
    )

    text.set_text(f"Samples shown: {min(frame * 100, len(X))}")
    return scatter, arrow[0], text


ani = FuncAnimation(
    fig,
    update,
    frames=len(history),
    interval=700,
    repeat=True
)

# =========================
# 5. GIF 저장
# =========================
ani.save("oja_rule_feature_learning.gif", writer="pillow", fps=1.5)

plt.show()
profile
Hello, I'm Terry! 👋 Enjoy every moment of your life! 🌱 My current interests are Signal processing, Machine learning, Python, Database, LLM & RAG, MCP & ADK, Multi-Agents, Physical AI, ROS2...

0개의 댓글