Vector Database (feat. Pinecone)

tura·2023년 6월 8일
5
post-thumbnail

unzip.dev에서 뉴스레터가 날라왔다.

Vector Database가 뭘까. 궁금해서 한 번 알아봤다.

사전 지식: 벡터와 임베딩

벡터 데이터베이스에 대해서 알기 위해서는 벡터, 그리고 임베딩이라는 두 가지 개념에 대해서 알아야 한다.


벡터는 다음과 같은 숫자의 리스트다. 이게 왜 벡터일까?

[0.3512, 0.4837, 0.1996, ...]

벡터- 라고 하면 힘이나 속도같은 물리량을 보통 떠올리기 마련이지만, 사실 벡터는 좀 더 포괄적인 의미로 사용된다. 위키피디아에 따르면 단 하나의 숫자로 나타낼 수 없는 양을 벡터라고 한다.

In mathematics and physics, vector is a term that refers colloquially to some quantities that cannot be expressed by a single number (a scalar), or to elements of some vector spaces.

기계학습 분야에서는 모델 학습을 위해서 사용하는 데이터나 가중치 혹은 모델의 결과값으로 나타나는 값들을 모두 벡터의 형태로 취급한다. 이 글에서는 이런 맥락으로 사용할 예정.


임베딩은 정의에 따르면 "고차원의 데이터를 저차원으로 매핑하면서, 그 의미를 보존하는 것"이다.

차원이라는 건 뭘까? 차원이라는 개념도 벡터와 연관지어서 생각할 수 있다.
세 개의 값을 가지는 벡터는 3차원 벡터, N개의 값을 가지는 벡터는 N차원 벡터. 이런 식이다.

그러므로 "고차원의 데이터를 저차원으로 매핑한다"는 것은 높은 차원의 벡터를(가령 10000차원) 낮은 차원의 벡터로(가령 10차원) 변환한다는 뜻일 것이다.

다음으로 의미를 보존한다는 건 무슨 뜻일까? 여기서는 간단한 예시를 들어보는게 좋을 것 같다.

두 개의 64x64 사이즈의 고양이 이미지가 있다. 이미지의 크기는 64x64이므로 이 두 이미지는 흑백이라고 가정했을 때 4096차원의 벡터로 표현될 수 있을거다.

임베딩을 통해서 이 고차원의 벡터를 저차원의 벡터로 축소시킬 수 있고, 그 과정을 잘 조율한다면, 두 개체의 임베딩이 비슷할 때 그 개체가 근본적으로 비슷한 경향을 보이도록 할 수 있다.

즉, 차원은 축소되었지만 그 의미는 보존되는 것이다.

임베딩을 찾아보면서 두 가지 궁금한 점이 생겼다.

  1. 왜 굳이 임베딩을 해야할까?
    이건 비교적 쉽게 답할 수 있다. 우선, 데이터가 너무 커서 저장할 때 효율적이지 않고 의미적인 '유사도'를 측정하기 어렵다는 문제가 있다. 두 번째로 숫자가 인공지능 모델이 아주 잘 다룰 수 있는 표현 형식이라 그렇다.
  2. 어떻게 저 많은 픽셀을 몇 개의 숫자로 표현하면서 의미가 보존될 수 있을까?
    사실 저 많은 픽셀 중에 "고양이"라는 의미를 만드는 픽셀의 개수나 조합은 한정적이고, 전체 가능성 중 극히 일부분일 것이다. 이렇게 고차원의 데이터에서 "의미"를 가지는 정보는 극히 일부분이고, 이러한 의미를 잡아내는 어떠한 부분공간(Latent Manifold)이 존재한다는 가설을 Manifold 가설이라고 한다.
    임베딩을 잘 사용하면 고차원의 데이터를 저차원으로 변환할 때 Latent Manifold를 따라 놓이도록 만들 수 있을 것이다.

임베딩을 통해서 글, 이미지나 동영상같은 비정형 데이터를 숫자로 표현할 수 있게 되었다.

이 숫자들간의 유사도를 비교하면, 임베딩하기 이전의 원본이 서로 비슷한 것들을 찾아낼 수 있을 것이다. 이렇게 입력 벡터로부터 가장 유사한 벡터를 찾아내는 접근을 Nearest Neighbor 라고 한다.

유사한 벡터를 찾아낼 때, 한 벡터가 다른 벡터와 얼마나 가까운지를 나타내는 metric은 다양한데, 그 중에 몇 개를 소개하면 다음과 같은 것들이 있다.

  1. 코사인 유사도: 두 벡터 사이의 각도의 코사인을 측정해서 -1에서 1까지의 범위로 나타냄
  2. 맨해튼 거리: 두 벡터의 해당 좌표 사이의 절대 차이의 합을 계산합니다. (L1이라고도 함)
  3. 유클리드 거리: 유클리드 공간에서 두 벡터 사이의 직선 거리. (L2라고도 함)

어렵게 써놓긴 했지만 모두 중고등학교 시절 수학 시간에 배웠던 것들이다. 물론 이것보다 더 복잡한 것들도 있지만.. 기본적인 골자는 "두 벡터(점) 사이의 거리"를 계산하는 것이다. (벡터는 여러 숫자를 가지는 양이고, 각각의 숫자는 좌표계의 한 축에 해당하는 값으로 볼 수 있다.)

