본문 바로가기

LLM을 활용한 실전 AI 애플리케이션 개발

[LLM을 활용한 실전 AI 애플리케이션 개발] 텍스트를 임베딩으로 변환하기

 

- 컴퓨터는 텍스트를 그대로 계산에 사용할 수 없다.

  따라서 텍스트를 숫자 형식의 데이터로 변경해야 한다.

  텍스트를 모델에 입력할 수 있는 숫자형 데이터인 임베딩으로 변환하기 위해서는 크게 세 가지 과정을 거쳐야 한다.

 

- 먼저, 텍스트를 적절한 단위로 잘라 숫자형 아이디(ID)를 부여하는 토큰화(tokenization)를 수행한다.

  다음으로 토큰 아이디를 토큰 임베딩 층을 통해 여러 숫자의 집합인 토큰 임베딩으로 변환한다. 

  마지막으로 위치 인코딩 층을 통해 토큰의 위치 정보를 담고 있는 위치 임베딩을 추가해

  최종적으로 모델에 입력할 임베딩을 만든다.

  이번 절에서는 세 가지 단계에서 어떤 일이 일어나는지 살펴봄으로써,

  입력 텍스트를 숫자형 데이터로 변환하는 방법을 알아본다.

 

 

1) 토큰화

- 토큰화란 텍스트를 적절한 단위로 나누고 숫자 아이디를 부여하는 것을 말한다.

  한글은 작게는 자모(자음과 모음)단위부터 크게는 단어 단위로 나눌 수 있다. 

  음절은 중간 정도 단위로 볼 수 있다. 

 

- 토큰화를 할 때는 어떤 토큰이 어떤 숫자 아이디로 연결됐는지 기록해 둔 사전(vocabulary)를 만들어야 한다.

  예를 들어, 단어를 단위로 토큰화하는 경우 어떤 단어를 몇 번으로 변환했는지 모두 저장한다.

  큰 단위를 기준으로 토큰화할수록 텍스트의 의미가 잘 유지된다는 장점이 있지만,

  사전의 크기가 커진다는 단점이 있다.

 

- 단어로 토큰화를 하는 경우 텍스트에 등장하는 단어의 수만큼

  토큰 아이디가 필요하기 때문에 사전이 커진다.

  또한, 이전에 본 적이 없는 새로운 단어는 사전에 없기 때문에 처리하지 못하는 OOV 문제가 자주 발생한다. 

 

- 반대로 작은 단위로 토큰화하는 경우 사전의 크기가 작고 OOV 문제를 줄일 수 있지만,

  텍스트의 의미가 유지되지 않는다는 단점이 있다.

  단어 '파리'를 자모 단위로 나누는 경우 'ㅍ, ㅏ, ㄹ, ㅣ'로 나뉘는데,

  이렇게 나누면 파리의 의미가 거의 사라진다.

 

- 작은 단위와 큰 단위 모두 각각의 장단점이 뚜렷하기 때문에 최근에는 데이터에 등장하는 빈도에 따라 토큰화 단위롤 결정하는

  서브워드(subword) 토큰화 방식을 사용한다.

  서브워드 토큰화 방식에서는 자주 나오는 단어는 단어 단위 그대로 유지하고, 가끔 나오는 단어는 더 작은 단위로 나눠

  텍스트의 의미를 최대한 유지하면서 사전의 크기는 작고 효율적으로 유지할 수 있다. 

 

- 예를 들어, 인사말로 자주 사용하는 '안녕'이나 '대한민국' 같은 국가 이름, 유명한 사람의 이름과 같이

  자주 나오는 단어는 그대로 단어 형태를 유지하지만,

  한글 데이터에서 비교적 드물게 등장하는 외국어나 특수 문자, 이모티콘 등은 작게 나눠 사전 크기가 커지지 않도록 한다. 

  한글의 경우 보통 음절과 단어 사이에서 토큰화된다. 

 

- 텍스트를 숫자 아이디로 바꾸는 과정은 다음 코드로 수행할 수 있다. 

# 띄어쓰기 단위로 분리 
input_text = "나는 최근 파리 여행을 다녀왔다"
input_text_list = input_text.split()
print("input_text_list: ", input_text_list)

# 토큰 -> 아이디 딕셔너리와 아이디 -> 토큰 딕셔너리 만들기
str2idx = {word:idx for idx, wrod in enumerate(input_text_list)}
idx2str = {idx:word for idx, word in enumerate(input_text_list)}
print("str2idx: ", str2idx)
print("idx2str: ", idx2str)

# 토큰을 토큰 아이디로 변환
input_ids = [str2idx[word] for word in input_text_list]
print("input_ids: ", input_ids)

  

- 최근의 토큰화는 서브워드 토큰화가 기본이지만, 실습의 편의를 위해 단어 단위(띄어쓰기 단위)로 토큰화를 수행했다.

  앞으로 등장하는 예시나 예제에서도 표현의 편의상 단어 단위로 토큰화한 경우가 있을 수 있는데,

  실제로는 서브워드 토큰화를 활용한다는 점은 변함이 없으니 혼동이 없기를 바란다.

  

- 이 코드에서는 "나는 최근 파리 여행을 다녀왔다"라는 문장을 띄어쓰기 단위로 분리하고

  각각의 토큰에 0부터 토큰 아이디를 부여해 str2idx 딕셔너리에 저장한다.

  마지막으로, 각각의 토큰을 str2idx 딕셔너리로 토큰 아이디로 변환해서 input_ids에 저장한다.