ELMoで文脈に応じた類似キーワード検索システムを作った話

田口雄哉氏:それでは、表記のタイトル(ELMoで文脈に応じた類似キーワード検索システムを作った話)で、朝日新聞の田口が紹介します。

まず簡単に自己紹介させてください。もともと僕は、2015年までWebメディアの編集スタッフをしていて、その後理系に転向して、NAIST(奈良先端科学技術大学院大学)に行きました。そこで自然言語処理を研究して、修士を取得したあとに、2017年4月から朝日新聞社で働いています。

業務内容としては、メディアラボとICTRADに所属していて、研究開発の仕事をしています。朝日新聞の研究開発といっても、イメージがつかない方が多いと思うので、少し宣伝させてください。

まずこちらなんですけれども、メディアラボでの研究開発です。こちらは主にアウトプットは学会発表がメインなんですけれど、自動要約や自動校正など、自然言語処理にまつわる基礎研究をしています。ありがたいことに、3月に行われたNLP2020では、言語資源賞をいただきました。

メディアラボでやっている自動要約に関しては、研究成果を要約APIとして無料で公開しているので、興味がある方はぜひ使ってみてください。今日のML@Loftの概要ページ、概要の文言を入れても、そこそこそれらしいものが13文字程度で出せたりするので、ニュース記事ではなくても、意外といいものが出せる感じになっているかなと思います。

次にもう1つ僕が兼務しているのが、このICTRADです。こちらは、どちらかというとプロトタイプ作成やサービス化がメインになっています。なのでRがメディアラボで、DがICTRADというかたちですかね。

サービスとしては、高校野球の自動戦評だったり、ちょうど今日プレスリリースを出したんですけど、AI経済記者を作っています。あと、四択の時事クイズサービスを作ったりしています。

Qrichにおける四択クイズの作り方

ちょっと前置きが長くなってしまいましたが、今日話すことはこちらです。「Qrich」というところでやっている、四択クイズの作成フロー。タイトルにもあったように、類似キーワード検索をまずword2vecでやってみて、その問題点についてお話しします。そしてそれを解決するために、ELMoによる類似キーワード検索について紹介します。

まずQrichという四択クイズをどういうふうに作るかというところ。最初は記事DBから記事のデータを取得し、そのあとにキーワードを抽出します。重要語を見つけて、そこを穴抜きにします。ちょうど今画面に映っているものが、クイズの穴抜き部分が抜けている状態ですね。

穴抜きをしたところから、それに似た単語をword2vecで探していきます。それを合わせると、ちょうど四択問題が自動が作れるので、これにて完了という流れですね。

今日話すのは、この類似単語をどうやって探してくるかというところです。今回キーワードというのは、NEologdの辞書で分割した際の名詞を指しています。

次にいきますと、word2vecによる類似キーワード検索です。使ったことのある方も多いかと思うのですが、word2vec、厳密にはskip-gramを使って、まず朝日新聞の記事データから単語ベクトルを作ります。単語ベクトルを作ったあとは、gensimというライブラリで簡単に読み込めるので、近傍を簡単に検索できます。

これですごくシンプルにさっきのサービスのパイプラインを実装はできるのですが、ちょっとこれだけだと物足りません。必ず近傍の単語が一緒なんですよね。そりゃそうなんだって感じなのですが、これをちょっと見ていこうと思います。

会社のソフトバンクと球団のソフトバンクが判別できない

具体的にword2vecの問題点をここでピックアップしていますが、主に2つ挙げています。

まずそもそも、いい表現が獲得できていないというところですね。これは何なのかというと、記事本文、ちょっと見づらいかもしれませんが、黄色の部分が実際のそのキーワードですね。近傍の単語を探したいターゲットになっています。「シリコンバレー」「ゲノム編集」というキーワードですね。

これの近傍にある単語は何なのかというのを見てみると、「シリコンバレー」は「IT企業」「サンノゼ」「バイオベンチャー」。「ゲノム編集」が「ES細胞」「ヒト」「万能細胞」。わからなくはないですけど、ちょっとこれをそのまま四択にするのは、しんどいかなと思います。

キーワードの近傍が常に一緒というところなんですけれども、これも文脈に応じて近傍を変えたいシチュエーションがあるんですけれども、それがこちらです。スポーツと経済記事における「ソフトバンク」。

これはどちらも「楽天」「DeNA」「オリックス」といって、野球記事、スポーツ記事のほうに引っ張られてしまっているんですね。このソフトバンク、右のほうにある経済記事のソフトバンクなら、まだこういう並びでも許せなくはないですが、許せないのは下のほうですね。

企業のアマゾンと熱帯雨林のアマゾンがあったときに、アマゾン(Amazon)は百歩譲ってまぁいいんですけど、ブラジルのアマゾンの近傍が「グーグル」「ネット通販」「キンドル」というのは、これは正直、最悪です。

こういったものを直して、選択肢として明らかに不自然じゃない、もう少し自然なものにしたいということでたどり着いたのが、ELMoでした。

ELMoでどうやって単語ベクトルを作るか?

ELMoについて少し簡単に紹介すると、言語モデルによるベクトル表現です。ELMo自体はbi-LSTMを使って、文を読み込んでいます。

ではword2vecと違って何がいいのかというと、bi-LSTMで読み込むので、先ほどみたいに毎回近傍の単語が同じになるわけではなく、読み込ませた文によって、単語のベクトル表現が変わってきます。だから、文脈を少し考慮できるというメリットがあります。

