在预训练模型中列出spaCy中最相似的词

时间:2019-08-28 17:27:28

标签: python spacy

使用Gensim,在训练了自己的模型之后,我可以使用schema并获得向量空间中最接近model.wv.most_similar('cat', topn=5)的20个单词的列表。例如:

cat

使用spaCy,根据documentation,我可以这样做:

from gensim.models import Word2Vec
model = Word2Vec.load('mymodel.model')

In: model.wv.most_similar('cat', topn=5)
Out: ('kitten', .99)
     ('dog', .98)
     ...

给出指定字符串中标记的相似性。但是梳理文档并进行搜索,我无法弄清楚是否存在一种gensim类型的方式来列出使用import spacy nlp = spacy.load('en_core_web_md') tokens = nlp(u'dog cat banana') for token1 in tokens: for token2 in tokens: print(token1.text, token2.text, token1.similarity(token2)) nlp = spacy.load('en_core_web_lg')的预加载模型的所有相似单词。有办法吗?

4 个答案:

答案 0 :(得分:5)

我使用了安迪的回答,它可以正常但缓慢地工作。为了解决这个问题,我采用了以下方法。

SpaCy在后端使用余弦相似度来计算.similarity。因此,我决定将word.similarity(w)替换为其优化的副本。我使用的优化方法是cosine_similarity_numba(w.vector, word.vector),如下所示,该方法使用Numba库来加快计算速度。您应该用以下代码行将most_like方法中的代码行12替换为下面的代码。

by_similarity = sorted(queries, key=lambda w: cosine_similarity_numba(w.vector, word.vector), reverse=True)

该方法的速度提高了2-3倍,这对我来说是必不可少的。

from numba import jit

@jit(nopython=True)
def cosine_similarity_numba(u:np.ndarray, v:np.ndarray):
    assert(u.shape[0] == v.shape[0])
    uv = 0
    uu = 0
    vv = 0
    for i in range(u.shape[0]):
        uv += u[i]*v[i]
        uu += u[i]*u[i]
        vv += v[i]*v[i]
    cos_theta = 1
    if uu != 0 and vv != 0:
        cos_theta = uv/np.sqrt(uu*vv)
    return cos_theta

我在这篇文章中做了更详细的解释:How to Build a Fast “Most-Similar Words” Method in SpaCy

答案 1 :(得分:2)

这里是对方法的性能检查,以获取最相似单词的列表。以某种方式,这是极端情况,其中模型既没有w.prob也没有w.cluster来缩小搜索空间。我使用了四种方法:上面提到的两种,SpaCy中的most_similar和Gensim中的most_similar:

def spacy_most_similar(word, topn=10):
  ms = nlp_ru.vocab.vectors.most_similar(
      nlp_ru(word).vector.reshape(1,nlp_ru(word).vector.shape[0]), n=topn)
  words = [nlp_ru.vocab.strings[w] for w in ms[0][0]]
  distances = ms[2]
  return words, distances

def spacy_similarity(word, topn=10):
  word = nlp_ru.vocab[str(word)]
  queries = [
      w for w in word.vocab if w.is_lower == word.is_lower and np.count_nonzero(w.vector)
  ]
  by_similarity = sorted(queries, key=lambda w: w.similarity(word), reverse=True)
  return [(w.lower_,w.similarity(word)) for w in by_similarity[:topn+1] if w.lower_ != word.lower_]

def spacy_similarity_numba(word, topn=10):
  word = nlp_ru.vocab[str(word)]
  queries = [
      w for w in word.vocab if w.is_lower == word.is_lower and np.count_nonzero(w.vector)
  ]
  by_similarity = sorted(queries, key=lambda w: cosine_similarity_numba(w.vector, word.vector), reverse=True)
  return [(w.lower_,w.similarity(word)) for w in by_similarity[:topn+1] if w.lower_ != word.lower_]

from numba import jit


@jit(nopython=True)
def cosine_similarity_numba(u:np.ndarray, v:np.ndarray):
    assert(u.shape[0] == v.shape[0])
    uv = 0
    uu = 0
    vv = 0
    for i in range(u.shape[0]):
        uv += u[i]*v[i]
        uu += u[i]*u[i]
        vv += v[i]*v[i]
    cos_theta = 1
    if uu != 0 and vv != 0:
        cos_theta = uv/np.sqrt(uu*vv)
    return cos_theta

以下是计时结果:

from time import time
import timeit, functools
from timeit import default_timer as timer
print(nlp_ru.vocab.vectors.shape)
arr = ("дерево")
print(f'Gensim most_similar: {timeit.Timer(functools.partial(wv.most_similar, arr)).timeit(1)}')
print(f'Spacy most_similar: {timeit.Timer(functools.partial(spacy_most_similar, arr)).timeit(1)}')
print(f'Spacy cosine_similarity_numba: {timeit.Timer(functools.partial(spacy_similarity_numba, arr)).timeit(1)}')
print(f'Spacy similarity: {timeit.Timer(functools.partial(spacy_similarity, arr)).timeit(1)}')

(1239964, 100)
Gensim most_similar: 0.06437033399993197
Spacy most_similar: 0.4855721250000897
Spacy cosine_similarity_numba: 13.404324778000046
Spacy similarity: 60.58928110700003

所有方法返回相同的结果。如您所见,Gensim与其他人相比非常快。而且,您甚至不需要缩小搜索空间。所有测量均在CPU上完成。从这里http://panchenko.me/data/dsl-backup/w2v-ru/all.norm-sz100-w10-cb0-it1-min100.w2v

提取的嵌入

答案 2 :(得分:1)

它不是开箱即用的。但是,基于此问题(https://github.com/explosion/spaCy/issues/276),下面的代码可以使其按需工作。

<script>
     if(navigator.userAgent!=='ReactSnap'){
        <script src='//cdnt.netcoresmartech.com/smartechclient.js'</script>
     }
</script>

答案 3 :(得分:0)

您目前无法进行询问。

这是因为Spacy和Gensim相似,但目前性质不同。

Spacy为许多NLP任务提供了NLP管道。

另一方面,Gensim提供了许多与媒介和主题化有关的功能。可以将它们作为NLP管道的“模块”进行比较。

Spacy仅将向量用于其机器学习活动,而Gensim则使用向量来总结文本并进行比较(主要目的是提供用于主题化的工具)。

这就是为什么(当前)您无法按照Spacy的要求进行操作。