FAQ 検索の精度改善の取り組みについての紹介

こんにちは。プロダクト開発部で弊社の AI・高性能チャットボット「スグレス」の開発および自然言語処理の R&D をしている中井です。

チャットボットとは、「チャット」と「ボット」を組み合わせた言葉で、人工知能 (AI) を組み込んだコンピューターが人間に代わって一定の会話を自動化する「自動会話プログラム」のことです。スグレスは人工知能 (AI) を搭載した高性能チャットボットサービスです。

スグレスには Frequently Asked Question (FAQ) 検索と呼ばれる、ユーザーが入力したメッセージ (以下、クエリと呼ぶ) から、適切な回答候補を推測する機能があります。

今回は、FAQ 検索の精度改善の取り組みについて紹介します。

はじめに

今回は FAQ 検索を 4 つの異なるモデルで実装し、日本語のデータセットによる比較実験をした結果を紹介します。
  1. BM25 による検索スコアを使った方法
  2. LASER の文埋め込みによる類似度検索による方法
  3. BERT による検索モデル
  4. Sentence-BERT の文埋め込みによる類似度検索による方法

FAQ 検索とは

FAQ 検索とは、事前に定義された問い合わせ文と回答文のペアからなる FAQ の集まりから、ユーザーからの自然文による問い合わせに対して、より適合する回答が上位になるように FAQ を並べ替えて応答するタスクと定義します。いわゆる情報検索におけるランキング問題と考えられますが、このブログでは FAQ に限定して取り組むため、FAQ 検索と呼ぶことにします。

FAQ 検索システムの仕事は、クエリと FAQ の適合の度合いを表すスコアを推定することです。あとは、全ての FAQ をスコアの降順に並べるだけです。多くの検索システムがこの方法をとっています。スコアの推定の方法が検索システムの性能を決定する大きな要因となります。

クエリは、ユーザーが必要とする情報を自然文である質問文で表現したものです。クエリと FAQ の適合の度合いとは、その FAQ の話題がユーザーの必要としていた情報とどれだけ合致しているかを表すものと定義します。一方、ユーザーが必要としている情報そのものをシステムが知ることはできません。このため、システムはクエリと FAQ のみで適合性スコアを推定します。

また、FAQ は問い合わせ文と回答文で構成されるので、スコアの推定にはそのどちらも考慮するのが自然ですが、本記事ではクエリ と FAQ の問い合わせ文から推定しています。これは、クエリと 問い合わせ文が似た意味を持つ FAQ には、ユーザーが必要としている情報が含まれている可能性が高いであろうという仮定によります。

BM25 による FAQ 検索について

BM25 とは

BM25 (Okapi BM25) は、古くからある情報検索における順位付けの手法です。文書における単語の出現頻度に基づいてスコアリングする手法です。情報検索における研究のベースラインとして用いられることが多く、本記事でも他モデルとの比較を目的としています。

単語 q_1, \ldots, q_n で構成されるクエリ Q が与えられたとき、文書 D の BM25 スコアは次の式で与えられます。

\operatorname{score}(D, Q) = \sum_{i=1}^n{\operatorname{IDF}(q_i) \frac{f(q_i, D) \cdot (k_1 + 1)}{f(q_i, D) + k_1 \cdot \left(1 - b + b \cdot \frac{|D|}{\mathrm{avgdl}}\right)}}

ここで |D| は文書 D の単語数、\mathrm{avgdl} は文書集合の平均単語数、f(q_i, D) は文書 D における単語 q_i の出現頻度です。k_1 および b はパラメーターです。k_1 \in {1.2, 2.0}b = 0.75 とすることが多いです。

BM25 スコア式の分母の |D| / \mathrm{avgdl} は、不要な情報が多くを占める長い文書に罰則を与えるためのものです。

\operatorname{IDF}(q_i) は逆文書頻度 (Inverse Document Frequency) と呼ばれるものです。多くの文書に出現する単語であるほどIDFは小さくなり、逆に文書にあまり出現しない単語であるほど大きくなります。

\operatorname{IDF}(q_i) = \ln{\left(\frac{N - f(q_i) + 0.5}{f(q_i) + 0.5}\right)}

N は全文書数、f(q_i) は単語 q_i を含む文書の数になります。

おおざっぱにまとめると、クエリに含まれる単語の出現頻度が高い文書であればあるほど、レアな単語であればあるほど、文書長が短ければ短いほどスコアが高くなる傾向になります。

LASER による FAQ 検索について

LASER とは

LASER とは、Facebook が公開している多言語文埋め込み (multilingual sentence embedding) 訓練済みモデルです。

