지난 글에서는 임베딩 값을 2D로 시각화 하는 예제를 분석해 봤습니다.
오늘은 임베딩 값을 3D로 시각화 하는 예제를 분석해 보겠습니다.
openai-cookbook/Visualizing_embeddings_in_3D.ipynb at main · openai/openai-cookbook · GitHub
Visualizing embeddings in 3D
지난 2D 예제에서는 1536 차원의 데이터를 2차원으로 만들어서 2D로 visualization을 했습니다.
오늘 예제에서는 이것을 3차원으로 만들어서 3D로 visualization을 하는 겁니다.
이것을 위해서 PCA를 사용합니다. (2D에서는 t-SJE를 이용했습니다.)
이 예제에서 사용하는 dbpedia_samples.jsonl은 이곳에서 구할 수 있습니다.
openai-cookbook/dbpedia_samples.jsonl at main · openai/openai-cookbook · GitHub
이 데이터의 첫 두줄은 아래와 같습니다. (총 200 줄이 있습니다.)
{"text": " Morada Limited is a textile company based in Altham Lancashire. Morada specializes in curtains.", "category": "Company"}
{"text": " The Armenian Mirror-Spectator is a newspaper published by the Baikar Association in Watertown Massachusetts.", "category": "WrittenWork"}
text 와 category 두 항목이 있습니다.
text는 한 문장이 있고 category에는 말 그대로 카테고리들이 있습니다.
어떤 카테고리들이 있고 각 카테고리는 몇개씩 있는지 알아 보겠습니다.
여기서는 pandas 모듈을 사용합니다.
read_json()을 사용해서 데이터세트를 읽어 옵니다. (samples)
그리고 이 데이터세트의 category를 수집해서 unique 한 리스트를 만든 후 정렬을 합니다. (categories)
print("Categories of DBpedia samples:", samples["category"].value_counts())
이것을 위 방식으로 프린트를 하면 이런 결과를 얻습니다.
카테고리는 총 14개가 있고 그 중에 가장 많이 있는 카테고리는 Artist 로 21번 나옵니다.
그 외에 다른 카테고리들과 각 카테고리별 갯수를 표시합니다.
그리고 samples.head() 를 하면 아래 결과를 얻습니다.
text와 category를 표 형식으로 보여 줍니다. head()를 사용하면 디폴트로 상위 5줄을 print 합니다.
그 다음은 openai api를 이용해서 각 text별로 임베딩 값을 받아 옵니다.
import openai
from openai.embeddings_utils import get_embeddings
def open_file(filepath):
with open(filepath, 'r', encoding='utf-8') as infile:
return infile.read()
openai.api_key = open_file('openaiapikey.txt')
# NOTE: The following code will send a query of batch size 200 to /embeddings
matrix = get_embeddings(samples["text"].to_list(), engine="text-embedding-ada-002")
embeddings_utils 의 get_embeddings를 사용해서 각 text 별로 openai로 부터 임베딩 값을 받아 옵니다.
Note : openai api는 유료입니다. 200개의 데이터에 대한 임베딩값을 받아오는데 대한 과금이 붙습니다.
저는 이 소스코드를 테스트 하는 과정에서 1센트가 과금이 되었습니다.
2. Reduce the embedding dimensionality
from sklearn.decomposition import PCA
pca = PCA(n_components=3)
vis_dims = pca.fit_transform(matrix)
samples["embed_vis"] = vis_dims.tolist()
이 부분에서 각 아이템별 임베딩을 PCA를 이용해서 3차원으로 만든다.
sklearn.decomposition.PCA — scikit-learn 1.2.1 documentation
PCA는 Principal Component Analysis (주성분 분석) 의 약자이다.
고차원의 데이터 (high-dimensional data)를 저차원으로 축소하여 새로운 데이터를 생성하는 방법이다.
PCA를 사용하면 N차원 데이터의 정보를 최대한 보존하면서 저차원의 데이터로 표현할 수 있다.
<PCA의 원리 요약>
1. 수학적인 방법으로 원래 데이터의 주성분(Principal Component)을 찾는다.
주성분은 원래 데이터의 차원의 수만큼 나온다.
2. 축소하려는 차원의 수만큼 주성분을 사용하여 새로운 데이터를 만든다.
PCA(주성분분석)의 원리와 응용 (tistory.com)
이 부분에서 PCA를 이용해 3차원으로 만든 데이터를 vis_dims에 담습니다.
여기까지 만든 데이터를 출력해 보면 아래와 같습니다.
openai api로 부터 받은 임베딩 값 (1536 차원)을 3차원으로 축소 시킨 값입니다.
이 값들을 리스트 타입으로 만들어서 해당 데이터에 embed_vis 컬럼에 넣는 것이 그 다음 줄에서 하는 작업입니다.
이제 각 text들의 임베딩 값을 3차원으로 축소 했으니 3D 그래픽으로 표현 할 수 있습니다.
3. Plot the embeddings of lower dimensionality
여기서 제 경우에는 ipympl 모듈이 없다는 메세지가 나와서 이 모듈을 설치 해야 했습니다.
이 모듈은 jupyter Lab에서 matplotlib 모듈을 사용할 수 있도록 하는 모듈입니다.
ipympl — ipympl (matplotlib.org)
이제 matplotlib를 JupyterLab에서 사용할 수 있습니다.
이 matplotlib의 pyplot은 지난 예제에서도 산점도 그래프를 그릴때 사용했었습니다. (scatter)
%matplotlib widget
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(figsize=(10, 5))
ax = fig.add_subplot(projection='3d')
cmap = plt.get_cmap("tab20")
# Plot each sample category individually such that we can set label name.
for i, cat in enumerate(categories):
sub_matrix = np.array(samples[samples["category"] == cat]["embed_vis"].to_list())
x=sub_matrix[:, 0]
y=sub_matrix[:, 1]
z=sub_matrix[:, 2]
colors = [cmap(i/len(categories))] * len(sub_matrix)
ax.scatter(x, y, zs=z, zdir='z', c=colors, label=cat)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
ax.legend(bbox_to_anchor=(1.1, 1))
pyplot의 figure() 함수는 이제 모양을 시작하겠다는 겁니다.
여기서는 figsize라는 파라미터를 사용했는데 Width, height 를 인치로 나타내는 겁니다.
그외 다른 파라미터들도 많은데 자세한 내용은 아래 페이지를 참조하세요.
matplotlib.pyplot.figure — Matplotlib 3.7.0 documentation
그 다음 나오는 add_subplot은 해당 figure에 Axes를 추가하는 것입니다.
matplotlib.figure — Matplotlib 3.7.0 documentation
[EDA Practice] Subplot 그리기 (tistory.com)
여기서는 projection 파라미터를 사용해서 3D 그래프로 그리도록 합니다.
그 다음 get_cmap()은 원하는 colormap의 타입을 정할 때 사용합니다. 여기서는 tab20 을 선택했습니다.
matplotlib.pyplot.get_cmap — Matplotlib 3.7.0 documentation
이 예제에서 사용한 tab20은 아래와 같이 설명 돼 있습니다.
Choosing Colormaps in Matplotlib — Matplotlib 3.7.0 documentation
다음에 나오는 for 문은 레이블 이름을 설정할 수 있도록 각 샘플 범주를 개별적으로 플로팅 합니다.
3차원을 위한 x,y,z에 해당 값과 color를 배정하고 scatter를 이용해서 3차원 좌표 안에 점을 찍습니다.
matplotlib.pyplot.legend — Matplotlib 3.7.0 documentation
legend() 함수는 정해진 legend를 어디에 위치할지 정하는 겁니다.
이 예제에서는 bbox_to_ancho,r 파라미터를 사용했는데 이 파라미터도 위 링크에 가시면 자세하기 볼 수 있습니다.
legend를 어디에 위치시키느냐를 결정하는 겁니다.
결과값은 아래와 같습니다.
참고로 legend는 오른쪽에 있는 범례 (Album, Animal ....) 입니다.
이 부분을 아래와 같이 고쳐 보겠습니다.
ax.legend(loc = 'lower right')
그러면 이 범례 부분의 위치가 바뀌었습니다.
이렇게 bbox_to_anchor는 그래프 밖에 범례를 위치시키고 싶을 때 사용합니다.
이 Openai api CookBook의 예제를 실행하면 아래와 같은 결과를 얻습니다.
각 카테고리 별로 다른 색으로 표시된 점들이 3차원 그래프 안에 표시 돼 있습니다.
이러면 어떤 카테고리에 있는 데이터들이 어느 위치에 분포해 있는지 알 수 있게 됩니다.
오늘 예제는 openai api로 부터 받은 리스트의 아이템별 임베딩값(1536 dimention) 을 PCA를 이용해서 3 차원 (3 dimention)으로 바꾸는 작업을 1차로 했습니다.
그 다음 matplotlib.pyplot 모듈을 이용해서 이 3차원 데이터들을 3차원 그래픽으로 표현을 했습니다.
'Open AI > CookBook' 카테고리의 다른 글
Openai cookbook : GPT - 3 , Guide How to work with large language models (0) | 2023.03.01 |
---|---|
Openai cookbook - API usage - How to stream completions (0) | 2023.03.01 |
Openai cookbook - API usage - How to count tokens with tiktoken (0) | 2023.03.01 |
Openai cookbook - API usage - How to handle rate limits (0) | 2023.02.28 |
Openai cookbook - Embeddings - Embedding long inputs (1) | 2023.02.26 |
Openai cookbook - Embeddings - Visualizing embeddings in 2D (1) | 2023.02.25 |
Openai cookbook - Embeddings - Clustering embeddings (0) | 2023.02.24 |
Openai cookbook - Embeddings - How to get embeddings (0) | 2023.02.24 |
Openai cookbook - Embeddings - Text comparison examples - Customizing embeddings (0) | 2023.02.17 |
Openai cookbook - Embeddings - Text comparison examples - Recommendation using embeddings (0) | 2023.02.16 |