벡터를 옮기면 달라진다
출발 문제
당신이 지금 북극점에 서 있다고 상상해 보자. 손에는 남쪽을 가리키는 화살표가 들려 있다. 이제 아주 중요한 규칙 하나를 정한다: 이 화살표를 절대로, 어떤 이유로도 회전시키지 않겠다. 오직 "앞으로 밀기"만 허용한다. 화살표가 가리키는 방향을 내 의지로 돌리는 행위는 금지다.
이 규칙을 지키며 걸어가 보자. 먼저 경도 0° 자오선(북극과 남극을 잇는 반원)을 따라 적도까지 내려간다. 화살표는 여전히 남쪽을 가리킨다 — 여기까지는 자연스럽다. 이제 적도를 따라 동쪽으로 90° 이동한다. 적도 위에서 화살표를 회전시키지 않고 옮기면, 화살표는 계속 남쪽을 가리킨다(적도에서 "남쪽"은 적도와 수직 방향이다). 마지막으로 경도 90° 자오선을 따라 다시 북극으로 올라온다. 화살표를 한 번도 회전시키지 않았으니, 당연히 원래 방향을 가리키고 있어야 하지 않을까?
놀랍게도, 화살표는 원래 방향에서 정확히 90° 돌아가 있다. 처음에는 경도 0° 자오선 쪽을 가리키던 화살표가, 이제는 방금 올라온 경도 90° 자오선 쪽을 가리킨다. 한 번도 회전시키지 않았는데 돌아간 것이다. 마술이 아니라, 평평한 바닥에서는 절대 일어나지 않는 이 현상은 구면이 휘어져 있기 때문에 벌어진다.
이 실험에서 한 가지만 바꿔 보자. 적도를 따라 90°가 아니라 180° 이동한 뒤 북극으로 돌아오면 화살표는 180° 돌아가 있다. 적도를 360° 전부 돌면 360°, 곧 원래 방향으로 돌아온다. 적도를 따라 간 거리가 두 배가 되면 경로가 둘러싼 넓이도 두 배가 되고 회전량도 두 배가 된다. 회전량은 경로가 둘러싼 넓이를 따라가는 것일까? 그리고 그 전에, 곡면 위에서 "돌리지 않고 옮긴다"는 것은 정확히 무엇일까?
밀고 눌러 내리기: 곡면 위에서 돌리지 않고 옮기기
출발 문제의 화살표는 한 번도 돌리지 않았는데 돌아가 있었다. 그렇다면 "돌리지 않는다"는 말이 정확히 무슨 뜻인지부터 따져 봐야 한다.
평면 위에서는 답이 분명하다. 화살표를 들고 어떤 경로를 따라 걸어간 뒤 출발점으로 돌아오면, 화살표는 반드시 원래 방향을 가리킨다. 경로가 직선이든 구불구불하든, 크든 작든 상관없다. 곡면 위에서는 사정이 다르다. 발밑이 휘어 있으니, 화살표를 3차원 공간에서 방향을 조금도 바꾸지 않고 들고 가면 화살표가 곡면에서 떠 버린다. 곡면 위에서도 이 "그냥 밀기"를 정의할 수 있을까?
접선공간에서 밀고 곡면으로 되돌리기
곡면을 바깥 3차원 공간에 놓고 보면 방법이 하나 떠오른다. 3차원에서는 "방향을 바꾸지 않는다"가 분명하니, 3차원에서 그대로 들고 간 뒤 곡면에 맞게 눌러 내리면 된다. 곡면 위의 "돌리지 않고 옮기기"를 처음 수학 개념으로 세운 레비-치비타도 곡면을 이렇게 바깥 공간에 놓고 생각했다.
숫자로 한 번 해 보자. 무대는 출발 문제의 구다. 구는 어느 점에서나 휜 정도가 같아서, 한 걸음을 계산해 두면 어디서나 같은 계산이 된다. 반지름 1인 구의 북극에서, 경도 0° 쪽(남쪽)을 가리키는 길이 1인 화살표를 들고 그 방향으로 0.1 rad 걸어간다.
- 화살표를 3차원 공간에서 방향을 조금도 바꾸지 않고 들고 간다.
- 새 자리에서는 곡면이 0.1 rad 기울어 있어서 화살표 끝이 곡면에서 떠 있다. 새 자리의 접선공간(그 점에서 곡면에 닿는 평면) 위로 수직으로 눌러 내린다(사영).
- 떠 있던 부분
이 잘려 나가고, 길이는 가 된다. 방향은 새 자리의 남쪽이다.
길이가 0.5% 줄었다. 돌리지 않고 옮긴다면서 길이가 줄면 곤란하다. 같은 0.1 rad을 잘게 쪼개 한 걸음마다 눌러 내려 보자.
| 쪼갠 걸음 수 | 한 걸음 | 도착한 화살표의 길이 |
|---|---|---|
| 1 | 0.1 | 0.99500 |
| 10 | 0.01 | 0.99950 |
| 100 | 0.001 | 0.99995 |
열 배 잘게 쪼갤 때마다 줄어든 양도 10분의 1이 된다. 까닭은 한 걸음의 손실에 있다. 한 걸음에 줄어드는 몫
이렇게 끝없이 쪼갠 극한이 곡면 위의 “돌리지 않고 옮기기”, 곧 평행이동(곡선을 따라 돌리지 않고 옮기기)이다. 좌표로 적으면 공변미분(좌표 탓 가짜 변화를 뺀 미분)이 0이 되게 옮기는 것과 같은 규칙이다. 평면에서는 이렇게 옮긴 화살표가 어떤 경로로 돌아와도 제자리였다. 이제 곡면 위에서 이 규칙대로 한 바퀴를 돌면 무엇이 남는지 볼 차례다.
문제 1 — 비스듬한 화살표를 밀고 눌러 내리면
계산 반지름 1인 구의 북극에서 경도 0° 자오선을 따라 남쪽으로 0.1 rad 걷는다. 이번에는 화살표가 걷는 방향(남쪽)과 45°를 이루며 경도 90° 쪽으로 기울어 있고, 길이는 1이다. (가) 0.1 rad을 한 번에 밀고 눌러 내리면, 도착한 화살표가 걷는 방향과 이루는 각과 길이는 얼마인가? 걸음을 10조각, 100조각으로 쪼개면 어떻게 되는가? (나) 출발 문제의 세 구간은 모두 대원(구의 중심을 지나는 평면이 구면을 자른 가장 큰 원) 조각이다. (가)에서 얻은 사실만으로 출발 문제의 화살표가 90° 돌아가 있는 까닭을 설명하라.
같이 풀기 세션 1

