使用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')
的预加载模型的所有相似单词。有办法吗?
答案 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的要求进行操作。