1. 程式人生 > >文字相似度及案例-語義分析演算法學習

文字相似度及案例-語義分析演算法學習

在做自然語言處理的過程中,我們經常會遇到需要找出相似語句的場景,或者找出句子的近似表達,這時候就需要把類似的句子歸到一起,這裡面就涉及到句子相似度計算的問題。

基本方法

句子相似度計算一共歸類了以下幾種方法:

  • 編輯距離計算
  • 傑卡德係數計算
  • TF 計算
  • TF-IDF 計算
  • Word2Vec 計算

下面來一一瞭解一下這幾種演算法的原理和 Python 實現。

編輯距離計算

編輯距離,英文叫做 Edit Distance,又稱 Levenshtein 距離,是指兩個字串之間,由一個轉成另一個所需的最少編輯操作次數,如果它們的距離越大,說明它們越是不同。許可的編輯操作包括將一個字元替換成另一個字元,插入一個字元,刪除一個字元。

例如我們有兩個字串:string 和 setting,如果我們想要把 string 轉化為 setting,需要這麼兩步:

  • 第一步,在 s 和 t 之間加入字元 e。
  • 第二步,把 r 替換成 t。

所以它們的編輯距離差就是 2,這就對應著二者要進行轉化所要改變(新增、替換、刪除)的最小步數。

那麼用 Python 怎樣來實現呢,我們可以直接使用 distance 庫:

#編輯距離
import distance

def edit_distance(s1, s2):
    return distance.levenshtein(s1, s2)

strings = [
    '你在幹什麼',
    '你在幹啥子',
    '你在做什麼',
    '你好啊',
    '我喜歡吃香蕉'
]

target = '你在幹啥'
results = list(filter(lambda x: edit_distance(x, target) <= 2, strings))
print(results)

'''
['你在幹什麼', '你在幹啥子']
'''

通過這種方式我們可以大致篩選出類似的句子,但是發現一些句子例如“你在做什麼” 就沒有被識別出來,但他們的意義確實是相差不大的,因此,編輯距離並不是一個好的方式,但是簡單易用。

傑卡德係數計算

傑卡德係數,英文叫做 Jaccard index, 又稱為 Jaccard 相似係數,用於比較有限樣本集之間的相似性與差異性。Jaccard 係數值越大,樣本相似度越高。

實際上它的計算方式非常簡單,就是兩個樣本的交集除以並集得到的數值,當兩個樣本完全一致時,結果為 1,當兩個樣本完全不同時,結果為 0。

演算法非常簡單,就是交集除以並集,下面我們用 Python 程式碼來實現一下:

#傑卡德係數計算
from sklearn.feature_extraction.text import CountVectorizer
import numpy as np


def jaccard_similarity(s1, s2):
    def add_space(s):
        return ' '.join(list(s))
    
    # 將字中間加入空格
    s1, s2 = add_space(s1), add_space(s2)
    # 轉化為TF矩陣
    cv = CountVectorizer(tokenizer=lambda s: s.split())
    corpus = [s1, s2]
    vectors = cv.fit_transform(corpus).toarray()
    # 求交集
    numerator = np.sum(np.min(vectors, axis=0))
    # 求並集
    denominator = np.sum(np.max(vectors, axis=0))
    # 計算傑卡德係數
    return 1.0 * numerator / denominator


s1 = '你在幹嘛呢'
s2 = '你在幹什麼呢'
print(jaccard_similarity(s1, s2))

'''
0.571428571