質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
86.12%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

解決済

BERTから得た単語ベクトルでcos類似度を求めたい

tako15
tako15

総合スコア11

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

3回答

0グッド

1クリップ

634閲覧

投稿2022/11/16 03:39

編集2022/11/16 05:54

前提

学習済みBERTから2つの単語ベクトルを抽出し、それらのcos類似度を求めたいです。
東北大版BERTのモデルを読み込みました。
単語ベクトルは11層のものを使用します。

実現したいこと

モデルを読み込み、単語ベクトルを画面出力するところまではできました。
その単語ベクトルからcos類似度を求めたいです。

エラーメッセージのように、"shapes (1,7,768) and (1,6,768) not aligned"となっているため、行又は列が一致していないために起こるエラーだと思っています。
この2つの語句でcos類似度を求める方法はありませんでしょうか?

発生している問題・エラーメッセージ

Traceback (most recent call last): File "/home/acd13859jl/grad_work/bert_prog.py", line 32, in <module> cos = cos_similarity(A, B) File "/home/acd13859jl/grad_work/bert_prog.py", line 28, in cos_similarity return np.dot(na, nb) File "<__array_function__ internals>", line 180, in dot ValueError: shapes (1,7,768) and (1,6,768) not aligned: 768 (dim 2) != 6 (dim 1)

該当のソースコード

python

1# tohoku-BERT 2from transformers import BertConfig, BertModel 3 4config = BertConfig.from_json_file('config.json') 5config.output_hidden_states = True # 各層の情報の取り出し 6model = BertModel.from_pretrained('pytorch_model.bin', config=config) 7 8from transformers import BertJapaneseTokenizer 9tknz = BertJapaneseTokenizer(vocab_file='vocab.txt', do_lower_case=False, do_basic_tokenize=False) 10 11from transformers.models.bert_japanese import tokenization_bert_japanese 12tknz.word_tokenizer = tokenization_bert_japanese.MecabTokenizer() 13 14 15import torch 16import numpy as np 17 18x = tknz.encode("欠けていたピース") # [2, 15201, 16, 21, 10, 14802, 3] 19y = tknz.encode("ぴったりかみ合う") # [2, 10411, 21087, 11620, 7393, 3] 20 21x = torch.LongTensor(x).unsqueeze(0) 22y = torch.LongTensor(y).unsqueeze(0) 23a = model(x) 24b = model(y) 25 26# cos類似度を求める(epsは母数がゼロにならないようにするため) 27# cos_similarityの中の処理を一部変更しました。結果自体は変わらないと思います。 28def cos_similarity(a, b, eps=1e-8): 29 cos = np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b)) + eps 30 return cos 31 32A = (a[2][11]).to('cpu').detach().numpy() 33B = (b[2][11]).to('cpu').detach().numpy() 34# https://tzmi.hatenablog.com/entry/2020/02/16/170928#pytorch-tensor%E3%81%8B%E3%82%89-numpy-ndarray%E3%81%B8%E5%A4%89%E6%8F%9B 35# このサイトをもとに一部A,Bを修正しました 36 37cos = cos_similarity(A, B) 38print(cos) 39

補足情報(FW/ツールのバージョンなど)

python 3.10
torch 1.12.1+cu116
numpy 1.23.4

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

回答3

1

エラーメッセージのように、"shapes (1,7,768) and (1,6,768) not aligned"となっているため、行又は列が一致していないために起こるエラーだと思っています。

a は(特殊トークンを含めて)7つのトークン、bは6つのトークンから成っていますから、単純にコサイン類似度は計算できません。


https://stackoverflow.com/questions/63461262/bert-sentence-embeddings-from-transformers

が大まかに似た質問で参考になると思います。

BERTで有意な文ベクトルが作れるかどうかは自明じゃない。といっても方法がないわけじやない。
という話が書かれています。

方法としては、Sentence BERTの論文でも議論されていることですが、(ps_aux_grep さんの回答にあるURLの解説にもあります)

“[CLS]"トークンに対応するベクトルを文のベクトルだと思う
各トークンのベクトルを平均したものを文のベクトルだと思う

のどちらかのようです。

