magnitudeの初期化2019-02-27概要magnitudeという単語埋め込みを扱うライブラリには、単語を構成する文字列を考慮したout-of-vocabularyの初期化の方法が実装されています。2018の論文と実際のコードを元に、その初期化の方法を実装して試してみました。Classificationが終わって上位陣の解法を眺めていたのですが、その中で目に止まったのがout-of-vocabulary(以降OOVと表記)の対応です。今回のコンペでは主催側が定めた幾つかの学習済み単語埋め込みしか使うことができないので、大規模コーパスから新しく学習することができません。そのため、データセットには含まれているが学習済み単語ベクトルには含まれていない単語であるout-of-vocabularyをどう扱うかが、前処理の重要な要素だったようです。それぞれの解法には以下のようなコメントが記載されています。kernel)興味深いのが3位のkernelのこの部分のコードで、単語ベクトルが見つからなかった場合にひたすら単語の表記をあれこれ変えて辞書に当てる努力をしています。(https://www.kaggle.com/wowfattie/3rd-place#L148)これらの努力は当然といえば当然で、近年の単語id(またはone-hot表現)から埋め込み層を経て再帰的ニューラルネットワークに流れるNNの場合では、対応する埋め込み表現が無い単語に関しては、その単語が欠損していると何ら変わらない状態になります。意味的な冗長さが少ない今回のコンペのようなテキストでは、含まれる単語の埋め込み表現が得られないと文章全体の表現として致命的である場合があると想像されます。低頻度語や固有名詞の場合では影響は少ないですが、こういったOOVの情報の損失はなるべく避けたいというのが戦法の一つだったと思われます。magnitudeにおけるOOVの扱いさて、OOVの対応事例をいろいろと見ているなかで、magnitudeというPythonパッケージにおいて特徴的なOOV対策がされているのを見つけました。基本的にはOOVにはランダムなベクトル表現を付与するのですが、下記の2つの工夫が入っています。2018にてmagnitudeの開発メンバーが発表した論文と、実際のmagnitudeの実装を参考にして、最低限な要素のみを取り出して実装してみました。magnitudeのロジックmagnitudeでは、OOVのベクトルは下記式のように2つの項から構成されています。引用)1項目OOVの計算まず1つ目のOOV_d(w)は、文字列からどうやってランダムなベクトルを作るかという部分です。これまた以下のような定義式で計算するのですが、CGRAM_w(3,6)では、単語における3-gramから6-gramまでの文字列をすべて列挙するoov_d(w)では、列挙したngramの文字列全部に対して、その文字列→数字に変換した値を疑似乱数のシードとしたときに、[-1,1]の一様乱数からd次元分のランダムベクトルを作成しその平均を取る最後にノルムで正規化するという構造になっています。このような回りくどい方法を取るかと言うと、1つ目の目的であった「文字列的に似ているOOVの単語同士には、なるべく似たベクトル表現を付与したい」に関連します。1.のngramの生成は、Pythonでの実装は以下のようになります(ngram()の実装は省いています)。'berxl']こうやって見ると、文字列で見たときに似ている単語同士は、当然ながらそのngramの構成も近くなります。あとは、各ngramから何かしらのランダムベクトルが計算できれば、その足し合わせで表現することでランダムベクトルも近くなるはずです。文字列を数字に変換した上で、それをシードとして一様乱数から分散表現の次元数分だけサンプリングすれば良いわけです。uberxとuberxlのngramで異なる部分は3つだけですので、その分少しだけ違うランダムさが加わったベクトルになります。generator"と呼んでいます。2項目MATCHの計算そして2つ目の構成要素のMATCH_3(3,6,w)では、与えられた単語に近い単語トップ3を抽出し、その平均を取ります。magnitudeのコード内ではSQLiteの機能を利用して類似文字列を検索したり、特定のパターンを元に単語の部分文字列を抽出しています。これらの2つを30%と70%の重みで足し合わせることで、最終的なランダムベクトルを計算します。実装magnitudeのコードを参考に、一部日本語の正規化のロジックも入れて実装しました。yagays/oov_magnitude_ja以下のように利用できます。類似単語の列挙model.similar_by_vector(moov.query(query_1))なお、英語→日本語の変換の過程で見出し語化などの特定の処理は行っておらず、また文字列の類似度計算には編集距離を用いています。magnitudeの完全な移植ではないのでご了承ください。テスト具体的なタスクでの精度向上みたいな話はなかなかできないので、ここでは幾つかのOOVの初期化の結果を示します。例1まず、文字列が似ている単語同士が近い距離になるかを確かます。「前前前世」という語彙中に存在する単語に対して、「前前前前世」と「前前前前前世」というOOVのランダムベクトルを作成しました。その結果コサイン距離は0.98となり、それぞれ独立したOOVながらも、それらの距離が近くなるような初期化ができました。0.9823038957021559また、語彙中で類似する単語トップ10をそれぞれ列挙したのが以下になります。ランダムベクトルなので、全然関係ない単語が列挙されていてランダムなベクトルでありながらも、「前前前世」という単語もその中に含まれていることがわかります。ダンシングディーヴァ例2ngramに幾つもの単語が含まれる場合も試してみます。「見える化傾向」というOOVを入れると、「見え」「見える」「見える化」など、その意味を表すようなベクトルに近いものが得られていることが分かります。