クロスリンガルユニバーサルセンテンスエンコーダによる言語間の類似性とセマンティック検索エンジン

TensorFlow.org で表示 Google Colabで実行 GitHub でソースを表示 ノートブックをダウンロード TF Hub モデルを参照

このノートブックでは、多言語ユニバーサルセンテンス エンコーダモジュールにアクセスして、複数の言語間の文章の類似性を得るために使用する方法を説明します。このモジュールは元のユニバーサルエンコーダモジュールを拡張したものです。

ノートブックは以下のように分けられています。

  • 第 1 部では、言語ペア間の文章を可視化します。これは、より学術的な演習です。
  • 第 2 部では、多言語の Wikipedia コーパスのサンプルからセマンティック検索エンジンを構築する方法を紹介します。

引用

研究論文でこの Colab で探索するモデルを使用する場合は以下のように引用してください。

セマンティック検索のための多言語ユニバーサルセンテンスエンコーダ

Yinfei Yang・Daniel Cer・Amin Ahmad・Mandy Guo・Jax Law・Noah Constant・Gustavo Hernandez Abrego・Steve Yuan・Chris Tar・Yun-Hsuan Sung・Brian Strope・Ray Kurzweil (2019) arXiv preprint arXiv:1907.04307

セットアップ

このセクションでは、多言語ユニバーサルセンテンスエンコーダモジュールへのアクセス環境を設定し、英語の文とその翻訳文のセットを準備します。以下のセクションでは、多言語モジュールを使用して、言語間の類似性を計算します。

Setup Environment

Setup common imports and functions

これは事前トレーニングされた ML モデルをインポートする追加のボイラープレートコードで、このノートブック全体でテキストをエンコードするために使用します。

# The 16-language multilingual module is the default but feel free
# to pick others from the list and compare the results.
module_url = 'https://tfhub.dev/google/universal-sentence-encoder-multilingual/3'

model = hub.load(module_url)

def embed_text(input):
  return model(input)

言語間のテキスト類似性を可視化する

文章埋め込みを使用すると、異なる言語間の意味的類似性の可視化が可能になります。

テキスト埋め込みを計算する

まずは、様々な言語に翻訳された文章のセットを並列に定義します。その次に、すべての文章の埋め込みを事前計算します。

# Some texts of different lengths in different languages.
arabic_sentences = ['كلب', 'الجراء لطيفة.', 'أستمتع بالمشي لمسافات طويلة على طول الشاطئ مع كلبي.']
chinese_sentences = ['狗', '小狗很好。', '我喜欢和我的狗一起沿着海滩散步。']
english_sentences = ['dog', 'Puppies are nice.', 'I enjoy taking long walks along the beach with my dog.']
french_sentences = ['chien', 'Les chiots sont gentils.', 'J\'aime faire de longues promenades sur la plage avec mon chien.']
german_sentences = ['Hund', 'Welpen sind nett.', 'Ich genieße lange Spaziergänge am Strand entlang mit meinem Hund.']
italian_sentences = ['cane', 'I cuccioli sono carini.', 'Mi piace fare lunghe passeggiate lungo la spiaggia con il mio cane.']
japanese_sentences = ['犬', '子犬はいいです', '私は犬と一緒にビーチを散歩するのが好きです']
korean_sentences = ['개', '강아지가 좋다.', '나는 나의 개와 해변을 따라 길게 산책하는 것을 즐긴다.']
russian_sentences = ['собака', 'Милые щенки.', 'Мне нравится подолгу гулять по пляжу со своей собакой.']
spanish_sentences = ['perro', 'Los cachorros son agradables.', 'Disfruto de dar largos paseos por la playa con mi perro.']

