【簡單總結】句子相似度計算的幾種方法

【簡單總結】句子相似度計算的幾種方法

1.句子相似度介紹:

句子相似度–指的是兩個句子之間相似的程度。在NLP中有很大的用處,譬如對話系統,文本分類、信息檢索、語義分析等,它可以爲我們提供檢索信息更快的方式,並且得到的信息更加準確。

2.句子相似計算的方法概括:

句子相似度計算主要分爲:

  • 基於統計的方法:
    • 萊文斯坦距離(編輯距離)

    • BM25

    • TFIDF計算

    • TextRank算法中的句子相似性

  • 基於深度學習的方法:

    • 基於Word2Vec的餘弦相似度

    • DSSM(Deep Structured Semantic Models)

3.句子相似計算方法具體介紹:

3.1基於統計的方法:

3.1.1萊文斯坦距離(編輯距離)

編輯距離是描述由一個字串轉化成另一個字串最少的編輯操作次數,如果它們的距離越大,說明它們越是不同。編輯操作包括將一個字符替換成另一個字符,插入一個字符,刪除一個字符。

舉例:there的幾個變形

 3.1.2BM25算法

BM25算法,BM25源於概率相關模型,而非向量空間模型,BM25同樣詞頻,逆文檔頻率以及字段長度歸一化,但是每個因子的定義都有細微差別。通常用來作搜索相關性平分。BM25算法通過加入文檔權值和查詢權值,拓展了二元獨立模型的得分函數。

主要思想:對Query進行語素解析,生成語素qi;然後,對於每個搜索結果D,計算每個語素qi與D的相關性得分,最後,將qi相對於D的相關性得分進行加權求和,從而得到Query與D的相關性得分。其實這個算法的原理很簡單,就是將需要計算的query分詞成w1,w2,…,wn,然後求出每一個詞和文章的相關度,最後將這些相關度進行累加,最終就可以的得到文本相似度計算結果。

計算公式:

其中,Q表示Query,qi表示Q解析之後的一個語素(對中文而言,我們可以把對Query的分詞作爲語素分析,每個詞看成語素qi。d表示一個搜索結果文檔;Wi表示語素qi的權重;R(qi,d)表示語素qi與文檔d的相關性得分。 這個公式第二項R(qi,d)表示我們查詢query中的每一個詞和文章d的相關度。

 3.1.3TFIDF計算

TFIDF :就是在詞頻 TF 的基礎上再加入 IDF 的信息,IDF 稱爲逆文檔頻率。TF-IDF是一種統計方法,用以評估一字詞對於一個文件集或一個語料庫中的其中一份文件的重要程度。TF意思是詞頻(Term Frequency)指的是某一個給定的詞語在該文件中出現的次數,IDF意思是逆文本頻率指數(Inverse Document Frequency)是一個詞語普遍重要性的度量。

主要思想:如果某個詞或短語在一篇文章中出現的頻率TF高,並且在其他文章中很少出現,則認爲此詞或者短語具有很好的類別區分能力,適合用來分類。

TF-IDF的計算公式分三步走:

其統計公式如下:

其中,tf表示詞頻(Term Frequency),即詞條在文檔i中出現的頻率;idf爲逆向文件頻率(Inverse Document Frequency),表示某個關鍵詞在整個語料所有文章中出現的次數的倒數(該指標用於降低常用詞的重要性)。

優點:能過濾掉一些常見的卻無關緊要的詞語,同時保留影響整個文本的重要詞語。

缺點:不能有效反應特徵詞的分佈情況,也沒有體現詞語的位置信息(通常文章首尾句詞的重要性較高)。

算法實現:

import jieba
import jieba.posseg as pseg
import os
import sys
from sklearn import feature_extraction
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import CountVectorizer
import sys
reload(sys)
sys.setdefaultencoding( "utf-8" )
sys.path.append("你的路徑")
from numpy import *
 
fr = open('你的文本名.txt')
fr_list = fr.read()
dataList = fr_list.split('\n')
data = []
for oneline in dataList:
    data.append(" ".join(jieba.cut(oneline))) 
 
#將得到的詞語轉換爲詞頻矩陣
freWord = CountVectorizer()
 
#統計每個詞語的tf-idf權值
transformer = TfidfTransformer()
#計算出tf-idf(第一個fit_transform),並將其轉換爲tf-idf矩陣(第二個fit_transformer)
tfidf = transformer.fit_transform(freWord.fit_transform(data))
 
#獲取詞袋模型中的所有詞語
word = freWord.get_feature_names()
 
#得到權重
weight = tfidf.toarray()
tfidfDict = {}
for i in range(len(weight)):
    for j in range(len(word)):
        getWord = word[j]
        getValue = weight[i][j]
        if getValue != 0:
            if tfidfDict.has_key(getWord):
                tfidfDict[getword] += string.atof(getValue)
            else:
                tfidfDict.update({getWord:getValue})
sorted_tfidf = sorted(tfidfDict.iteritems(),
                      key = lambda d:d[1],reverse = True)
fw = open('result.txt','w')
for i in sorted_tfidf:
    fw.write(i[0] + '\t' + str(i[1]) +'\n')

 3.1.4TextRank算法中的句子相似性

公式中,Si,Sj分別表示兩個句子,Wk表示句子中的詞,那麼分子部分的意思是同時出現在兩個句子中的相同詞的個數,分母是對句子中詞的個數求對數之和。分母這樣設計可以遏制較長的句子在相似度計算上的優勢。

代碼實現:

def two_sentences_similarity(sents_1, sents_2):
    counter = 0
    for sent in sents_1:
        if sent in sents_2:
            counter += 1
    sents_similarity=counter/(math.log(len(sents_1))+math.log(len(sents_2)))
    return sents_similarity

 3.2基於深度學習的方法:

3.2.1基於Word2Vec的餘弦相似度

首先對句子分詞,使用Gensim的Word2Vec訓練詞向量,獲取每個詞對應的詞向量,然後將所有的詞向量相加求平均,得到句子向量,最後計算兩個句子向量的餘弦值(餘弦相似度)。

餘弦相似度:用向量空間中的兩個向量夾角的餘弦值作爲衡量兩個個體間差異大小的度量,值越接近1,就說明夾角角度越接近0°,也就是兩個向量越相似。

計算公式:

#對每個句子的所有詞向量取均值,來生成一個句子的vector
#sentence是輸入的句子,size是詞向量維度,w2v_model是訓練好的詞向量模型
def build_sentence_vector(sentence,size,w2v_model):
    vec=np.zeros(size).reshape((1,size))
    count=0
    for word in sentence:
        try:
            vec+=w2v_model[word].reshape((1,size))
            count+=1
        except KeyError:
            continue
    if count!=0:
        vec/=count
    return vec
 
#計算兩個句向量的餘弦相似性值
def cosine_similarity(vec1, vec2):
    a= np.array(vec1)
    b= np.array(vec2)
    cos1 = np.sum(a * b)
    cos21 = np.sqrt(sum(a ** 2))
    cos22 = np.sqrt(sum(b ** 2))
    cosine_value = cos1 / float(cos21 * cos22)
    return cosine_value
 
#輸入兩個句子,計算兩個句子的餘弦相似性
def compute_cosine_similarity(sents_1, sents_2):
    size=300
    w2v_model=Word2Vec.load('w2v_model.pkl')
    vec1=build_sentence_vector(sents_1,size,w2v_model)
    vec2=build_sentence_vector(sents_2,size,w2v_model)
    similarity = cosine_similarity(vec1, vec2)
    return similarity

 3.2.1DSSM(Deep Structured Semantic Models)

DSSM(Deep Structured Semantic Models)的原理很簡單,通過搜索引擎裏 Query 和 Title 的海量的點擊曝光日誌,用 DNN 把 Query 和 Title 表達爲低緯語義向量,並通過 cosine 距離來計算兩個語義向量的距離,最終訓練出語義相似度模型。該模型既可以用來預測兩個句子的語義相似度,又可以獲得某句子的低緯語義向量表達。

DSSM 從下往上可以分爲三層結構:輸入層、表示層、匹配層

優點:DSSM 用字向量作爲輸入既可以減少切詞的依賴,又可以提高模型的範化能力,因爲每個漢字所能表達的語義是可以複用的。另一方面,傳統的輸入層是用 Embedding 的方式(如 Word2Vec 的詞向量)或者主題模型的方式(如 LDA 的主題向量)來直接做詞的映射,再把各個詞的向量累加或者拼接起來,由於 Word2Vec 和 LDA 都是無監督的訓練,這樣會給整個模型引入誤差,DSSM 採用統一的有監督訓練,不需要在中間過程做無監督模型的映射,因此精準度會比較高。

缺點:上文提到 DSSM 採用詞袋模型(BOW),因此喪失了語序信息和上下文信息。另一方面,DSSM 採用弱監督、端到端的模型,預測結果不可控。

1. DSSM 是端到端的模型,雖然省去了人工特徵轉化、特徵工程和特徵組合,但端到端的模型有個問題就是效果不可控。

2. DSSM 是弱監督模型,因爲引擎的點擊曝光日誌裏 Query 和 Title 的語義信息比較弱。
 

參考文章:

https://blog.csdn.net/Jaygle/article/details/80927732

https://blog.csdn.net/u014665013/article/details/90045408

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章