장단점

결과적으로 "벡터" 데이터베이스는 일반적인 DB와 다르게 이런 벡터들을 저장하고 있다는 걸 알 수 있다.

벡터 데이터베이스가 기존 DB에 비해 가지는 장점들은 어떤 것들이 있을까?

  • 저장된 데이터들의 의미를 기반으로 하는 쿼리가 가능하다.
  • 언급한 것처럼 벡터들끼리의 유사도를 측정하고 이를 기반으로 쿼리를 하는 것이 중요한데, 기존에 널리 사용되는 DB들은 텍스트를 포함한 다양한 데이터를 저장하고, 스키마들간의 관계를 통한 모델링에 포커스를 맞추고 있기 때문에 이러한 요구 사항을 만족시키기 어렵다. 벡터 데이터베이스는 애초에 벡터를 저장하기 위해 설계된 DB이니 기존 DB에 비해 벡터 저장을 더 효율적으로 할 수 있을 것이다.

반면에 단점들도 있다.

  • 벡터 데이터베이스가 저장하는 건 오직 벡터 뿐이다. <- 이 부분 검증 필요
  • "정확히 'Vector'라는 키워드가 포함된 글을 검색하기"와 같은 작업은 오히려 어렵다.

벡터 데이터베이스가 갑자기 떠오른 키워드이긴 하지만, 이런 특수성때문에 널리 사용되지는 않을 것 같고, AI 모델을 위한 메모리로 사용되거나.. 아니면 기존 검색 시스템에 보조적으로 사용될 수 있을 것 같다.

직접 써보기 (with Pinecone)

직접 사용해볼 수 있을까? 다행히 직접 설치하지 않고도 빠르게 사용해볼 수 있는 방법이 있다.

Pinecone은 사용하기 쉬운 클라우드 기반 벡터 데이터베이스 서비스다. 이를 사용하여 우리가 원하는 데이터를 벡터로 변환하고 이들을 데이터베이스에 저장할 수 있다.

나는 AI 연구자가 아니라 개발자인 만큼, 의미 기반의 검색이 쉽다는 점에 포커스해서 조금 색다른 검색 시스템을 만들어보려고 한다. 개요는 이렇다.

  1. 우선 다음 세 가지 주제에 대한 짤막한 글들을 ChatGPT를 통해서 생성한다. 안드로이드 앱 개발, 안드로이드 운영 체제, 그리고 아이폰 앱 개발.
  2. 작성한 글을 Pinecone에 저장한다.
  3. 잘 동작한다면, "안드로이드"라는 키워드로 앱 개발과 운영 체제에 관한 글을, 그리고 "앱 개발"이라는 키워드로 안드로이드 앱 개발과 아이폰 갭 개발에 관한 글을 찾을 수 있을 것이다.
  4. 만약 언어의 의미를 보존했다면 글을 한글로 작성했더라도 영어, 혹은 다른 언어로 검색했을 때 동일한 결과를 얻을 수 있어야 한다.

과정과 결과는 아래 링크에서 확인할 수 있다.

글 생성 내용
샘플 Gist (Colab)

간단하게 시도해본 결과, 3번까지는 굉장히 잘 됬는데, 4번은 아예 의미가 없는 수준이었다. 아무래도 임베딩을 위해서 사용한 Transformer가 한국어에 대한 이해도가 없어서 그런 것 같다. (찾아보니 한국어 임베딩에 관한 오픈소스 기여가 있었다.)


여기서는 Pinecone을 직접적으로 활용했는데, 기존 Postgres DB에 벡터 유사도 검색 기능을 추가해주는 오픈소스 Postgres 확장이 있다.

만약 일반적인 웹사이트에 유사도 기반 검색 기능을 추가하려고 한다면 처음부터 곧바로 벡터 DB를 도입하기보다, 이런 확장을 쓰는게 더 나을 수도 있을 것 같다.

결론

정리를 해보자면 다음과 같다.

  • 임베딩을 통해서 비정형 데이터의 의미를 보존하는 벡터를 만들 수 있다. (어떤 임베딩을 사용하는지에 따라 어떤 의미를 보존하는지가 달라진다)
  • 벡터 데이터베이스는 임베딩 벡터를 저장하는데 최적화된 데이터베이스다. 이미지 비전이나 LLM 등의 분야에서 벡터 임베딩에 대한 수요가 늘면서 많이 언급되고 있다.
  • 일반적인 DB와 달리 쿼리를 벡터로 변환한 뒤 벡터들간의 유사도를 기반으로 검색을 할 수 있다. 이 때문에 의미 기반의 검색이 가능하다.

글을 작성하면서 Pinecone에서 작성한 아티클을 많이 참조했는데, 무척 잘 정리가 되어있다. 기술적인 디테일이나 모호한 내용이 있다면, 아래 레퍼런스를 참고하면 좋을 것 같다.

이 레퍼런스들은 unzip.dev 글에서 언급하고 있는 것들인데, 너무 유용한 것 같아서 그대로 가져왔다.

0개의 댓글