0 评论

0 收藏

分享

【NLP-01】文本相似度算法:Cosine Similarity、Levenshtein Distance、Word2Vec等介

        文本相似度计算的算法是自然语言处理领域中的关键技术,主要用于衡量两段文本在内容、语义或结构上的相似程度。以下是一些常用的文本相似度计算算法:

image.png

  • 余弦相似度(Cosine Similarity):
            余弦相似度是通过计算两个向量的夹角余弦值来评估它们的相似度。在文本相似度计算中,首先将文本转换为向量表示(如TF-IDF向量),然后计算这些向量之间的余弦值。余弦值越接近1,表示文本越相似。
  • Jaccard相似度:
            Jaccard相似度基于集合的交集与并集的比值来计算相似度。在文本相似度中,可以将文本表示为词汇的集合,然后计算两个集合的Jaccard相似度。这种方法适用于短文本或关键词列表的比较。
    -编辑距离(Levenshtein Distance):
            编辑距离衡量的是将一个字符串转换为另一个字符串所需的最少编辑操作(如插入、删除或替换)次数。编辑距离越小,两个字符串越相似。这种方法适用于字符级或词级的文本相似度比较。
  • Word2Vec与词向量:
            Word2Vec是一种神经网络模型,用于学习词汇的向量表示。通过将文本中的词汇转换为Word2Vec向量,可以计算文本之间的相似度。常用的相似度度量包括余弦相似度和欧氏距离。这种方法能够捕捉词汇间的语义关系,适用于较长文本或复杂语义的比较。
  • TF-IDF与向量空间模型:
            TF-IDF(词频-逆文档频率)是一种常用的文本表示方法,用于衡量一个词在文档中的重要程度。结合向量空间模型,可以将文本表示为TF-IDF向量的集合,并通过计算向量之间的相似度来评估文本的相似程度。
  • BM25算法:
            BM25是一种用于信息检索的排名函数,也可以用于文本相似度计算。它考虑了查询词在文档中的词频、逆文档频率以及文档长度等因素,从而评估查询与文档之间的相似度。
  • 基于深度学习的相似度计算:
            近年来,深度学习模型(如卷积神经网络CNN、循环神经网络RNN或Transformer模型)在文本相似度计算中取得了显著进展。这些模型能够自动学习文本的复杂表示,并通过训练来优化相似度计算的性能。
    在实际应用中,根据文本的特点和相似度计算的需求,可以选择合适的算法或组合多种算法来提高计算的准确性和效率。此外,随着自然语言处理技术的不断发展,新的算法和模型不断涌现,为文本相似度计算提供了更多的可能性。

各种相似度算法的python实现

1、余弦相似度

from sklearn.metrics.pairwise import cosine_similarity  
from sklearn.feature_extraction.text import TfidfVectorizer  

# 假设我们有两个文本  
text1 = "This is the first document."  
text2 = "This document is the second document."  

# 使用TF-IDF向量化器将文本转换为向量  
vectorizer = TfidfVectorizer().fit_transform([text1, text2])  

# 计算余弦相似度  
cosine_sim = cosine_similarity(vectorizer[0:1], vectorizer[1:2])  
print(f"Cosine Similarity: {cosine_sim[0][0]}")

2、Jaccard相似度

def jaccard_similarity(list1, list2):  
    intersection = len(set(list1).intersection(list2))  
    union = len(set(list1)) + len(set(list2)) - intersection  
    return intersection / float(union)  

# 将文本转换为词汇集合  
text1_words = set(text1.split())  
text2_words = set(text2.split())  

# 计算Jaccard相似度  
jaccard_sim = jaccard_similarity(text1_words, text2_words)  
print(f"Jaccard Similarity: {jaccard_sim}")

3、编辑距离(Levenshtein Distance)

from Levenshtein import distance  

# 计算编辑距离  
edit_dist = distance(text1, text2)  
print(f"Edit Distance: {edit_dist}")

        注意:Levenshtein库可能不是Python标准库的一部分,你可能需要使用pip install python-Levenshtein来安装它。

4、Word2Vec与词向量

        首先,你需要一个预训练的Word2Vec模型。这里我们使用Gensim库加载一个模型,并计算文本间的相似度。

from gensim.models import KeyedVectors  
import numpy as np  

# 加载预训练的Word2Vec模型  
model = KeyedVectors.load_word2vec_format('path_to_your_model.bin', binary=True)  

# 将文本转换为词向量的平均值  
def get_average_word2vec(words, model, num_features):  
    feature_vec = np.zeros((num_features,), dtype="float32")  
    nwords = 0.  
    for word in words:  
        if word in model:  
            nwords = nwords + 1.  
            feature_vec = np.add(feature_vec, model[word])  
    if nwords:  
        feature_vec = np.divide(feature_vec, nwords)  
    return feature_vec  

# 将文本分词  
text1_words = text1.split()  
text2_words = text2.split()  

# 假设我们知道词向量的维度  
num_features = 300  

# 计算平均词向量  
vec1 = get_average_word2vec(text1_words, model, num_features)  
vec2 = get_average_word2vec(text2_words, model, num_features)  

