在nlp任務中,經常會遇到求解相似語句判斷的場景,這就涉及到了句子的相似性判斷。目前常用的兩種方法是基於word-level級別和sentence-level級別。
一、word-level的思想是通過對句子進行分詞,分別計算兩個比較句子中所含詞彙的相似度。主要包含兩個核心問題,乙個是詞的相似度計算問題,另乙個是對多個詞進行相似度加權融合問題
1.1 基於word的相似度計算問題
目前重用的方法是基於語義知識庫進行詞的相似度計算,比如hownet和哈工大研發的詞林。可以在一定程度上解決問題,但知識庫的詞彙有限,難以大規模使用。
1.2 基於word相似度的句子加權融合問題
這裡主要涉及詞相似的句子相似度度量的問題,常用的方法是jaccard編輯距離和語義距離
定義如下:
word1 = [token for token in s1]
word2 = [token for token in s2]
jaccard距離
sim(s1,s2) = intersection(word1,word2)/union(word1,word2)
語義距離
sim(s1,s2) = 1/2*(sum(max(sim(word1,word2)for wrd1 in words1 for word2 in words2))/len(words1)+ sum(max(sim(word2,word1)for word2 in words2 for word1 in words2))/len(words2))
二、sentence-level是採用句子建模的方法,核心思想是利用向量空間模型,將句子進行向量表徵,通常有兩種方式,基於word-vector的組合以及sentence-vector
2.1 基於word-vector的組合
目前常用的是使用預先訓練好的word-embedding向量,對於乙個句子,將詞向量的每一位進行求和或者平均。另一種是使用one-hot結合的tfidf對句子進行vsm表示。
2.2 基於sentence-vector的方法
目前關於sentence建模的方法包括skip-gram,cbow的doc2vec建模方法,基於autoencoder建模、基於skip-thought的句子建模方法。基於sentence-vector的方法能夠更好的保留句子語義資訊,這是詞袋所不能達到的。
本文主要提供兩種相似性的計算方法,一種是基於simhash演算法計算相似度(沒有考慮語義),另一種是基於詞向量計算其相似性
**如下:
# 基於simhash演算法進行句子相似度的計算from simhash import simhash
import jieba.posseg as poseg
def haming_distanc(code_s1,code_s2):
# 利用64位數,計算海明距離
x = (code_s1^code_s2)&((1<<64)-1)
ans = 0
while x:
ans +=1
x &=x-1
return ans
def get_features(string):
word_list = [word.word for word in poseg.cut(string) if word.flag[0] not in ['u','x','w','o','p','c','m','q']]
return word_list
# 計算兩個全文編碼距離
def get_distance(code_s1,code_s2):
return haming_distanc(code_s1,code_s2)
# 對全文進行編碼
def get_code(string):
return simhash(get_features(string)).value
def distance(s1,s2):
code_s1 = get_code(s1)
code_s2 = get_code(s2)
similarity = (100 - haming_distanc(code_s1,code_s2)*100/64)/100# 總共是利用的64位數
return similarity
s1 ="我喜歡你"
s2 = "你非常的喜歡我"
# 基於詞向量的句子相似性總結import gensim
import numpy as np
import jieba.posseg as pesg
embedding_path = "d:\workspace\project\\nlpcase\\sentencesimilarity\\data\\word_vector.bin"
model = gensim.models.keyedvectors.load_word2vec_format(embedding_path,binary=false)
# 獲取詞向量
def get_wordvector(word):
try:
return model[word]
except:
return np.zeros(200)
# 基於余弦相似度計算句子之間的相似度,句子向量求平均
def similarity_cosin(word_list1,word_list2):
vector1 = np.zeros(200)
for word in word_list1:
vector1+=get_wordvector(word)
vector1 = vector1/len(word_list1)
vector2 = np.zeros(200)
for word in word_list2:
vector2 += get_wordvector(word)
vector2 = vector2 / len(word_list2)
cos1 = np.sum(vector1*vector2)
cos21 = np.sqrt(sum(vector1 ** 2))
cos22 = np.sqrt(sum(vector2 ** 2))
similarity = cos1 / float(cos21 * cos22)
return similarity
'''計算句子相似度'''
def distance(text1, text2):
word_list1=[word.word for word in pesg.cut(text1) if word.flag[0] not in ['w','x','u']]
word_list2=[word.word for word in pesg.cut(text2) if word.flag[0] not in ['w','x','u']]
return similarity_cosin(word_list1,word_list2)
主要用於學習筆記的使用,句子向量的模型的訓練可以借鑑於word2vec的方法。
參考文獻
734 句子相似性
題目描述 給定兩個句子 words1,words2 每個用字串陣列表示 和乙個相似單詞對的列表 pairs 判斷是否兩個句子是相似的。例如,當相似單詞對是 pairs great fine acting drama skills talent 的時候,great acting skills 和 fi...
856 句子相似性
中文english 給出兩個句子words1和words2 每個用乙個字串陣列表示 和乙個相似詞對陣列pairs,你需要判斷兩個句子是否相似。例如,如果相似詞對是pairs great fine acting drama skills talent 那麼words1 great acting ski...
1813 句子相似性 III
先把每個句子分成乙個個單詞 然後比較即可,設定flag1 flag2,如果第一次出現不一樣flag 1,之後若一樣flag2 1,若再次不一樣,同時若flag2 1,就是false 如果到最後短的句子沒遍歷到尾,則false 有a a a a a a a a情形 如果從前向後比false,則再從後向...