Word2Vec#

Hide code cell source
# packageのimport
import os 
import math 
from typing import Any, Union, Callable, Type, TypeVar
from tqdm.std import trange,tqdm
import numpy as np 
import numpy.typing as npt
import pandas as pd 
import matplotlib.pyplot as plt 
import plotly.express as px
import seaborn as sns

# pytorch関連のimport
import torch
import torch.nn as nn 
import torch.nn.functional as F 
import torch.optim as optim 

単語のベクトル表現#

自然言語処理において,単語をそのまま機械学習モデルに扱わせることはできません.そのため,それぞれの単語に対応するベクトル表現を利用することになります.このベクトル表現方法はいろいろとあり,離散表現と分散表現という大別ができます.これらについて見ていきましょう.

離散表現と分散表現#

単語をベクトルとして表現する方法として古くから使われているのがone-hot表現(1-of-K表現とも呼ばれます)です.これはある要素のみが1でそれ以外が0であるような表現のことであり,単語に対応したベクトルのある要素のみが1でそれ以外が0であるようなベクトルを用いることで,単語をベクトル表現します.

one-hotベクトルはシンプルなアイディアで理解しやすいですが,語彙の数だけベクトルの次元数が必要になることに注意が必要です.また,「オートバイ」と「バイク」のようなほぼほぼ似たような意味の単語同士の類似度をcosine類似度で計算しようとしても,それぞれが別の次元が立っているだけのベクトルなので内積0となってしまい,意味的な類似度を測ることには適さないことがわかります.

ここではこのone-hot表現を離散表現の例として紹介しました.

また,文書中に登場した単語のone-hotベクトルを足し合わせることで,文書をベクトル表現するBag-of-Words(BoW)という表現方法もあります.

この場合はただ足し合わせるだけなので,文書中に同じ単語が何回か登場したら,1以上の整数がベクトル内に現れることもあります.

onehotやbowの様な表現方法は非常に簡便で分かりやすい反面,語彙数分だけの次元数が常に必要になるなどの嬉しくない特徴を持ちます.

様々な分散表現#

one-hot表現に対して,分散表現とは単語を語彙数に比べて低次元の実数値ベクトルで表す表現です.気持ちとしては,one-hotで表現された単語をより低次元空間の座標として表現し,one-hot→embedding→onehotの様に可逆圧縮しているイメージです.そのため多くの場合任意の比較的小さい次元数(50, 100, 200, 300次元など)が用いられています.これの利点としては,

  • 語彙数に左右されずにベクトルの次元数を決定できるため計算量を抑えられる

  • 同じような意味の単語に同じようなベクトル表現を当てがうことができるのならば,cosine類似度のような簡単な計算で意味の類似度(のようなもの)を評価することができる

などが考えられます.現代の自然言語処理においても,このアプローチが取られることが多いです.

この分散表現の作り方には色々な方法があります.例えばBoWで表現された文章データをNMF(Non-Negative Matrix Factorization, 非負値行列因子分解)[Lee and Seung, 1999, Lee and Seung, 2000]やLSA(Latent Semantic Analysis, 潜在的意味解析)[Deerwester et al., 1990]のような手法で行列分解することで作成することもできます.ただし作成できるベクトルが持つ意味(作成されたベクトルがどのような使い方に適したものなのか)は手法により様々です.今回は,ニューラルネットワークを用いて単語の分散表現が作れるword2vec[Mikolov et al., 2013, Mikolov et al., 2013, Mikolov et al., 2013]と呼ばれる手法群の中でも,CBOWについて紹介します.

Continuous Bag-of-Words#

CBOWと分布仮説#

例えば以下の文章があったときに,XXXYYY に相当する単語がなんなのかがわかるでしょうか?

(この例ではもちろんXXXは ガンダム ですし,YYYは ノリス・パッカード大佐 ですね.)

私たちはある単語を聞きそびれたり,何かの固有名詞が分からなくても,周辺の言葉から大体類推して言葉の意味を把握することができます.

このような「単語の意味は、周囲の単語によって形成される」という仮説を自然言語処理では 分布仮説 と呼びます.

この文脈において,対象の単語の周辺の単語のことをコンテキストと呼びます.


説明したい単語「goodbye」と,その周辺にあってこの単語の意味を推測するのに使えそうな単語達(コンテキスト)の関係.
出典: ゼロから作るDeep Learning 2 自然言語処理編

この分布仮説をもとに,ニューラルネットワークを使って単語の意味をある程度表現できるようなベクトル表現を獲得できる手法がこれから紹介するCBOWです.

CBOWのアーキテクチャ#

CBoWでは,周辺の単語を入力にして目的の単語を予測するネットワークを構築します.


コンテキストを使った単語の予測.
出典: ゼロから作るDeep Learning 2 自然言語処理編

CBOWは単純なMLPを利用して,語彙数\(V\),埋め込み次元数\(N\)の場合に,全ての語彙それぞれに対応する単語埋め込みベクトルの束である\(\mathbf{W}_{V, N}\)を作成します.(ノーテーションは正しく定義しておけばなんでもいいのですが,私は埋め込み次元数を\(L\)と置くことが多いです.)

Illustration of the word2vec models: (a) CBOW, (b) skip-gram [16, 33].
word2vecのアーキテクチャ.左側がCBoW,また右側はSkip-Gram.
出典: Demographic Prediction Based on User Reviews about Medications

実装#

まずは,forwardメソッドの入力値が「コンテクストのBoW表現」である場合の実装を考えます.一層目の全結合層の結合重みをそれぞれの語彙に対応する単語埋め込みベクトルとして利用しましょう.

一つ目のnn.Linearはこのモデルで扱いたい語彙(異なり語,ユニークな単語)の数\(V\)(コード中では vocab_size)の数だけベクトルを持っており,入力された語彙に対応したベクトルを取り出して返します.この語彙に対応したベクトルを 単語埋め込みベクトル と呼びます.また,単語埋め込みベクトルの次元数\(N\)埋め込み次元数 などと呼び,コード中では embedding_dimという変数で扱います.
ある単語は,同じ文書中に存在する「その単語の周辺に出現する単語」によって類推することができるというのが自然言語処理の分布仮説でした.これに則り,周辺単語を入力として,予測したい単語の出現確率を出力するMLPを作ります.

class CBoW(nn.Module):
    def __init__(self, vocab_size:int, embedding_dim:int) -> None:
        super().__init__()
        self.embeddingbag = nn.Linear(vocab_size, embedding_dim, bias=False)
        self.linear = nn.Linear(embedding_dim, vocab_size)

    def forward(self, inputs:Any)->Any:
        h = self.embeddingbag(inputs) / inputs.sum(1)[:,None]
        return self.linear(h)

この実装のCBoWクラスはMLPとほぼ同じなので非常にわかりやすいですが,contextsをBoW表現に直す必要があります.データが少ない場合は問題になりませんが,データ量が増えた時には大変です.

PyTorchでは,このような実装をしなくとも単語のid列を入力に,onehotやbowを介さずに埋め込みベクトルを返してくれるnn.Embeddingクラスとnn.Embeddingbagクラスがあります.これを使ってより賢い実装を以下に示します.

Hint

単語idを一つ一つ単語埋め込みベクトルに変換したいならnn.Embeddingを使います.文書(単語idのシーケンス)に対する単純な埋め込みベクトルが欲しいならばnn.Embeddingbagを使います.

class CBoW(nn.Module):
    def __init__(self, vocab_size:int, embedding_dim:int) -> None:
        super().__init__()
        self.embeddingbag = nn.EmbeddingBag(vocab_size, embedding_dim)
        self.linear = nn.Linear(embedding_dim, vocab_size)

    def forward(self, inputs:Any)->Any:
        h = self.embeddingbag(inputs) / inputs.size(-1)
        return self.linear(h)

