17장 — 스핀 글래스와 레플리카 방법

기억 용량: 홉필드 네트워크는 패턴을 몇 개까지 기억하나

무작위 결합은 합금에만 있는 것이 아니다. 홉필드 네트워크는 뉴런 N개를 서로 결합해 두고, 결합에 패턴을 새겨 그 패턴 근처에서 출발한 상태가 패턴으로 돌아오게 만든 네트워크다. 무작위 패턴을 새기면 결합도 무작위가 된다. 더 많은 패턴을 새길수록 쓸모 있는 기억 장치이니, 패턴을 늘려 가면 기억은 언제 무너질까?

역사: 시뮬레이션의 0.15와 계산의 0.138

1982년 홉필드는 뉴런 30개와 100개짜리 네트워크를 컴퓨터로 돌려 보고, 뉴런 수의 0.15배쯤 되는 패턴을 저장하면 되살리기의 오류가 심해진다고 적었다. 그 근처에서는 패턴의 절반은 잘 남고 나머지는 나쁘게 남았다. 작은 네트워크의 시뮬레이션은 경계가 어디쯤인지는 보여 주지만, 뉴런이 많아질 때 경계가 날카로워지는지, 어디에 서는지는 말해 주지 못한다. 1985년 아미트, 구트프로인트, 솜폴린스키는 저장한 패턴을 굳은 무질서로 두고 홉필드 네트워크를 스핀 글래스처럼 다뤄, 레플리카 방법으로 그 경계를 계산했다.

헤브 규칙으로 새긴 결합

무작위 패턴 P개를 헤브 규칙 Jᵢⱼ = (1/N)Σ_μ ξᵢ^μ ξⱼ^μ(ξ는 크사이)로 새기면 결합이 무작위가 된다. 첫 패턴에서 출발해 온도 0으로 업데이트한 뒤 패턴과의 겹침이 0.9 넘게 남는지, 곧 기억을 지켰는지 재 보면 다음과 같다.

뉴런 수 N P/N = 0.12 0.14 0.16 0.18
500 (40번) 0.98 0.90 0.62 0.35
2000 (20번) 1 0.95 0.40 0.05
4000 (10번) 1 1 0.2 0

뉴런이 많을수록 0.14와 0.16 사이에서 더 가파르게 떨어지므로, 기억이 조금씩 흐려지는 것이 아니라 어떤 경계에서 한꺼번에 무너지는 모습이다. 왜 그럴까? 패턴 하나를 떠올릴 때 나머지 패턴들이 입력 합에 보태는 항은 무작위 결합의 SK 모델과 같은 노이즈고, 그 크기는 P/N이 정한다. 레플리카 방법으로 계산하면 온도 0에서 다음 방정식이 기억 상태를 정한다.