文埋め込みとは、文をベクトル空間の中に配置することです。

このモデルを用いると、例えば、「病院はどこですか?」と「Where’s a hospital?」のような意味合いが似ている文をベクトル空間上で近い距離にマッピングすることができます。日本語と英語のような異なる言語の文であったとしても類似度を計算することができます。

LASER概要図

アーキテクチャ

LASER はゼロショット翻訳 (zero-shot translation) で訓練された双方向 LSTM ベースのエンコーダです。翻訳モデルの訓練によって得られた文埋め込み (sentence embedding) の情報を様々なタスクに転用します。

LASER ([Artetxe et al., 2019] Figure 1 より引用)
ゼロショット翻訳とは、モデルが直接訓練されていない言語間での翻訳を行うことです。例えば、日本語→英語、英語→中国語の翻訳を行うためのデータがあるときに、英語を挟んで日本語→中国語の翻訳を行うことを指します。

LASER は、英語との対訳データがある 93 言語を使って訓練されており、日本語のデータは 320 万文が用いられました。

なお、訓練済みモデルは GitHub 上で公開されていますが、訓練のためのコマンドは非公開なので、 新たなデータで訓練することはできません。

FAQ 検索への応用

LASER によりクエリと問い合わせ文の文埋め込みを計算し、それらのコサイン類似度を適合の度合いのスコアとします。

BERT による FAQ 検索について

BERT とは

BERT (Bidirectional Encoder Representations from Transformers) とは、2018 年に Google が公開した訓練済みニューラル言語モデルです。この事前訓練済み (pre-trained) のモデルに最終出力層を 1 層追加し、再学習 (fine tuning) することで様々な言語タスクに応用することができます。応用できる言語タスクには、質問応答、機械翻訳、構文解析、固有表現抽出などがあり、これらすべてのタスクで優れた成績をおさめています。

BERT のモデルは、トランスフォーマーエンコーダーを積み重ねた構造をしており、数億にもおよぶパラメーターを持ちます。トランスフォーマーエンコーダーは、文を構成するすべての単語の間の関係を見るため、単語の出現する文脈を考慮した埋め込みベクトルを作ることができます。

事前学習には、Wikipedia と BooksCorpus にある大量のテキストデータを用い、MLM (Masked language modeling) と NSP (Next sentence prediction) と呼ばれる 2 つのタスクを使って学習します。MLM は文中の一部の単語をマスクし、マスクされていない残りの文を見て、マスクされた単語を予測するタスクです。NSP は 2 つの文を入力し、それらが実際に隣り合う文であるかどうかを予測するタスクです。

トランスフォーマーを用いた大容量のモデルと事前学習を組み合わせることで、周囲の文脈を考慮した言語モデルを訓練することができ、再学習と組み合わせることで、現実的な計算資源と時間の中で、パワフルなモデルを得ることができるのが BERT の特徴といえそうです。

近年では、情報検索の分野でも BERT を応用したものが数多く出現しています。例えば、MS MARCO のリーダーボードでも BERT を使ったモデルが多くを占めています。

FAQ 検索への応用

検索システムの仕事は、入力クエリと FAQ の適合の度合いであるスコアを推定することでした。ここでは、このスコアの推定を BERT で行う方法について述べたいと思います。

BERT の検索システムへの応用は多くの研究がなされていますが、今回は、[Nogueira et al. 2019] の方法に従って、文のペアの分類タスクを応用しました。つまり、BERT をベースにしたクエリと FAQ が適合するかしないかの二値分類を行うネットワークを訓練し、このネットワークの出力である適合確率を FAQ 検索でのスコアとして採用します。

ネットワークの構成は、BERT のトランスフォーマーの最終層に全結合層 (Fully Connected layer) を追加し、softmax を出力層に用いたものになります。

ネットワークへの入力は、[CLS] トークン、クエリ、セパレータトークン、FAQ の問い合わせ文の順で結合し、最大 128 トークンに切り詰めたものです。

事前学習済みのモデルとして、東北大の乾・鈴木研究室が日本語データで事前訓練を行った BERT (bert-base-japanese-whole-word-masking) を用い、交差エントロピー誤差を使って再学習 (fine-tuning) しました。

実装には、HuggingFace の Transformers と PyTorch を使いました。

Sentence-BERT による FAQ 検索について

Sentence-BERT (SBERT) とは

上記の方法で適合度のスコアを計算するためには、ネットワークにクエリと FAQ の問い合わせ文のペアを同時に入力する必要があります。クエリに適合する順に FAQ の回答文を並べ替えるには、FAQ の数だけのペアをネットワークに入力する必要があります。BERT が巨大なモデルであることを考えると、非常に大きな計算量が必要であることが分かるかと思います。