クラスの実装上で明確に異なるのはMLPの最初のLinear層の代わりに,Embeddingbagレイヤーと名付けられた層が追加されていることです.これによりforwardメソッドへの入力をいちいちonehotやbowにしなくとも,単語idのシーケンスを渡すだけで,埋め込みベクトルを返してくれます.

最終層は「ターゲットの単語が出現する確率」なので,Softmax関数を用います(ここでもSoftmaxを利用することにします).ただし,word2vecが発表された当初はGPUで計算するのではなく,CPUで計算できるような工夫として,Softmaxを近似した別の関数を利用していました.これにはHierarchical Softmax(階層的ソフトマックス)やNegative Sampling(不例サンプリング)が用いられます.是非調べてみてください.

損失関数#

\(x\)の出現確率\(p(x)\)とモデルの予測した\(x\)の出現確率\(q(x)\)の交差エントロピーは以下のように求まります.

(1)#\[ H(p, q) = -\sum_{x} p(x) \log(q(x)) \]

今回の場合,予測したい単語が\(y\)であり,これは単語idになっています.これを語彙数\(V\)のonehotベクトルにする関数を\(\operatorname{onehot}(y)\)としましょう.
コード中,CBoWのforwardメソッドの出力(予測する値)はself.linear(h)であり,下に示す訓練ループの中ではlogitsとされてますが,これは全結合層の出力でしかありません.本来はこれをSoftmaxに通した値が出力値であり,これが予測したい単語の出現確率です.よってここでのクロスエントロピーは

(2)#\[ H(y,\operatorname{logits}) = -\operatorname{onehot}(y) \cdot \log(\operatorname{softmax}(\operatorname{logits})) \]

で求められます.ただし,minibatchごとに訓練する場合は,データ一つ一つに対して計算した後に平均をとる必要があります.

実験#

データのダウンロード#

wikipediaを使いやすい形で公開してくれているtext8の日本語版,ja.text8を使ってw2vを学習してみましょう.

import os 
if "ja.text8" not in os.listdir("./input"):
    !wget -P ./data https://s3-ap-northeast-1.amazonaws.com/dev.tech-sketch.jp/chakki/public/ja.text8.zip
    !unzip ./input/ja.text8.zip -d ./input/

データの準備#

with open("./input/ja.text8") as f:
    text8 = f.read()

print(text8[:200])
ちょん 掛け ( ちょん がけ 、 丁 斧 掛け ・ 手斧 掛け と も 表記 ) と は 、 相撲 の 決まり 手 の ひとつ で ある 。 自分 の 右 ( 左 ) 足 の 踵 を 相手 の 右 ( 左 ) 足 の 踵 に 掛け 、 後方 に 捻っ て 倒す 技 。 手斧 ( ちょう な ) を かける 仕草 に 似 て いる こと から 、 ちょう な が 訛っ て ちょん 掛け と なっ 

ja.text8では(英文のように)単語ごとにスペースを入れてくれているので,簡単にこれ以降の自然言語処理に進めます.このような処理を 分かち書き と呼びます.

本当はtext8の全てのデータを使いたいのですが,学習に時間がかかりすぎるので1/10の量を使うことにします.

LIMIT = math.floor(len(text8)*0.1)
print(f"{LIMIT}/ {len(text8)}")

text8 = text8[:LIMIT]
4650779/ 46507793

読み込んだテキストから,以下の条件で単語をフィルタリングします.

  1. 日本語のみで構成された単語だけを取り出します.

  2. 5個以上の文書に出現している単語のみを取り出し

ここまでやった後に,語彙の辞書を作ります.

  1. id2word(id→単語)

  2. word2id (単語→id)

import re
def build_simply_dictionary(texts):
    token_set = set(token for text in texts for token in text.split())
    word2id = {token:id for id, token in enumerate(token_set)}  
    return word2id

def my_analyzer(text):
    #text = code_regex.sub('', text)
    tokens = text.split()
    tokens = filter(lambda token: re.search(r'[ぁ-ん]+|[ァ-ヴー]+|[一-龠]+', token), tokens)
    return tokens 

def build_dictionary(texts, min_df=1):
    from sklearn.feature_extraction.text import CountVectorizer
    countvectorizer = CountVectorizer(min_df=min_df, analyzer=my_analyzer)

    X = countvectorizer.fit_transform(texts)
    id2word = {id:w for id,w in enumerate(countvectorizer.get_feature_names_out())}
    word2id = {w:id for id,w in id2word.items()}
    return id2word, word2id, X

texts = text8.split("。")
id2word, word2id,X = build_dictionary(texts,5)
V = len(id2word)
D = len(texts)
print(f"文書数: {D}, 語彙数: {V}")
文書数: 57498, 語彙数: 17143

ここでは,予測したい単語とコンテキストを合わせたものをウィンドウと呼びます.このウィンドウサイズを5として,予測したい単語の前後2単語をまとめた5単語を取り出し,contextsとtargetを作成します.

def build_contexts_and_target(preprocessed_texts, window_size=5):
    contexts = []
    target = []
    a = window_size//2
    for text in preprocessed_texts:
        for i in range(a, len(text)-a):
            target.append(text[i])
            tmp = text[i-a:i]
            tmp += text[i+1:i+1+a]
            contexts.append(tmp)
    return np.array(contexts), np.array(target)
WINDOW_SIZE = 11

preprocessed_texts = [[word2id[w] for w in text.split() if w in word2id] for text in texts]
preprocessed_texts = [text for text in preprocessed_texts if len(text) > WINDOW_SIZE]
contexts, target = build_contexts_and_target(preprocessed_texts, WINDOW_SIZE)
print("前処理後の文書数:", len(preprocessed_texts))
print(f"contextsの数: {len(contexts)}")
前処理後の文書数: 44599
contextsの数: 750947

ミニバッチを作成する関数を用意します.

def get_batch(contexts, target, batch_size=32, shuffle=True):
    D = target.size
    index = np.arange(D)
    
    if shuffle:
        np.random.shuffle(index)

    n_batches = D // batch_size
    for minibatch_indexes in np.array_split(index, n_batches):
        a = torch.tensor(contexts[minibatch_indexes])
        b = torch.tensor(target[minibatch_indexes])
        yield a,b

訓練ループの作成#

通常のMLPと同様の学習ループを作成します.w2vの学習は時間がかかるので,プログレスバーを表示するようにしておきます.ここではepochごとに更新するバーとミニバッチごとに更新するバーを用意します.(ここで使うコーパスサイズだと,CPUで10~20分程度かかります)

学習が終わり次第,損失関数の増減を折れ線グラフにして確認できるようにもしておきましょう.

max_epochs = 10
lr = 0.01
batch_size = 512
L = 50
n_batches = len(target) // batch_size
DEVICE="cpu"
if torch.cuda.is_available():
    DEVICE ="cuda:0"

cbow = CBoW(V, L)
criterion = nn.CrossEntropyLoss()
save_fname = f"{cbow.__class__.__name__}_ep{max_epochs}_lr{lr}_b{batch_size}_emb{L}.pth"

"""
# 学習済みの重みがある場合
print("loading pretrained weights...")
cbow.load_state_dict(torch.load(f"./output/w2v-{save_fname}"))
cbow.eval()
"""

# 学習済みの重みがない場合
print("training CBoW from scrach...")
cbow.train()
cbow = cbow.to(DEVICE)
optimizer = optim.Adam(cbow.parameters(), lr=lr)
monitoring_loss = []

for epoch in trange(max_epochs):
    with tqdm(total=n_batches) as tbar:
        for batch in get_batch(contexts, target, batch_size):
            x,y = batch
            x,y = x.to(DEVICE), y.to(DEVICE)

            optimizer.zero_grad()
            logits = cbow(x)
            loss = criterion(logits, y)
            loss.backward()
            optimizer.step()
            
            monitoring_loss.append(float(loss))
            tbar.update(1)
cbow.eval()
cbow = cbow.cpu()
torch.save(cbow.state_dict(), f"./output/w2v-{save_fname}")


