句子相似性

2021-09-12 03:37:54 字數 3483 閱讀 6230

在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,則再從後向...