# Multilingual example
multilingual_example = ["Willkommen zu einfachen, aber", "verrassend krachtige", "multilingüe", "compréhension du langage naturel", "модели.", "大家是什么意思" , "보다 중요한", ".اللغة التي يتحدثونها"]
multilingual_example_in_en =  ["Welcome to simple yet", "surprisingly powerful", "multilingual", "natural language understanding", "models.", "What people mean", "matters more than", "the language they speak."]
# Compute embeddings.
ar_result = embed_text(arabic_sentences)
en_result = embed_text(english_sentences)
es_result = embed_text(spanish_sentences)
de_result = embed_text(german_sentences)
fr_result = embed_text(french_sentences)
it_result = embed_text(italian_sentences)
ja_result = embed_text(japanese_sentences)
ko_result = embed_text(korean_sentences)
ru_result = embed_text(russian_sentences)
zh_result = embed_text(chinese_sentences)

multilingual_result = embed_text(multilingual_example)
multilingual_in_en_result = embed_text(multilingual_example_in_en)

類似性を可視化する

テキスト埋め込みを使用すると、そのドット積を用いて言語間でどのように文章が類似しているかを可視化することができます。濃い色は埋め込みが意味的に似ていることを示します。

多言語間の類似性

visualize_similarity(multilingual_in_en_result, multilingual_result,
                     multilingual_example_in_en, multilingual_example,  "Multilingual Universal Sentence Encoder for Semantic Retrieval (Yang et al., 2019)")

英語とアラビア語の類似性

visualize_similarity(en_result, ar_result, english_sentences, arabic_sentences, 'English-Arabic Similarity')

英語とロシア語の類似性

visualize_similarity(en_result, ru_result, english_sentences, russian_sentences, 'English-Russian Similarity')

英語とスペイン語の類似性

visualize_similarity(en_result, es_result, english_sentences, spanish_sentences, 'English-Spanish Similarity')

英語とイタリア語の類似性

visualize_similarity(en_result, it_result, english_sentences, italian_sentences, 'English-Italian Similarity')

イタリア語とスペイン語の類似性

visualize_similarity(it_result, es_result, italian_sentences, spanish_sentences, 'Italian-Spanish Similarity')

英語と中国語の類似性

visualize_similarity(en_result, zh_result, english_sentences, chinese_sentences, 'English-Chinese Similarity')

英語と韓国語の類似性

visualize_similarity(en_result, ko_result, english_sentences, korean_sentences, 'English-Korean Similarity')

中国語と韓国語の類似性

visualize_similarity(zh_result, ko_result, chinese_sentences, korean_sentences, 'Chinese-Korean Similarity')

その他…

上記の例は、英語、アラビア語、中国語、オランダ語、フランス語、ドイツ語、イタリア語、日本語、韓国語、ポーランド語、ポルトガル語、ロシア語、スペイン語、タイ語、トルコ語の任意の言語ペアに拡張が可能です。コーディングをお楽しみください!

多言語セマンティック類似性検索エンジンを作成する

前の例では少数の文章を可視化しましたが、このセクションでは Wikipedia コーパスから約 20 万文の意味検索インデックスを構築します。約半分は英語、残りの半分はスペイン語から成り、ユニバーサルセンテンスエンコーダの多言語能力を実演します。

データをインデックスにダウンロードする

まず、ニュース解説コーパス [1] から多言語のニュースの文章をダウンロードします。このアプローチは、サポートされている他の言語のインデックス作成においても、一般性を損なわずに使用することができます。

ここではデモを高速化するため、1 言語あたり 1000 文に制限しています。

corpus_metadata = [
    ('ar', 'ar-en.txt.zip', 'News-Commentary.ar-en.ar', 'Arabic'),
    ('zh', 'en-zh.txt.zip', 'News-Commentary.en-zh.zh', 'Chinese'),
    ('en', 'en-es.txt.zip', 'News-Commentary.en-es.en', 'English'),
    ('ru', 'en-ru.txt.zip', 'News-Commentary.en-ru.ru', 'Russian'),
    ('es', 'en-es.txt.zip', 'News-Commentary.en-es.es', 'Spanish'),
]

language_to_sentences = {}
language_to_news_path = {}
for language_code, zip_file, news_file, language_name in corpus_metadata:
  zip_path = tf.keras.utils.get_file(
      fname=zip_file,
      origin='http://opus.nlpl.eu/download.php?f=News-Commentary/v11/moses/' + zip_file,
      extract=True)
  news_path = os.path.join(os.path.dirname(zip_path), news_file)
  language_to_sentences[language_code] = pd.read_csv(news_path, sep='\t', header=None)[0][:1000]
  language_to_news_path[language_code] = news_path

  print('{:,} {} sentences'.format(len(language_to_sentences[language_code]), language_name))