# プロット
plt.title("cross entropy of training set")
plt.xlabel("iteration")
plt.ylabel("cross entropy loss")
plt.plot(monitoring_loss)
plt.show()
Hide code cell output
training CBoW from scrach...
  0%|                                                                                                                                                                                                                                                                                                                | 0/10 [00:00<?, ?it/s]

  0%|                                                                                                                                                                                                                                                                                                              | 0/1466 [00:00<?, ?it/s]


  0%|▊                                                                                                                                                                                                                                                                                                     | 4/1466 [00:00<00:41, 35.12it/s]


  1%|█▌                                                                                                                                                                                                                                                                                                    | 8/1466 [00:00<00:42, 34.44it/s]


  1%|██▊                                                                                                                                                                                                                                                                                                  | 14/1466 [00:00<00:33, 43.42it/s]


  1%|████▏                                                                                                                                                                                                                                                                                                | 21/1466 [00:00<00:28, 51.11it/s]


  2%|█████▌                                                                                                                                                                                                                                                                                               | 28/1466 [00:00<00:25, 56.80it/s]


  2%|██████▉                                                                                                                                                                                                                                                                                              | 35/1466 [00:00<00:23, 59.89it/s]


  3%|████████▌                                                                                                                                                                                                                                                                                            | 43/1466 [00:00<00:22, 63.59it/s]


  3%|█████████▉                                                                                                                                                                                                                                                                                           | 50/1466 [00:00<00:21, 65.33it/s]


  4%|███████████▍                                                                                                                                                                                                                                                                                         | 57/1466 [00:00<00:21, 66.61it/s]


  4%|████████████▊                                                                                                                                                                                                                                                                                        | 64/1466 [00:01<00:25, 55.74it/s]


  5%|█████████████▉                                                                                                                                                                                                                                                                                       | 70/1466 [00:01<00:25, 55.81it/s]


  5%|███████████████▍                                                                                                                                                                                                                                                                                     | 77/1466 [00:01<00:23, 59.19it/s]


  6%|████████████████▊                                                                                                                                                                                                                                                                                    | 84/1466 [00:01<00:22, 60.53it/s]


  6%|██████████████████▏                                                                                                                                                                                                                                                                                  | 91/1466 [00:01<00:22, 62.15it/s]


  7%|███████████████████▌                                                                                                                                                                                                                                                                                 | 98/1466 [00:01<00:21, 64.16it/s]


  7%|████████████████████▉                                                                                                                                                                                                                                                                               | 105/1466 [00:01<00:21, 64.57it/s]


  8%|██████████████████████▌                                                                                                                                                                                                                                                                             | 113/1466 [00:01<00:20, 66.42it/s]


  8%|████████████████████████                                                                                                                                                                                                                                                                            | 121/1466 [00:02<00:19, 68.11it/s]


  9%|█████████████████████████▍                                                                                                                                                                                                                                                                          | 128/1466 [00:02<00:23, 56.21it/s]


  9%|██████████████████████████▋                                                                                                                                                                                                                                                                         | 134/1466 [00:02<00:23, 56.03it/s]


 10%|████████████████████████████                                                                                                                                                                                                                                                                        | 141/1466 [00:02<00:23, 57.57it/s]


 10%|█████████████████████████████▍                                                                                                                                                                                                                                                                      | 148/1466 [00:02<00:22, 59.20it/s]


 11%|██████████████████████████████▊                                                                                                                                                                                                                                                                     | 155/1466 [00:02<00:21, 60.99it/s]


 11%|████████████████████████████████▎                                                                                                                                                                                                                                                                   | 162/1466 [00:02<00:21, 62.04it/s]


 12%|█████████████████████████████████▋                                                                                                                                                                                                                                                                  | 169/1466 [00:02<00:20, 62.93it/s]


 12%|███████████████████████████████████                                                                                                                                                                                                                                                                 | 176/1466 [00:03<00:24, 52.68it/s]


 12%|████████████████████████████████████▎                                                                                                                                                                                                                                                               | 182/1466 [00:03<00:23, 53.91it/s]


 13%|█████████████████████████████████████▋                                                                                                                                                                                                                                                              | 189/1466 [00:03<00:22, 57.63it/s]


 13%|███████████████████████████████████████                                                                                                                                                                                                                                                             | 196/1466 [00:03<00:21, 59.43it/s]


 14%|████████████████████████████████████████▍                                                                                                                                                                                                                                                           | 203/1466 [00:03<00:20, 61.38it/s]


 14%|█████████████████████████████████████████▊                                                                                                                                                                                                                                                          | 210/1466 [00:03<00:20, 61.32it/s]


 15%|███████████████████████████████████████████▏                                                                                                                                                                                                                                                        | 217/1466 [00:03<00:19, 63.42it/s]


 15%|████████████████████████████████████████████▌                                                                                                                                                                                                                                                       | 224/1466 [00:03<00:19, 65.07it/s]


 16%|██████████████████████████████████████████████                                                                                                                                                                                                                                                      | 231/1466 [00:03<00:19, 64.77it/s]


 16%|███████████████████████████████████████████████▍                                                                                                                                                                                                                                                    | 238/1466 [00:04<00:21, 55.92it/s]


 17%|████████████████████████████████████████████████▌                                                                                                                                                                                                                                                   | 244/1466 [00:04<00:21, 55.90it/s]


 17%|█████████████████████████████████████████████████▉                                                                                                                                                                                                                                                  | 251/1466 [00:04<00:20, 58.99it/s]


 18%|███████████████████████████████████████████████████▍                                                                                                                                                                                                                                                | 258/1466 [00:04<00:19, 60.78it/s]


 18%|████████████████████████████████████████████████████▊                                                                                                                                                                                                                                               | 265/1466 [00:04<00:19, 62.88it/s]


 19%|██████████████████████████████████████████████████████▏                                                                                                                                                                                                                                             | 272/1466 [00:04<00:18, 63.93it/s]


 19%|███████████████████████████████████████████████████████▌                                                                                                                                                                                                                                            | 279/1466 [00:04<00:18, 64.59it/s]


 20%|████████████████████████████████████████████████████████▉                                                                                                                                                                                                                                           | 286/1466 [00:04<00:17, 65.81it/s]


 20%|██████████████████████████████████████████████████████████▌                                                                                                                                                                                                                                         | 294/1466 [00:04<00:17, 67.12it/s]


 21%|███████████████████████████████████████████████████████████▉                                                                                                                                                                                                                                        | 301/1466 [00:04<00:17, 67.03it/s]


 21%|█████████████████████████████████████████████████████████████▎                                                                                                                                                                                                                                      | 308/1466 [00:05<00:20, 55.95it/s]


 21%|██████████████████████████████████████████████████████████████▌                                                                                                                                                                                                                                     | 314/1466 [00:05<00:20, 56.56it/s]


 22%|███████████████████████████████████████████████████████████████▉                                                                                                                                                                                                                                    | 321/1466 [00:05<00:19, 59.95it/s]


 22%|█████████████████████████████████████████████████████████████████▎                                                                                                                                                                                                                                  | 328/1466 [00:05<00:18, 62.63it/s]


 23%|██████████████████████████████████████████████████████████████████▋                                                                                                                                                                                                                                 | 335/1466 [00:05<00:17, 64.54it/s]


 23%|████████████████████████████████████████████████████████████████████                                                                                                                                                                                                                                | 342/1466 [00:05<00:17, 63.13it/s]


 24%|█████████████████████████████████████████████████████████████████████▌                                                                                                                                                                                                                              | 349/1466 [00:05<00:17, 64.90it/s]


 24%|██████████████████████████████████████████████████████████████████████▉                                                                                                                                                                                                                             | 356/1466 [00:05<00:16, 66.07it/s]


 25%|████████████████████████████████████████████████████████████████████████▎                                                                                                                                                                                                                           | 363/1466 [00:05<00:16, 66.85it/s]


 25%|█████████████████████████████████████████████████████████████████████████▋                                                                                                                                                                                                                          | 370/1466 [00:06<00:19, 57.55it/s]


 26%|███████████████████████████████████████████████████████████████████████████                                                                                                                                                                                                                         | 377/1466 [00:06<00:19, 56.88it/s]


 26%|████████████████████████████████████████████████████████████████████████████▍                                                                                                                                                                                                                       | 384/1466 [00:06<00:18, 58.98it/s]


 27%|█████████████████████████████████████████████████████████████████████████████▉                                                                                                                                                                                                                      | 391/1466 [00:06<00:18, 58.54it/s]


 27%|███████████████████████████████████████████████████████████████████████████████▎                                                                                                                                                                                                                    | 398/1466 [00:06<00:17, 59.98it/s]


 28%|████████████████████████████████████████████████████████████████████████████████▋                                                                                                                                                                                                                   | 405/1466 [00:06<00:17, 60.86it/s]


 28%|██████████████████████████████████████████████████████████████████████████████████                                                                                                                                                                                                                  | 412/1466 [00:06<00:19, 53.00it/s]


 29%|███████████████████████████████████████████████████████████████████████████████████▎                                                                                                                                                                                                                | 418/1466 [00:07<00:19, 54.03it/s]


 29%|████████████████████████████████████████████████████████████████████████████████████▋                                                                                                                                                                                                               | 425/1466 [00:07<00:19, 53.96it/s]


 29%|█████████████████████████████████████████████████████████████████████████████████████▊                                                                                                                                                                                                              | 431/1466 [00:07<00:19, 52.04it/s]


 30%|███████████████████████████████████████████████████████████████████████████████████████                                                                                                                                                                                                             | 437/1466 [00:07<00:19, 52.69it/s]


 30%|████████████████████████████████████████████████████████████████████████████████████████▏                                                                                                                                                                                                           | 443/1466 [00:07<00:21, 47.68it/s]


 31%|█████████████████████████████████████████████████████████████████████████████████████████▋                                                                                                                                                                                                          | 450/1466 [00:07<00:19, 52.05it/s]


 31%|██████████████████████████████████████████████████████████████████████████████████████████▊                                                                                                                                                                                                         | 456/1466 [00:07<00:18, 53.78it/s]


 32%|████████████████████████████████████████████████████████████████████████████████████████████                                                                                                                                                                                                        | 462/1466 [00:07<00:20, 48.94it/s]


 32%|█████████████████████████████████████████████████████████████████████████████████████████████▏                                                                                                                                                                                                      | 468/1466 [00:07<00:19, 50.67it/s]


 32%|██████████████████████████████████████████████████████████████████████████████████████████████▍                                                                                                                                                                                                     | 474/1466 [00:08<00:21, 46.76it/s]


 33%|███████████████████████████████████████████████████████████████████████████████████████████████▊                                                                                                                                                                                                    | 481/1466 [00:08<00:19, 51.29it/s]


 33%|█████████████████████████████████████████████████████████████████████████████████████████████████▏                                                                                                                                                                                                  | 488/1466 [00:08<00:17, 54.86it/s]


 34%|██████████████████████████████████████████████████████████████████████████████████████████████████▍                                                                                                                                                                                                 | 494/1466 [00:08<00:17, 56.12it/s]


 34%|███████████████████████████████████████████████████████████████████████████████████████████████████▌                                                                                                                                                                                                | 500/1466 [00:08<00:20, 48.30it/s]


 35%|████████████████████████████████████████████████████████████████████████████████████████████████████▉                                                                                                                                                                                               | 507/1466 [00:08<00:18, 52.59it/s]


 35%|██████████████████████████████████████████████████████████████████████████████████████████████████████▍                                                                                                                                                                                             | 514/1466 [00:08<00:16, 56.41it/s]


 35%|███████████████████████████████████████████████████████████████████████████████████████████████████████▌                                                                                                                                                                                            | 520/1466 [00:08<00:16, 55.65it/s]


 36%|████████████████████████████████████████████████████████████████████████████████████████████████████████▊                                                                                                                                                                                           | 526/1466 [00:09<00:19, 49.11it/s]


 36%|██████████████████████████████████████████████████████████████████████████████████████████████████████████▏                                                                                                                                                                                         | 533/1466 [00:09<00:17, 52.60it/s]


 37%|███████████████████████████████████████████████████████████████████████████████████████████████████████████▎                                                                                                                                                                                        | 539/1466 [00:09<00:17, 53.70it/s]


 37%|████████████████████████████████████████████████████████████████████████████████████████████████████████████▌                                                                                                                                                                                       | 545/1466 [00:09<00:19, 46.44it/s]


 38%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████▋                                                                                                                                                                                      | 551/1466 [00:09<00:18, 49.03it/s]


 38%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████▉                                                                                                                                                                                     | 557/1466 [00:09<00:20, 44.43it/s]


 38%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏                                                                                                                                                                                   | 563/1466 [00:09<00:19, 47.01it/s]


 39%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏                                                                                                                                                                                  | 568/1466 [00:10<00:20, 43.01it/s]


 39%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌                                                                                                                                                                                 | 575/1466 [00:10<00:18, 48.12it/s]


 40%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋                                                                                                                                                                                | 581/1466 [00:10<00:17, 50.23it/s]


 40%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉                                                                                                                                                                               | 587/1466 [00:10<00:19, 45.52it/s]


 40%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████                                                                                                                                                                              | 593/1466 [00:10<00:17, 48.84it/s]


 41%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎                                                                                                                                                                            | 599/1466 [00:10<00:17, 50.98it/s]


 41%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌                                                                                                                                                                           | 605/1466 [00:10<00:18, 47.71it/s]


 42%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌                                                                                                                                                                          | 610/1466 [00:10<00:17, 48.25it/s]


 42%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉                                                                                                                                                                         | 617/1466 [00:10<00:16, 52.74it/s]


 42%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████                                                                                                                                                                        | 623/1466 [00:11<00:17, 48.34it/s]


 43%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎                                                                                                                                                                      | 629/1466 [00:11<00:16, 49.98it/s]


 43%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍                                                                                                                                                                     | 635/1466 [00:11<00:17, 47.19it/s]


 44%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋                                                                                                                                                                    | 641/1466 [00:11<00:16, 49.62it/s]


 44%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊                                                                                                                                                                   | 647/1466 [00:11<00:15, 51.90it/s]


 45%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████                                                                                                                                                                  | 653/1466 [00:11<00:17, 46.65it/s]


 45%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎                                                                                                                                                                | 659/1466 [00:11<00:16, 48.94it/s]


 45%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍                                                                                                                                                               | 665/1466 [00:12<00:18, 44.01it/s]


 46%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊                                                                                                                                                              | 672/1466 [00:12<00:16, 48.59it/s]


 46%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏                                                                                                                                                            | 679/1466 [00:12<00:15, 52.13it/s]


 47%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋                                                                                                                                                           | 686/1466 [00:12<00:15, 51.20it/s]


 47%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊                                                                                                                                                          | 692/1466 [00:12<00:15, 49.78it/s]


 48%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏                                                                                                                                                        | 699/1466 [00:12<00:14, 53.47it/s]


 48%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌                                                                                                                                                       | 706/1466 [00:12<00:13, 55.77it/s]


 49%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊                                                                                                                                                      | 712/1466 [00:12<00:13, 56.37it/s]


 49%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████                                                                                                                                                     | 718/1466 [00:13<00:14, 50.07it/s]


 49%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍                                                                                                                                                   | 725/1466 [00:13<00:13, 53.63it/s]


 50%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊                                                                                                                                                  | 732/1466 [00:13<00:13, 55.96it/s]


 50%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉                                                                                                                                                 | 738/1466 [00:13<00:14, 49.79it/s]


 51%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍                                                                                                                                               | 745/1466 [00:13<00:13, 53.76it/s]


 51%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊                                                                                                                                              | 752/1466 [00:13<00:12, 56.62it/s]


 52%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉                                                                                                                                             | 758/1466 [00:13<00:12, 57.07it/s]


 52%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎                                                                                                                                           | 765/1466 [00:13<00:12, 54.64it/s]


 53%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌                                                                                                                                          | 771/1466 [00:13<00:13, 52.76it/s]


 53%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊                                                                                                                                         | 777/1466 [00:14<00:12, 53.83it/s]


 53%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉                                                                                                                                        | 783/1466 [00:14<00:13, 50.88it/s]


 54%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏                                                                                                                                      | 789/1466 [00:14<00:13, 51.30it/s]


 54%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌                                                                                                                                     | 796/1466 [00:14<00:12, 54.65it/s]


 55%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋                                                                                                                                    | 802/1466 [00:14<00:12, 55.29it/s]


 55%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉                                                                                                                                   | 808/1466 [00:14<00:14, 46.41it/s]


 55%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉                                                                                                                                  | 813/1466 [00:14<00:15, 42.88it/s]


 56%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎                                                                                                                                | 820/1466 [00:14<00:13, 47.64it/s]


 56%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌                                                                                                                               | 826/1466 [00:15<00:13, 49.08it/s]


 57%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋                                                                                                                              | 832/1466 [00:15<00:13, 47.07it/s]


 57%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉                                                                                                                             | 838/1466 [00:15<00:12, 49.71it/s]


 58%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████                                                                                                                            | 844/1466 [00:15<00:11, 52.17it/s]


 58%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌                                                                                                                          | 851/1466 [00:15<00:11, 55.28it/s]


 59%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉                                                                                                                         | 858/1466 [00:15<00:10, 56.90it/s]


 59%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎                                                                                                                       | 865/1466 [00:15<00:10, 59.16it/s]


 59%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋                                                                                                                      | 872/1466 [00:15<00:09, 60.64it/s]


 60%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████                                                                                                                     | 879/1466 [00:16<00:11, 52.22it/s]


 60%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎                                                                                                                   | 885/1466 [00:16<00:11, 52.25it/s]


 61%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋                                                                                                                  | 892/1466 [00:16<00:10, 56.20it/s]


 61%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████                                                                                                                 | 899/1466 [00:16<00:09, 58.68it/s]


 62%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍                                                                                                               | 906/1466 [00:16<00:09, 61.30it/s]


 62%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊                                                                                                              | 913/1466 [00:16<00:08, 63.26it/s]


 63%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏                                                                                                            | 920/1466 [00:16<00:08, 63.79it/s]


 63%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋                                                                                                           | 927/1466 [00:16<00:08, 64.27it/s]


 64%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████                                                                                                          | 934/1466 [00:16<00:08, 65.16it/s]


 64%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍                                                                                                        | 941/1466 [00:17<00:08, 65.03it/s]


 65%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊                                                                                                       | 948/1466 [00:17<00:09, 52.89it/s]


 65%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏                                                                                                     | 955/1466 [00:17<00:09, 55.26it/s]


 66%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌                                                                                                    | 962/1466 [00:17<00:08, 58.17it/s]


 66%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████                                                                                                   | 969/1466 [00:17<00:08, 60.63it/s]


 67%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍                                                                                                 | 976/1466 [00:17<00:07, 62.74it/s]


 67%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉                                                                                                | 984/1466 [00:17<00:07, 64.72it/s]


 68%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍                                                                                              | 991/1466 [00:17<00:07, 64.79it/s]


 68%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊                                                                                             | 998/1466 [00:17<00:07, 65.15it/s]


 69%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍                                                                                           | 1005/1466 [00:18<00:07, 58.21it/s]


 69%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋                                                                                          | 1011/1466 [00:18<00:08, 53.67it/s]


 69%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████                                                                                         | 1018/1466 [00:18<00:08, 55.78it/s]


 70%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎                                                                                       | 1024/1466 [00:18<00:07, 56.01it/s]


 70%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋                                                                                      | 1031/1466 [00:18<00:07, 58.48it/s]


 71%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████                                                                                     | 1038/1466 [00:18<00:07, 60.23it/s]


 71%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍                                                                                   | 1045/1466 [00:18<00:06, 61.31it/s]


 72%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊                                                                                  | 1052/1466 [00:18<00:06, 62.66it/s]


 72%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏                                                                                | 1059/1466 [00:19<00:06, 60.07it/s]


 73%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌                                                                               | 1066/1466 [00:19<00:06, 60.16it/s]


 73%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉                                                                              | 1073/1466 [00:19<00:07, 51.65it/s]


 74%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏                                                                            | 1079/1466 [00:19<00:07, 52.35it/s]


 74%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌                                                                           | 1086/1466 [00:19<00:06, 55.77it/s]


 75%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉                                                                          | 1093/1466 [00:19<00:06, 58.61it/s]


 75%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎                                                                        | 1100/1466 [00:19<00:07, 51.29it/s]


 75%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌                                                                       | 1106/1466 [00:19<00:06, 53.13it/s]


 76%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉                                                                      | 1113/1466 [00:20<00:07, 49.25it/s]


 76%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████                                                                     | 1119/1466 [00:20<00:06, 50.66it/s]


 77%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎                                                                   | 1125/1466 [00:20<00:06, 51.47it/s]


 77%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌                                                                  | 1131/1466 [00:20<00:07, 45.76it/s]


 78%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋                                                                 | 1137/1466 [00:20<00:06, 48.78it/s]


 78%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉                                                                | 1143/1466 [00:20<00:07, 43.29it/s]


 78%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████                                                               | 1149/1466 [00:20<00:06, 47.10it/s]


 79%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎                                                             | 1155/1466 [00:20<00:06, 49.15it/s]


 79%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍                                                            | 1161/1466 [00:21<00:06, 43.72it/s]


 80%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋                                                           | 1167/1466 [00:21<00:06, 46.72it/s]


 80%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋                                                          | 1172/1466 [00:21<00:06, 42.45it/s]


 80%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊                                                         | 1178/1466 [00:21<00:06, 45.88it/s]


 81%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏                                                       | 1185/1466 [00:21<00:06, 46.31it/s]


 81%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏                                                      | 1190/1466 [00:21<00:05, 46.18it/s]


 82%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍                                                     | 1196/1466 [00:21<00:05, 49.20it/s]


 82%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌                                                    | 1202/1466 [00:22<00:05, 45.86it/s]


 82%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉                                                   | 1209/1466 [00:22<00:05, 50.24it/s]


 83%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏                                                 | 1215/1466 [00:22<00:04, 51.89it/s]


 83%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎                                                | 1221/1466 [00:22<00:05, 47.51it/s]


 84%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌                                               | 1227/1466 [00:22<00:04, 50.05it/s]


 84%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉                                              | 1234/1466 [00:22<00:04, 49.99it/s]


 85%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏                                            | 1240/1466 [00:22<00:04, 48.86it/s]


 85%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎                                           | 1246/1466 [00:22<00:04, 50.44it/s]


 85%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌                                          | 1252/1466 [00:23<00:04, 45.02it/s]


 86%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋                                         | 1258/1466 [00:23<00:04, 48.10it/s]


 86%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉                                        | 1264/1466 [00:23<00:04, 50.30it/s]


 87%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████                                       | 1270/1466 [00:23<00:04, 45.03it/s]


 87%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎                                     | 1276/1466 [00:23<00:03, 48.43it/s]


 88%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋                                    | 1283/1466 [00:23<00:03, 52.73it/s]


 88%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊                                   | 1289/1466 [00:23<00:03, 46.27it/s]


 88%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████                                  | 1295/1466 [00:23<00:03, 48.96it/s]


 89%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏                                | 1301/1466 [00:24<00:03, 50.64it/s]


 89%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍                               | 1307/1466 [00:24<00:03, 48.23it/s]


 90%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋                              | 1313/1466 [00:24<00:03, 50.38it/s]


 90%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊                             | 1319/1466 [00:24<00:03, 46.90it/s]


 90%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏                           | 1326/1466 [00:24<00:02, 51.16it/s]


 91%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌                          | 1333/1466 [00:24<00:02, 55.30it/s]


 91%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉                         | 1340/1466 [00:24<00:02, 59.04it/s]


 92%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍                       | 1347/1466 [00:24<00:01, 61.72it/s]


 92%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉                      | 1355/1466 [00:24<00:01, 64.95it/s]


 93%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎                    | 1362/1466 [00:25<00:01, 62.47it/s]


 93%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋                   | 1369/1466 [00:25<00:01, 54.09it/s]


 94%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏                 | 1376/1466 [00:25<00:01, 56.63it/s]


 94%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌                | 1383/1466 [00:25<00:01, 56.33it/s]


 95%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋               | 1389/1466 [00:25<00:01, 56.34it/s]


 95%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉              | 1395/1466 [00:25<00:01, 56.33it/s]


 96%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████             | 1401/1466 [00:25<00:01, 57.17it/s]


 96%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎           | 1407/1466 [00:25<00:01, 56.80it/s]


 96%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍          | 1413/1466 [00:25<00:00, 57.35it/s]


 97%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋         | 1419/1466 [00:26<00:00, 57.89it/s]


 97%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊        | 1425/1466 [00:26<00:00, 47.72it/s]


 98%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████       | 1431/1466 [00:26<00:00, 48.71it/s]


 98%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍     | 1438/1466 [00:26<00:00, 52.39it/s]


 99%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊    | 1445/1466 [00:26<00:00, 55.07it/s]


 99%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏  | 1452/1466 [00:26<00:00, 58.21it/s]