numpy로 해 봤어요. 앞(남쪽) 성분 0.707은 한 번 눌러 내리면

옆 성분은 왜 안 잘려?

북극에서 경도 90° 쪽은 이 자오선 위에서는 어디서나 동쪽이고, 동쪽은 자오선을 따라 내려가도 3차원에서 같은 방향이거든. 새 자리의 접선공간에 처음부터 놓여 있어.

그런데 이상해요. 길이 손실은 쪼개면 사라진다고 했지만, 각도는 걸음마다 늘 옆쪽으로만 기울잖아요. 같은 쪽으로 쌓이니까 쪼개도 45.14°보다 작아지지 않을 것 같아요. 그러면 평행이동도 비스듬한 화살표는 옆으로 돌리는 거네요.

쪼개서 직접 계산해 볼까요? 10조각이면 한 조각에서 각이 얼마나 기울어요?

한 조각에 0.0014°쯤이고, 10조각을 합해도 45.014°예요. 100조각이면 45.0014°. 같은 쪽으로 쌓이긴 하는데, 합이 쪼갤 때마다 10분의 1로 줄어요.

한 조각에서 기우는 양이 걸음의 무엇에 비례하길래 그럴까요?

앞 성분이

그럼 (나)요. 대원을 따라 옮기는 동안 화살표와 경로 사이의 각이 그대로라는 걸 출발 문제에 써 볼까요?