Downloading data from http://opus.nlpl.eu/download.php?f=News-Commentary/v11/moses/ar-en.txt.zip
24715264/24714354 [==============================] - 2s 0us/step
1,000 Arabic sentences
Downloading data from http://opus.nlpl.eu/download.php?f=News-Commentary/v11/moses/en-zh.txt.zip
18104320/18101984 [==============================] - 2s 0us/step
1,000 Chinese sentences
Downloading data from http://opus.nlpl.eu/download.php?f=News-Commentary/v11/moses/en-es.txt.zip
28106752/28106064 [==============================] - 2s 0us/step
1,000 English sentences
Downloading data from http://opus.nlpl.eu/download.php?f=News-Commentary/v11/moses/en-ru.txt.zip
24854528/24849511 [==============================] - 2s 0us/step
1,000 Russian sentences
1,000 Spanish sentences

事前トレーニングされたモデルを使用して文章をベクトルに変換する

GPU の RAM に収まるようにバッチで埋め込みを計算をします。

# Takes about 3 minutes

batch_size = 2048
language_to_embeddings = {}
for language_code, zip_file, news_file, language_name in corpus_metadata:
  print('\nComputing {} embeddings'.format(language_name))
  with tqdm(total=len(language_to_sentences[language_code])) as pbar:
    for batch in pd.read_csv(language_to_news_path[language_code], sep='\t',header=None, chunksize=batch_size):
      language_to_embeddings.setdefault(language_code, []).extend(embed_text(batch[0]))
      pbar.update(len(batch))
0%|          | 0/1000 [00:00<?, ?it/s]
Computing Arabic embeddings
83178it [00:30, 2768.60it/s]
  0%|          | 0/1000 [00:00<?, ?it/s]
Computing Chinese embeddings
69206it [00:18, 3664.60it/s]
  0%|          | 0/1000 [00:00<?, ?it/s]
Computing English embeddings
238853it [00:37, 6319.00it/s]
  0%|          | 0/1000 [00:00<?, ?it/s]
Computing Russian embeddings
190092it [00:34, 5589.16it/s]
  0%|          | 0/1000 [00:00<?, ?it/s]
Computing Spanish embeddings
238819it [00:41, 5754.02it/s]

セマンティックベクトルのインデックスを構築する

Annoy ライブラリのラッパーである、SimpleNeighbors ライブラリを使用して、効率的にコーパスから結果を検索します。

%%time

# Takes about 8 minutes

num_index_trees = 40
language_name_to_index = {}
embedding_dimensions = len(list(language_to_embeddings.values())[0][0])
for language_code, zip_file, news_file, language_name in corpus_metadata:
  print('\nAdding {} embeddings to index'.format(language_name))
  index = SimpleNeighbors(embedding_dimensions, metric='dot')

  for i in trange(len(language_to_sentences[language_code])):
    index.add_one(language_to_sentences[language_code][i], language_to_embeddings[language_code][i])

  print('Building {} index with {} trees...'.format(language_name, num_index_trees))
  index.build(n=num_index_trees)
  language_name_to_index[language_name] = index
0%|          | 1/1000 [00:00<02:21,  7.04it/s]
Adding Arabic embeddings to index
100%|██████████| 1000/1000 [02:06<00:00,  7.90it/s]
  0%|          | 1/1000 [00:00<01:53,  8.84it/s]
Building Arabic index with 40 trees...

Adding Chinese embeddings to index
100%|██████████| 1000/1000 [02:05<00:00,  7.99it/s]
  0%|          | 1/1000 [00:00<01:59,  8.39it/s]
Building Chinese index with 40 trees...

Adding English embeddings to index
100%|██████████| 1000/1000 [02:07<00:00,  7.86it/s]
  0%|          | 1/1000 [00:00<02:17,  7.26it/s]
Building English index with 40 trees...