100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 1459/1466 [00:26<00:00, 61.07it/s]


100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1466/1466 [00:26<00:00, 61.75it/s]

100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1466/1466 [00:26<00:00, 54.45it/s]
 10%|█████████████████████████████▌                                                                                                                                                                                                                                                                          | 1/10 [00:26<04:02, 26.93s/it]

  0%|                                                                                                                                                                                                                                                                                                              | 0/1466 [00:00<?, ?it/s]


  0%|█▍                                                                                                                                                                                                                                                                                                    | 7/1466 [00:00<00:22, 65.51it/s]


  1%|██▊                                                                                                                                                                                                                                                                                                  | 14/1466 [00:00<00:22, 65.87it/s]


  1%|████▏                                                                                                                                                                                                                                                                                                | 21/1466 [00:00<00:28, 50.55it/s]


  2%|█████▍                                                                                                                                                                                                                                                                                               | 27/1466 [00:00<00:27, 53.27it/s]


  2%|██████▊                                                                                                                                                                                                                                                                                              | 34/1466 [00:00<00:24, 57.75it/s]


  3%|████████▍                                                                                                                                                                                                                                                                                            | 42/1466 [00:00<00:22, 62.18it/s]


  3%|█████████▉                                                                                                                                                                                                                                                                                           | 50/1466 [00:00<00:21, 65.13it/s]


  4%|███████████▌                                                                                                                                                                                                                                                                                         | 58/1466 [00:00<00:21, 66.94it/s]


  4%|████████████▉                                                                                                                                                                                                                                                                                        | 65/1466 [00:01<00:22, 62.37it/s]


  5%|██████████████▍                                                                                                                                                                                                                                                                                      | 72/1466 [00:01<00:25, 53.83it/s]


  5%|███████████████▌                                                                                                                                                                                                                                                                                     | 78/1466 [00:01<00:26, 51.65it/s]


  6%|████████████████▉                                                                                                                                                                                                                                                                                    | 85/1466 [00:01<00:25, 54.32it/s]


  6%|██████████████████▍                                                                                                                                                                                                                                                                                  | 92/1466 [00:01<00:23, 57.75it/s]


  7%|███████████████████▉                                                                                                                                                                                                                                                                                | 100/1466 [00:01<00:22, 61.20it/s]


  7%|█████████████████████▎                                                                                                                                                                                                                                                                              | 107/1466 [00:01<00:21, 62.50it/s]


  8%|██████████████████████▋                                                                                                                                                                                                                                                                             | 114/1466 [00:01<00:21, 63.61it/s]


  8%|████████████████████████▎                                                                                                                                                                                                                                                                           | 122/1466 [00:02<00:20, 65.61it/s]


  9%|█████████████████████████▋                                                                                                                                                                                                                                                                          | 129/1466 [00:02<00:24, 55.10it/s]


  9%|██████████████████████████▉                                                                                                                                                                                                                                                                         | 135/1466 [00:02<00:24, 55.30it/s]


 10%|████████████████████████████▍                                                                                                                                                                                                                                                                       | 143/1466 [00:02<00:22, 59.69it/s]


 10%|█████████████████████████████▉                                                                                                                                                                                                                                                                      | 150/1466 [00:02<00:21, 62.33it/s]

 11%|██████████████████████████████▊                                                                                                                                                                                                                                                                     | 155/1466 [00:02<00:22, 59.15it/s]
 10%|█████████████████████████████▌                                                                                                                                                                                                                                                                          | 1/10 [00:29<04:26, 29.58s/it]

