🔖
文章をベクトル化する言語モデルSentence BERTを使ってみた
来週のハッカソンでAI×日記アプリを作成することが決まり、「今日起こった出来事と似ている出来事を過去の出来事から探す」機能があったら面白いと思ったので調べたところSentence BERTに遭遇した。BERTとはGoogleが開発した自然言語処理モデルで、Sentence BERT(SBERT)は、その名の通りBERTを文章埋め込み(sentence embedding)向けに最適化したモデル。実際に使用して見るにあたり、https://www.sbert.net/ を参考にgooglecolabでこのサイトのコードをコピーし、色々触ってみた。
入力1
sentences1 = [
"大阪から東京に行きます",
"おおさかからとうきょうにいきます",
"大阪から東京に行きません",
"大阪から名古屋に行きます",
"I go to Tokyo from Osaka",
"I come Tokyo from Osaka",
"東京から大阪からに行きます"
]
出力(類似度)
tensor([[1.0000, 0.3943, 0.9740, 0.7368, 0.3046, 0.3206, 0.9708],
[0.3943, 1.0000, 0.4063, 0.3542, 0.1978, 0.2128, 0.4009],
[0.9740, 0.4063, 1.0000, 0.7052, 0.2823, 0.2965, 0.9433],
[0.7368, 0.3542, 0.7052, 1.0000, 0.0967, 0.1206, 0.7024],
[0.3046, 0.1978, 0.2823, 0.0967, 1.0000, 0.8891, 0.3036],
[0.3206, 0.2128, 0.2965, 0.1206, 0.8891, 1.0000, 0.3061],
[0.9708, 0.4009, 0.9433, 0.7024, 0.3036, 0.3061, 1.0000]])
ここから
- 明らかに同じ内容の文章でもひらがな化、英訳されると同じと認識されない
- 否定文や逆の意味の違いが認識されない
- 日本語の細かな言い回しよりも、大まかな単語や文のパターン(AからBへ行くなど)を優先的に捉えている
ことがわかる
入力2
sentences2 = [
"江ノ島にいってアイスクリームを食べた",
"江ノ島にいって神社に参拝した",
"京都に行って神社に参拝した"
]
出力
tensor([[1.0000, 0.7241, 0.6333],
[0.7241, 1.0000, 0.7882],
[0.6333, 0.7882, 1.0000]])
ここから
- 実践的な観点では位置関係や細部の違いよりも「主要トピック」を優先する
- 類似度0.7が類似度の閾値
である事が推測される
結論
実践的な観点で言うと、細かい違い見落としがちだが、主要となる名詞・トピックはちゃんと拾ってくれるので、「連想される過去のエピソードを表示」という日記アプリの要件はみたせそう。
追記
入力1,入力2を英訳してもう一回コードを実行してみた
sentences1 = [
"I am going from Osaka to Tokyo.",
"I am going from Osaka to Tokyo.",
"I am not going from Osaka to Tokyo.",
"I am going from Osaka to Nagoya.",
"I go to Tokyo from Osaka.",
"I come to Tokyo from Osaka.",
"I am going from Tokyo to Osaka."
]
sentences2 = [
"I went to Enoshima and ate ice cream.",
"I went to Enoshima and visited a shrine.",
"I went to Kyoto and visited a shrine."
]
出力
tensor([[1.0000, 0.3943, 0.9740, 0.7368, 0.3046, 0.3206, 0.9708],
[0.3943, 1.0000, 0.4063, 0.3542, 0.1978, 0.2128, 0.4009],
[0.9740, 0.4063, 1.0000, 0.7052, 0.2823, 0.2965, 0.9433],
[0.7368, 0.3542, 0.7052, 1.0000, 0.0967, 0.1206, 0.7024],
[0.3046, 0.1978, 0.2823, 0.0967, 1.0000, 0.8891, 0.3036],
[0.3206, 0.2128, 0.2965, 0.1206, 0.8891, 1.0000, 0.3061],
[0.9708, 0.4009, 0.9433, 0.7024, 0.3036, 0.3061, 1.0000]])
tensor([[1.0000, 0.7241, 0.6333],
[0.7241, 1.0000, 0.7882],
[0.6333, 0.7882, 1.0000]])
英訳した事で、時制、肯否、意図といった繊細な部分が反映され、"江ノ島にいって神社に参拝した", "京都に行って神社に参拝した"の類似度が下がった。つまり精度が明らかに上がった。
ただ、精度が上がったからいいのかというとそういうものでもなさそうで、人間の連想も、厳密な意味解析よりも主要な名詞やトピックを手がかりにした連想が優先されがちらしく、プライミング効果(例: "bread" を見ると "butter" を思い浮かべる)も報告されているそう。日記アプリで実装する時は精度が低くてもあえて日本語のままでいくのもよさそう。
Discussion