Sentence-BERT (SBERT) [Reimers et al., 2019] は BERT を用いた文埋め込みを計算するためのモデルです。ソースコードが GitHub 上で公開されています。

前述の BERT の方法とは異なり、FAQ の問い合わせ文の文埋め込みを事前に計算しておくことができるため、高速な検索システムが実現できます。

SBERT ではディープメトリックラーニングの一手法である Siamese Network を用いることで、意味的に類似した文をベクトル空間の中の近い位置に配置するように訓練します。

アーキテクチャ

SBERT では、BERT の出力層にプーリング操作を行う層を追加します。

BERT の出力は、可変個の埋め込みベクトルの列です。各ベクトルは、文を構成する各トークンに対応します。プーリング操作は、可変個のベクトル列を 1 つの固定長次元のベクトルに変換する操作です。

SBERT には、3 種類のプーリング操作が実装されています。CSL トークンに対応するベクトル出力するもの (CLS-strategy)、各ベクトルの平均をとるもの (MEAN-strategy)、各ベクトル要素の最大値をとるもの (MAX-strategy) です。今回の実験では、デフォルトのプーリング操作である MEAN-strategy を使いました。

訓練には、以下の図のように、プーリング層の後に全結合層と softmax を追加し、自然言語推論 (Natural Language Inference, NLI) のデータセットで分類問題を学習します。NLI は、二文を入力値として与え、含意・矛盾・中立の 3 クラスに分類するタスクです。

Sentence-BERT 概要図 ([Reimers et al., 2019] Figure 1 より引用)
訓練時に文 A と文 B をエンコードする BERT の重みは共有されますが、このように同一のモデルの重みを共有するのが Siamese Network の特徴になります。

FAQ 検索への応用

訓練時には、文 A として、チャットボットへの入力となるユーザーのクエリ、文 B として、FAQ の問い合わせ文を用いました。また、NLI のフォーマットに合わせるために、正解ペアには含意、それ以外のペアには矛盾のラベルを付与しました。

推論時には、クエリと FAQ の問い合わせ文の文埋め込みをそれぞれ SBERT で求め、それらのコサイン類似度を適合度のスコアとして採用します。

訓練の初期値には東北大の乾・鈴木研究室が日本語データで事前訓練を行った BERT (bert-base-japanese-whole-word-masking) を用いました。

実験

データセット

FAQ 検索システムを評価するためには、FAQ データセットとクエリの集合および、それぞれのクエリと FAQ が適合するか否かをひも付けるラベルが必要になります。あるクエリと FAQ が適合する場合を正例とよび、そうでない場合を負例とよびます。

今回は、スグレスを利用していただいているお客様に承諾をいただき、実際に使われている FAQ データセットを利用させていただきました。このデータセットは、1,614 件の FAQ と 46,391 件のクエリからなります。クエリは FAQ の問い合わせ文をさまざまな形で言い換えることで作成したものです。言い換えの元となった FAQ がクエリに対する正例となります。

モデルの学習のためにデータセットを、訓練セット、検証セットおよびテストセットに分割しました。それぞれ正例が 35,000 件、10,000 件および 5,000 件になります。BERT および SBERT の再学習においては、どの程度の量の正例が必要かを判断するために 5,000 件 の正例からなる訓練セットも利用しました。

実験手順

BM25

実装には、オープンソースの検索エンジンある Elasticsearch を用いました。形態素解析には、MeCab の Java への移植版である kuromoji を NEologd 辞書で拡張した mecab-ipadic-NEologd を使いました。

BM25 スコアのパラメーターは k_1=1.2、および b=0.75 を設定しました。

FAQ の応答文は無視して、クエリと FAQ 問い合わせ文のみから BM25 スコアを算出し、上位 100 件抽出します。

前処理として、クエリと問い合わせ文は、Unicode 正規化 (NFKC CF) と踊り字の正規化をした後でトークンに分割しました。さらに、それぞれのトークンは正規化 (動詞・形容詞の原型化、カタカナの末尾の部分の長音除去等) し、検索には重要でない「が」「を」「に」「の」「と」などの助詞を取り除きました。

LASER

モデル訓練の実装が公開されていないため、公式で配布されているモデルを用いました。また、調整可能なパラメーターもなかったためチューニングも不要でした。

配布されているスクリプトを使って、クエリと FAQ の問い合わせ文の埋め込みベクトルを求め、コサイン類似度を計算し、上位 100 件を出力しました。