---------------------------------------------------------------------------
KeyboardInterrupt                         Traceback (most recent call last)
Cell In[10], line 37
     35 logits = cbow(x)
     36 loss = criterion(logits, y)
---> 37 loss.backward()
     38 optimizer.step()
     40 monitoring_loss.append(float(loss))

File ~/workspace/prpy/.venv/lib/python3.11/site-packages/torch/_tensor.py:525, in Tensor.backward(self, gradient, retain_graph, create_graph, inputs)
    515 if has_torch_function_unary(self):
    516     return handle_torch_function(
    517         Tensor.backward,
    518         (self,),
   (...)
    523         inputs=inputs,
    524     )
--> 525 torch.autograd.backward(
    526     self, gradient, retain_graph, create_graph, inputs=inputs
    527 )

File ~/workspace/prpy/.venv/lib/python3.11/site-packages/torch/autograd/__init__.py:267, in backward(tensors, grad_tensors, retain_graph, create_graph, grad_variables, inputs)
    262     retain_graph = create_graph
    264 # The reason we repeat the same comment below is that
    265 # some Python versions print out the first line of a multi-line function
    266 # calls in the traceback and some print out the last line
--> 267 _engine_run_backward(
    268     tensors,
    269     grad_tensors_,
    270     retain_graph,
    271     create_graph,
    272     inputs,
    273     allow_unreachable=True,
    274     accumulate_grad=True,
    275 )