첫 구간에서 화살표는 경로와 같은 방향이니 각이 0°예요. 적도에 닿으면 경로가 남쪽에서 동쪽으로, 왼쪽으로 90° 꺾이는데 화살표는 안 꺾이니까 이제 화살표는 경로의 오른쪽 90°예요. 둘째 모퉁이에서 또 왼쪽으로 90° 꺾으면 화살표는 경로의 정반대가 되고, 마지막 구간을 북쪽으로 올라가는 내내 뒤쪽, 곧 경도 90° 자오선을 따라 남쪽을 가리켜요. 처음엔 경도 0° 자오선을 따라 남쪽이었으니까 90° 어긋났어요.

모퉁이에서 꺾인 건 경로였지 화살표가 아니었네요. 조교님이 채점 기준표의 줄을 하나 밀어 놓은 걸 보고 제 점수가 바뀐 줄 알고 따지러 간 적이 있는데, 제 점수는 그대로였고 기준이 움직였던 거예요.
문제 2 — 라이브러리가 모멘텀을 옮기는 법
계산 길이를 1로 맞춘 임베딩처럼 매개변수가 반지름 1인 구면 위에 묶인 모델을 모멘텀과 함께 학습한다. 최적화 라이브러리 Manopt(매트랩)와 geoopt(PyTorch)의 구면은 한 걸음 옮긴 뒤, 지난 모멘텀을 새 점의 접선공간 위로 수직으로 눌러 내려 옮긴다. 지금 모멘텀은 길이 1이고, 이번 걸음(대원을 따라 0.2 rad)의 방향과 60°를 이룬다. 그래디언트(손실이 가장 가파르게 커지는 방향의 벡터)가 새로 더하는 몫은 빼고 지난 모멘텀만 보자. (가) 한 번 눌러 내린 모멘텀의 길이와, 걸음 방향과 이루는 각은 얼마인가? (나) 학습률을 10분의 1로 줄여 같은 0.2 rad을 10걸음에 가면? (다) 눌러 내리기 대신 평행이동으로 옮기면?
같이 풀기 세션 2

걸음마다 모멘텀을 눌러 내려 잘라 내면, 학습이 길어질수록 잘린 몫이 쌓여서 모멘텀이 다 닳아 없어지는 거 아니에요? 그러면 모멘텀을 쓰는 의미가 없는데요.

한 걸음에서 얼마나 잘리는지부터 볼까요? 잘려 나가는 부분은 어느 방향을 향하고 있죠?

걸음 방향 성분 0.5만 곡면에서 떠요. 떠 있는 높이는

0.5%밖에 안 줄었네요. 잘려 나간 건 곡면 밖으로 삐져나온 부분이라, 원래 길이에는 거의 보태지 않고 있었어요.

그럼 걸음을 쪼개면 쌓이는 양은 어떻게 될까요? (나)예요.

numpy로 10걸음 돌리니까 길이 0.9995, 각 60.05°예요. 걸음을 잘게 쪼갰더니 쌓인 어긋남이 오히려 10분의 1로 줄었어요. (다)는 평행이동이니까 길이 1, 각 60° 그대로고요.

아까 45° 화살표 문제랑 같은 계산이네요. 그때도 같은 쪽으로 쌓일 줄 알았는데 쪼갤수록 줄었죠. 라이브러리가 평행이동 대신 눌러 내리기를 쓰는 건, 걸음이 작으면 둘이 거의 같아서였어요.

맞아요. 눌러 내리기는 평행이동을 한 걸음으로 어림한 것이고, 걸음이 작을수록 그 어림이 좋아져요. 벡터에서 법선 방향 성분을 한 번 빼기만 하면 되니 계산도 싸고요. Manopt는 정확한 평행이동도 따로 준비해 두었어요.

수치해석 시간에 오일러 방법으로 미분방정식을 풀 때, 한 걸음의 오차는 걸음의 제곱이라 걸음을 줄이면 전체 오차도 따라 준다고 배웠는데 그거랑 같네.