「ELMoによる単語ベクトル」というと、ちょっとなかなか言い分けるのが難しいので、今回は「ELMoベクトル」と略しますが、bi-LSTMで文章をエンコードした際に、その1層目と2層目のhidden stateを結合して、今回その「ELMoベクトル」を出す、というふうにして扱っています。

なので今回、例えば「ML@Loftは主にAWS……」という文章が今(スライドに)映っていると思うんですけれども、AWSのあとの部分が、AWSのキーワードベクトル、ELMoベクトルに相当するものになっています。

意味の多様性に対処するためにELMoを使う

次に、なぜELMoなんですかというところ。word2vec以外にも、GloVeだったりfastTextだったりという単語ベクトルのモデルはあるのですが、どれを使っても、結局1単語につきベクトルは1つなので、意味の多様性には対処できないという問題点があります。

あとBERTを使うのも考えられるのですが、BERTの場合は、そもそもBPEで単語分割をしており、NEologdの辞書で単語分割をしている今回のタスクには合わないので見送っています。もちろん作れなくはないですけれども、かなりパラメータ数も増えるので、訓練コストが大きいことが見送った理由です。

逆にELMoの何がいいかというと、単語のrepresentationを作る際に、char-CNNで文字からCNNで畳み込んで単語ベクトルを作って、bi-LSTMに入力しているので、語彙サイズがいろいろな語彙があったとしても、対応が容易というメリットがあります。なので、今回はELMoで進めていきました。

中心と一番遠い記事を読み込ませる

ELMoを作って終わりというわけではなくて、ELMoを作ったら今度はそれを読み込ませる記事、要するに文脈が大事になってくるので、その文脈を与えるためにどういう記事を読み込ませようかというのが重要になってきます。

先ほど出てきたソフトバンクだったりアマゾンといった言葉のように、さっき見せた例は2つだったんですけれども、今回は事前に意味の多様性というのはどれぐらいあるのかはわからないので、すべてのキーワードが2つ意味の多様性をもつと仮定して、各単語2つ、2種類のベクトルを作るというふうにしてアプローチしています。

なので、なるべく意味が違う記事を2つ見つけたいんですね。例えば、ソフトバンクのスポーツ記事を2つELMoに読み込ませても似たベクトルができてしまうので、結局それだと近傍探索をしたときに、あまり意味の多様性に対して解決につながっていないので、なるべく違うものを選びたいと思います。

記事を選ぶ際に、文章をベクトル化する方法はいろいろとあるのですが、今回はTF-IDFとSWEMを結合して、文書ベクトルとして表現して、ベクトル空間上に埋め込んでいます。

選び方としては、乱暴と言えば乱暴なんですけど、中心に近いものを候補記事の1つ、そこから一番遠いものを候補2記事に、というふうにして選んでいます。

これを絵として見せると、このような感じですね。今ソフトバンクについての100記事ぐらいをベクトル空間上に埋め込み、そこから中心点に一番近いものを選んであげると、候補記事1のほうが野球の記事ですね。スポーツ記事。そこから一番遠いものを選んであげると、今度はスプリント再編に関するソフトバンクの経済記事が取れました。

これで無事に、ELMoに読み込ませる記事を選んでいきました。ここまで来たら、ゴールまであと少しです。キーワードと記事を2つ選んだので、それを使ってELMoベクトルを作ります。今回、近傍探索にはAnnoyを使っています。それでインデックスを作って、実際にクイズを作る際には、記事本文と穴抜き対象のキーワードを読み込ませて、ELMoのベクトルができます。それを近傍探索して似た単語を出しています。

これでELMoのベクトルを使ったインデックスは作れましたが、今後新しいキーワード、例えば新しいスポーツ選手名などが出てきたりするので、そういう問題に対応するために、人手でキーワードと記事を選んで、ELMoベクトルを作って、Annoyに新しくインデックスを追加して更新する運用をしています。

会社と球団の判別ができるようになった

最後にELMoでどれだけよくなったかというところをお見せします。word2vecだと、ソフトバンクは(左右の文章)どっちも野球チームが出てきてしまっていたんですが、今回(ELMo)は、右のほうがいわゆる企業としてのソフトバンクですが、それが「ライブドア」「ソニー」「キヤノン」というふうにちゃんと経済記事に出てきそうな企業名が取れています。

一方で(左の)スポーツ記事のほうは、「レッドソックス」ってメジャーリーグのチームが出ているのですが、ある程度野球チームというラインナップで揃えられています。

下のほうも一緒で、企業のアマゾンのほうが「ネットフリックス」「レノボ」「ダイムラー」というかたちでとれています。また、最初に一番問題視していた熱帯雨林のほうも、アマゾン(地名)に関しては「メンフィス」「ボズニア」「ガボン」というかたちで、ベストにはまだ遠いですが、ベターな解決につながっているかと思います。

最後にまとめです。今回はQrichのクイズ作成フローを紹介して、word2vecの問題点として、常に近傍の単語が変わらないという問題があることを説明しました。それに対して、今回はELMoでアプローチをしました。

(ELMoの)いい点が、語彙サイズが大きくても訓練可能なところ。あと、ELMoに使うといっても、どういう記事を読み込ませるかというのが、representationを作る上ではけっこう重要です。

実際のアウトプットを見てみても、文脈に応じて近傍の単語をうまく変えられているので、先ほどお見せしたように、word2vecと比較としてもある程度類似キーワードがうまく取れていると思います。

こちらが参考文献ですね。

以上です。ご清聴ありがとうございました。

(会場拍手)