File ~/workspace/prpy/.venv/lib/python3.11/site-packages/torch/autograd/graph.py:744, in _engine_run_backward(t_outputs, *args, **kwargs)
    742     unregister_hooks = _register_logging_hooks_on_whole_graph(t_outputs)
    743 try:
--> 744     return Variable._execution_engine.run_backward(  # Calls into the C++ engine to run the backward pass
    745         t_outputs, *args, **kwargs
    746     )  # Calls into the C++ engine to run the backward pass
    747 finally:
    748     if attach_logging_hooks:

KeyboardInterrupt: 

類似単語検索#

CBoWでは第一層目の結合重みが単語埋め込みベクトルとして利用できます.例えばこれは,以下のようなコードで取り出すことが可能です.

word_embeddings = list(cbow.embeddingbag.parameters())[0].data.detach().cpu().numpy()

ここから更にクエリとして与えられた単語に対応する単語埋め込みベクトルを取り出して,自分以外の全ての埋め込みベクトルとの類似度を計算することで,類似単語検索が実装できます. ここでは類似として コサイン類似度 (3)を使います.

(3)#\[ \cos (\mathbf{x}, \mathbf{y})=\frac{\langle\mathbf{x}, \mathbf{y}\rangle}{\|\mathbf{x}\|\|\mathbf{y}\|} =\frac{\sum_{k=1}^N x_k y_k}{\sqrt{\sum_{k=1}^N x_k^2} \sqrt{\sum_{k=1}^N y_k^2}} \]