# 计算余弦相似度  
cos_sim = np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))  
print(f"Word2Vec Cosine Similarity: {cos_sim}")

5、TF-IDF算法

from sklearn.feature_extraction.text import TfidfVectorizer  
from sklearn.metrics.pairwise import cosine_similarity  

# 假设我们有两个文本  
text1 = "我喜欢阅读科幻小说。"  
text2 = "科幻小说是我最喜欢的书籍类型之一。"  

# 将文本放入列表中  
texts = [text1, text2]  

# 初始化TF-IDF向量器  
vectorizer = TfidfVectorizer()  

# 将文本转换为TF-IDF向量  
tfidf_matrix = vectorizer.fit_transform(texts)  

# 计算余弦相似度  
similarity = cosine_similarity(tfidf_matrix[0:1], tfidf_matrix[1:2])  

print(f"文本之间的相似度: {similarity[0][0]}")

6、使用BM25计算文本相似度

        对于BM25,我们可以使用rank_bm25库来计算文档的得分,然后比较这些得分以获取一个相似度的度量。但请注意,BM25本身不直接计算相似度;它用于计算查询和文档之间的相关性得分。要计算相似度,我们可以将得分标准化或比较得分的大小。以下是一个简单的示例,展示如何使用BM25来计算文本之间的相关性得分,但这并不是严格的相似度计算。

from rank_bm25 import BM25Okapi  
import jieba  # 用于中文分词  

# 假设我们有两个文本  
text1 = "我喜欢阅读科幻小说。"  
text2 = "科幻小说是我最喜欢的书籍类型之一。"  

# 对文本进行分词  
tokenized_text1 = list(jieba.cut(text1))  
tokenized_text2 = list(jieba.cut(text2))  

# 将一个文本作为查询,另一个文本作为文档集合  
query = tokenized_text1  
documents = [tokenized_text2]  

# 初始化BM25模型  
bm25 = BM25Okapi(documents)  

# 计算查询和每个文档之间的BM25得分  
scores = bm25.get_document_scores(query, k1=1.5, b=0.75)  

# 输出得分作为相似度的度量(这不是标准的相似度计算,但可以作为一个指标)  
print(f"文本之间的BM25得分: {scores[0]}")

7、基于深度学习的相似度计算(以bert为例)

        基于BERT进行文本相似度计算通常涉及以下步骤:

  • 加载预训练的BERT模型。
  • 将文本转换为BERT模型可以接受的输入格式(即token IDs、attention masks等)。
  • 使用BERT模型获取文本的嵌入表示。
  • 计算嵌入表示之间的相似度(例如,使用余弦相似度)。
            下面是一个使用Hugging Face的Transformers库和BERT模型进行文本相似度计算的Python代码示例:
from transformers import BertTokenizer, BertModel  
from torch import nn  
import torch  

# 加载预训练的BERT tokenizer和model  
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')  
model = BertModel.from_pretrained('bert-base-uncased')  

# 定义函数来计算文本嵌入  
def get_sentence_embedding(sentence, tokenizer, model):  
    # 对句子进行编码  
    inputs = tokenizer(sentence, return_tensors='pt', padding=True, truncation=True, max_length=128)  

    # 获取BERT模型的输出  
    with torch.no_grad():  
        outputs = model(**inputs)  

    # 通常使用CLS token的隐藏状态作为句子的嵌入  
    sentence_embedding = outputs.last_hidden_state[:, 0, :]  

    return sentence_embedding  

# 示例文本  
text1 = "This is a sentence."  
text2 = "This sentence is similar."  

# 计算嵌入  
embedding1 = get_sentence_embedding(text1, tokenizer, model)  
embedding2 = get_sentence_embedding(text2, tokenizer, model)  

# 计算余弦相似度  
cos_sim = nn.CosineSimilarity(dim=0, eps=1e-6)(embedding1.unsqueeze(0), embedding2.unsqueeze(0))  

print(f"Cosine Similarity: {cos_sim.item()}")

        在上面的代码中,我们首先加载了BERT的tokenizer和model。然后定义了一个函数get_sentence_embedding,它接受一个句子、tokenizer和model作为参数,并返回该句子的嵌入表示。这个函数使用tokenizer对句子进行编码,然后获取BERT模型的输出,并使用CLS token的隐藏状态作为句子的嵌入。

        接着,我们为两个示例文本计算了嵌入,并使用PyTorch的nn.CosineSimilarity来计算它们之间的余弦相似度。

        请注意,这个示例使用了BERT的base版本('bert-base-uncased'),并且假设句子长度不会超过BERT的最大长度限制(在这里是128个token)。如果你的句子更长,你可能需要调整max_length参数或者对句子进行截断。

        此外,为了获得更好的性能,你可能需要在GPU上运行这段代码。你可以通过将模型和输入张量移动到GPU上来实现这一点(例如,使用.to(device),其中device是一个指向GPU的torch设备对象)。

回复

举报

全部回复
暂无回帖,快来参与回复吧
云天徽上
超级版主
主题 71
回复 1
粉丝 0