前者は
https://nikkie-ftnext.hatenablog.com/entry/text-classification-with-features-from-bert#fnref:8
あたりがコードの参考になるかと思います。


「コサイン類似度を計算する」は目的ではないはずです、
「コサイン類似度を計算して実際に解きたいタスク」に向けてファインチューニングを考えるべきです。
その時、“[CLS]"トークンを使うのと平均を使うのとでそのタスクにおいてどちらがいいのか? は実際にやってみないと分からないと思います。

投稿2022/11/16 09:53

編集2022/11/16 09:57
quickquip

総合スコア10419

ps_aux_grep👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

1

ベストアンサー

今回利用されているのは単語ベクトルを導出するBERTですが,文章で比較したいなら文章ベクトルを取得できるSentence BERTを利用する必要があります.簡単にしか探していませんが東北大版BERTのモデルに文章ベクトルを導出するものは見つからなかったものの,次のサイトが参考になるでしょう.

はじめての自然言語処理 - 第9回 Sentence BERT による類似文章検索の検証

もし,単語同士の類似度でいいのであれば,求めたい単語同士のindexをそれぞれi,jとしてcos_similarity(A, B)cos_similarity(A[0][i], B[0][j])と書くことができます.

投稿2022/11/16 06:28

編集2022/11/16 06:55
PondVillege

総合スコア1032

tako15❤️を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

tako15

2022/11/16 06:52

回答ありがとうございます! 少し誤解していたのですが、ソースコードにある「欠けていたピース」などはすべてsentenceとして扱われるということですね。逆に、「冬」「雪」などの単語であれば東北大版BERTでも比較できると。 私の場合、ソースコードのようなsentence同士を比較したいので、SentenveBERTを試してみます。 ありがとうございました。
PondVillege

2022/11/16 07:00

> ソースコードにある「欠けていたピース」などはすべてsentenceとして扱われるということですね。 それも少し違いますね,MecabTokenizerによって単語に分割され,その単語の羅列が解析された.というのが正しい状態と思います. > 「冬」「雪」などの単語であれば東北大版BERTでも比較できる 入力を必ず文章にしなければならないという縛りはないので,これは比較可能ですね.
tako15

2022/11/16 07:20

>それも少し違いますね,MecabTokenizerによって単語に分割され,その単語の羅列が解析された.というのが正しい状態と思います なるほど。入力を文にしたとしても、単語に分割されて解析される。単語の羅列の解析なので、文全体の比較はできないが、入力文中の単語の比較は出来るということですか? ご厚意に甘えて、加えて質問させていただきますが、sentenceBERTでは「冬」「雪」のような単語同士の比較も可能なのでしょうか?
PondVillege

2022/11/16 07:30 編集

> 単語の羅列の解析なので、文全体の比較はできないが、入力文中の単語の比較は出来るということですか? そうですね,文章全体として,ケースbyケースで単語のもつ意味が異なるのは周知の事実と思います.こういった状態の単語を比較することになります.まさに上で示したcos_similarity(A[0][i], B[0][j])で実行されます. > sentenceBERTでは「冬」「雪」のような単語同士の比較も可能なのでしょうか? 一応,得られる出力の次元数は一致するので,先述のようなコサイン類似度は導出可能です.その点で比較可能ですが,「精度」や「意味を捉える」といった点ではどうなるのか見当もつかないので,要検証ですね.多分,単語ベクトルと同等のものが得られるものと予測します.
tako15

2022/11/16 21:27

分かりやすい言い方で丁寧に説明して頂いて、理解があやふやだった所が、腑に落ちました。 本当にありがとうございます。

1

Text

1cosは内積である。

投稿2022/11/16 05:01

atcoderyellow

総合スコア481

退会済みユーザー👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

2022/11/16 05:41

こちらの回答が複数のユーザーから「質問に対する回答となっていない投稿」という指摘を受けました。

回答へのコメント

tako15

2022/11/16 05:37

回答ありがとうございます。 そうですね。どういう意図なのかもう少しお教えいただいてもよろしいでしょうか? Tensorからnumpyに型を変換して、内積を求めても求められないのです

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
86.12%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。