Adding Russian embeddings to index
100%|██████████| 1000/1000 [02:06<00:00,  7.91it/s]
  0%|          | 1/1000 [00:00<02:03,  8.06it/s]
Building Russian index with 40 trees...

Adding Spanish embeddings to index
100%|██████████| 1000/1000 [02:07<00:00,  7.84it/s]
Building Spanish index with 40 trees...
CPU times: user 11min 21s, sys: 2min 14s, total: 13min 35s
Wall time: 10min 33s

%%time

# Takes about 13 minutes

num_index_trees = 60
print('Computing mixed-language index')
combined_index = SimpleNeighbors(embedding_dimensions, metric='dot')
for language_code, zip_file, news_file, language_name in corpus_metadata:
  print('Adding {} embeddings to mixed-language index'.format(language_name))
  for i in trange(len(language_to_sentences[language_code])):
    annotated_sentence = '({}) {}'.format(language_name, language_to_sentences[language_code][i])
    combined_index.add_one(annotated_sentence, language_to_embeddings[language_code][i])

print('Building mixed-language index with {} trees...'.format(num_index_trees))
combined_index.build(n=num_index_trees)
0%|          | 1/1000 [00:00<02:00,  8.29it/s]
Computing mixed-language index
Adding Arabic embeddings to mixed-language index
100%|██████████| 1000/1000 [02:06<00:00,  7.92it/s]
  0%|          | 1/1000 [00:00<02:24,  6.89it/s]
Adding Chinese embeddings to mixed-language index
100%|██████████| 1000/1000 [02:05<00:00,  7.95it/s]
  0%|          | 1/1000 [00:00<02:05,  7.98it/s]
Adding English embeddings to mixed-language index
100%|██████████| 1000/1000 [02:06<00:00,  7.88it/s]
  0%|          | 1/1000 [00:00<02:18,  7.20it/s]
Adding Russian embeddings to mixed-language index
100%|██████████| 1000/1000 [02:04<00:00,  8.03it/s]
  0%|          | 1/1000 [00:00<02:17,  7.28it/s]
Adding Spanish embeddings to mixed-language index
100%|██████████| 1000/1000 [02:06<00:00,  7.90it/s]
Building mixed-language index with 60 trees...
CPU times: user 11min 18s, sys: 2min 13s, total: 13min 32s
Wall time: 10min 30s

セマンティック類似性検索エンジンの動作を確認する

このセクションでは以下を実演します。

  1. セマンティック検索機能 : 与えられたクエリに意味的に類似した文をコーパスから検索します。
  2. 多言語機能: 複数の言語において言語とインデックス言語の一致をクエリする場合に、1. と同じことを行います。
  3. クロスリンガル機能: インデックス化されたコーパスとは異なる言語でクエリを発行します。
  4. 混合言語コーパス: 1~3 のすべてを行い、全言語の全エントリを単一のインデックス上に収録します。

セマンティック検索クロスリンガル機能

このセクションでは、サンプル英文のセットに関連する文の検索方法を紹介します。以下を試してみてください。

  • 複数の異なるサンプル文を試す。
  • 返される結果の数を変えてみる(結果は類似度が高い順に返されます)。
  • 異なる言語で結果を返し、クロスリンガル機能を試してみる。(サ二ティーチェックとして、Google翻訳 を使用して結果を母国語に訳してみてもよいでしょう)

English sentences similar to: "The stock market fell four points."
['Nobel laureate Amartya Sen attributed the European crisis to four failures – political, economic, social, and intellectual.',
 'Just last December, fellow economists Martin Feldstein and Nouriel Roubini each penned op-eds bravely questioning bullish market sentiment, sensibly pointing out gold’s risks.',
 'His ratings have dipped below 50% for the first time.',
 'As a result, markets were deregulated, making it easier to trade assets that were perceived to be safe, but were in fact not.',
 'Consider the advanced economies.',
 'But the agreement has three major flaws.',
 'This “predetermined equilibrium” thinking – reflected in the view that markets always self-correct – led to policy paralysis until the Great Depression, when John Maynard Keynes’s argument for government intervention to address unemployment and output gaps gained traction.',
 'Officials underestimated tail risks.',
 'Consider a couple of notorious examples.',
 'Stalin was content to settle for an empire in Eastern Europe.']