ただし, \(\|\mathbf{x}\|=\sqrt{\sum_{k=1}^N x_k^2}\) はL2ノルム, \(\langle\mathbf{x}, \mathbf{y}\rangle=\sum_{k=1}^n x_k y_k\) はベクトルの内積です.

これが大きい順にtopn個を取り出して表示する関数を作りましょう.例えば,クエリとして「インド」を渡した時に,以下のような結果を返す予定です.

>>> インド
1:アフリカ 	0.9803917407989502
2:ホルシュタイン 	0.9631898403167725
3:セルビア 	0.962059497833252
4:ハンガリー 	0.9611229300498962
word_embeddings = list(cbow.embeddingbag.parameters())[0].data.detach().cpu().numpy()
def get_similar_words(query, topn=5, word2id=word2id, word_embeddings=word_embeddings):
    """単語埋め込みベクトルを使って似た単語を検索する

    Args:
        query (str): 類似単語を検索したい単語
        topn (int, optional): 検索結果の表示個数. Defaults to 5.
        word2id (dict[str,int], optional): 単語→単語idの辞書. Defaults to word2id.
        word_embeddings (np.ndarray, optional): 単語埋め込み行列.必ず(語彙数x埋め込み次元数)の行列であること. Defaults to word_embeddings.
    """
    id=word2id[query]
    E = (word_embeddings.T / np.linalg.norm(word_embeddings,ord=2, axis=1)).T # {(V,L).T / (V)}.T = (V,L)
    target_vector = E[id]
    cossim = E @ target_vector # (V,L)@(L)=(V)
    sorted_index = np.argsort(cossim)[::-1][1:topn+1] # 最も似たベクトルは自分自身なので先頭を除外

    print(f">>> {query}")
    _id2word = list(word2id.keys())
    for rank, i in enumerate(sorted_index):
        print(f"{rank+1}:{_id2word[i]} \t{cossim[i]}")
get_similar_words("ソフトウェア")
get_similar_words("インド")
get_similar_words("犬")
get_similar_words("日本")
>>> ソフトウェア
1:システム 	0.71828293800354
2:アプリケーション 	0.7057948112487793
3:ファイル 	0.6742259860038757
4:プロセス 	0.6577709913253784
5:ユーザ 	0.6575205326080322
>>> インド
1:ローマ帝国 	0.6802298426628113
2:山岳 	0.6691959500312805
3:ヨーロッパ 	0.667682409286499
4:アメリカ大陸 	0.6496357917785645
5:アフリカ 	0.6466898918151855
>>> 犬
1:ペット 	0.5876853466033936
2:火山灰 	0.5164925456047058
3:嫌気 	0.5149425864219666
4:サメ 	0.510272741317749
5:鳥類 	0.5028554201126099
>>> 日本
1:きょう 	0.5488061308860779
2:関西 	0.5252450704574585
3:世論 	0.5072933435440063
4:取締役 	0.49071943759918213
5:ジャーナリズム 	0.4820699095726013

今回の例では訓練に使うコーパスの量が圧倒的に足りないので,対応している語彙の数も学習して得られる単語埋め込みの質もイマイチです.そのため時間がある場合はtext8全体を利用して更なる実験を行なってみてください.より人間の感覚に近い類似単語検索が可能になるはずです.

学習済みword2vecの利活用#

類似単語検索#

Wikipediaのdumpファイルのような大規模で広いドメイン知識を含んだテキストを使って,word2vecやそれに類する手法を訓練したPretrained model, Pretrained weightsが様々なところで公開されています.ここではこの様な学習済みの単語埋め込みベクトルをダウンロードして,利用する手順を確認します.

日本語の学習済み単語埋め込みの例:

  1. 日本語 Wikipedia エンティティベクトル |東北大学 乾・岡崎研究室

  2. chiVe: SudachiとNWJCによる日本語単語ベクトル |Works Applications

今回は日本語 Wikipedia エンティティベクトル |東北大学 乾・岡崎研究室からファイル(20170201.tar.bz2)をダウンロードし,これを使って類似単語検索を行います. Pythonのトピックモデル手法パッケージであるGensimには,word2vecのクラスが実装されています.これを使ってもOKです.ここでは自力で埋め込みベクトルを取り出してみます.
ファイルの中身は一行目に「単語数,埋め込み次元数」が書かれています.また,データは全て半角スペースがセパレータとして利用されてます.

今回はデータ読み込みのために以下の様な関数を用意しました.この関数は返り値として,keyを単語,valueを埋め込みベクトルにした辞書keyedvectorsを返します.

if "entity_vector" not in os.listdir("./input"):
    !wget -O ./input/entity_vector.model.tar.bz2 https://www.cl.ecei.tohoku.ac.jp/~m-suzuki/jawiki_vector/data/20170201.tar.bz2
    !tar -jxvf ./input/entity_vector.model.tar.bz2 -C ./input
def load_keyedvectors(fpath):
    keyedvectors = {}
    with open(fpath) as f:
        lines = f.readlines()[1:]
    with tqdm(total=len(lines)) as t:
        for i, line in enumerate(lines):
            word,*arr = line.split()
            keyedvectors[word] = np.array(arr).astype(np.float32)
            t.update(1)
    return keyedvectors

fpath="./input/entity_vector/entity_vector.model.txt"
kv=load_keyedvectors(fpath)
Hide code cell output
100%|██████████| 333136/333136 [00:19<00:00, 17306.15it/s]
delete_keys = []
for key,vec in kv.items():
    if vec.shape != (200,):
        print(key, vec.shape)
        delete_keys.append(key)
        continue

for key in delete_keys:
    del kv[key]

類似単語検索の関数は上に示したものを少し修正すればいいでしょう.またはkvからword2idと単語埋め込み行列を使ってもいいかもしれません.何にせよ十分に訓練された単語埋め込みベクトルを使って,埋め込みベクトルが人間の感覚に近い結果を返すか確認してみましょう.

tohoku_w2id = {k:id for id,k in enumerate(kv)}
tohoku_emb = np.vstack([vec for vec in kv.values()])
topn=10
get_similar_words("ソフトウェア",topn,tohoku_w2id,tohoku_emb)
get_similar_words("インド",topn,tohoku_w2id,tohoku_emb)
get_similar_words("犬",topn,tohoku_w2id,tohoku_emb)
get_similar_words("東京",topn,tohoku_w2id,tohoku_emb)
>>> ソフトウェア
1:[ソフトウェア] 	0.9343680739402771
2:アプリケーション 	0.8889141082763672
3:ハードウェア 	0.8524743318557739
4:[アプリケーションソフトウェア] 	0.8515217900276184
5:ソフトウエア 	0.8409579992294312
6:ツール 	0.8184429407119751
7:[オペレーティングシステム] 	0.818361759185791
8:[ハードウェア] 	0.8154588341712952
9:ディストリビューション 	0.8022889494895935
10:[プラグイン] 	0.7999409437179565
>>> インド
1:[インド] 	0.8461795449256897
2:チベット 	0.7447131872177124
3:東南アジア 	0.7305631637573242
4:エジプト 	0.7292859554290771
5:アフリカ 	0.7172137498855591
6:イラン 	0.6968802213668823
7:西アジア 	0.6928515434265137
8:アラビア 	0.6927241683006287
9:中国 	0.6918002963066101
10:中東 	0.6847600936889648
>>> 犬
1:[犬] 	0.8519492745399475
2:[イヌ] 	0.8118769526481628
3:[ネコ] 	0.7639949917793274
4:[猫] 	0.7535459995269775
5:猟犬 	0.75133216381073
6:猫 	0.7439810037612915
7:[猟犬] 	0.7298945188522339
8:子犬 	0.727935254573822
9:[オオカミ] 	0.7274285554885864
10:[牧羊犬] 	0.7150676846504211
>>> 東京
1:大阪 	0.8608449697494507
2:[東京] 	0.8446128368377686
3:名古屋 	0.7717304825782776
4:[大阪] 	0.7522143721580505
5:横浜 	0.7329142093658447
6:神戸 	0.7294299602508545
7:京都 	0.7215739488601685
8:札幌 	0.7169389724731445
9:関西 	0.7126983404159546
10:浅草 	0.687187135219574

類似単語検索ではある程度納得できる答えが出ていると思います.このように大規模な言語資源を使って訓練された単語埋め込みモデルはベクトル表現として「言葉の意味」をある程度上手に獲得できる様です.

単語ベクトルの足し算,引き算#

作成した単語埋め込みベクトルは,うまく訓練すると意味の足し引きができることが知られています.


Trained Word2Vec Vectors with Semantic and Syntactic relationship
出典: Word2Vec Research Paper Explained

# 例
女王 -  = 

これが正しく動作するか確認してみましょう.

def get_similar_words_from_vector(query, topn=5, word2id=word2id, word_embeddings=word_embeddings):
    E = word_embeddings.T / np.linalg.norm(word_embeddings,ord=2, axis=1)
    target_vector = query / np.linalg.norm(query, ord=2)
    cossim = target_vector@E # (K)@(K,V)->(V)
    sorted_index = np.argsort(cossim)[::-1][:topn]
    id2word = list(word2id.keys())
    for i in sorted_index:
        print(f"{id2word[i]} \t{cossim[i]}")

x = "女王"
y = "女"
print(f">>> {x}+{y}")
get_similar_words_from_vector(tohoku_emb[tohoku_w2id[x]] - tohoku_emb[tohoku_w2id[y]],
                  5,tohoku_w2id,tohoku_emb)

print('\n参考までに,"女王"と"女"と"王"の類似単語-----')
get_similar_words("女王",5,tohoku_w2id,tohoku_emb)
get_similar_words("女",5,tohoku_w2id,tohoku_emb)
get_similar_words("王",5,tohoku_w2id,tohoku_emb)
>>> 女王+女
女王 	0.4823855757713318
[エリザベス2世] 	0.4214708209037781
国王 	0.4064805805683136
[イギリスの君主] 	0.40320464968681335
[国王] 	0.39549919962882996

参考までに,"女王"と"女"と"王"の類似単語-----
>>> 女王
1:王女 	0.7546545267105103
2:[女王] 	0.7532833814620972
3:国王 	0.7170188426971436
4:王妃 	0.7075302600860596
5:[王配] 	0.6518748998641968
>>> 女
1:男 	0.8477675318717957
2:姫君 	0.6818373203277588
3:老女 	0.6539143323898315
4:美女 	0.6511508822441101
5:女房 	0.6428915858268738
>>> 王
1:[王] 	0.7630562782287598
2:は王 	0.7305535078048706
3:国王 	0.7254170775413513
4:大王 	0.7170721292495728
5:皇帝 	0.6928742527961731

期待通りの答えにはなっていませんが,訓練を工夫することで欲しい答えを返してきそうな雰囲気はありますね.他のキーワードペアも試してみましょう.

add_vecs = lambda x,y:(print(f">>> {x}+{y}"),get_similar_words_from_vector(tohoku_emb[tohoku_w2id[x]] + tohoku_emb[tohoku_w2id[y]],
                  5,tohoku_w2id,tohoku_emb))
sub_vecs = lambda x,y:(print(f">>> {x}-{y}"),get_similar_words_from_vector(tohoku_emb[tohoku_w2id[x]] - tohoku_emb[tohoku_w2id[y]],
                  5,tohoku_w2id,tohoku_emb))

add_vecs("王","女性")
add_vecs("王","女性")
sub_vecs("女王","女性");
add_vecs("ナルト","写輪眼")
sub_vecs("ナルト","写輪眼");
>>> 王+女性
王 	0.8152725696563721
女性 	0.7048346400260925
王妃 	0.694212019443512
[王] 	0.665898323059082
王族 	0.6649366617202759
>>> 王+女性
王 	0.8152725696563721
女性 	0.7048346400260925
王妃 	0.694212019443512
[王] 	0.665898323059082
王族 	0.6649366617202759
>>> 女王-女性
女王 	0.5956607460975647
国王 	0.4080067276954651
王 	0.3981504440307617
聖王 	0.39811012148857117
王国 	0.38871991634368896
>>> ナルト+写輪眼
ナルト 	0.9913040995597839
サスケ 	0.8586304783821106
[うずまきナルト] 	0.8437241315841675
カカシ 	0.8275482654571533
[うちはサスケ] 	0.8235551118850708
>>> ナルト-写輪眼
ナルト 	0.9860733151435852
[うずまきナルト] 	0.849785327911377
サスケ 	0.8380293846130371
カカシ 	0.8109899163246155
一護 	0.8019787669181824

word2vecの応用#

このような便利な特性を持つ単語埋め込みベクトルは,この論文の発表後に様々なNLP技術の中で当たり前に利用されるようになりました.前提として,通常データが少ない場合にはうまく単語の意味を訓練によって習得させることは難しいことが知られていましたが,このような問題にうまく対処できるのが,事前学習済み単語埋め込みの利用です.この例に大規模な言語リソースを使って事前訓練された単語埋め込みを使えば,効率的に各々のタスクを解決するモデルを作成できます.

例として,文書からの話題抽出タスクに事前学習モデルを利用する場合のワークフローを示します.下図において,NTM(ニューラルトピックモデル)は学習用コーパスのみを使って単語埋め込みを含めたモデルのパラメータを訓練します.これに対して,NTM-PWEは事前学習した埋め込みを利用します.この場合は単語埋め込みに相当するパラメータは学習用データを使ってパラメータ更新をしません.一番右のNTM-PWE/finetuningはNTM-PWEのように事前学習した埋め込みを利用し,単語埋め込みに相当するパラメータも学習用データを使ってパラメータ更新します.つまり,パラメータのより良い初期値として事前学習済み単語埋め込みを利用するということです.その方針を取るのかは状況によって異なりますが,多くの場合で事前学習済みモデルを初期値として利用すると良い結果をもたらすでしょう.


文書からの話題抽出タスクに事前学習モデルを利用する場合のワークフロー

この事前学習済みのモデルを(pretrained model, pretrained weights)などと呼びます.事前学習済みモデルを利用するアプローチは,現在ではNLPのみならず,CV(Computer Vision)などの様々な分野で当たり前に利用されています.

参考文献#

[DDF+90]

Scott Deerwester, Susan T Dumais, George W Furnas, Thomas K Landauer, and Richard Harshman. Indexing by latent semantic analysis. J. Am. Soc. Inf. Sci., 41(6):391–407, September 1990. doi:10.1002/(sici)1097-4571(199009)41:6<391::aid-asi1>3.0.co;2-9.

[LS99]

D D Lee and H S Seung. Learning the parts of objects by non-negative matrix factorization. Nature, 401(6755):788–791, October 1999. doi:10.1038/44565.

[LS00]

Daniel Lee and H Sebastian Seung. Algorithms for non-negative matrix factorization. In T Leen, T Dietterich, and V Tresp, editors, Advances in Neural Information Processing Systems, volume 13. MIT Press, 2000.

[MSC+13]

Tomas Mikolov, Ilya Sutskever, Kai Chen, Greg S Corrado, and Jeff Dean. Distributed representations of words and phrases and their compositionality. Adv. Neural Inf. Process. Syst., 2013.

[MYZ13]

Tomas Mikolov, Wen-Tau Yih, and Geoffrey Zweig. Linguistic regularities in continuous space word representations. In Proceedings of the 2013 Conference of the North American Chapter of the Association for Computational Linguistics: Human Language Technologies, 746–751. Atlanta, Georgia, June 2013. Association for Computational Linguistics.

[MCCD13]

Tomás Mikolov, Kai Chen, Greg Corrado, and Jeffrey Dean. Efficient estimation of word representations in vector space. In Yoshua Bengio and Yann LeCun, editors, 1st International Conference on Learning Representations, ICLR 2013, Scottsdale, Arizona, USA, May 2-4, 2013, Workshop Track Proceedings. 2013.