OpenAI Embeddings APIとSimCSEをふんわりと定性的に比較する

# まえがき
最近も変わらずChatGPTなどのLLMが盛り上がっています。
OpenAIのLLMというとテキストの入力に続けて返すチャットボットとして使われる印象が強いですが、
少し前にテキスト生成の話題に混じってOpenAIで[文章ベクトル化API](https://platform.openai.com/docs/guides/embeddings/what-are-embeddings)が出ているとの情報を見て

「LLMで生成されたembeddingか〜、BERT系のモデルで生成したのとどう違うんだろう？」

と思ったので、比較してみます。




## 関連記事
自分で比較する前に、公開されている記事を少し調べてみました。
### JSTSデータセットによる評価
こちらの記事では、OpenAIのEmbeddings APIをSimCSEや教師あり学習をした際のBERTと比較しています。

https://qiita.com/akeyhero/items/ce371bfed64399027c23

* 教師なし学習ではOpenAIの結果も悪くはありませんでした（SimCSEの方がスコアが良いですが）。
* 教師あり学習をした場合にはBERTなどローカルで学習できるモデルのスコアの方が良い結果となっています。

### 医療テキストによる比較
続いてこの記事では医療テキストを用いて比較しています。

https://fintan.jp/page/9002/
* この記事でも、既に提案されていたJMedRoBERTaというモデルの方がOpenAI Embeddings APIよりも良いスコアを出しています。

---
2つの記事を見ると、どちらも定量評価して従来手法の方で良いスコアが確認されていて、OpenAI Embedding APIってそんななのかなー？という感じがしてきます。
しかしそこで

「OpenAIのEmbeddings APIはそんなに良くない！解散！」

となっても面白くないです。
定性的に見てみるとどのような違いが出てくるでしょうか。
（あんまり期待はしてないですが）そこで何か違いがあればそれはそれで勉強になりますよね。

ということで本記事では、両者をふんわりと定性的に比較してみようと思います。
サンプルとしてクチコミデータを使用し、エンコードされた結果どのようなテキストが近いベクトルとして出力されているのかを確認してみます。



# データセット準備
## データセット
リクルートが公開している[じゃらん](https://github.com/megagonlabs/ebe-dataset)のデータセットを使用します。
プレス↓

https://www.recruit.co.jp/newsroom/2020/1019_18866.html

データセットは次の2種類で構成されます。
* 含意関係データセット
  >「部屋はオーシャンビューで景色がよかったです。」という文が成り立つとき「部屋から海が見える。」という文も成り立つかどうか（含意関係の有無）というラベルを付与したデータセットです。(約55,000件)
　ポジティブ／ネガティブ／ニュートラルといった感情極性ラベルや、宿の特徴が含まれているかどうかというラベルも付与した文も含まれています。（約5,600件）
* 根拠説明データセット
  >宿をお薦めする際に、ユーザーの要求に対する推薦根拠を説明するためのデータセットです。（約37,300件）
　例えば、「お子様連れに優しい宿」を求めるユーザーに対して、「この宿には大きなキッズスペースがあるので、あなたにオススメです」と根拠付きで返答することを目指しています。文単位で要求に対応する根拠かどうかをラベル付けし、その後、根拠と判断された文を推薦文へと言い換えています。

（個人的な事情から）今回はただの口コミレビューのようなデータを扱いたいです。

幅広い表現が含まれる方が好ましく、根拠説明データセットを少し覗いたところ色々と含まれていそうだったため、今回はこちらのデータを使用して比較していきます。

## 整形
じゃらんデータには根拠説明判定のタスクを行いやすいように`一文目[SEP]二文目`のフォーマットで整えられている物が含まれます。

今回はただのテキストが欲しいので、ひとまず`二文目`だけ取得するように少し修正します。
### 修正前
```
穴場 の ホテル [SEP] 他 府県 の 方 に は 、 市 内 中心 部 から 離れて いる ように 思わ れ がちの 地域 です が 、 実は 近くて 価格 を 考える と 、 大阪 の 穴場 的な ホテル と 思い ます 。
古い けど キレイです [SEP] 通路 室 内 など 、 見た 感じ は 築年 数 が 長い 感じ が し ます が （ エレベーター の 動作 も 遅い です ） 清掃 整理 さ れて いる ので 悪い 印象 は あり ませ ん でした 。
アクセス の 良い ホテル です 。 [SEP] スカイツリー も ディズニー も 近く 駅 も 近い ので 便利な 場所 です 。
```
### 修正後
```
他府県の方には、市内中心部から離れているように思われがちの地域ですが、実は近くて価格を考えると、大阪の穴場的なホテルと思います。
通路室内など、見た感じは築年数が長い感じがしますが（エレベーターの動作も遅いです）清掃整理されているので悪い印象はありませんでした。
スカイツリーもディズニーも近く駅も近いので便利な場所です。
```
### スクリプト
（短いですが）修正に使用したスクリプトです。
```python
# ebe-dataset/evidence_explanation_dataset にあるデータを整形して
# ebe-dataset/evidence_explanation_prepared に吐き出す

from glob import glob

glob_path = 'ebe-dataset/evidence_explanation_dataset/*.src'
paths = glob(glob_path)
os.mkdir('ebe-dataset/evidence_explanation_prepared')

def extract_text(text):
    space_deleted = text.replace(' ', '')
    extracted = space_deleted.split('[SEP]')[1]
    return extracted

for path in paths:
    with open(path) as f:
        lines = f.readlines()
    extracted_lines = list(map(extract_text, lines))
    content = ''.join(extracted_lines)
    with open(path.replace('evidence_explanation_dataset', 'evidence_explanation_prepared'), 'w') as f:
        f.write(content)
```

実際には、以下のようなクチコミデータをエンコードに使用していきます。

```
サービスについては普通のビジネスホテルですが、朝食つきでしかも子どもは無料だったので、コストパフォーマンスはかなり高い方だと思います。
４，５００円というお安い料金だったので、正直、期待はあまりしていませんでしたが、ベッドも洗面所も広く、とても清潔感のあるホテルでよかったです。
デパートが至近なのに１本裏の為前日に利用したホテルよりとても静かに感じました。
ホテル全体が新しくて綺麗ですし、立地もすごく便利だと思います。
日曜市をめあてに行ったので、朝食はパスしようかと思っていたのですが、旅行中につい不足がちになってしまう野菜がふんだんにあり、ついつい食べてしましました。
この朝食が無料とは驚き！
ヒメマスが美味しくて、夕食を囲炉裏会席にして良かったと思います。
由布院駅と金鱗湖のほぼ中間地点に位置しており歩いて観光するのに大変便利です。
事前に冷蔵の荷物を預かっていただいたことなど、融通を利いていただき助かりました。
そして何より嬉しかったのは、誕生日ケーキを持参してるのを察して、チェックイン後に部屋までナイフとフォークを持ってきていただいたことに感動しました。
何気ないところに、工夫がこなされていて思わず感心し、あったかさを感じ心が和らいできます。
思っていたよりお部屋が可愛いので、気分良く泊まらせていただきました。
部屋タイプお任せプランを利用しましたがすてきな部屋にびっくり広い、ゆったり、内装も凝っててゴージャス気分が味わえます。
どこも案内や対応があんまりな中、こちらの電話対応はすごく丁寧で分かりやすく素晴らしかったです。
さすが「じゃらんアワードユーザーが選んだ接客サービス１位」を受賞したホテルだけあってサービスは満点以上です。
シャンプーやコンディショナーも良い物を使っているなと思いました。
高級旅館というわけではありませんが、宿泊料金が安いので、年金生活の方も利用しやすいと思います。
部屋からや露天風呂からの海や島の眺めは、天気も良く波も穏やかで最高でした。
部屋のトイレも広くて綺麗で、海も見えてよかったです。
部屋も広く、ゆったりとした時間が流れる空間と感じることができました。
...
```

# SimCSEによるEmbedding
それでは、実際にSimCSEを使用してクチコミデータのEmbeddingを取得していきます。

今回は以下リポジトリのモデルを使用します。

https://huggingface.co/pkshatech/simcse-ja-bert-base-clcmlp

## エンコード
Huggingface Hubからモデルをダウンロードし、読み込んだクチコミデータをエンコードします。
```python
from sentence_transformers import SentenceTransformer

model = SentenceTransformer('pkshatech/simcse-ja-bert-base-clcmlp')
embeddings = model.encode(lines)
```

エンコードされたEmbeddingは768次元になっています。

## 近傍ベクトルを算出
近傍のベクトルを算出します。
算出にはscikit-learnのNearestNeighborsを使用します。
```python
from sklearn.neighbors import NearestNeighbors

# ベクトル間の距離はコサイン類似度を使用
nn = NearestNeighbors(metric='cosine')

nn.fit(embeddings)

# 自身(anchor) + 近傍5件 で n_neighbors=6 を指定
dists, result = nn.kneighbors(embeddings, n_neighbors=6)
```

## 近傍の口コミを確認
ベクトルが近くなった口コミを検索します。
例として、今回は近かったクチコミ上位5件を1入力のみで確認します。

```
入力： サービスについては普通のビジネスホテルですが、朝食つきでしかも子どもは無料だったので、コストパフォーマンスはかなり高い方だと思います。
1位： 相変わらず子どもへのサービスも行き届いた最高のホテルでした。
2位： 朝食はもう少し品数が欲しいところだが、コスパの高いビジネスホテルと言えるでしょう。
3位： 一般のビジネスホテルより宿泊費はやや高めですが、グレードが高く割安感がありました。
4位： ビジネスホテルでありながら和室も大浴場もあるので、子供連れで利用しやすいと思いました。
5位： 朝食は無料なのにすごくおいしかったですまた、利用したいと思えたホテルです
...
```

子供へのサービスやコストパフォーマンスの話題が入力のみでなく1位、2位でも見られ、近い口コミがEmbeddingsとしても近傍にあることが分かります。

## Embeddingsの散布図
SimCSEでエンコードしたEmbeddingsをPCAで2次元に圧縮した際の散布図を作成しました。
作成にあたって使用したスクリプトが以下になります。

```python
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA

# PCAで2次元に削減
pca = PCA(n_components=2)
emb_pca = pca.fit_transform(embeddings)

# cmapをplasmaに指定
cmap = plt.get_cmap("plasma")

# 最大長さは75文字
max_len = 75 

# 描画
plt.figure()
for i in range(len(emb_pca)):
  plt.scatter(emb_pca[i,0], emb_pca[i,1], alpha=0.5, color=cmap(len(lines[i])/max_len))
plt.grid()
plt.colorbar()
plt.show()
```

# OpenAI APIによるEmbedding
次に、OpenAIのAPIを使用して口コミデータのEmbeddingを取得してみます。

PricingでDavinciやCurieなどラインナップがあると思っていたのですが、Embeddings APIでは「とりあえずこれ使っとけ」的なモデルとして`text-embedding-ada-002`が公開されているようです。
もう少し補足すると、安いし使いやすくなってるからこっちの方がいいぞ、とのことでした。

以下のv2モデルのリリース記事ではより詳しく先代モデルとの比較を確認できます。

https://openai.com/blog/new-and-improved-embedding-model

## エンコード
OpenAI Embeddings APIにリクエストを投げて、口コミデータをエンコードしていきます。
APIを利用するためには、以下ページでAPIキーを払い出し、

https://platform.openai.com/account/api-keys

さらにアカウントに支払い情報を登録し課金額上限を設定する必要があります。

参照：

https://qiita.com/kotattsu3/items/d6533adc785ee8509e2c

**スクリプト**

```python
import openai

# APIキーを以下のOpenAIページから払い出す
# https://platform.openai.com/account/api-keys
openai.api_key = 'xx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'

# Embeddings格納用のリスト
res_lines = []

# 2191件を一括で投げたところInvalidRequestErrorとなってしまったため
# ざっくり313件ずつ分割してリクエストを投げる
for i in range(0, len(lines), 313):
  line_res = openai.Embedding.create(
    model='text-embedding-ada-002',
    input = lines[i:i+313]
  )

  # レスポンスのjsonからembeddingを取り出してリストに入れる
  for j in range(313):
    res_lines.append(line_res['data'][j]['embedding'])
```

OpenAIでは、それぞれのEmbeddingは1536次元で表現されています。

## 近傍ベクトルを算出
SimCSEと同様に近傍ベクトルを算出します。
※ 同様の処理のためスクリプトは省略

## 近傍の口コミを確認
同じくベクトルが近くなった口コミを検索します。

先ほどと同様、近かったクチコミ上位5件を1入力のみで確認します。

```
入力： サービスについては普通のビジネスホテルですが、朝食つきでしかも子どもは無料だったので、コストパフォーマンスはかなり高い方だと思います。
1位： お部屋は一般的なビジネスホテルとしては普通かなと思いましたが、朝食はおかずの点数がとても多く充実していました。
2位： ビジネスホテルでありながら和室も大浴場もあるので、子供連れで利用しやすいと思いました。
3位： 過剰なサービスがあるわけでもなく、ごく普通のホテルなのですが、値段も手頃で気楽に利用できる良い宿だと思います。
4位： 一般のビジネスホテルより宿泊費はやや高めですが、グレードが高く割安感がありました。
5位： ここ数年各地のビジネスホテルを利用していますが部屋の広さ、アメニティのサービス、朝食、清潔度、スタッフの方の対応、宿泊料金、とにかく快適で満足しました。
```

いくつかSimCSEと同じ口コミが出力されましたが、順位は異なっているようです。
またビジネスホテルとしての評価であることや、朝食へ言及していることなどは入力の口コミと共通していることが分かります。

## Embeddingsの散布図
SimCSEと同様に散布図を作成します。
※ 同様の処理のためスクリプトは省略

# 比較
今回は
* 近傍ベクトルの比較
* Embeddingsの散布図

の2点を見ていきます。

（いずれともふわっとした評価なので悪しからず。。。）

## 近傍ベクトルの比較
Embeddingsを比較して近傍にあったクチコミデータを少し確認してみます。

近傍として出力されたベクトルに違いはあるのでしょうか。

### #1
```
# SimCSE
入力： サービスについては普通のビジネスホテルですが、朝食つきでしかも子どもは無料だったので、コストパフォーマンスはかなり高い方だと思います。
1位： 相変わらず子どもへのサービスも行き届いた最高のホテルでした。
2位： 朝食はもう少し品数が欲しいところだが、コスパの高いビジネスホテルと言えるでしょう。
3位： 一般のビジネスホテルより宿泊費はやや高めですが、グレードが高く割安感がありました。
4位： ビジネスホテルでありながら和室も大浴場もあるので、子供連れで利用しやすいと思いました。
5位： 朝食は無料なのにすごくおいしかったですまた、利用したいと思えたホテルです

# OpenAI Embeddings API
入力： サービスについては普通のビジネスホテルですが、朝食つきでしかも子どもは無料だったので、コストパフォーマンスはかなり高い方だと思います。
1位： お部屋は一般的なビジネスホテルとしては普通かなと思いましたが、朝食はおかずの点数がとても多く充実していました。
2位： ビジネスホテルでありながら和室も大浴場もあるので、子供連れで利用しやすいと思いました。
3位： 過剰なサービスがあるわけでもなく、ごく普通のホテルなのですが、値段も手頃で気楽に利用できる良い宿だと思います。
4位： 一般のビジネスホテルより宿泊費はやや高めですが、グレードが高く割安感がありました。
5位： ここ数年各地のビジネスホテルを利用していますが部屋の広さ、アメニティのサービス、朝食、清潔度、スタッフの方の対応、宿泊料金、とにかく快適で満足しました。
```
入力は「ビジネスホテルとしては普通」で、「朝食付きで子供は無料」のため「コスパはかなり高い」という内容です。

SimCSEの結果は1位、2位は近い内容と言えそうです。ただ4位などは「子連れにおすすめ」なだけなので、あまり近いとはいえなさそうです。

OpenAI Embeddings APIの方は、まず「コスパが良い」というレビューが出力されていません（４位：「グレードが高く割安感」はニアピンですが）。SimCSEでも4位に表示されていた「ビジネスホテルでありながら和室も大浴場も...」というレビューはOpenAIモデルでは2位に表示されていて、あまり関係ないもののより近傍に寄ってしまったと思われます。

#1では、SimCSEの結果の方が良いと言えそうです。

---

### #2
```
# SimCSE
入力： ４，５００円というお安い料金だったので、正直、期待はあまりしていませんでしたが、ベッドも洗面所も広く、とても清潔感のあるホテルでよかったです。
1位： 料金が安く、清潔感もあり、いいホテルでした。
2位： 普通の安いビジネスホテルと思ってましたが、広くはないけど部屋はとても綺麗で、温泉もとても気持ちよかったです。
3位： ビジネスホテルで低価格なのに、ホテルは開放的で清潔感もあります。
4位： 過剰なサービスがあるわけでもなく、ごく普通のホテルなのですが、値段も手頃で気楽に利用できる良い宿だと思います。
5位： ホテル自体新しいので清潔感があり、風呂、デスク、洗面、ベッドも必要十分で、コストパフォーマンスは良いです。

# OpenAI Embeddings API
入力： ４，５００円というお安い料金だったので、正直、期待はあまりしていませんでしたが、ベッドも洗面所も広く、とても清潔感のあるホテルでよかったです。
1位： 料金が安く、清潔感もあり、いいホテルでした。
2位： お値段が手頃だったので撰んだのですが、お部屋もとてもきれいで居心地がよかったです。
3位： 素泊まりで安い宿ということだけで予約をし、それほど期待せずに、行ったのですが、全体的に清潔感があり、綺麗で驚きました。
4位： 普通の安いビジネスホテルと思ってましたが、広くはないけど部屋はとても綺麗で、温泉もとても気持ちよかったです。
5位： 価格が安く、風呂、朝飯付きで大変満足でした。
```
次は「期待していなかった」が、「ベッドと洗面所が広かった」かつ「清潔感があった」ため「良かった」、というものです。

SimCSEは全体的にうまく算出されているようですが、「広くはないけど」という文言が2位に入っています。ただ、他の口コミは近い内容が出力されています。

OpenAIの方も全体的に同じようにうまく算出されている印象ですが、5位のものがほとんど関係ない内容になっています。

#2では、わずかにSimCSEの結果の方が好ましいように思います。

---

### #3
```
# SimCSE
入力： デパートが至近なのに１本裏の為前日に利用したホテルよりとても静かに感じました。
1位： ホテルは繁華街とは逆方向に位置しますが、その分静かで良かったです。
2位： また、オフィス街近くのホテルなので、小ぶりですが静かで落ち着くホテルです。
3位： 繁華街にあり便利がいいのに、ホテル中は静かでボーッとする落ち着くホテルです。
4位： 道路から敷地を１ｋｍほど入った所に立っているため大変静かでいいホテルです。
5位： ビジネスホテルでは周りがうるさい時もありますが、繁華街から少し離れてる住宅地にあるので静かで良かったです。

# OpenAI Embeddings API
入力： デパートが至近なのに１本裏の為前日に利用したホテルよりとても静かに感じました。
1位： 駅からも近く、意外と静かなところで居心地よく泊まれました。
2位： 繁華街から離れているので、静かで落ち着いたホテルでした。
3位： 出張での利用でしたが、コンビニ、飲食店、繁華街に近いのに静かでした。
4位： お部屋からのロケーションがとにかく最高で、本当に静かでのんびりできました。
5位： ホテルは繁華街とは逆方向に位置しますが、その分静かで良かったです。
```
入力は「繁華街に近いわりに静か」といったところでしょうか。ただの「静か」ではなく逆説的なニュアンスが入っていて評価に向いている口コミですね。

SimCSEでは1位、2位はそのまま「静か」に引っかかっていますが、3位、4位では入力に近いニュアンスが込められています。

OpenAIの方では、入力に近いニュアンスが1位、3位に入っています。

この例では、OpenAI Embedding APIの方が「繁華街が近いのに静か」というニュアンスを上位に出せていて、逆説的でしたがうまく扱えているようです。

#3では、OpenAIの方が良い結果のように見えます。

---

### #4
```
# SimCSE
入力： ホテル全体が新しくて綺麗ですし、立地もすごく便利だと思います。
1位： 建物は新しくありませんが細かい気配り、サービスの良いホテルだと思います。
2位： 新しい感じのきれいなホテルでした。
3位： まだ新しいホテルなのでお部屋は綺麗に保たれていて気持ちいいですね。
4位： 新しさも感じるキレイなホテルです。
5位： ホテルが新しいため、清潔感があり気持ちよかったです。

# OpenAI Embeddings API
入力： ホテル全体が新しくて綺麗ですし、立地もすごく便利だと思います。
1位： ホテルは新しく清潔な感じがして、機能的でとても快適に過ごすことができました。
2位： ホテルは全体的に清潔感があり、設備も整っているので快適です。
3位： 新しいホテルだけあって設備も新しく、部屋の掃除も行き届いていると感じました。
4位： まだ新しいということもあり、大変きれいで清潔感のあるホテルでした。
5位： まだ新しいホテルなのでお部屋は綺麗に保たれていて気持ちいいですね。
```
今回はシンプルです。「新しくて綺麗」で、「立地がすごく便利」という入力です。

SimCSEでは、まず1位に 大丈夫ですか...と思ってしまう結果が出ました。他は「新しくて綺麗」は拾えていますが立地の観点が一切入っていません。"立地"自体は2191件中52件が言及しているため、他に拾ってくれても良さそうなものでしたが。

OpenAIの方もSimCSEのような外し方はしないものの、いずれとも「綺麗です」といった方向に持ってかれていて、立地の観点が抜けています。

#4ではどちらも五十歩百歩な印象です。

---

### #5
```
# SimCSE
入力： 日曜市をめあてに行ったので、朝食はパスしようかと思っていたのですが、旅行中につい不足がちになってしまう野菜がふんだんにあり、ついつい食べてしましました。
1位： 出発が早い日があったので、朝食をキャンセル旨お願いしたところ、朝食の時間を前倒しして調整して提供していただきました。
2位： 朝食はバイキングでしたが、種類も豊富で食べ過ぎてしまうくらいおいしくいただくことができました。
3位： 夕朝食ともバイキングで、期待通りの料理の豊富さ、味付けも良かったです。
4位： 徒歩範囲に観光場所がありゆっくり過ごせる場所朝食はバイキングでどれもとても美味しくコストパフォーマンスはとても良かったと思う。
5位： ２回目の利用でしたが、朝ごはんのバイキングのメニューが豊富で、とても良かったです。

# OpenAI Embeddings API
入力： 日曜市をめあてに行ったので、朝食はパスしようかと思っていたのですが、旅行中につい不足がちになってしまう野菜がふんだんにあり、ついつい食べてしましました。
1位： お食事はどれも美味しく朝食時は時間が足りない程でした。
2位： 朝御飯も夕御飯も美味しい野菜がたくさんで最初は食べきれないかと思いましたがしっかりいただきました。
3位： 朝食のみのプランにしたため夕食は外で食べましたが、新潟駅前の繁華街のため選びたい放題といった感じでした。
4位： 朝食、夕食ともに大変美味しく、ついつい食べ過ぎてしまいました。
5位： 出発が早い日があったので、朝食をキャンセル旨お願いしたところ、朝食の時間を前倒しして調整して提供していただきました。
```
5点目もまた特徴的な口コミです。なんと言及しているのは朝食のみで、要約すると「食べ過ぎちゃった」という口コミです。でもホテルのご飯って美味しくて食べ過ぎちゃいますよね。分かります。

SimCSEの結果では、2位がざっくり言うと「おいしかったです」なので少し近いでしょうか。他にも4位では旅行先の目的もからめられています。1位はあまり関係ないようですが、"パス"を"キャンセル"の意味で拾ってしまっている可能性もありますね。

OpenAIの方では、1位「どれも美味しかった」、2位「全部食べました」が並びます。そして4位には「食べ過ぎちゃった」が拾えています。他はあまり関係ない口コミのようです。

#5の例では、少しOpenAIの方が良い様子でしょうか。

---

#1~#5をふんわりと確認してみて、近傍ベクトルの結果を少し見ただけでは優劣をつけるのは難しいように思いました。
ただ、#3でOpenAI Embeddings APIが逆説的なニュアンスもうまく扱えていた点が印象的でした。
もし精度が変わらないとすれば、同じことがローカルで実行可能ならわざわざOpenAIのAPIを叩きにはいかないよね、と言えそうです。

## Embeddingsの散布図
続いて、EmbeddingsをPCAで2次元に削減したデータの散布図を確認してみます。
※ プロットの色はその口コミデータのテキストの長さで変えています（短い→0, 長い→1）。

### SimCSE
パッと見た印象ですが、SimCSEのEmbeddingsでは短い文章（紫色）は大きく2つに左右で分かれており、長い文章(黄色）は散布図中に満遍なく広がっているようです。

文字列の長さで分布が割れる可能性を考えていましたが、2次元だけで綺麗に分離されることはなさそうです。

![スクリーンショット 2023-06-01 23.04.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203679/00e924cd-511c-73cb-7b6e-5ec26c675828.png)

### OpenAI Embeddings
SimCSEと同様のフォーマットで描画しています。
SimCSEと比較して分布が大きく変わるものと想定していましたが、思っていたよりも両者の分布が似ています。

分布全体がやんわりと三角形状に分布している点は両者で共通しているようです。

一方で、SimCSEでは文字列長に従って分布が分かれていく様子がありましたが、OpenAIのモデルではその傾向が弱まり分布の隔たりが文字列長以外に移っているような印象でした。

![スクリーンショット 2023-06-02 23.34.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203679/4f27dd0c-2d4e-bbe6-5760-93a4e8e61434.png)


# おわりに
今回はじゃらんのホテル口コミデータセットを用意して、SimCSEとOpenAI Embeddings APIをふんわりと比較しました。

比較には
* 近傍ベクトルの口コミ
* PCAによってEmbeddingsを2次元に削減した際の散布図

を使用しました。

アプローチがアプローチであるためはっきりとした優劣はつけられませんが、出力のされ方に少し違いが見られることが分かりました。

個人的には OpenAIのモデルでは逆説的な表現も文脈としてEmbeddingsに埋め込まれやすくなるのではないか と感じました。

---

まだまだ全容が分かりきっていない各種LLMですが、この記事が読者の方の更なる理解の一助となれば嬉しいです。

最後までお読みいただきありがとうございました。