1、计算两个句子相似度,句子表征(工业界效果较好)
参考:https://www.zhihu.com/question/29978268/answer/55338644?utm_source=wechat_session&utm_medium=social&utm_oi=795302198023192576
原材料:整理好的词表比如 10W个词,已经训好的词向量,如 Word2vec ,已经分好词的句子a:
步骤:(1)跑出10W个词的词向量,按照词索引构成 10w维向量 Wd
(2)跑出句子a中每个词的词向量 Wav ,用Wd中每一维度分别与句子中每个词进行相似度计算,每一维度都取相似度最大的值,最后得到一个10W句子表达向量,原作者取了句子中每个词最相似的TOP10。
2、未登录词技巧:
OOV(out of vocabulary,OOV)未登录词向量问题
未登录词可以粗略划分为如下几种类型:
①新出现的普通词汇,如博客、房奴、给力等,尤其在网络用语中这种词汇层出不穷。
②专有名词(proper names)。专有名词在早期主要是指人名、地名和组织机构名这三类实体名称。1996年第六届信息理解会议对此进行了扩展,首次提出了命名实体(named entity)的概念,新增了时间和数字表达(日期、时刻、时段、数量值、百分比、序数、货币数量等),并且地名被进一步细化为城市名、州(省)名和国家名称等。
③专业名词和研究领域名称。特定领域的专业名词和新出现的研究领域名称也是造成生词的原因之一,如三聚氰胺、苏丹红、禽流感、堰塞湖等。
④其他专用名词,如新出现的产品名,电影、书籍等文艺作品的名称,等等。
该问题在kaggle的《Toxic Comment Classification Challenge》提供了一些解决办法。
---------------------
原文:https://blog.csdn.net/sinat_26917383/article/details/83584728
https://blog.csdn.net/sinat_26917383/article/details/83999966
笔者借鉴了fasttext之中的方式,当出现未登录词或短语的时候,会:
- 先将输入词进行n-grams
- 然后去词表之中查找
- 查找到的词向量进行平均
主要函数可见:
1 import numpy as np 2 3 def compute_ngrams(word, min_n, max_n): 4 #BOW, EOW = ('<', '>') # Used by FastText to attach to all words as prefix and suffix 5 extended_word = word 6 ngrams = [] 7 for ngram_length in range(min_n, min(len(extended_word), max_n) + 1): 8 for i in range(0, len(extended_word) - ngram_length + 1): 9 ngrams.append(extended_word[i:i + ngram_length]) 10 return list(set(ngrams)) 11 12 13 def wordVec(word,wv_from_text,min_n = 1, max_n = 3): 14 ''' 15 ngrams_single/ngrams_more,主要是为了当出现oov的情况下,最好先不考虑单字词向量 16 ''' 17 # 确认词向量维度 18 word_size = wv_from_text.wv.syn0[0].shape[0] 19 # 计算word的ngrams词组 20 ngrams = compute_ngrams(word,min_n = min_n, max_n = max_n) 21 # 如果在词典之中,直接返回词向量 22 if word in wv_from_text.wv.vocab.keys(): 23 return wv_from_text[word] 24 else: 25 # 不在词典的情况下 26 word_vec = np.zeros(word_size, dtype=np.float32) 27 ngrams_found = 0 28 ngrams_single = [ng for ng in ngrams if len(ng) == 1] 29 ngrams_more = [ng for ng in ngrams if len(ng) > 1] 30 # 先只接受2个单词长度以上的词向量 31 for ngram in ngrams_more: 32 if ngram in wv_from_text.wv.vocab.keys(): 33 word_vec += wv_from_text[ngram] 34 ngrams_found += 1 35 #print(ngram) 36 # 如果,没有匹配到,那么最后是考虑单个词向量 37 if ngrams_found == 0: 38 for ngram in ngrams_single: 39 word_vec += wv_from_text[ngram] 40 ngrams_found += 1 41 if word_vec.any(): 42 return word_vec / max(1, ngrams_found) 43 else: 44 raise KeyError('all ngrams for word %s absent from model' % word) 45 46 vec = wordVec('千奇百怪的词向量',wv_from_text,min_n = 1, max_n = 3) # 词向量获取 47 wv_from_text.most_similar(positive=[vec], topn=10) # 相似词查找
compute_ngrams函数是将词条N-grams找出来,譬如:
compute_ngrams('萌萌的哒的',min_n = 1,max_n = 3)
>>> ['哒', '的哒的', '萌的', '的哒', '哒的', '萌萌的', '萌的哒', '的', '萌萌', '萌']
这边没有沿用fasttext之中的<>来区分词头、词尾。
wordVec函数是计算未登录词的,其中笔者小小加了一些内容,就是:当出现oov的情况下,最好先不考虑单字词向量,如果能匹配到两个字以上的内容就优先进行平均。
在得到未登录词或短语的向量之后,就可以快速进行查找,gensim里面是支持给入向量进行相似词查找:
wv_from_text.most_similar(positive=[vec], topn=10)