Bi-Encoder의 장점은 임베딩한 벡터를 미리 연산을 해두어 속도가 빠르다는 장점이 있다.
여기서 임베딩값들을 메모리(RAM) 자원에 가지고 있는 것이 가장 좋지만 전 포스팅에서 이야기하였듯이 높은 메모리는 곧 서버 비용이다.
비용 절감을 위해서 벡터를 문자열로 변환해서 RDBMS에 저장해서 불러오는 방식으로 구현하기로했다.
flaot 형식으로 저장하지 않고 문자열로 저장하는 이유는 문자열로 저장하는 것이 용량도 적게 들고 768열로 각각의 float를 저장해서 불러오는 것보다. 문자열로 저장한 값을 numpy에 np.fromstring() 매서드를 사용하는 것이 더 효과적이기 때문이다.
하지만 위 방법에는 몇 가지 문제가 있다.
1. 문자열의 길이가 너무 길다.
: BERT는 기본적으로 768차원이고 flaot32를 기준으로 했을 때 평균적으로 8500자~9000자 정도의 문자열 길이를 가진다.
2. 문자열 길이가 길어서 RDBMS에서 fetch 하는데 오랜 시간이 걸린다.
: 문자열의 길이와 fetch 속도는 비례한다.
그래서 어쩔 수 없이 flaot32를 float16으로 바꿔서 저장해서 속도 문제를 해결할 수 있었다.
평균 9000자에서 4500자로 줄었기 때문에 속도도 2배로 빨라졌다.
flaot16이면 당연히 flaot32보다 정확도가 떨어질 수밖에 없다.
다른 방법을 찾던 중 vector를 문자열로 저장할 때 숫자를 유지할 필요가 없을 수도 있겠다는 생각을 했고
결과적으로 flaot32 형식을 유지하면서 3870자로 저장할 수 있는 방법을 찾았다.
해결 방법:
(1). vector를 byte 형식으로 변경한다.
byte 형식으로 변경하면 위 문자로 변경되는데 위 문자를 그대로 문자열로 변경하여 저장해도 좋을 것 같지만
byte를 str로 변경하는 과정에서 '\' 문자가 '\\'로 변경되어 문자열의 길이가 늘어나고
'//'로 변경된 상태에서 다시 byte 형식으로 변경하기가 어렵다.
(2). byte형식을 base85 형식으로 변경한다.
base85 형식은 '\'문자를 사용하지 않기 때문에 위 문제가 나타나지 않는다.
Base64도 있고 Base85도 있는데 왜 하필 Base85 이냐 하면 단순하게 Base85로 인코딩한 문자열이 더 적기 때문이다.
*아마 Base85가 더 많은 방법으로 표현할 수 있기 때문이 아닌가 싶다.
(3). base85 형식을 string 형식으로 변경하여 RDBMS에 저장
decode() 함수를 사용하면 바로 문자열 형식으로도 변경이 가능하다.
768차원 flaot32를 Base85 문자열로 변경하면 일정하게 3870자가 나온다.
Python 코드로 구현
import base64
import numpy as np
#-------벡터를 문자열로 변환-------------------
#랜덤으로 768차원의 flaot32 벡터 생성
random_v = np.float32(np.random.random(768))
# vector를 byte타입으로 변경
v = random_v.tobytes()
# byte타입을 base85로 인코딩하고 문자열로 변환
v_tostring = base64.b85encode(v).decode()
#--------문자열을 벡터로 변환-------------------
#base85 문자열을 byte 타입으로 디코딩
v_decode = base64.b85decode(v_tostring)
# random_v 와 동일한 vector로 복원
original_v = np.frombuffer(v_decode,dtype = np.float32)
각각을 RDBMS에 저장
기존 방법과 비교
여기서 이제 문자열을 RDBMS에서 불러와서 디코딩하는데 시간이 걸릴 수 있는데
fetchall()을 할경우 불러오는 데이터 수에 따라서 디코딩 속도는 그 만큼 배가 되기 때문에
많은 select를 할 경우에는 사용하는 것을 권장하지 않는다.
'Machine learning > NLP' 카테고리의 다른 글
[NLP]. 오타 생성기 구현하기 : Text Noise Augmentation (1) | 2022.10.29 |
---|---|
[NLP]. 챗봇 답변 Top-k sampling 구현 (0) | 2022.09.27 |
[NLP]. 구어체(채팅)데이터에서 필요한 품사만 가져오기 (feat.꼬꼬마 형태소 분석기) (0) | 2022.03.04 |
[NLP]. 도로명 주소 & 지번 주소 인식 정규표현식 (0) | 2022.01.11 |
[NLP] Fine-tuning(파인튜닝)과 in-context learning(인컨텍스트 러닝) (0) | 2021.12.14 |