LoginSignup
62
48

More than 3 years have passed since last update.

Universal Sentence Encoderを日本語で試す

Last updated at Posted at 2019-09-08

Universal Sentence Encoderとは

その名の通り、文をエンコード、すなわち文をベクトル化する手法です。
Googleの研究者達が開発したもので、2018年にTensorflow Hubで公開されました。
公開当初は英語のみの対応でしたが、2019年9月現在では日本語、中国語、ドイツ語など16言語に対応しています。

これまで文をベクトル化する手法としては、

  • 単語の分散表現を利用したもの
    • 具体的な方法としてはこの記事が分かりやすいです。
  • Sentence2Vec
  • Skip-thought

など様々な手法が提案されてきましたが、これといった決定打に欠ける状況です。
ただ、Universal Sentence EncoderはSTSbenchmarkで高い精度を達成しており、また言語の違いを意識する必要がない(≒異なる言語でも同じベクトル空間上にマップされる)ので、今後は文のベクトル化のデファクトスタンダードになるかもしれません。

Universal Sentence Encoderのモデル

下記の2つのモデルを提案しています。

  1. Transformer
  2. Deep Averaging Network(DAN)

Transformのモデルは精度が高いもののモデルが複雑で多くのリソースを使うのに対して、DANのモデルは精度が少し落ちるもののシンプルなモデルでリソースの消費量が少なく済みます。
アルゴリズムの詳細を知りたい方は元の論文をご覧下さい。
なお、Tensorflow Hubで公開されているものは、DANのモデルが使われています。

Universal Sentence Encoder(Version 1)の使い方

2020/04/19時点ではVersion 3が最新版になります。Version 3の使い方はこちらをご覧下さい。

使い方は非常に簡単です。最新バージョンのtensorflowtensorflow_hubnumpytf_sentencepiecepipでインストールすれば、わずか十数行で書けます。
下記のプログラムでは、文をベクトル化した上でコサイン類似度で文同士の類似度を計算しています。
ベクトル化したい文をリストに格納しますが、異なる言語の文を同じリストのオブジェクトに格納しても問題ありません。

import tensorflow as tf
import tensorflow_hub as hub
import numpy as np
import tf_sentencepiece

def cos_sim(v1, v2):
    return np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2))

if __name__ == "__main__":
    # Graph set up.
    g = tf.Graph()
    with g.as_default():
      text_input = tf.placeholder(dtype=tf.string, shape=[None])
      # どちらを使っても大丈夫
      embed = hub.Module("https://tfhub.dev/google/universal-sentence-encoder-multilingual-large/1")
      # embed = hub.Module("https://tfhub.dev/google/universal-sentence-encoder-multilingual/1")
      embedded_text = embed(text_input)
      init_op = tf.group([tf.global_variables_initializer(), tf.tables_initializer()])
    g.finalize()

    # Initialize session.
    session = tf.Session(graph=g)
    session.run(init_op)

    # Make sentence vectors.
    texts = ["昨日、お笑い番組を見た。", "昨夜、テレビで漫才をやっていた。", "昨日、公園に行った。", "I saw a comedy show last night.", "Yesterday, I went to the park."]
    vectors = session.run(embedded_text, feed_dict={text_input: texts})

    print(texts[0], texts[1], cos_sim(vectors[0], vectors[1]), sep="\t")
    print(texts[0], texts[2], cos_sim(vectors[0], vectors[2]), sep="\t")
    print(texts[0], texts[3], cos_sim(vectors[0], vectors[3]), sep="\t")
    print(texts[0], texts[4], cos_sim(vectors[0], vectors[4]), sep="\t")

結果は以下のようになります。
日本語同士で似た意味の文の類似度が高くなっているだけでなく、日本語と英語でも似た意味の文の類似度が高くなっていることが分かります。

昨日、お笑い番組を見た。    昨夜、テレビで漫才をやっていた。    0.80579656
昨日、お笑い番組を見た。    昨日、公園に行った。  0.32864782
昨日、お笑い番組を見た。    I saw a comedy show last night. 0.7474545
昨日、お笑い番組を見た。    Yesterday, I went to the park.  0.26472652

Universal Sentence Encoder(Version 3)の使い方

Version3ではさらに簡単に使えるようになりました。

import tensorflow_hub as hub
import numpy as np
import tensorflow_text

# for avoiding error
import ssl
ssl._create_default_https_context = ssl._create_unverified_context

def cos_sim(v1, v2):
    return np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2))

embed = hub.load("https://tfhub.dev/google/universal-sentence-encoder-multilingual/3")

texts = ["昨日、お笑い番組を見た。", "昨夜、テレビで漫才をやっていた。", "昨日、公園に行った。", "I saw a comedy show last night.", "Yesterday, I went to the park."]
vectors = embed(texts)

print(texts[0], texts[1], cos_sim(vectors[0], vectors[1]), sep="\t")
print(texts[0], texts[2], cos_sim(vectors[0], vectors[2]), sep="\t")
print(texts[0], texts[3], cos_sim(vectors[0], vectors[3]), sep="\t")
print(texts[0], texts[4], cos_sim(vectors[0], vectors[4]), sep="\t")

結果は以下のようになります。

昨日、お笑い番組を見た。    昨夜、テレビで漫才をやっていた。    0.59764516
昨日、お笑い番組を見た。    昨日、公園に行った。  0.43056923
昨日、お笑い番組を見た。    I saw a comedy show last night. 0.71707606
昨日、お笑い番組を見た。    Yesterday, I went to the park.  0.3018708

Universal Sentence Encoderの応用方法

ここまで文のベクトル化ということで紹介してきましたが、単語、フレーズ、複文であってもベクトル化が可能です。
ですので、口コミのポジネガ判定やアンケート回答のクラスタリングなどの文書分類に落とし込める問題では、Universal Sentence Encoderを活用できると思います。
さらに、言語の違いを意識する必要がないので、日本語のクエリ文から英語の類似文を抽出するというような処理も簡単にできるようになっています。

Universal Sentence Encoderは、精度だけでなく異なる言語でも同じベクトル空間上で表現できるというのが非常に大きな強みだと思います。
是非、自分たちの研究や業務ではどのような場面に活かせそうかという事を考えてみて下さい。

62
48
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
62
48