이동 모델: TransE와 그 계열
📍 현재 위치: I부 · 지식 그래프 임베딩 — 2장. 링크 예측은 채점판을 세웠습니다: 점수 함수, 필터링된 순위 매김 프로토콜, 그리고 어떤 모델이든 반드시 넘어서야 하는 고정 무작위 기준선입니다. 이 장은 실제로 경기를 뛰는 첫 번째 모델을 만듭니다.
앞 장은 하나의 숫자로 된 도전으로 끝을 맺었습니다: 무작위 기하는 우리의 여섯 개 순위 질의에서 필터링된 평균 역순위(Mean Reciprocal Rank, MRR) 0.1062점을 벌어들이므로, 이름값을 하는 어떤 모델이든 그 점수를 넘어서야 합니다. 이 장은 누군가 지식 그래프를 위해 내놓은 가장 단순한 기하학적 가설로, 그리고 가장 영향력 있는 가설 가운데 하나로 답합니다 [1]. 모든 개체에 벡터 공간 안의 점 하나를 부여하십시오. 모든 관계에는 하나의 고정된 화살표, 즉 이동(translation)을 부여하십시오. 머리의 점을 관계의 화살표를 따라 밀었을 때 꼬리의 점 가까이에 떨어질 때, 정확히 그때에만 트리플이 그럴듯하다고 선언하십시오. 그것이 모델의 전부입니다. 은닉층도, 비선형성도 없으며, 우리의 학계 세계에서는 학습해야 할 숫자가 겨우 288개뿐인데도, 이를 훈련시키면 기준선 MRR이 일곱 배로 불어납니다. 모델이 이토록 작기 때문에 우리는 온전한 정직함을 감당할 수 있습니다: 모든 그래디언트를 손으로 유도하고 커밋된 코드에 대조해 확인하며, 모든 훈련 숫자는 실제 실행에서 인용하고, 모델의 특징적인 실패는 먼저 종이 위에서 유도된 뒤 출력 표에서 가리켜지는데, 그 표 위에서 이 실패는 carol과 dave라는 두 학생에게 눈에 보이게 실제로 벌어집니다.
사람, 논문, 대학교 모두가 압정이고, 모든 종류의 관계는 모두에게 똑같이 고정된 나침반 지시인 도시 지도를 상상해 보십시오: "지도한다"는 아마도 북동쪽으로 300미터 걷기를 뜻할 것입니다. 어떤 주장된 사실을 확인하려면, 머리의 압정 위에 서서 관계의 지시를 따라간 다음, 지금 누구의 압정에 가장 가까운지를 봅니다. "alice에서 시작해 지도한다를 걸으면" bob에게 떨어진다면, "alice가 bob을 지도한다"는 그럴듯한 것입니다. 훈련이란 알려진 사실들이 모두 짧은 걸음으로 맞아떨어질 때까지 압정을 이리저리 옮기고 나침반 지시를 조율하는 과정입니다. 함정은 이 비유 안에 이미 박혀 있습니다: 하나의 고정된 지시는 출발 압정 하나마다 착지 지점을 딱 하나만 내주므로, 만약 bob이 학생 두 명을 지도한다면, 둘의 압정 모두 같은 한 뙈기의 포장도로 쪽으로 끌려가게 됩니다.
이 장에서 다루는 내용
- 어떤 수학보다도 먼저 풀어낸 모델링의 승부수: "관계는 벡터 공간의 변위다"라는 말이 무엇을 표현할 수 있는지(사슬과 합성) 그리고 구조적으로 무엇을 표현할 수 없는지(일대다 관계는 그 꼬리들을 서로 밀어붙일 수밖에 없으며, 이는 삼각부등식으로 유도됩니다)를 다룹니다.
- 형식적 설정: 안의 임베딩, 점수 , 인 마진 랭킹 손실, 그리고 알려진 참 오염을 다시 뽑는 균등 음성 샘플링을
transe.py에서 그대로 인용하여 다룹니다. - 손으로 유도한 모든 그래디언트: 에 연쇄 법칙을 적용해 유도한 , 그다음 힌지의 여섯 개 편미분 전부, 영-노름 안전장치, 그리고 확률적 경사 하강 갱신을 다루며, 각각을
loss_and_grads의 줄 범위에 대응시킵니다. - 부정행위를 막는 제약: 매 에폭이 끝날 때마다 개체들을 단위 구로 다시 정규화하는 이유를 다룹니다: 이 제약이 없다면 모든 노름을 부풀리는 것만으로 아무것도 배우지 않은 채 손실을 0으로 만들 수 있습니다.
- 커밋된 실행을 하나의 유도 자취로: 에폭 1/10/100/500/1000에서의 손실, 훈련된 평가와 기준선 평가(0.7778 대 0.1062), 그리고 질의 (bob, advises, ?)에 대한 순위 표의 상위권을 다루며, 모든 숫자가 실제입니다.
- 우리 자신의 그래프 위에서 측정한 실패: carol과 dave가 단일한 목표점 를 두고 경쟁하며, 순위 표는 정확히 누가 이기고 얼마나 차이가 나는지를 보여 줍니다.
- 수선책으로서의 계열: TransH, TransR, RotatE 각각이 순수 이동의 한계를 하나씩 고치는 방식과, 네 가지 점수 함수 모두를 담은 표 하나를 다룹니다.
승부수: 관계는 변위다
이 권의 모든 모델은 관계가 기하학적으로 무엇인지에 관한 승부수에서 시작합니다. TransE의 승부수는 가장 작기 때문에 가장 대담합니다: 관계는 변위(displacement), 즉 시작점이 어디든 거기에 더해지는 고정된 벡터 하나입니다 [1]. 어떤 기호가 등장하기도 전에, 이것이 우리에게 무엇을 강제하는지 풀어 봅시다. 우리 그래프에서 관계 advises는 한 번 학습된 화살표 하나가 될 것이고, 그 단 하나의 화살표는 alice를 bob으로, bob을 carol로, carol을 erin으로 동시에 실어 날라야 하는데, 왜냐하면 이 세 사실 모두가 훈련 집합에 들어 있기 때문입니다. 관계는 누가 누구를 지도하는지 적어 놓은 조회 표가 아닙니다; 그것은 지도하는 모든 쌍이 한꺼번에 따라야 하는 운동 규칙입니다.
그 약속은 실질적인 표현력을 사 줍니다. 변위는 합성됩니다: advises를 걷고 나서 다시 advises를 걸을 수 있다면, 두 화살표는 더해지고, 그 합성 화살표 는 2권에서 도출된 grandAdvisor 역할을 위한 후보 기하가 됩니다. 일대일 사실들의 사슬은 이 모델의 본거지입니다: 각자가 다음 사람을 지도하는 사람들의 사슬은 하나의 화살표를 따라 행진하는 점들의 수열로 임베딩됩니다.
같은 약속은 다른 것들을 금지하며, 우리는 오직 뺄셈만으로 그중 하나를 바로 증명할 수 있습니다. 모델이 두 사실을 정확히 맞춘다고 해 봅시다: bob이 carol을 지도하고 bob이 dave를 지도한다는 사실이며, 그러면
좌변은 같은 벡터이므로, 우변도 같아야 합니다: . 정확한 적합은 두 지도학생을 같은 점 위로 강제하여, 그 둘을 구별해 주는 모든 것을 지워 버립니다. 근사적인 판본도 그에 못지않게 치명적이며, 삼각부등식(triangle inequality, 돌아가는 길은 곧은 길보다 결코 짧을 수 없다는 사실, 이며, 여기서 는 벡터 의 길이, 즉 그 좌표 제곱합의 제곱근입니다)으로부터 따라 나옵니다. 두 사실의 남은 오차 벡터인 잔차(residual) 두 개를 적어 보고, 훈련이 둘 다 짧게 만들어 두 길이 모두 어떤 작은 이하가 되었다고 해 봅시다:
첫 단계는 (0이므로 아무것도 바뀌지 않습니다)를 끼워 넣고 다시 묶은 것입니다. 부등식을 적용하기 전에 묶인 두 항을 살펴보십시오. 두 번째 항 는 정확히 (bob, advises, dave)의 잔차이며, 가정에 의해 길이가 최대 입니다. 첫 번째 항 는 (bob, advises, carol) 잔차의 부호를 뒤집은 것이며, 모든 좌표의 부호를 뒤집어도 제곱합 안에서는 아무것도 바뀌지 않으므로 이고, 그 길이 역시 최대 입니다. 이제 삼각부등식은 두 항의 합을 으로 묶어 줍니다. 결론: TransE가 일대다 관계를 더 잘 맞출수록, 그 꼬리들은 잔차 한계의 두 배를 넘지 않는 거리로 서로 더 가깝게 강제됩니다. 이는 에폭을 더 돌리는 것으로 고칠 수 있는 훈련상의 어려움이 아닙니다; 이것은 점수 함수에 관한 정리입니다. 이것을 잘 붙들어 두십시오, 이 장의 끝에서 우리는 커밋된 출력 안에서 이 일이 carol과 dave에게 실제로 벌어지는 것을 지켜볼 것이고, 후계 모델들의 온 "계열"은 바로 이것을 피하기 위해 존재하기 때문입니다 [2].
형식적 설정: 점들, 관계마다 화살표 하나, 점수 하나
이제 기호를 도입하되, 사용 전에 모두 풀어서 말합니다. 임베딩 차원(embedding dimension) , 즉 각 벡터가 받는 좌표의 개수를 고정합니다; 동반 코드는 을 씁니다(transe.py 42–46행). 공간 는 개의 실수로 이루어진 목록 전체의 집합이므로, 은 16개짜리 숫자 목록들의 공간입니다. 13개 개체 각각은 (연상 기호: head, 머리) 또는 (tail, 꼬리)로서 개체 임베딩(entity embedding) , 즉 점 하나를 받습니다. 5개 관계 각각인 은 관계 임베딩(relation embedding) , 즉 변위 화살표를 받습니다(코드는 이것들을 (13, 16) 행렬 ent와 (5, 16) 행렬 rel의 행으로 저장합니다). 파라미터 개수는 정확히 개의 실수입니다: 모델 전체가 그렇습니다.
모델의 주장 "트리플 는 참이다"는 벡터 방정식 가 됩니다. 이 방정식이 얼마나 잘 성립하는지 채점하기 위해, 잔차 를 정의하고 유클리드 노름(Euclidean norm, 로 표기하며, 좌표 제곱합의 제곱근)으로 그 길이를 잽니다. 그 길이가 트리플의 거리(distance)이고, 점수(score)는 그것의 부호를 뒤집은 값이며, 그래서 점수가 높을수록 더 그럴듯하다는, 지난 장의 평가 프로토콜이 요구한 관례와 맞아떨어집니다:
여기서 첨자 는 개의 좌표를 훑고, 는 의 번째 좌표입니다. 코드에서 이것은 한 줄짜리이며, kg.evaluate에 건네지는 클로저입니다(transe.py 171–176행):
def make_score_fn(ent: np.ndarray, rel: np.ndarray):
"""The scoring closure ``kg.evaluate`` expects: s(h,r,t) = -‖e_h+e_r-e_t‖₂
over entity/relation *names* (higher = more plausible)."""
def score(h: str, r: str, t: str) -> float:
return -float(np.linalg.norm(ent[E_ID[h]] + rel[R_ID[r]] - ent[E_ID[t]]))
return score
한 그림 안의 TransE: 관계마다 공유되는 화살표 하나가 모든 머리를 그 꼬리 쪽으로 옮기고(왼쪽), 훈련은 양성과 오염된 거리를 마진을 사이에 두고 견주며(가운데), 일대다 관계는 그 꼬리들을 하나의 목표점 쪽으로 끌어당기는데(오른쪽), 이는 나머지 계열이 고쳐 나가는 실패입니다.
저자가 AI의 도움을 받아 직접 제작한 원본 도해.
마진 랭킹 손실과 음성 샘플링
점수만으로는 아무것도 훈련되지 않습니다; 그 경사 하강이 참인 트리플을 거짓인 트리플보다 더 높게 점수 매기도록 만드는 손실이 필요합니다. 지난 장의 개방 세계 논의에서 물려받은 미묘한 점은, 지식 그래프는 거짓 트리플을 하나도 내주지 않는다는 것입니다. TransE의 답은 그것들을 직접 만들어 내는 것입니다: 각 훈련 양성마다, 한쪽 끝을 무작위 개체로 바꿔치기해 음성(negative)으로 오염시킨 다음, 양성이 고정된 간격만큼 음성을 이기라고 요구합니다 [1]. 참 트리플의 거리를 로, 그 오염물의 거리를 로 씁니다. 이 쌍에 대한 마진 랭킹 손실(margin ranking loss)은
이며, 여기서 마진(margin) 입니다(transe.py 43행). 이를 허용 오차가 딸린 요구로 읽으십시오: 우리는 를 원하며, 가짜 사실이 진짜 사실보다 적어도 만큼은 더 멀기를 바랍니다. 요구가 충족되면 이고, 가 0으로 눌리며, 그 쌍은 아무것도 기여하지 않습니다: 모델은 지나치게 벌려 놓았다고 해서 보상받지 않습니다. 요구가 어겨지면 손실은 양수가 되고 위반량에 따라 선형적으로 커집니다. 이렇게 눌린 모양의 손실을 힌지(hinge)라 부르며, 그 한쪽으로만 작동한다는 점이 핵심입니다: 이 손실은 오직 순서를 매기는 오류에만 역량을 쓰는데, 이는 정확히 순위 매김 평가가 재는 것입니다.
오염 단계에는 코드를 그대로 인용할 만한 함정이 있습니다. 우리 그래프는 작고 밀도가 높아서, 참인 트리플을 "무작위로" 오염시킨 결과가 때로는 다른 참인 트리플이 되어 버립니다: (bob, advises, carol)의 꼬리를 dave로 오염시키면 (bob, advises, dave)를 만들어 내는데, 이는 제외해 둔 참인 사실이지 음성이 아닙니다. 이것을 음성으로 삼아 훈련하면 참인 사실의 거리를 오히려 늘리는 방향으로 밀게 됩니다. 그래서 샘플러는 오염물이 알려진 트리플이 아닐 때까지 다시 뽑습니다(transe.py 114–125행):
def _sample_negative(pos: tuple[int, int, int],
rng: np.random.Generator) -> tuple[int, int, int]:
"""One uniform negative for ``pos``: flip a coin to corrupt head or tail,
draw the replacement entity uniformly, and resample while the corruption
happens to be a known-true triple (so "negatives" are really negative)."""
h, r, t = pos
side = int(rng.integers(2)) # 0 = corrupt the head, 1 = corrupt the tail
while True:
e = int(rng.integers(len(ENTITIES)))
cand = (e, r, t) if side == 0 else (h, r, e)
if cand not in KNOWN_IDS:
return cand
지난 장의 방법론 절에서 이미 짚었던 정직한 유보 하나: KNOWN_IDS는 시험 트리플까지 포함한 18개 트리플 전부로부터 만들어지므로, 샘플러는 결코 시험 사실로 오염시키지 않습니다. 벤치마크에서라면 이는 일종의 누출이겠지만, 여기서는 일관되게 적용되는 표준 필터링 관례이며, 공개적으로 밝혀 둔 것입니다.
손으로 유도하는 그래디언트
동반 코드는 자동 미분을 전혀 쓰지 않습니다; 모든 도함수가 그대로 적혀 있고, 별도의 스크립트(torch_check.py)가 같은 함수를 autograd 아래에서 재현하여 이를 검증합니다. 따라서 아래의 유도는 장식이 아닙니다; 그것이 곧 훈련 알고리즘 자체입니다. 손실에는 여섯 개의 임베딩 행이 관여합니다: 양성 트리플의 머리, 관계, 꼬리, 그리고 음성 트리플의 머리, 관계, 꼬리입니다. 우리는 각각에 대해 가 필요합니다.
1단계: 노름의 도함수. 모든 것은 하나의 사실로 환원됩니다: 벡터 가 변할 때 그 길이 가 어떻게 변하는가입니다. 노름을 내적과 제곱근의 합성으로 적어 봅시다, , 그리고 연쇄 법칙으로 좌표 하나 에 대해 미분합니다. 바깥 함수는 이고 도함수는 이며; 안쪽 함수는 이고, 에 대한 그 도함수는 인 항만 남겨 를 줍니다:
개의 좌표를 다시 벡터로 쌓으면,
이는 단위 잔차(unit residual)입니다: 길이가 1인 의 방향입니다. 기하학적으로 이는 벡터의 길이가 자기 자신을 따라 늘릴 때 정확히 비율 1로 가장 빠르게 자란다는 말이며, 이것이 바로 그래디언트의 길이가 1인 이유입니다. 이 공식은 오직 에서만 실패하는데, 그곳에서는 노름이 꺾임점(모서리, 에서의 처럼)을 가져 도함수가 존재하지 않습니다; 그곳에서 코드는 꺾임점에서 정당하게 쓸 수 있는 대체값인 서브그래디언트(subgradient) 을 쓰며, if d_pos > 0.0으로 지켜집니다(transe.py 92–94행).
2단계: 힌지를 관통하기. 손실 에는 두 영역이 있습니다. 마진이 충족되면 이 그 근방 전체에서 항등적으로 성립하므로 모든 편미분은 0입니다; 코드는 0벡터 여섯 개를 반환하고(transe.py 87–90행) 훈련 루프는 갱신을 아예 건너뜁니다(150행의 if loss > 0.0 보호문). 마진이 어겨지면 는 둘째 인자에 대해 항등함수이므로,
(경계값 에서는 힌지 자체가 꺾임점을 가집니다; 코드의 loss == 0.0 검사는 이 경계를 0-그래디언트 영역에 두는데, 이 역시 정당한 서브그래디언트 선택입니다.)
3단계: 잔차를 관통하기. 양성 잔차는 입니다. 머리 임베딩을 만큼 흔들면 잔차는 정확히 만큼 움직이고; 꼬리를 흔들면 만큼 움직입니다. 행렬 언어로는, (항등 행렬), , 입니다. 양성 머리에 대해 세 단계를 연쇄해 봅시다, 이때 는 단위 잔차입니다:
여섯 개의 행 전부에 대해 똑같은 연쇄를 되풀이하면(음성 쪽은 2단계에서 을 얻습니다) 완전한 그래디언트 집합이 나옵니다:
이것이, 기호 하나하나까지, 코드가 반환하는 사전입니다(transe.py 101–108행):
grads = {
"h_pos": u_pos.copy(),
"r_pos": u_pos.copy(),
"t_pos": -u_pos,
"h_neg": -u_neg,
"r_neg": -u_neg.copy(),
"t_neg": u_neg.copy(),
}
4단계: 갱신, 그리고 그것이 기하학적으로 하는 일. 확률적 경사 하강은 학습률 로 관여하는 각 행에 를 적용합니다(transe.py 156–161행):
ent[h_p] -= LR * g["h_pos"]
rel[r_p] -= LR * g["r_pos"]
ent[t_p] -= LR * g["t_pos"]
ent[h_n] -= LR * g["h_neg"]
rel[r_n] -= LR * g["r_neg"]
ent[t_n] -= LR * g["t_neg"]
부호를 힘으로 읽으십시오. 양성 머리는 만큼, 즉 자신의 잔차에 곧바로 반해서 움직이고, 양성 꼬리는 만큼, 즉 그 방향을 따라 움직입니다: 두 움직임 모두 를 줄여, 참인 사실을 서로 끌어당깁니다. 음성 머리는 만큼, 음성 꼬리는 만큼 움직입니다: 두 움직임 모두 를 늘려, 가짜 사실을 서로 밀어냅니다. 한 행이 두 트리플 모두에 등장하면(오염되지 않은 자리, 언제나 관계를 포함합니다), 그 행은 단순히 두 갱신을 모두 받는데, 이는 다변수 연쇄 법칙이 공유된 파라미터에 대해 처방하는 두 그래디언트의 합과 정확히 같습니다.
구 제약: 노름 팽창이라는 탈출구를 막기
훈련 루프의 한 줄이 아직 설명되지 않은 채 남아 있으며, 이 줄이 사업 전체를 지켜 줍니다. 매 에폭이 끝날 때마다, 각 개체 임베딩은 길이가 1이 되도록 다시 스케일링되어, 단위 구(unit sphere) 위로 되돌아갑니다(transe.py 164–167행):
# The TransE constraint: entities back to the unit sphere ‖e‖₂ = 1
# after every epoch (stops the loss cheating by inflating norms).
norms = np.linalg.norm(ent, axis=1, keepdims=True)
ent /= np.where(norms == 0.0, 1.0, norms)
왜 이것이 필요할까요? 마진 손실에는 아무것도 배우지 않고도 0에 도달하는 퇴화된 방법이 있기 때문입니다: 모든 것을 그냥 키우는 것입니다. 어느 시점에 모든 양성이 그 음성보다 아주 조금이라도 더 가깝다고 해 봅시다, 즉 어떤 작은 에 대해 라고 합시다. 모든 개체와 관계 임베딩에 상수 을 곱합니다. 모든 잔차 는 가 되므로, 모든 거리는 로 스케일되고, 힌지의 인자는
가 되며, 이는 가 되는 즉시 0에 도달합니다(그 너머로는 음수가 됩니다). 손실은 정확히 0에 도달하지만, 평가가 재는 유일한 것인 후보들의 순서는 전혀 바뀌지 않았습니다: 를 곱하는 것은 모든 점수에 를 곱하는 것이고 모든 순위를 그대로 보존합니다. 마진 는 진짜 간격이어야 했지만, 팽창은 0이 아닌 어떤 간격이든 진짜 간격처럼 보이게 만듭니다. 더 나쁜 것은, 그래디언트의 동역학 자체가 이 탈출구를 적극적으로 좇는다는 점입니다: 음성 쪽 갱신은 매 단계 개체 행들을 서로 밀어내므로, 제약이 없다면 임베딩 구름은 에폭이 거듭될수록 바깥으로 표류하고, 손실은 공짜로 줄어들며, 양성 잔차에 대한 훈련 압력은 증발해 버립니다. 그래서 원래의 레시피는 개체 노름을 제약하며, 이 구현은 매 에폭이 끝날 때마다 다시 정규화합니다 [1]. 구 위로 다시 투영하는 것은 반지름 방향의 자유도를 지워 버립니다; 마진을 만족시킬 남은 유일한 방법은 점들을 배치하는 것이며, 이것이 바로 우리가 원했던 학습입니다. 관계 벡터는 제약되지 않은 채로 남는데, 구 위의 점들 사이 간격을 자유롭게 이어 줄 수 있어야 하기 때문입니다.
구는 또한 이동이 할 수 있는 일을 조용히 다시 빚어냅니다. 어떤 사실이 구 위에 정확히 맞아떨어진다면, 즉 을 만족하며 이라면, 꼬리의 노름을 제곱하면 이 되고, 을 대입해 풀면,
관계 의 모든 머리는 위로의 사영이 동일해야 합니다: 정확히 맞아떨어지는 머리들은 구의 한 초평면 조각 위에 삽니다. 그 항등식은 사슬에 대해 즉각적인 대가를 치릅니다. 우리 그래프에서 alice는 bob을 지도하고 bob은 carol을 지도하며; 두 연결 모두 구 위에 정확히 맞아떨어진다고 해 봅시다. 그러면 이고, 양변에 와의 내적을 취하면 를 얻습니다. 그런데 alice와 bob은 이제 둘 다 advises의 정확히 맞아떨어지는 머리이므로, 초평면 항등식은 두 내적 모두를 와 같도록 강제하며, 이 두 진술이 일치하려면 이어야만 합니다. 0이 아닌 이동은 사슬로 이어진 두 홉을 구 위에 결코 정확히 맞출 수 없습니다. 이런 종류의 제약이야말로, 실제로는 훈련된 잔차가 사라지기보다 작지만 0이 아닌 값 근처에서 맴도는 이유입니다; 아래의 점수를 읽을 때 이 점을 염두에 두십시오.
커밋된 실행: 하나의 유도 자취
위의 모든 것은 train(transe.py 130–168행) 안에 조립되어 있습니다: 개체와 관계 행을 구간(원래 레시피의 스케일, 137–141행)에서 균등하게 초기화한 다음, 1000에폭 동안 15개의 훈련 트리플을 훑으면서 각각 음성 하나를 샘플링하고, loss_and_grads를 호출하고, 여섯 행 갱신을 적용하고, 개체를 다시 정규화합니다. 이 실행은 결정론적이므로(NumPy default_rng(0)), 아래의 숫자들은 운 좋은 한 번의 뽑기가 아닙니다; 이것들은 python3 transe.py가 내놓는 바로 그 커밋된 출력이며, 자릿수까지 재현 가능합니다. 15개 양성에 대한 평균 마진 손실은 다음과 같이 떨어집니다:
| 에폭 | 평균 마진 손실 |
|---|---|
| 1 | 1.5827 |
| 10 | 0.6812 |
| 100 | 0.1594 |
| 500 | 0.0602 |
| 1000 | 0.0072 |
첫 행은 풀어 볼 가치가 있습니다. 에폭 1에서 평균 손실 1.5827은 마진 을 넘어섭니다. 양성이 이미 이기고 있다면(즉 인 쌍이라면) 이런 일은 일어날 수 없습니다, 그런 쌍은 최대 만 기여하기 때문입니다. 그러니 평균이 이라는 것은 전형적인 쌍에서 임을 강제합니다. 초기화 시점에는 참인 트리플이 평균적으로 자신의 오염물보다 더 먼데, 무작위 점들은 그래프에 관해 아무것도 모르기 때문입니다. 에폭 10에 이르면 평균 위반량이 마진 이하로 내려가고; 에폭 1000에서는 0.0072가 되는데, 이는 거의 모든 (양성, 음성) 쌍이 을 그대로 만족하며 0을 기여한다는 뜻입니다. 훈련은 사실상 힌지를 포화 상태로 만들었습니다.
기하는 일반화했을까요, 아니면 그저 암기했을까요? 지난 장의 평가는 세 개의 제외해 둔 트리플에 대한 여섯 개의 필터링된 순위 질의로, 고정 무작위 기준선(시드 1, 결코 훈련되지 않음, transe.py 179–186행)에 맞서 답합니다. 커밋된 출력은 다음과 같습니다:
filtered ranking over 6 queries (3 test triples × tail/head)
model MRR H@1 H@3 H@10 ranks
random (seed 1) 0.1062 0.0000 0.0000 0.8333 [10, 10, 12, 7, 10, 9]
TransE trained 0.7778 0.6667 1.0000 1.0000 [3, 3, 1, 1, 1, 1]
per query (filtered rank, random → trained):
(bob, advises, ?dave) 10 → 3
(?bob, advises, dave) 10 → 3
(bob, authored, ?p1) 12 → 1
(?bob, authored, p1) 7 → 1
(erin, affiliated, ?cmu) 10 → 1
(?erin, affiliated, cmu) 9 → 1
순위로부터 손으로 직접 이 헤드라인 숫자를 확인해 봅시다, 평균 역순위는 그저 역순위들의 평균이기 때문입니다: 이고, Hits@1은 입니다: 제외해 둔 여섯 개 질의 가운데 네 개가, 그 사실들을 한 번도 본 적 없는 288개의 숫자에 의해 순위 1에서 완벽하게 답해집니다. (erin, affiliated, cmu) 같은 사실들이 되찾아지는 이유는, erin의 유일한 훈련 엣지인 (carol, advises, erin)이 그녀를 cmu 학생인 carol 가까이에 고정시키고, 공유된 affiliated 화살표가 나머지를 해내기 때문입니다. 이 모듈의 역량 검사는 이 결과를 단언합니다(훈련된 MRR이 최소 0.5로 기준선을 이겨야 함, transe.py 220–223행), 그래서 이 주장은 산문이 아니라 종료 코드로 강제됩니다.
하지만 네 개의 완벽한 답이 그 표에서 흥미로운 부분이 아닙니다. 흥미로운 부분은 3점 두 개이며, 이는 정확히 이 장 첫머리의 정리가 그것들이 있을 것이라고 말한 자리입니다.
일대다 실패, 우리 자신의 그래프 위에서 측정하기
두 개의 3순위 질의는 (bob, advises, dave)의 양쪽 끝이며, bob은 우리 그래프에서 지도학생이 두 명인 유일한 개체입니다: carol(훈련 트리플)과 dave(제외해 둠)입니다. 두 사실 모두 같은 것을 원합니다, : 목표점 하나에 청구인 둘입니다. 이 모듈은 질의 (bob, advises, ?)에 대해 13개 개체 전부를 꼬리로 점수 매기고 상위 다섯을 인쇄합니다; 다음이 커밋된 출력입니다:
query (bob, advises, ?) — top 5 tails by s = -‖e_bob + e_advises - e_t‖
(gold answers carry their filtered rank: other known-true answers
are skipped, the same protocol as the MRR/Hits numbers above)
rank tail score
1 carol -0.3681 * gold (train), filtered rank 1
2 bob -0.4794
3 erin -0.7101
4 dave -0.7409 * gold (test), filtered rank 3
5 alice -0.8321
한 줄씩 읽어 봅시다, 모든 줄이 기하가 하는 말이기 때문입니다.
1행, 거리 0.3681의 carol. 훈련된 지도학생이며, 그녀가 목표점을 소유합니다. 하지만 힌지가 포화 상태에 이른 뒤에도 그 거리가 0.3681이지 0에 가깝지는 않다는 점을 주목하십시오: 공유된 advises 화살표는 alice→bob과 carol→erin도 함께 실어 날라야 하며, 구 절 끝의 사슬 논증은 0이 아닌 이동이 사슬로 이어진 두 홉을 정확히 맞출 수 없음을 증명했습니다. 남은 잔차는 하나의 화살표를 세 방향으로 잡아당기는 세 사실 사이의 타협입니다.
2행, 0.4794의 bob 자신. 이 행은 관계 벡터에 대한 공짜 측정값입니다. bob을 그 자신의 꼬리로 점수 매기면 개체 항들이 상쇄됩니다: . 그러므로 이 표는 우리에게 임을 말해 줍니다: advises 화살표는 짧으며, 개체 구 반지름의 절반도 되지 않습니다. 그럴 수밖에 없습니다. 긴 화살표는 하나의 홉은 맞출 수 있겠지만, 단위 구 위에서 홉들의 사슬은 한 고정된 방향으로 계속 멀리 움직일 수 없으므로, 훈련은 한 연결만 정확히 맞고 나머지 사슬 전체가 크게 틀리는 대신 사슬 전체가 견딜 만한 정도로만 틀리도록 화살표를 줄여 나갑니다. 짧은 화살표는 다시, 모든 개체가 자기 자신의 지도학생으로서는 그저 그런 후보라는 것을 뜻하며, 이것이 바로 bob이 여기서 실제 사람 셋을 앞지르는 이유입니다.
3행과 4행, 0.7101의 erin과 0.7409의 dave. 여기 붕괴가 측정되어 있습니다. dave는 bob의 진짜 지도학생이지만, 단일한 목표점 는 이미 carol의 차지이고, dave의 다른 엣지들(그가 p3를 저술했다는 것, 그가 cmu에 소속되어 있다는 것)이 그를 다른 곳에 붙들어 둡니다. 우리의 유도는, 두 잔차가 모두 까지 줄어들었다면 이라고 한계 지었습니다; 옵티마이저는 dave의 다른 사실들을 존중하면서 둘 다를 작게 만들 수 없어서, carol의 것은 작게(0.3681) 만들고 dave의 것은 0.7409로 남겨 두었습니다. 일대다 긴장은 제외해 둔 사실을 희생시킴으로써 해소됩니다. erin이 dave를 근소하게 앞서는 것도 다른 각도에서 본 같은 기하입니다: erin은 carol의 지도학생이므로, 훈련은 가 되도록 끌어당기고, carol이 bob의 목표점 근처에 앉아 있으므로, erin은 그 목표점에 짧은 화살표 하나를 더한 위치 근처에 앉아, 끼어들 만큼 충분히 가깝습니다. 필터링된 프로토콜(kg.py 79–104행)은 이미 참으로 알려진 답인 carol을 dave의 후보 목록에서 제거하므로, dave의 필터링된 순위는 3이 되어 bob과 erin 뒤에 놓입니다: 이는 개별 질의 표가 보고한 정확히 그 10 → 3의 개선이며, 그 이상은 아닙니다. 훈련된 TransE는 이 질의에서 우연보다 극적으로 낫지만 구조적으로 완벽할 수는 없습니다. "실패 양상이 정리다"라는 말이 순위 표 안에서 실제로 어떤 모습인지가 바로 이것입니다.
계열: 증명 가능한 실패에 대한 표적 수선
위에서 잘못된 모든 것은 경사 하강이 아니라 점수 함수가 잘못된 것이므로, 후계 모델들은 훈련 레시피(마진 손실, 음성 샘플링, 노름 제약)는 그대로 유지한 채 기하학만 다시 설계합니다. 각 수선은 이제 정확하게 진술할 수 있는 하나의 한계에 답하며, 여기 정직하게 구별해 둘 점 하나가 있습니다: 그중 둘은 이 장에서 유도된 정리입니다(위의 일대다 붕괴와 아래의 대칭 붕괴), 반면 TransR의 동기는 유도된 불가능성이 아니라 용량에 관한 설계 논증입니다.
| 모델 | 관계 파라미터 | 점수 | 고치는 실패 |
|---|---|---|---|
| TransE [1] | (기준선) | ||
| TransH [2] | , | with | 일대다 붕괴 |
| TransR [3] | , | 모든 관계에 대해 하나뿐인 기하 | |
| RotatE [4] | , | , | 대칭 관계 (반대칭성, 역, 합성은 유지) |
표에 대한 세 가지 읽기 노트가 있습니다. 첫째, TransH와 TransR 논문은 점수를 제곱 노름 으로 진술합니다; 이 표에서는 행 사이의 일관성을 위해 제곱을 뺐고, 아무것도 잃지 않는데, 제곱은 음이 아닌 거리 위에서 단조 사상이므로 모든 순위를 그대로 보존하기 때문입니다. 둘째, 는 단위 법선과 의 내적을 나타내는 전치 표기법입니다(대응하는 좌표끼리 곱해 더한 것): 하나의 숫자로, 의 그림자가 법선을 따라 드리운 길이입니다. 셋째, RotatE 행의 는 복소수의 모듈러스(modulus), 즉 그 길이입니다: 그 복소평면에서 0으로부터의 거리이며, 그래서 제약 은 의 각 좌표를 단위원 위에 둡니다.
TransH: 먼저 사영하고, 그다음 이동하기 [2]. 각 관계는 초평면 하나를 받는데, 이는 그 평면에 수직인 단위 법선(unit normal) (평면에 수직인 길이 1짜리 벡터)과, 평면 안에 사는 이동 로 기술됩니다. 이동하기 전에, 두 개체 모두 초평면 위로 사영됩니다: 은 법선을 따르는 의 성분을 빼고, 평면과 평행한 부분만 남깁니다. 우리의 붕괴 유도를 다시 돌려 보면 그것이 깨지는 것을 볼 수 있습니다: 두 지도학생에 대한 정확한 적합은 이제 만을, 즉 사영만의 동등함을 강제합니다. carol과 dave는 버려진 방향 에서는 자유롭게 다를 수 있으므로, 다른 모든 관계에서는 구별되는 별개의 점으로 남으면서도 advises 앞에서는 똑같아 보일 수 있습니다. 일대다 정리는 사영이 의도적으로 정보를 잃기 때문에 무너집니다.
TransR: 관계마다 별도의 공간 [3]. TransH는 여전히 모든 관계가 하나의 공유된 차원 공간 안에서 작동하게 만듭니다. TransR은 각 관계에 자기만의 차원 공간과 사영 행렬(projection matrix) (개체 공간을 관계 공간으로 사상하는, 학습된 가중치로 이루어진 격자)을 부여합니다; 개체는 로 사상된 다음 이동됩니다. 그 동기는 서로 다른 관계가 한 개체의 서로 다른 특징에 관심을 둔다는 것입니다: affiliated는 bob의 소속 기관 좌표를 읽고 그의 연구 좌표는 무시해야 하며, authored는 그 반대를 해야 합니다. 관계마다 전체 행렬 하나를 두면 각 관계에 대해 독립적으로 늘리고, 회전시키고, 차원을 무너뜨릴 수 있으며, 그 대가는 실질적입니다: 은 관계마다 개의 파라미터를 더하는데, 이는 TransH의 관계마다 개 추가와 대비되므로, TransR은 15개의 트리플로 훈련 가능하게 만들어 주었던 TransE의 파라미터 검약을, 훨씬 더 많은 데이터를 필요로 하는 표현력과 맞바꿉니다.
RotatE: 위치 대신 각도를 이동시키기 [4]. 사영 수선이 결코 건드리지 못하는 실패가 하나 있습니다. 대칭(symmetric) 관계, 즉 와 가 함께 성립하는 관계를 하나 잡아, 둘 다 이동으로 정확히 맞춰 봅시다: 이고 입니다. 두 방정식을 더하면: 이므로 이고, 따라서 이며, 다시 대입하면 입니다. 이동은 관계를 사라지게 만들고 개체를 일치시킴으로써만 대칭을 모델링할 수 있습니다. RotatE는 산술을 복소수로 옮깁니다: 개체는 안의 벡터(각 좌표가 하나의 복소수, 평면 위의 점)이고, 관계는 좌표별 회전(rotation), 즉 모든 모듈러스 을 갖는 복소 벡터 (각 좌표가 길이 1짜리 복소수, 단위원 위의 점)이며, 원소별 곱셈 로 적용됩니다. 단위 복소수를 곱하는 것은 그 좌표를 위상 각도 만큼 회전시킵니다. 이제 대칭 논증을 다시 돌려 보면, 양방향 모두 정확히 맞아떨어진다는 것은 이고 라는 뜻입니다. 첫 방정식의 양변에 을 적용하고 둘째 방정식을 대입하면: 이며, 이는 좌표별로 , 즉 이라고 읽힙니다. 인 모든 좌표에서(훈련된 개체는 정확히 0인 좌표를 갖지 않는다는, 진술할 가치가 있는 일반 위치 가정입니다) 이는 을, 즉 을 강제합니다: 위상 0 또는 입니다. 만큼의 회전은 항등원이 아니면서도 스스로의 역원이므로, 개체들을 무너뜨리지 않고도 대칭 관계가 존재할 수 있습니다. 여기서 무엇이 새로운지 정확히 짚어 둡시다: 순수 이동은 이미 다른 세 가지 고전적인 패턴을 다룰 수 있었습니다. 반대칭성은 이기만 하면 되고(만약 이 정확히 성립한다면, 뒤집은 트리플의 잔차는 이므로, 역방향은 엄격하게 더 나쁜 점수를 받습니다), 역은 이며, 합성은 벡터 덧셈 그 자체입니다. 회전은 이 세 가지를 모두 유지하면서(역은 복소 켤레 로, 즉 되돌아가는 회전으로; 반대칭성은 0과 가 아닌 모든 위상으로; 합성은 회전이 위상을 더함으로써 합성되기 때문에) 이동이 증명 가능하게 담아낼 수 없었던 그 한 가지 패턴을 더합니다. 계열의 한 구성원, 네 가지 관계 패턴, 각각이 한 줄로 검증할 수 있는 대수적 항등식입니다 [4].
아직 풀리지 않은 부분
계열은 우리가 유도할 수 있었던 실패들을 고쳤으며, 바로 그 점이 여러분을 걱정하게 만들어야 합니다. 각 수선은 반응적이었습니다: 어떤 정리가 이동이 담아낼 수 없는 패턴 하나를 드러냈고, 그 패턴을 위한 새로운 점수 함수가 설계되었습니다. 이 장의 그 무엇도 그런 정리가 앞으로 얼마나 더 기다리고 있는지 말해 주지 않으며, 계열의 어떤 구성원도 "이 기하는 모든 유한한 지식 그래프를 충실하게 표현할 수 있다"는 형태의 보장을 갖추고 있지 않습니다. 정직한 진술은, 각 모델이 자신이 다룰 수 있는 관계 패턴의 부류(사슬, 위계, 대칭)를 도려내고 나머지에 대해서는 침묵한다는 것입니다; 이 분야는 그것들을 유도하기 전에 한 번에 하나씩 벤치마크에서 경험적으로 실패 양상을 찾아냈습니다. 훈련 쪽에서도 우리가 조용히 갖고 있지 않은 보장이 하나 있습니다: 마진 손실은 임베딩에 대해 볼록하지 않으므로, 1권의 단일 뉴런과 달리 확률적 경사 하강이 최선의 배치를 찾아낸다는 정리는 없으며, 오직 이 그래프 위에서 이 시드로는 좋은 배치 하나를 찾아냈다는 관측된 사실만이 있을 뿐입니다. 어떤 점수 함수가 어떤 그래프를 표현할 수 있는지에 관한 원칙에 입각한 설명, 즉 임기응변식 수선들의 목록이 아닌 그런 설명이야말로 이 권이 향해 가는 곳입니다: 그 질문은 표현력의 천장 장에서 이름을 얻고 몇 가지 날카로운 답을 얻습니다.
왜 중요한가
TransE는 이 시리즈의 두 절반을 잇는 경첩입니다. 2권은 증명되지 않은 그 무엇에 대해서도 침묵하는, 건전하고 완전한 추론기로 끝을 맺었습니다; 이 장은 이 시리즈에서 추측하는 첫 번째 시스템을 만들었고, 앞으로의 모든 설계 선택은 그 원형의 변주입니다: 개체를 위한 기하학적 유형, 관계를 위한 기하학적 연산, 미분 가능한 점수, 그리고 순위 비교에 대한 경사 하강입니다. 이 권의 뒤에 나올 온톨로지-임베딩 장들은 점을 공과 박스로 바꾸어, 2권의 개체뿐 아니라 개념에도 기하를 부여할 것입니다; 질의-임베딩 장들은 이동과 그 후계자들을 사슬처럼 엮어 다중 홉 질문을 만들 것입니다; 그리고 4권의 신경-기호 통합기들은 정확히 우리가 여기서 연습한 것, 즉 진리 같은 점수를 관통해 흐르는 그래디언트를 필요로 할 것입니다. 그만큼 중요한 것은 이 시리즈가 되풀이하는 교훈인 인식론적 교훈입니다: 이 모델의 핵심 약점은 그것을 돌려 봄으로써 발견된 것이 아니라, 훈련 전에 유도되었고 그다음 출력 표에서 순위 하나하나까지 확인되었습니다. 기하학은 어떤 모델의 약속과 그 실패를 모두 증명 가능하게 만들며, 그것이야말로, 어떤 MRR 숫자 하나보다도, 임베딩 연구가 연금술이 아니라 수학인 이유입니다.
핵심 용어
- 이동 모델(Translational model) — 관계 연산이 벡터 덧셈인 지식 그래프 임베딩입니다: 일 때 트리플이 그럴듯합니다.
- 잔차(Residual) — 트리플의 오차 벡터 이며, 그 유클리드 노름이 트리플의 거리이고, 점수는 그 거리의 음수입니다.
- 마진 랭킹 손실(힌지)(Margin ranking loss (hinge)) — : 참인 트리플이 오염물을 마진 만큼 이기면 0이고, 그렇지 않으면 위반량에 대해 선형입니다.
- 음성 샘플링(Negative sampling) — 참인 트리플의 머리나 꼬리를 균등 무작위 개체로 오염시켜 거짓 트리플을 만들어 내는 것으로, 그 오염 자체가 이미 참으로 알려진 트리플이면 다시 뽑습니다.
- 단위 잔차 (Unit residual) — 에 연쇄 법칙을 적용해 유도한 유클리드 노름의 그래디언트입니다; TransE의 모든 그래디언트는 단위 잔차의 입니다.
- 노름 팽창 탈출구(Norm-inflation escape) — 모든 임베딩을 로 스케일링하면 모든 거리가 만큼 스케일되어, 단 하나의 순위도 바꾸지 않은 채 올바르게 정렬된 어떤 쌍이든 마진을 넘게 만들어 버립니다; 개체에 대한 단위 구 재정규화가 이 방향을 없앱니다.
- 일대다 붕괴(1-to-many collapse) — 잘 맞아떨어진 이동은 공유된 (머리, 관계) 쌍의 모든 꼬리를 서로 이내로 강제한다는 정리입니다; carol(순위 1)이 dave(필터링된 순위 3)를 밀어내는 것으로 관측됩니다.
- TransH / TransR / RotatE — 계열입니다: 관계별 초평면 사영, 관계별 사영 행렬을 통한 관계-특화 공간으로의 사상, 좌표별 복소 회전이며, 각각 일대다 붕괴, 모든 관계에 하나의 기하라는 한계, 대칭 관계를 고칩니다(회전은 이동의 반대칭성, 역, 합성을 유지하면서 대칭성을 더합니다).
이 장이 향하는 곳
이동은 하나의 대수적 선택입니다: 관계는 개체 공간에 덧셈으로 작용합니다. 다음 장 쌍선형 모델: DistMult와 ComplEx는 다른 기본적인 선택을 하여 관계가 곱셈으로 작용하게 하며, 거리 대신 머리와 꼬리 좌표의 가중된 곱으로 트리플을 채점합니다. 그 맞바꿈은 유익합니다: 곱셈은 덧셈이 잃어버린 것 일부를 되사 오지만, 그 가장 단순한 형태인 DistMult는 새로운 정리급 실패를 대가로 치릅니다, 바로 양방향에서 증명 가능하게 동일한 점수인데, 이는 모든 관계를 대칭으로 만들어 버립니다; 그리고 그 수선인 ComplEx는 RotatE와 똑같은 도구, 즉 복소수에 손을 뻗습니다. 다른 대수, 같은 이야기입니다: 기하학이 하나의 약속을 하고, 유도가 그 균열을 찾아내며, 더 날카로운 기하학이 답합니다.
동반 코드: examples/neural/transe.py는 여기서 유도된 모든 것을 구현하며, loss_and_grads(57–109행)가 그 수학의 단일 근거입니다; examples/neural/kg.py는 18개의 트리플, 결정론적 15/3 분할(65–74행), 필터링된 평가(rank_of와 evaluate, 79–122행)를 공급합니다. 이 장의 모든 숫자를 재현하려면 python3 examples/neural/transe.py를 실행하십시오; 그 assert문(220–223행)은 훈련된 모델이 기준선을 이기지 못하게 되면 실행을 실패시키며, torch_check.py는 수동 그래디언트를 autograd에 대조해 검증합니다.