핵심 요약

  • 안드레이 카파시의 makemore는 문자 단위로 다음 글자를 예측해 이름과 비슷한 문자열을 생성한다.
  • 이번 실습의 바이그램 모델은 앞선 글자 하나만 보고 다음 글자의 확률을 정한다.
  • 글자 쌍의 출현 횟수를 세거나 신경망의 가중치를 학습하는 두 방식이 비슷한 결과에 도달한다.
  • 모델의 품질은 실제 다음 글자에 부여한 확률을 바탕으로 계산한 평균 음의 로그 가능도로 평가한다.

이름 하나에 담긴 여러 학습 사례

카파시는 약 3만 2천 개의 이름이 담긴 데이터로 makemore를 만든다. 데이터에서 가장 짧은 이름은 두 글자, 가장 긴 이름은 15글자다. 모델은 이름을 통째로 외우는 대신 각 이름을 문자 배열로 보고 다음 글자를 예측한다.

예를 들어 ‘Emma’에는 이름의 시작 뒤에 e가 오고, e 뒤에 m, m 뒤에 m과 a가 오며, 마지막 a 뒤에는 이름이 끝난다는 정보가 들어 있다. 카파시는 시작과 끝을 표시하는 기호로 점(.) 하나를 사용했다. 영어 알파벳 26개와 점을 합쳐 가능한 기호는 27개가 된다.

출현 횟수로 다음 글자 예측하기

바이그램은 연속된 두 글자다. 카파시는 데이터의 모든 바이그램을 세어 27×27 표에 넣었다. 각 행은 현재 글자, 각 열은 다음 글자를 뜻한다. 시작 기호에 해당하는 행에는 이름의 첫 글자가 나온 횟수가, 점에 해당하는 열에는 이름이 끝난 횟수가 담긴다.

한 행의 수치를 그 행의 합으로 나누면 현재 글자 다음에 각 기호가 올 확률이 된다. 생성할 때는 점에서 출발해 그 확률에 따라 글자를 하나 뽑고, 뽑힌 글자의 행에서 다시 다음 글자를 뽑는다. 점이 나오면 생성을 멈춘다.

결과가 이름처럼 보이기는 해도 어색한 문자열이 많다. 한 글자짜리 이름이 생성되기도 한다. 모델은 바로 앞 글자만 알 뿐, 지금까지 몇 글자를 만들었는지 모른다. 카파시는 모든 기호를 같은 확률로 뽑는 경우보다 결과가 낫지만 바이그램 모델 자체는 약하다고 평가했다.

확률 계산에서 생기는 오류와 한계

카파시는 행마다 확률을 한 번에 계산하면서 배열 연산의 주의점도 보였다. 행의 합을 구할 때 차원을 유지하지 않으면, PyTorch의 브로드캐스팅이 그 결과를 행 벡터로 해석해 의도와 다른 방향으로 나눌 수 있다. 계산이 실행되더라도 각 행의 합이 1인지 확인해야 하는 이유다.

모델 평가는 실제로 나타난 글자 쌍에 부여한 확률을 이용한다. 그 확률들을 곱한 값이 가능도이며, 카파시는 계산하기 편한 평균 음의 로그 가능도를 손실로 사용했다. 값이 낮을수록 학습 데이터의 실제 다음 글자에 높은 확률을 준 것이다. 출현 횟수로 만든 모델의 전체 학습 데이터 손실은 약 2.45였다.

한 번도 관측되지 않은 글자 쌍은 확률이 0이어서 손실이 무한대가 된다. 이를 완화하려고 모든 칸에 가상의 출현 횟수를 더하는 평활화를 적용했다. 더 많이 더할수록 확률 분포는 균등해진다.

같은 문제를 신경망으로 풀기

카파시는 같은 바이그램 문제를 신경망으로 다시 구성했다. 현재 글자를 27칸 중 한 칸만 1인 벡터로 표현하고, 이를 27×27 가중치 행렬에 곱한다. 출력값인 로짓은 지수화와 정규화를 거치는 소프트맥스를 통해 다음 글자의 확률 분포가 된다.

이 모델은 실제 다음 글자에 부여한 확률로 손실을 계산한 뒤, 역전파로 각 가중치가 손실에 미치는 영향을 구한다. 그 기울기의 반대 방향으로 가중치를 조정한다. 카파시의 실습에서는 약 22만 8천 개의 바이그램으로 학습한 손실이 횟수를 세는 방식의 약 2.45 수준에 가까워졌다.

두 방식이 비슷한 결과를 내는 이유는 입력된 글자를 나타내는 벡터와 가중치 행렬의 곱이 결국 해당 글자의 행을 꺼내는 연산이기 때문이다. 이 신경망에서도 예측에 쓰는 정보는 앞 글자 하나뿐이다. 카파시는 가중치를 0에 가깝게 유도하는 정규화가 확률 분포를 더 균등하게 만드는 효과도 설명했다.

결론

이 실습은 다음 글자 예측을 출현 횟수 표와 기울기 기반 학습으로 각각 구현했다. 바이그램의 제한은 생성 결과에도 드러난다. 카파시는 이후 더 많은 앞선 글자를 입력으로 받는 모델로 확장할 계획이라고 밝혔다.