混合コーパス機能

クエリは英語で発行しますが、結果はインデックスされた言語のいずれかになります。

English sentences similar to: "The stock market fell four points."
['Nobel laureate Amartya Sen attributed the European crisis to four failures – political, economic, social, and intellectual.',
 'It was part of the 1945 consensus.',
 'The end of the East-West ideological divide and the end of absolute faith in markets are historical turning points.',
 'Just last December, fellow economists Martin Feldstein and Nouriel Roubini each penned op-eds bravely questioning bullish market sentiment, sensibly pointing out gold’s risks.',
 'His ratings have dipped below 50% for the first time.',
 'As a result, markets were deregulated, making it easier to trade assets that were perceived to be safe, but were in fact not.',
 'Consider the advanced economies.',
 'Since their articles appeared, the price of gold has moved up still further.',
 'But the agreement has three major flaws.',
 'Gold prices even hit a record-high $1,300 recently.',
 'This “predetermined equilibrium” thinking – reflected in the view that markets always self-correct – led to policy paralysis until the Great Depression, when John Maynard Keynes’s argument for government intervention to address unemployment and output gaps gained traction.',
 'What Failed in 2008?',
 'Officials underestimated tail risks.',
 'Consider a couple of notorious examples.',
 'One of these species, orange roughy, has been caught commercially for only around a quarter-century, but already is being fished to the point of collapse.',
 'Meanwhile, policymakers were lulled into complacency by the widespread acceptance of economic theories such as the “efficient-market hypothesis,” which assumes that investors act rationally and use all available information when making their decisions.',
 'Stalin was content to settle for an empire in Eastern Europe.',
 'Intelligence assets have been redirected.',
 'A new wave of what the economist Joseph Schumpeter famously called “creative destruction” is under way: even as central banks struggle to maintain stability by flooding markets with liquidity, credit to business and households is shrinking.',
 'It all came about in a number of ways.',
 'The UN, like the dream of European unity, was also part of the 1945 consensus.',
 'The End of 1945',
 'The Global Economy’s New Path',
 'But this scenario failed to materialize.',
 'Gold prices are extremely sensitive to global interest-rate movements.',
 'Fukushima has presented the world with a far-reaching, fundamental choice.',
 'It was Japan, the high-tech country par excellence (not the latter-day Soviet Union) that proved unable to take adequate precautions to avert disaster in four reactor blocks.',
 'Some European academics tried to argue that there was no need for US-like fiscal transfers, because any desired degree of risk sharing can, in theory, be achieved through financial markets.',
 '$10,000 Gold?',
 'One answer, of course, is a complete collapse of the US dollar.',
 '1929 or 1989?',
 'The goods we made were what economists call “rival" and “excludible" commodities.',
 'This dream quickly faded when the Cold War divided the world into two hostile blocs. But in some ways the 1945 consensus, in the West, was strengthened by Cold War politics.',
 'The first flaw is that the spending reductions are badly timed: coming as they do when the US economy is weak, they risk triggering another recession.',
 'One successful gold investor recently explained to me that stock prices languished for a more than a decade before the Dow Jones index crossed the 1,000 mark in the early 1980’s.',
 'Eichengreen traces our tepid response to the crisis to the triumph of monetarist economists, the disciples of Milton Friedman, over their Keynesian and Minskyite peers – at least when it comes to interpretations of the causes and consequences of the Great Depression.',
 "However, America's unilateral options are limited.",
 'Once it was dark, a screen was set up and Mark showed home videos from space.',
 'These aspirations were often voiced in the United Nations, founded in 1945.',
 'Then I got distracted for about 40 years.']

自分でクエリを試してみましょう。

