Writing

Sentence Similarity

Approach one: compute sentence vectors, then cosine similarity.

Approach 1: Sentence Vectors, Then Cosine Similarity

1. Sentence Vectors for Two Sentences

  • Word-frequency vectors Using term frequency ignores synonyms, semantics, and scales poorly on long texts (e.g. 10k-word articles)—huge sparse dimensions, costly and inefficient.

  • TF-IDF sentence vectors Reduces dimensionality but still misses semantics.

  • Deep learning captures semantics; see Generating Sentence Vectors with BERT.

  • Traditional sentence vectors

Sum word vectors and average:

def sent2vec(s):
    words = s
    M = []
    for w in words:
        try:
            M.append(w2v.wv[w])
        except:
            continue
    M = np.array(M)
    v = M.sum(axis=0)
    return v / np.sqrt((v ** 2).sum())

2. Cosine Similarity Between Vectors

####计算余弦夹角
def cos_sim(vector_a, vector_b):
    """
    计算两个向量之间的余弦相似度
    :param vector_a: 向量 a
    :param vector_b: 向量 b
    :return: sim
    """
    vector_a = np.mat(vector_a)
    vector_b = np.mat(vector_b)
    num = float(vector_a * vector_b.T)
    denom = np.linalg.norm(vector_a) * np.linalg.norm(vector_b)
    cos = num / denom
    sim = 0.5 + 0.5 * cos
    return sim

Approach 2: Word Vectors and Word Mover’s Distance (WMD)

Word Mover’s Distance

Word2Vec maps words to vectors where similar words are close. Word Mover’s Distance (WMD) uses that: Euclidean distance between any pair of word vectors across two documents, then weighted sum.

image

image

Weight matrix T is somewhat like an HMM transition matrix, but probabilities become weights.

Suppose “Obama” has weight 0.5 in document 1 (from frequency or TF-IDF). Because “Obama” and “president” are similar, much weight (e.g. 0.4) flows from “Obama” to “president”; other words in doc 2 get less. Constraint: outflow from word i in doc 1 equals i’s weight in doc 1; inflow to word j in doc 2 equals j’s weight in doc 2.

References:

Supervised Word Mover’s Distance — NIPS 2016 paper selection #2

https://blog.csdn.net/qrlhl/article/details/78512598

https://blog.csdn.net/weixin_40547993/article/details/89475630

  • WMD code:
from gensim.models import KeyedVectors
import jieba
import time
import os

start = time.time()
model = KeyedVectors.load_word2vec_format('vectors.bin', binary=True, unicode_errors='ignore')
end = time.time()
print('Cell took %.2f seconds to run.' % (end - start))
s01= "今天是个好日子"
s02= "今天是晴天"
s03= "天气多云转阴"
sentence_01 = list(jieba.cut(s01))
sentence_02= list(jieba.cut(s02))
sentence_03= list(jieba.cut(s03))

Results:

Cell took 16.98 seconds to run.
Loading model cost 0.701 seconds.
distance = 24.3276
Prefix dict has been built succesfully.
distance = 55.7726