m=erf(m2(P/N) r),χ=2π(P/N) r  e−m2/(2(P/N) r),r=1(1−χ)2\textcolor{#dd6677}{m} = \mathrm{erf}\Big( \frac{\textcolor{#dd6677}{m}}{\sqrt{2 (\textcolor{#1f77b4}{P}/\textcolor{#1f77b4}{N})\, \textcolor{#8c5200}{r}}} \Big), \qquad \textcolor{#008b8b}{\chi} = \sqrt{\frac{2}{\pi (\textcolor{#1f77b4}{P}/\textcolor{#1f77b4}{N})\, \textcolor{#8c5200}{r}}}\; e^{-\textcolor{#dd6677}{m}^2 / (2 (\textcolor{#1f77b4}{P}/\textcolor{#1f77b4}{N})\, \textcolor{#8c5200}{r})}, \qquad \textcolor{#8c5200}{r} = \frac{1}{(1 - \textcolor{#008b8b}{\chi})^2}
m떠올린 패턴과 네트워크 상태의 겹침 (1이면 완벽한 기억)P/N뉴런 수에 대한 저장한 패턴 수의 비χ뉴런들이 입력 합의 변화에 반응하는 정도 (응답)r다른 패턴들이 만든 노이즈가 상태의 반응 때문에 커지는 배율erf오차 함수 erf(x)=2π∫0xe−t2dt (표준정규 변수가 −2x 와 2x 사이에 있을 확률)\begin{array}{ll} \textcolor{#dd6677}{m} & \text{떠올린 패턴과 네트워크 상태의 겹침 (1이면 완벽한 기억)} \\ \textcolor{#1f77b4}{P}/\textcolor{#1f77b4}{N} & \text{뉴런 수에 대한 저장한 패턴 수의 비} \\ \textcolor{#008b8b}{\chi} & \text{뉴런들이 입력 합의 변화에 반응하는 정도 (응답)} \\ \textcolor{#8c5200}{r} & \text{다른 패턴들이 만든 노이즈가 상태의 반응 때문에 커지는 배율} \\ \mathrm{erf} & \text{오차 함수 } \mathrm{erf}(x) = \tfrac{2}{\sqrt{\pi}} \int_0^x e^{-t^2} dt \text{ (표준정규 변수가 } -\sqrt{2}x \text{ 와 } \sqrt{2}x \text{ 사이에 있을 확률)} \end{array}

노이즈가 뉴런의 상태를 조금 바꾸면 바뀐 상태가 다른 패턴들과 겹치며 노이즈를 다시 키우는데, r은 그 되먹임의 배율로 TAP 방정식의 반작용 항과 같은 종류다. r을 1로 두면 겹침이 P/N에 따라 서서히 줄어 0.55에서야 절반이 되고 2/π ≈ 0.64에서 0이 된다는 엉뚱한 답이 나오지만, r을 넣으면 해가 P/N = 0.138에서 사라지고 그 직전의 겹침은 0.967이다. 기억은 조금씩 흐려지지 않고 97% 가까운 겹침을 지키다가 경계에서 한꺼번에 무너져, 패턴과의 겹침이 작은 스핀 글래스 상태로 떨어진다. 이처럼 기억 상태가 사라지는 경계의 P/N을 기억 용량 (되살릴 수 있는 패턴 수를 뉴런 수로 나눈 값의 한계, storage capacity)이라 한다.

떠올린 패턴과의 겹침 m을 패턴 수의 비 P/N에 따라 그린 것(온도 0의 레플리카 대칭 방정식). 실선의 기억 상태는 겹침을 1 가까이 지키다가 P/N ≈ 0.138에서 겹침 0.967을 끝으로 사라지고, 네트워크는 패턴과의 겹침이 작은 스핀 글래스 상태로 떨어진다. 점선은 되먹임 배율 r을 1로 둔 어림으로, 겹침이 서서히 줄어 2/π ≈ 0.64에서야 0이 된다.
떠올린 패턴과의 겹침 m을 패턴 수의 비 P/N에 따라 그린 것(온도 0의 레플리카 대칭 방정식). 실선의 기억 상태는 겹침을 1 가까이 지키다가 P/N ≈ 0.138에서 겹침 0.967을 끝으로 사라지고, 네트워크는 패턴과의 겹침이 작은 스핀 글래스 상태로 떨어진다. 점선은 되먹임 배율 r을 1로 둔 어림으로, 겹침이 서서히 줄어 2/π ≈ 0.64에서야 0이 된다.
직접 움직여 보기홉필드 네트워크의 용량새 창에서 열기 ↗

레플리카 계산이 주는 경계와, 위 표의 시뮬레이션을 코드로 다시 낸다.

import numpy as np
from scipy.special import erf
rng = np.random.default_rng(0)

# (1) 레플리카 계산(온도 0)이 주는 기억 경계
y = np.linspace(0.5, 4, 200_001)                       # y = m / √(2(P/N)r)
chi = 2 / np.sqrt(np.pi) * np.exp(-y**2) * y / erf(y)  # 응답 χ
load = (erf(y) / y)**2 * (1 - chi)**2 / 2              # 이 해가 성립하는 P/N
i = load.argmax()
print(f"레플리카 계산: 기억 상태가 있는 가장 큰 P/N = {load[i]:.4f}, 그때 겹침 m = {erf(y[i]):.3f}")

# (2) 시뮬레이션: 패턴에서 출발해 온도 0으로 업데이트한 뒤의 겹침
def hopfield(N, P):
    xi = rng.choice([-1.0, 1.0], size=(P, N))
    J = xi.T @ xi / N; np.fill_diagonal(J, 0)
    s = xi[0].copy(); h = J @ s
    for _ in range(50):
        flips = 0
        for k in rng.permutation(N):
            if h[k] * s[k] < 0:
                s[k] = -s[k]; h += 2 * s[k] * J[:, k]; flips += 1
        if flips == 0:
            break
    return s @ xi[0] / N

for N, trials in ((500, 40), (2000, 20), (4000, 10)):
    row = [np.mean([hopfield(N, round(a * N)) > 0.9 for _ in range(trials)]) for a in (0.12, 0.14, 0.16, 0.18)]
    print(f"N = {N}: 기억을 지킨 비율 (P/N = 0.12, 0.14, 0.16, 0.18)", np.round(row, 2))
# 레플리카 계산: 기억 상태가 있는 가장 큰 P/N = 0.1379, 그때 겹침 m = 0.967
# N = 500: 기억을 지킨 비율 (P/N = 0.12, 0.14, 0.16, 0.18) [0.98 0.9  0.62 0.35]
# N = 2000: 기억을 지킨 비율 (P/N = 0.12, 0.14, 0.16, 0.18) [1.   0.95 0.4  0.05]
# N = 4000: 기억을 지킨 비율 (P/N = 0.12, 0.14, 0.16, 0.18) [1.  1.  0.2 0. ]

레플리카 계산의 경계 0.1379는 시뮬레이션에서 기억을 지킨 비율이 가파르게 떨어지기 시작하는 0.14 근처와 맞고, 홉필드가 작은 네트워크에서 본 0.15와도 멀지 않다.

ML에서: 어텐션과 현대 홉필드 네트워크

2020년 람자우어 등은 상태가 연속인 「현대 홉필드 네트워크」를 내놓으면서, 논문 요약에 이 네트워크가 연관 공간의 차원에 대해 지수적으로 많은 패턴을 저장할 수 있고 그 업데이트 규칙이 트랜스포머의 어텐션 메커니즘과 같다고 적었다. 같은 요약은 에너지 최솟값을 세 종류로 나눈다. 모든 패턴의 평균에 머무는 점, 패턴 몇 개의 평균에 머무는 준안정 상태, 패턴 하나를 저장한 점이다. 0.138N이라는 경계는 이 계보의 출발점이고, 「패턴 몇 개의 평균」은 아래 문제의 섞인 기억과 닮았다.

문제 12. 저장하지 않은 기억

뉴런 1000개의 홉필드 네트워크에 무작위 패턴 10개를 헤브 규칙으로 저장한다. (가) 첫 세 패턴의 다수결 sgn(ξ¹ + ξ² + ξ³)에서 출발해 온도 0으로 업데이트하면 어디에 멈추는가? (나) 두 패턴의 합 sgn(ξ¹ + ξ²)에서 출발하면? (다) 멈춘 상태들의 뉴런 하나당 에너지를 저장한 패턴과 비교하라.

김민준 M05
김민준

(가)부터 돌렸어요. 세 패턴과의 겹침이 0.52, 0.50, 0.48에서 멈춰요. 패턴 어느 것도 아닌데 안 움직여요. 저장하지도 않은 걸 기억하고 있어요!

이서연 S01
이서연

다수결 상태는 처음부터 세 패턴과 0.5씩 겹쳐. 그러면 뉴런마다 입력 합의 부호가 세 패턴 값의 다수결과 같아져서 안 움직이지.

김민준 M01
김민준

(나)는 두 패턴이 다른 뉴런에서 합이 0이라 동전을 던져 정했어요. 50번 가운데 40번은 한 패턴으로 떨어지고, 나머지는 세 번째 패턴을 끌어와 세 패턴 섞기로 멈췄어요.

이서연 S07
이서연

짝수 개를 섞으면 동점인 뉴런이 생겨서 버티지 못하고, 홀수 개일 때만 멈출 수 있는 거네.

김민준 M02
김민준

그럼 다섯 개를 섞으면?

이서연 S07
이서연

겹침이 3/8 = 0.375씩이 되고.

선생님 T02
선생님

(다)는요?

김민준 M07
김민준

저장한 패턴은 −0.500, 세 패턴 섞기는 −0.375, 다섯 패턴 섞기는 −0.351이에요. 가짜 기억이 더 얕은 골짜기네요.

선생님 T14
선생님

그래서 온도를 조금 올리면 얕은 가짜 골짜기부터 사라져요. 아미트, 구트프로인트, 솜폴린스키가 계산한 것도 이런 골짜기들이 온도와 패턴 수에 따라 언제 나타나고 사라지는지였어요.