BERT

学習に用いるデータ件数によるモデルの性能差を見るために、正例が 5,000 件と 35,000 件の 2 つの訓練セットを用いて実験を行いました。

再学習に用いるデータは、クエリ、FAQ の問い合わせ文およびラベルの3つの組になります。ラベルは、正例と負例の二値になります。今回は、負例の組は正例以外の FAQ を K 件をランダムに抽出することで作成しました。ラベルの分布に偏りが生じることを避けるために、正例は K 個のコピーを作ることで、正例と負例のサンプル数の比率が同じになるようにしました。検証セットでの実験によって K=100 としました。

バッチサイズは 128、オプティマイザは Adam、L2 weight decay は 0.01、初期学習率は 3𝑒-6 としました。ウォームアップステップ数は、正例 5,000 件の訓練セットを用いる場合は 1,000 ステップ、正例 35,000 件の訓練セットを用いる場合は、2,000 ステップとしました。

検証セットで確認したところ、1 エポック以上回しても、MAP (Mean Average Precision) がほとんど上昇しなくなったため、1 エポックで打ち切りました。

SBERT

今回は SBERT の訓練を二段階に分けて実施しました。BERT の場合と同じように正例が 5,000 件と 35,000 件の 2 つの訓練セットを用いて実験を行いました。

第一段階においては、SBERT が基礎的な学習を行うことを目的としました。訓練データは BERT の実験で用いたものと同じものです。第二段階では、SBERT に難易度の高い問題を与えることにより能力の向上を図りました。負例をランダムに抽出するのではなく、BM25 と LASER で推論した結果のうち誤っていたものから抽出しました。あるクエリに対する負例の件数 K は、正例が 5,000 件の訓練セットの場合は K=40、正例が 35,000 件の訓練セットの場合は K=20 としました。後者の値が小さいのは、訓練に数日を要すことが分かり、訓練時間を短縮するためにデータ件数とエポック数を減らしたためです。第二段階では第一段階よりもデータ数が減るため、パラメーターの更新回数を維持するためにバッチサイズを小さくしました。

定量評価

ランキング指標

テストセット 5,000 件を使い、各クエリに対する上位 100 件の FAQ を出力し、各モデルの各種ランク指標を計測しました。結果を以下に示します。

モデルP@1P@10P@20P@100MAP
BM250.28670.05990.03410.00850.3765
LASER0.17990.04140.02510.00720.2500
BERT 50000.38830.07870.04280.00970.501
BERT 350000.40820.08150.04450.00990.5257
SBERT 5,0000.23960.06170.03630.00910.3485
SBERT 35,0000.27220.06590.03810.00930.3809
ここで、P@k は推論結果の上位 k 件のうち正解であるものの割合です。

LASER は、すべての指標で最も低い結果となりました。

BERT が今回試したモデルの中においては、各種指標で優れた結果を残しました。学習件数が少ない場合においても、他のモデルを大幅に上回っていることが確認できます。

SBERT の場合、P@1 においては学習セットの件数によらず BM25 に及ばないようですが、P@10、P@20、P@100 においては BM25 に比べて改善しています。このことから、上位をピンポイントで推論する能力は低いが、ランク学習アルゴリズムと組み合せて、検索システムの前段としてフィルタとして用いることで、高性能な検索システムを構築できることが期待できます。

訓練時間

NVIDIA Tesla V100 (1台) で、訓練に要した時間を示します。

モデル正例数、負例数バッチサイズエポック数時間
BERT 5000それぞれ100件12814時間33分
BERT 35000それぞれ100件128115時間24分
SBERT 5000 (第1段階)それぞれ100件80511時間36分
SBERT 5000 (第2段階)それぞれ40件16510時間1分
SBERT 35000 (第1段階)それぞれ100件80190時間54分
SBERT 35000( 第2段階)それぞれ20件1616時間42分

推論時間

NVIDIA Tesla V100 (1 台) で計算したときの推論にかかる時間を測定しました。1 クエリあたり、BERT の場合でおよそ 4 秒、SBERT の場合で 0.012 秒でした。

定性評価

SBERT と BM25 の有利・不利の傾向を把握するために、テストセットからおよそ 100 クエリを抽出し、人手で評価を行いました。

結論としては、SBERT を用いることでユーザーが訊ねたい内容の本質を捉え、適切な回答に辿り着く能力が向上したと言えますが、特徴的な名詞等を含むクエリに対しては BM25 を用いる方が良くなる傾向にあることが分かりました。

