文章間の類似度を測定する方法まとめ

# はじめに
先日、文章間の類似度を測定したくなりました。サクッとできると思っていたのですが、なかなか思うような精度が出なくて苦労しました。
調査の過程で類似度を測定する方法は色々とあることを学んだのでまとめておきます。
精度に関しての言及は今回私が試した文章（=チャットのような短文）を対象としています。

# 文章間の類似度測定の流れ
文章間の類似度を測定するときはまず文章分散表現を取得します。文章分散表現を取得する方法は色々とあります。
その後、取得した分散表現同士を比較することで文章間の類似度を測定します。分散表現同士の比較方法はコサイン類似度を使うのが一般的です。
そのためこの記事では、色々な文章分散表現の取得方法を紹介します。
 
# 文章分散表現の取得方法
## 単語分散表現を基に文章分散表現を算出
単語分散表現を取得した後、取得した単語分散表現から文章分散表現を算出します。
それぞれについて色々なやり方があるので記載していきます。

### 単語分散表現の取得方法
- **word2vec**    
    - 2013年にGoogleの研究者たちによって提案された最も有名な単語分散表現の取得方法です。    
    - 自前で分散表現を作ってもよいが、学習済モデルを使う方がお手軽です。  
    - 学習済モデルはいくつかありますが、[こちらの記事](https://blog.hoxo-m.com/entry/2020/02/20/090000)によると[fastText](https://fasttext.cc/)と[chiVe](https://github.com/WorksApplications/chiVe)がよさそうでした。
        - **fastText**
            - 2016年にFacebookが開発したものです。
            - 日本語モデルは[公式サイト](https://fasttext.cc/docs/en/crawl-vectors.html#models)から取得可能です。
        - **chiVe**
            - ワークスアプリケーションズが開発した日本語の学習済モデルです。
            - 日本語NLPライブラリである[GiNZA](https://megagonlabs.github.io/ginza/)で使われています。
            - IT系の用語（例：サイボウズ）にfastTextより強かったです。
    - 多義語の場合に問題が生じます。例えば、地名の「香川」とサッカー選手の「香川」は違う意味を持ちますが、単語分散表現としては同じになります。
- **BERT**
    - 2018年にGoogleが提案したものです。     
    - 前述したword2vwcの多義語問題を解決できる文脈を考慮した単語分散表現であり、文脈により同じ単語でも分散表現が変わります。
    - ただし、fine-tuningを行わずに素のBERTからの出力で文章分散表現を算出しても精度がよくないことが知られています。後述するSentenceBERTなどを使います。
- **ELMo**
    - 2018年にストックマークが公開したものです。
    - 複数の単語ベクトルを連結させて精度を向上させるというアイデアを[紹介記事](https://qiita.com/mkt3/items/9577b63900109ff91665)から学びました。
    - 簡単には試せそうになかったので試していません。
- **Electra**
    - 2020年にGoogleが提案したBERTの事前学習手法の改良したものです。
    - [GiNZA](https://megagonlabs.github.io/ginza/)のv5では`ja_ginza_electra`が利用可能です。
    - [こちらの記事](https://tech-blog.optim.co.jp/entry/2021/09/21/100000)でGiNZAからELECTRAベースの単語ベクトルを取得する方法が紹介されていますが、精度はいまいちな印象でした。

### 単語分散表現から文章分散表現を取得する方法
- まずは、単純に**単語分散表現の平均**を文章分散表現とする方法があります。
- 次に、**TF-IDFで単語の重要度に応じた重みをつけた単語分散表現の平均**を文章分散表現とする方法があります。
    - [こちらの記事](https://qiita.com/hrappuccino/items/19bcdc097246865bea86)や[こちらの記事](https://speakerdeck.com/cordx56/tf-idftoword2vecfalsebing-yong-niyoruwen-zhang-jian-lei-si-du-pan-ding-falseshi-zhuang) が参考になります。
    - 間違いが少なく精度が高いように感じました。
    - ただし、大幅な言い換えには対応できない気がします。
- **SCDV**
    - [こちらの記事](https://logmi.jp/tech/articles/321131)で採用されており精度は高そうでした。
    - ただし、今回私が対象とする文章は短く、精度が出なそうに感じたので、あまり調べていません。

## 直接文章分散表現を算出する方法
単語分散表現は使わず、文章分散表現を算出します。

- **doc2vec**
    - 2014年に発表されたものです。
    - [こちら](https://yag-ays.github.io/project/pretrained_doc2vec_wikipedia/)で日本語の学習モデルが公開されています。
    - [こちらの記事](https://logmi.jp/tech/articles/321131)にも記載がありますが、私が試した感じでも精度はいまいちでした。
- **SentenceBERT**
    - 文章の類似度を測るようなタスクを下流のタスクとしてBERTをfine-tuningしたものです。
    - [こちらの記事](https://qiita.com/sonoisa/items/1df94d0a98cd4f209051)で日本語モデルが公開されています。
    - 私が試した感じでは、時々光る答えをみせてくれましたが、間違いも多かった印象です。
- **Universal Sentence Encoder**
    - 2018年にGoogleが提案したものです。
    - [こちらの記事](https://qiita.com/kenta1984/items/9613da23766a2578a27a])使い方が紹介されています。
    - 少しだけ試していまいちな気がしたのですぐやめてしまいました。
- **BERTScore**
    - 自動生成した文章がどれだけ自然かのスコアを付ける方法です。
    - 名前の通りBERTを使用しています。
    - [こちらの記事](https://www.nogawanogawa.com/entry/bertscore)によると文章間の類似度測定にも使えるそうです。
    - 少しだけ試していまいちな気がしたのですぐやめてしまいました。

以下は、どこに入れるか迷ったものです。単語分散表現から文章間の類似度を算出する方法です。

- **WMD**(Word Mover's Distance)
    - ある文章に含まれる単語群と別の文章に含まれる単語群の距離の長さによって類似度を測ります。
    - [gensim](https://radimrehurek.com/gensim/auto_examples/tutorials/run_wmd.html)にWMDを計算する関数がある。
    - 進化系のWRDがあることを知ったのであまり試していません。
- **WRD**(Word Rotator's Distance)  
    - 2020年に東北大学の乾研が提案したWMDを改良した手法です。
    - 単語ベクトルのノルムは単語の重要度を表し偏角は単語の意味を表すと考えている点が特徴です。
    - 単語分散表現の平均からコサイン類似度を計算する手法よりも高精度であることが示されています。
    - [こちらの記事](https://qiita.com/kenta1984/items/bad7e2f68331849d0053)が参考になります。
    - 私が試した感じでは、TF-IDF＋単語分散表現の平均と同じくらいの精度で類似度を測定することができました。

# その他参考にした文献
大変参考にさせて頂きました。ありがとうございました。

https://qiita.com/kenta1984/items/6dc327c31b6c36e66863

https://zenn.dev/koukyo1994/articles/9b1da2482d8ba1#fasttext%E3%81%AE%E6%96%87%E7%AB%A0%E3%83%99%E3%82%AF%E3%83%88%E3%83%AB

https://www.ogis-ri.co.jp/otc/hiroba/technical/similar-document-search/part1.html

https://note.com/npaka/n/n5c3e4ca67956