English sentences similar to: "The stock market fell four points."
['(Chinese) 新兴市场的号角',
 '(English) It was part of the 1945 consensus.',
 '(Russian) Брюссель. Цунами, пронёсшееся по финансовым рынкам, является глобальной катастрофой.',
 '(Arabic) هناك أربعة شروط مسبقة لتحقيق النجاح الأوروبي في أفغانستان:',
 '(Spanish) Su índice de popularidad ha caído por primera vez por debajo del 50 por ciento.',
 '(English) His ratings have dipped below 50% for the first time.',
 '(Russian) Впервые его рейтинг опустился ниже 50%.',
 '(English) As a result, markets were deregulated, making it easier to trade assets that were perceived to be safe, but were in fact not.',
 '(Arabic) وكانت التطورات التي شهدتها سوق العمل أكثر تشجيعا، فهي على النقيض من أسواق الأصول تعكس النتائج وليس التوقعات. وهنا أيضاً كانت الأخبار طيبة. فقد أصبحت سوق العمل أكثر إحكاما، حيث ظلت البطالة عند مستوى 3.5% وكانت نسبة الوظائف إلى الطلبات المقدمة فوق مستوى التعادل.',
 '(Russian) Это было частью консенсуса 1945 года.',
 '(English) Consider the advanced economies.',
 '(English) Since their articles appeared, the price of gold has moved up still further.',
 '(Russian) Тогда они не только смогут накормить свои семьи, но и начать получать рыночную прибыль и откладывать деньги на будущее.',
 '(English) Gold prices even hit a record-high $1,300 recently.',
 '(Chinese) 另一种金融危机',
 '(Russian) Европейская мечта находится в кризисе.',
 '(English) What Failed in 2008?',
 '(Spanish) Pero el acuerdo alcanzado tiene tres grandes defectos.',
 '(English) Officials underestimated tail risks.',
 '(English) Consider a couple of notorious examples.',
 '(Spanish) Los mercados financieros pueden ser frágiles y ofrecen muy poca capacidad de compartir los riesgos relacionados con el ingreso de los trabajadores, que constituye la mayor parte de la renta de cualquier economía avanzada.',
 '(Chinese) 2008年败在何处?',
 '(Spanish) Consideremos las economías avanzadas.',
 '(Spanish) Los bienes producidos se caracterizaron por ser, como señalaron algunos economistas, mercancías “rivales” y “excluyentes”.',
 '(Arabic) إغلاق الفجوة الاستراتيجية في أوروبا',
 '(English) Stalin was content to settle for an empire in Eastern Europe.',
 '(English) Intelligence assets have been redirected.',
 '(Spanish) Hoy, envalentonados por la apreciación continua, algunos están sugiriendo que el oro podría llegar incluso a superar esa cifra.',
 '(Russian) Цены на золото чрезвычайно чувствительны к мировым движениям процентных ставок.',
 '(Russian) Однако у достигнутой договоренности есть три основных недостатка.']

その他のトピック

多言語

最後に、サポートされている言語でクエリを試してみることをお勧めします。現在サポートされている言語は、英語、アラビア語、中国語、オランダ語、フランス語、ドイツ語、イタリア語、日本語、韓国語、ポーランド語、ポルトガル語、ロシア語、スペイン語、タイ語、トルコ語です。

また、ここでは一部の言語のサブセットのみでインデックスを作成しましたが、サポートされているどの言語のコンテンツでもインデックスを作成することができます。

モデルの多様性

メモリ、レイテンシー、品質など、様々な点を最適化した、多様なユニバーサルエンコーダモデルを提供しています。自由に実験を行い、用途に合ったものを見つけてください。

最近傍ライブラリ

Annoy を使用して、最近傍の検索が効率よく行えるようにしました。木の数(メモリに依存)と検索するアイテムの数(遅延に依存)についてはトレードオフのセクションをご覧ください。SimpleNeighbors では木の数の制御しかできませんが、直接 Annoy を使用するコードのリファクタリングはシンプルであるべきなので、一般ユーザーのためにこのコードを可能な限りシンプルなものにしたいと考えました。

Annoy でアプリケーションをスケーリングできない場合は、FAISS もチェックしてみてください。

多言語セマンティックアプリケーション構築の成功を祈ります!

[1] J. Tiedemann (2012)「OPUS における並列データ、ツール、インタフェース」第 8 回言語資源と評価に関する国際会議 (LREC 2012) 議事録