以下は、BM25 では捉えられなかったが、SBERT が言い替えをうまく捉えることができたクエリの一例です。「お手入れ方法を教えて下さい。」という文字列を「洗いたい」や「清掃したい」という文字列に近い意味合いだと見なしています。

クエリFAQ の問い合わせ文
食器洗い乾燥機を洗いたい食器洗い乾燥機のお手入れ方法を教えてください。
食器洗い乾燥機を清掃したい食器洗い乾燥機のお手入れ方法を教えてください。
食器洗い乾燥機をきれいにしたい食器洗い乾燥機のお手入れ方法を教えてください。
以下は、BM25 でのみ正解を抽出できたケースです。低頻度語である「メッキ」を含んでいることが正解を抽出できた要因であると考えられます。

クエリFAQ の問い合わせ文
メッキのついた食器は洗えますか金・銀メッキを施した食器は、なぜ洗えないのですか。(ビルトイン食器洗い乾燥機に関して)
機械にメッキされた食器は入れられますか金・銀メッキを施した食器は、なぜ洗えないのですか。(ビルトイン食器洗い乾燥機に関して)
SBERT が文埋め込みを用いていること、BM25 が単語の重なりを見ていることを踏まえれば、人手による定性的評価は妥当な結果でしょう。

まとめ

本記事では、BM25、LASER、BERT、SBERT を用いて FAQ 検索を実現し、それぞれのモデルの実験結果を紹介しました。

BM25 は、一位を推定する能力では BERT に次ぐ結果となりました。定性評価では特徴的な単語を含むクエリでは正解を捉える能力が高いが、言い換え文を捉える能力に課題があることを見ました。このことは単語の一致数を見ていることに起因するものでした。この課題に対するアプローチとして類義語辞書を作成する方法があります。辞書を運用していくコストの問題、活用形のある形容詞と動詞の取り扱いが難しいなどの問題などがありますが、これらを解消・改善することで、運用負荷を下げ、かつさらなる精度の向上が期待できます。

LASER は、モデルが公開されているので簡単に実験ができるという利点がありましたが、それは再学習できないといった欠点でもあり、今回試した中では最も精度が低い結果となりました。また、記事中で紹介できませんでしたが、語尾によって結果が微妙に変わってしまい、それによって精度を下げていることが明らかになりました。LASER のエンコーダは双方向 LSTM によって構成されているため、クエリの最初の単語と最後の単語の影響力が大きすぎる可能性があります。

ランキング指標における性能では期待通り BERT が最も良い結果を示しました。しかし、小規模な FAQ でない限り、推論にかかる時間の問題から、リアルタイムアプリケーションでの利用は難しいということも見ることができました。

一方で、SBERT での FAQ 検索は、一位を正解する能力は低いが、上位数 10〜100 件でみると、単語でのマッチングによる BM25 よりも優れていることを見ました。また、非常に短い時間で推論することもできます。SBERT でまず検索を行い、そのフィルタリング結果を、BERT やランク学習のような別のモデルで並べかえることで、リアルタイム性の高い、高性能なシステムを実現できる可能性があります。

BERT においては、精度を維持したまま、モデルサイズを小さくする試みがいくつか提案されているようです。例えば、知識蒸留 (knowledge-distillation) を用いたモデルの圧縮や、あるいはトランスフォーマーの層をいくつかドロップするなどの手法が紹介されています。今後は、こういった手法を用いて、精度を犠牲にせずに、スピードアップを追求するというのもやってみられたらいいなあと思っています。

ALBERTというと機械学習・データ分析のイメージが強いかと思いますが、優れたAIシステムを構築する為には、ユーザビリティ、保守性、セキュリティなどの、ソフトウェアの品質も非常に重要な要素であり、ソフトウェアエンジニアも多く活躍しています。 これまでのご経験を活かしながら、AIを活用したシステム開発・プロダクト開発に関わりたいソフトウェアエンジニアの方にもぴったりな職場だと思いますので、是非ご応募いただきたいです。(募集要項はこちらからご覧ください。)

参考文献

  • Robertson, S. (2010). The Probabilistic Relevance Framework: BM25 and Beyond. In Foundations and Trends® in Information Retrieval (Vol. 3).
  • Artetxe, M., & Schwenk, H. (2019). Massively Multilingual Sentence Embeddings for Zero-Shot Cross-Lingual Transfer and Beyond. Transactions of the Association for Computational Linguistics, 7, 597–610.
  • Devlin, J., Chang, M.-W., Lee, K., & Toutanova, K. (2018). BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding.
  • Nogueira, R., & Cho, K. (2019). Passage Re-ranking with BERT.
  • Reimers, N., & Gurevych, I. (2019). Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks.