GluonNLPを使ってみる

はじめに

  • 以前にGloveやFastTextを試してみた。

touch-sp.hatenablog.com
touch-sp.hatenablog.com

  • 今回はGluonNLPでGloveの学習済みモデルを使ってみた。

環境

Windows7 64bit
Python 3.6.6
GPUなし

バージョン確認(pip freeze)

astroid==2.0.4
certifi==2018.10.15
chardet==3.0.4
colorama==0.4.0
gluonnlp==0.4.0
graphviz==0.8.4
idna==2.6
isort==4.3.4
lazy-object-proxy==1.3.1
mccabe==0.6.1
mxnet==1.3.1b20181018
numpy==1.14.6
pylint==2.1.1
requests==2.18.4
six==1.11.0
typed-ast==1.1.0
urllib3==1.22
wrapt==1.10.11

実行スクリプト

import mxnet as mx
import gluonnlp as nlp

def norm_vecs_by_row(x):
    return x / mx.nd.sqrt(mx.nd.sum(x * x, axis=1) + 1E-10).reshape((-1,1))

def get_knn(vocab, k, word_vec):
    word_vec = word_vec.reshape((-1, 1))
    vocab_vecs = norm_vecs_by_row(vocab.embedding.idx_to_vec)
    dot_prod = mx.nd.dot(vocab_vecs, word_vec)
    indices = mx.nd.topk(dot_prod.reshape((-1, )), k=k, ret_typ='indices')
    indices = [int(i.asscalar()) for i in indices]
    return vocab.to_tokens(indices)

glove = nlp.embedding.create('glove', source='glove.6B.100d')

vocab = nlp.Vocab(nlp.data.Counter(glove.idx_to_token))
vocab.set_embedding(glove)

word_embedding = vocab.embedding['bad', 'worst', 'big']
word_vec = word_embedding[1] - word_embedding[0] + word_embedding[2]

get_knn(vocab, 3, word_vec)

学習済みモデルの種類

  • 「glove」「word2vec」「fasttext」それぞれ用意されている
  • 以下で確認できる
gluonnlp.embedding.list_sources('glove')
gluonnlp.embedding.list_sources('word2vec')
gluonnlp.embedding.list_sources('fasttext')

2019年9月4日追記

以下のように書くとすこし短くなる。

import mxnet as mx
import gluonnlp as nlp

def get_knn(vocab, k, word_vec):
    word_vec = word_vec.reshape((-1, 1))
    vocab_vecs = mx.nd.L2Normalization(vocab.embedding.idx_to_vec)
    dot_prod = mx.nd.dot(vocab_vecs, word_vec)
    indices = mx.nd.topk(dot_prod.reshape((-1, )), k=k, ret_typ='indices')
    indices = [int(i.asscalar()) for i in indices]
    return vocab.to_tokens(indices)

glove = nlp.embedding.create('glove', source='glove.6B.100d')

vocab = nlp.Vocab(nlp.data.Counter(glove.idx_to_token))
vocab.set_embedding(glove)

word_embedding = vocab.embedding['do', 'did', 'go']
word_vec = word_embedding[1] - word_embedding[0] + word_embedding[2]

get_knn(vocab, 3, word_vec)

2019年9月5日追記

このようにも書ける。

import mxnet as mx
import gluonnlp as nlp

glove = nlp.embedding.create('glove', source='glove.6B.100d')

vocab = nlp.Vocab(nlp.data.Counter(glove.idx_to_token))
vocab.set_embedding(glove)

word_embedding = vocab.embedding['tokyo', 'japan', 'london']
word_vec = word_embedding[1] - word_embedding[0] + word_embedding[2]

cos_sim = nlp.embedding.evaluation.CosineSimilarity()

result = cos_sim(word_vec.broadcast_like(vocab.embedding.idx_to_vec), vocab.embedding.idx_to_vec)
indices = mx.nd.topk(result, k=3, ret_typ='indices')
indices = [int(i.asscalar()) for i in indices]
vocab.to_tokens(indices)

最後の部分はこれでも良い。

for i in indices:
    num = int(i.asscalar())
    print('%s : %f'%(vocab.to_tokens(num), result[num].asscalar()))