精华内容
下载资源
问答
  •   在自然语言处理的学习和研究中,有好多问题涉及到如何检测两个文本的相似度问题,尤其是在度量句子或者短语之间的相似度。测算度量文本相似度的方法大体有三种:基于关键词匹配的传统方法、基于向量空间的方法和...

    前言

      在自然语言处理的学习和研究中,有好多问题涉及到如何检测两个文本的相似度问题,尤其是在度量句子或者短语之间的相似度。测算度量文本相似度的方法大体有三种:基于关键词匹配的传统方法、基于向量空间的方法和利用深度学习进行文本相似度检测的方法。随着近些年深度学习学科的发展,文本相似度的方法逐渐从基于关键词匹配的传统方法转变为深度学习,且结合向量空间和深度学习进行文本相似度检测。

    文本相似度算法

    基于关键词匹配

      基于关键词匹配方法具有代表性的有:N-gram 相似度与Jaccard 相似度

    N-Gram相似度

      使用N-Gram相似度进行文本相似度匹配是一种模糊匹配方式,关键在于通过两个长的很像的句子之间的差异来度量相似度。
      N-Gram相似度计算具体指假设有一个字符串,那么字符串的N-Gram表示为按照长度N切分这个字符串原句得到词段(词段即原句中所有长度为N的子串)。设想如果有两个字符串,然后分别求它们的N-Gram,那么就可以从它们的共有子串的数量这个角度去定义两个字符串间的N-Gram距离。通过N-Gram距离来判断这两个句子的相似程度。即:Similarity=GN(S)+GN(T)2×GN(S)GN(T)Similarity=|G_N(S)| + |G_N(T)|-2 × |G_N(S)\cap G_N(T)|  其中,GN(S)G_N(S)GN(T)G_N(T) 分别表示字符串S和T的N-Gram集合,当 SimilaritySimilarity 值越低时,两字符串越相似。
      N-Gram忽略了两个字符串长度差异可能导致的问题。比如字符串 girl 和 girlfriend,二者所拥有的公共子串数量显然与 girl 和其自身所拥有的公共子串数量相等,但是并不能据此认为 girl 和girlfriend 是两个等同的匹配。

    Jaccard相似度

      jaccard index又称为jaccard similarity coefficient。主要用于比较有限样本集之间的相似性和差异性。
      原理:计算两个句子之间词集合的交集和并集的比值。该值越大,表示两个句子越相似,在涉及大规模并行运算的时候,该方法在效率上有一定的优势,公式如下:J(A,B)=ABAB=ABA+BAB0J(A,B)1J(A,B)=\frac{|A\cap B|}{|A\cup B|}=\frac{|A\cap B|}{|A|+|B|-|A\cap B|} \quad\quad 0\leqslant J(A,B) \leqslant 1 jaccard值越大说明相似度越高
      Jaccard不相似度:与jaccard 系数相关的指标是jaccard距离用于描述不相似度,公式如下:dj(A,B)=1J(A,B)=ABABAB=AΔBABd_j(A,B)=1-J(A,B)=\frac{|A\cup B|-|A\cap B|}{|A\cup B|}=\frac{A\Delta B}{|A\cup B|}
      jaccard相似度的缺点是只适用于二元数据集合。

    基于向量空间

    Word2vec

      word2vec核心思想是认为词的意思可以从它频繁出现的上下文信息中体现。分为两种结构,一种是Skip-gram,利用中心词预测窗口内的上下文;另一种是CBOW,利用窗口内的上下文预测中心词。
      以CBOW为例,CBOW是一种基于窗口的语言模型。一个窗口指的是句子中的一个固定长度的片段,窗口中间的词语称为中心词,窗口其他词语称为中心词的上下文。CBOW模型通过三层神经网络接受上下文的特征向量,预测中心词是什么。在这里插入图片描述

    图1:Word2vec模型结构示意图

    TF-IDF

      TF-IDF的核心思想是:在一篇文章中,某个词语的重要性与该词语在这篇文章中出现的次数成正相关,同时与整个语料库中出现该词语的文章数成负相关.
      TF(term frequency):词频,某一个给定的词语在该文件中出现的频率,表示一个词语与该文章的相关性。这个数字是对词数(term count)的归一化,以防止它偏向长的文件。
      IDF(inverse document frequency):逆向文件词频,表示一个词语出现的普遍程度。某一特定词语的idf,可以由总文件数目除以包含该词语之文件的数目,再将得到的商取以10为底的对数得到。
      一篇文章中某个词语的重要程度,可以标记为词频和逆向文件词频的乘积.tfidf=tfidftfidf=tf∗idf   通过计算出文档中每个词的TF-IDF值,然后结合相似度计算方法(一般采用余弦相似度)就可以计算两个文档的相似度。

    向量空间与相似度计算

      假设有两个对象 X,YX,Y,这两个对象都包括N维特征X=(x1,x2,...,xn)X=(x_1,x_2, ... ,x_n)Y=(y1,y2,...,yn)Y=(y_1,y_2, ... ,y_n),常用的计算XXYY相似性的方法有:欧氏距离、曼哈顿距离、余弦相似度等。
        欧氏距离:最常用的距离计算公式,以多维空间各个点的绝对距离做衡量。适用于数据稠密且连续的情况。拿两个文档所有的词(不重复)在A文档的词频作为x,在B文档的作为y进行计算。d=t=1n(xiyi)2d=\sqrt{\sum_{t=1}^n(x_i-y_i)^2}    例如:A=你是个坏人、B=小明是个坏人 ,词频分别为A={1 0 1 1} 、B={0 1 1 1}。则距离为21.414\sqrt 2 \approx 1.414,再通过1÷(1+)1 ÷ (1 + 欧几里德距离)得到相似度。

        曼哈顿距离:使用在几何度量空间的几何学用语,用以标明两个点上在标准坐标系上的绝对轴距总和。与欧氏距离有点像,即:d=i=1nxiyid=\sum_{i=1}^n|x_i-y_i|    同理xnx_nyny_n分别代表两个文档所有的词(不重复)在AABB的词频。
        余弦相似度:余弦相似度用向量空间中两个向量夹角的余弦值作为衡量两个个体间差异的大小。相比距离度量,余弦相似度更加注重两个向量在方向上的差异,而非距离或长度上。cosθ=i=1nxi×yii=1nxi2i=1nyi2\cos \theta = \frac{\sum_{i=1}^nx_i×y_i}{\sqrt{\sum_{i=1}^nx_i^2\sum_{i=1}^ny_i^2}}    例如:判断两句话

         A=你是个坏人 B=小明是个坏人
         (1)进行分词
         A=你 / 是 / 个 / 坏人 B=小明 / 是 / 个 / 坏人
         (2) 列出所有的词
          { 你 小明 是 个 坏人 }
         (3)计算词频(出现次数)
          A={1 0 1 1} (每个数字对应上面的字) B={0 1 1 1}
         (4)后把词频带入公式
          cosθ=0.667\cos\theta=0.667
        余弦值越接近1,就表明夹角越接近0度,也就是两个向量越相似,这就叫余弦相似度。

    基于深度学习

    卷积神经网络(CNN)

      CNN通过设计卷积神经网络,结合不同规格的卷积神经网络的差异性度量句子的相似程度。
    在这里插入图片描述

    图2:CNN判断句子相似度结构图
      如上图所示,分别对两个句子建模,然后利用一个句子相似度测量层计算句子相似度,最后通过一个全连接层输出相似度得分。

    文章参考以下博客及书籍:
    Vico_Men_浅析文本相似度
    lbky_文本相似度
    何晗_《自然语言处理入门》

    展开全文
  • 我们不可避免地应用到自然语言处理(NLP)技术去解决问题,比如智能问答系统、资讯舆情分析等……在自然语言处理中,很多实际应用具有共性问题,本文就以文本相似度的计算为例介绍自然语言处理解决问题思路。...

    文 | 光大科技大数据部 卢格润

    在金融科技的业务场景下,我们不可避免地应用到自然语言处理(NLP)的技术去解决问题,比如智能问答系统、资讯舆情的分析等……

    在自然语言处理中,很多实际应用具有共性问题,本文就以文本相似度的计算为例介绍自然语言处理解决问题的思路。

    • 文本向量化

    • 相似度的计算

    • 相关示例

    • 总结

    文本向量化

    无论是中文、英文还是标点符号,都是机器无法直接做计算的,需要先将文本转化为可计算和比较的数学表示的形式。

    如何将一句话转化为数学的形式呢?人们能想到最简单的方式就是统计一句话有多少个词;然后很自然的比较两句话的相似程度就看它们有多少个词一样就好了;再比上两个句子的总词数,就能得到一个 0-1 之间的相似度了。这就是 Jaccard 相似度计算方法:

    仅从一个词语是否出现的角度,进行数学表示,进而进行相似度计算显然是没有充分利用文本中的信息的。人们希望对一句话数学的表示能够更多地体现它包含的语义信息。因此人们想到,比起统计词的总数,记录每个出现的词和其出现的频率会获得更多的信息,这就是构造 Bag of words(词袋)。比如下列一个片段:

    1.it was the best of times

    2.it was the worst of times

    3.it was the age of wisdom

    4.it was the age of foolishness

    这个片段中出现的所有词构成一个词袋["it","was","the","best","of","times","worst","age","wisdom","foolishness"],词袋中共有10个词,根据每个词是否出现可以将每个句子转化为10维的向量。对应词语在整个片段中出现的顺序,第一句话可以转化为向量, 相应地,第二、三、四句话分别为

    在词袋的基础上能获得哪些语义特征呢?首先每个词的重要性是不同的,希望比较相似度时更重要的词能占有更多的权重。因此需要想办法能够给句子中的词做关键词排序,一个经典的评估一个单词重要程度的方法是 TF-IDF(词频-逆文档频率)。人们在阅读时知道一个词重要是因为人们读过很多书,学习到了这个词是重要的。TF-IDF 在做重要性排序时,也是学习了很多文档才获得的有关重要性的信息。基本思想是一个词在一篇文章中出现的频率越高且在其它文章中出现的频率越低,这个词就越重要。计算一个词在一篇文档中的重要性时考虑:

    该词在该文档中出现的频率该文档所有词出现的词频总数语料库的文档总数包含该次的文档数

    词语的权重就是 。对于之前例子中的向量,每个元素都需要乘上这个对应的权重。

    之后人们又想到,词袋模型并不能保留原本语句的语序信息,而我们或许可以通过语序得到一些同义词,这些词本身就比另一些词更相似。这时一个假设被提出:如果两个词的上下文相似,那么这两个词更有可能是同义词。Word2Vec[1]就是利用这一假设训练出词向量来表示一个词。Word2Vec 有两种训练方法,这里介绍通过上下文预测中间这个词被称为 CBOW(Continuous Bag-of-Words Model)的方法(另一种训练方法SKIP-GRAM与它正相反,通过中间词预测上下文)。它其实是一个三层神经网络模型。如图所示:

    17b884ed0dbfe008137b9c1427c2534c.png

    以图中的神经网络为例,它Input Layer 是一个词上下文各两个词的 one-hot 编码4个10维的向量:,实际的 Output 是一个概率分布,训练目标是让这个概率分布尽可能接近所要预测词的 one-hot 编码.

    具体过程如下:

    1. 这里one-hot 编码是 10维向量,假设需要得到的是 8 维词向量。

    2. 通过训练得到两个权值矩阵 ()()

    3. 从 Input Layer 到 Hidden Layer,分别乘上 W 得到4个 8 维的向量,再取平均得到一个 8 维向量

    4. 从 Hidden Layer 到 Output Layer, 又与 相乘,再用 Softmax 处理得到一个概率分布。

    5. 这个概率分布与要预测的词的 one-hot 编码越接近越好。

    6. 事实上,就是我们需要的8维词向量;

    有了每个词对应的词向量后,我们可以将句子转化为一组向量表示。例如词向量为8维,片段一中的每句话有6个词,就将每个句子转化为6个8维的向量作为一组。

    将词转化为词向量也就称之为词嵌入(Word Embedding),这里所说的 Word2Vec 是实现词嵌入的一种算法。

    由词嵌入再往下就要讲到预训练语言模型了。预训练语言模型是 NLP 中很重要的研究领域,它的想法等同要让一个小孩去写作,要先让其识字、读书、理解文字的意义之后再动笔写东西。为了让机器实现这一想法,先通过一些任务预训练(Pre-training)出一个模型,这个模型能够提取出一些通用的语义特征,然后再在一些具体的任务上比如文本分类、序列标注上做精调(Fine-tuning),这样通过之前对语义理解能够去做各种各样的下游任务。

    其实词嵌入就相当于预训练语言模型中预训练的这一部分。当然现在的预训练语言模型已经在 CBOW 的基础上改进了很多,并且运用了特征抽取器使学习到的语义能够更好地运用于下游任务。

    关于预训练语言模型这里暂不做更多的介绍,先继续讲讲将句子转化为能比较的向量以后该怎样计算相似度。

    相似度的计算

    从第一部分的内容我们将一个句子转化成了两种形式:一种是一个句子转化为一个向量的形式;另一种是句子中的每个词都转化为一个向量(Word2Vec)。

    通常比较两个长度相等的向量(N 维)可以计算余弦距离或欧式距离:

    • 余弦相似度:
    • 欧氏距离:

    而 Word2Vec 将每个句子转化为了一组 N 维向量,要比较两组 N 维向量,我们需要再将每组 N 维向量转化为一个 N 维向量再计算余弦相似度或欧氏距离。这个过程称为 Sentence embedding。

    首先可以将一个句子中所有词向量取平均;另外可以结合第一部分所说的 TF-IDF 给所有词向量赋予权重后做加权平均。

    还有一种取权重做加权的方法称为SIF(smooth inverse frequency)[2],这种方法的核心是通过去掉一组句子的共有成分来保留各自关键的部分,以之前的片段为例,共有4个句子,每个句子包含6个词向量,每个词向量有8维:

    • 首先对每个词 计算一个权重为 其中 为超参数, 在所有句子中的词频(通过在训练集句子中的词频做估计),得词频越低权重越大;
    • 对每个句子中6个词向量根据对应词的权重做加权平均得到4个8维的句向量 ~
    • ~作为列得到一个矩阵 X,X 的第一主成分为 u(通过奇异值分解得到);
    • 最后减去在 u 上的投影得到最终的句向量

    相关示例

    利用gensim 库[3]训练 word2vec 模型:

    from gensim.models import Word2Vec
    #text为语料库
    model = Word2Vec(text, size=8, window=5, min_count=1)
    model.save("word2vec.model")
    sentence0=['it''was''the''best''of''times']
    sentence1=['it''was''the''worst''of''times']
    #vector0和vector1分别存两组词向量
    vector0=dict()
    for word in sentence0:
        vector0[word]=model.wv[word]
    vector1=dict()
    for word in sentence1:
        vector1[word]=model.wv[word]

    在实际训练时 text 为我们所准备的语料库,size 是我们所需要的词向量维度,window 是每次去上下文共多少个词训练,min_count 为词最少出现的次数。之后通过这个 word2vec.model 我们可以将需要计算相似度的句子做一个 word embedding。

    利用 gensim 库训练 TF-IDF 模型:

    from gensim.models import TfidfModel
    from gensim.corpora import Dictionary
    #document为一组句子,包括sentence0和sentence0
    dct = Dictionary(document)  
    corpus = [dct.doc2bow(line) for line in document]
    model1= TfidfModel(corpus) 

    根据TF-IDF模型找到每个词向量与对应的权重,每个句子中所有词向量加权平均得到句向量 s0 和 s1:

    s0=0
    wd=dict(model1[corpus[0]])
    for word in sentence0:
        w=wd[dct.token2id[word]]
        s0+= vector0[word]*w
    s0=s0/len(sentence0)
    s1=0
    wd1=dict(model1[corpus[1]])
    for word in sentence1:
        w=wd1[dct.token2id[word]]
        s1+= vector1[word]*w
    s1=s1/len(sentence1)

    利用公式计算余弦相似度:

    import numpy as np
    d1=np.dot(s0,s1)/(np.linalg.norm(s0)*np.linalg.norm(s1))

    总结

    NLP 是一个发展很快的人工智能领域,新的算法不断出现打败之前的算法,本文讲解了做文本相似度计算在内的自然语言处理任务一个很基本的思路:都是需要先在大量的语料上进行学习,然后根据所学将文本用数学表示,再根据数学表示的形式进行之后的处理。

    本文介绍的方法也存在一些明显缺点,主要有两点:1、没有考虑多义词;2、没法根据具体任务做动态优化。

    在此希望对自然语言处理感兴趣的读者能持续关注这一专题,之后会继续给大家分享现在的 NLP 算法是如何处理这些问题的。

    参考资料

    [1]

    Efficient Estimation of Word Representation in Vector Space: https://arxiv.org/pdf/1301.3781v3.pdf

    [2]

    Sanjeev Arora, et al. 2017. A Simple but Tough-to-Beat Baseline for Sentence Embeddings: https://openreview.net/pdf?id=SyK00v5xx

    [3]

    GENSIM: https://radimrehurek.com/gensim/models/word2vec.html

    我们是光大科技公司的追光实验室团队,将不定期推出数据挖掘和算法相关的数据科学原创文章。团队定位打造基于知识驱动的机器学习实验室,由实践经验丰富的数据分析挖掘工程师和专注算法的数据科学家精心准备相关作品,志在分享结合实际业务的理论应用和算法创新,以及其中的心得体会。

    往期回顾
    评分卡建模工具之变量聚类

    展开全文
  • 1、文本相似度: 1) 语义相似、但字面不相似 2) 字面相似、但是语义不相似 2、方案: 1) 语义相似:依靠用户行为,最基本方法:(1)基于共点击行为(协同过滤),(2)借助回归算法 2) 字面相似:(1) LCS...

    1、文本相似度:

    1) 语义相似、但字面不相似

    2) 字面相似、但是语义不相似

    2、方案:

    1) 语义相似:依靠用户行为,最基本的方法:(1)基于共点击的行为(协同过滤),(2)借助回归算法

    2) 字面相似:(1) LCS最大公共子序列 (2) 利用中文分词

    3 字面相似的问题解决:
           余弦相似度 cosine
                        举例:A(1,2,3),B(2,3,4)
                        cosine(A,B) = 分子 / 分母
                        分子:A*B = 1*2+2*3+3*4 = 20

                        |A| = sqrt(1*1+2*2+3*3) = 3.74
                        |B| = sqrt(2*2+3*3+4*4) = 5.38
                        分母:|A|*|B| = 20.12

    4 tfidf:

    1) TF:词频
                
                        关键词:在当前文章出现较多,但在其他文章中出现较少
                
    2) IDF:反文档频率
                                        
    score = TF * IDF

    5、自动摘要:

    1) 确定关键词集合(两种方法(a)top-10 (b)阈值截断 > 0.8 )
    2)哪些句子包含关键词,把这些句子取出来
    3)  对关键词排序,对句子做等级划分
    4)把等级高的句子取出来,就是摘要

    6.实践:

    1.idf实践:

    一共508篇文章

    (1)数据预处理:把所有文章的内容,全部收集到一个文件中

    ]# python convert.py input_tfidf_dir/ > idf_input.data

    (2)计算IDF:通过mr批量计算IDF

             计算方法:文档总数/包含该词的文档数

    代码:

    convert.py:

    import os

    import sys

    file_path_dir = sys.argv[1]

    def read_file_handler(f):
        fd = open(f, 'r')
        return fd

    file_name = 0
    for fd in os.listdir(file_path_dir):
        file_path = file_path_dir + '/' + fd

        content_list = []

        file_fd = read_file_handler(file_path)
        for line in file_fd:
            content_list.append(line.strip())

        print '\t'.join([str(file_name), ' '.join(content_list)])

        file_name += 1

    map.py:

    import sys

    for line in sys.stdin:
        ss = line.strip().split('\t')
        if len(ss) != 2:
            continue
        file_name, file_content = ss
        word_list = file_content.strip().split(' ')

        word_set = set(word_list)

        for word in word_set:
            print '\t'.join([word, '1'])

    red.py:

    import sys
    import math

    current_word = None
    sum = 0

    docs_cnt = 508

    for line in sys.stdin:
        ss = line.strip().split('\t')
        if len(ss) != 2:
            continue
        word, val = ss
        if current_word == None:
            current_word = word
        if current_word != word:
            idf = math.log(float(docs_cnt) / (float(sum) + 1.0))
            print '\t'.join([current_word, str(idf)])
            current_word = word
            sum = 0

        sum += int(val)

    idf = math.log(float(docs_cnt) / (float(sum) + 1.0))
    print '\t'.join([current_word, str(idf)])

    编写run.sh脚本运行MapReduce:

    7.LCS(最长公共子序列)解决方案:

    动态规划解决:

    LCSpython实践:

    1.数据:

    2.python代码:

    map.py:

    # -*- coding: utf-8 -*-
    #!/usr/bin/python

    import sys

    def cal_lcs_sim(first_str, second_str):
        len_vv = [[0] * 50] * 50

        first_str = unicode(first_str, "utf-8", errors='ignore')
        second_str = unicode(second_str, "utf-8", errors='ignore')

        len_1 = len(first_str.strip())
        len_2 = len(second_str.strip())

        for i in range(1, len_1 + 1):
            for j in range(1, len_2 + 1):
                if first_str[i - 1] == second_str[j - 1]:
                    len_vv[i][j] = 1 + len_vv[i - 1][j - 1]
                else:
                    len_vv[i][j] = max(len_vv[i - 1][j], len_vv[i][j - 1])

        return float(float(len_vv[len_1][len_2] * 2) / float(len_1 + len_2))


    for line in sys.stdin:
        ss = line.strip().split('\t')
        if len(ss) != 2:
            continue
        first_str = ss[0].strip()
        second_str = ss[1].strip()

        sim_score = cal_lcs_sim(first_str, second_str)
        print '\t'.join([first_str, second_str, str(sim_score)])

    执行脚本run.sh

    执行:

    结果:

     

    shell终端做快速计算:
                ]# echo $[60000*2/16]
                ]# echo $((60000*2/16))

    展开全文
  • snownlp:分词、词性标注、情感分析、文本分析、转化拼音、繁体字转简体字、提取文本关键词、提取文本摘要、tf、idf、句子分割、文本相似度、 xmnlp:今日头条团队、轻量级NLP deepnlp 概述 每年毕业季,各位...

    工具类

    • jieba
    • snownlp:分词、词性标注、情感分析、文本分析、转化拼音、繁体字转简体字、提取文本关键词、提取文本的摘要、tf、idf、句子分割、文本相似度、
    • xmnlp:今日头条团队的、轻量级的NLP
    • deepnlp

    概述

    每年毕业季,各位学子都会使用一个叫做论文查重系统,来检测是否毕业论文存在抄袭嫌疑。如何衡量两篇论文之间的相似度呢?面对类似的问题,人们提出了文档相似度的概念。文档相似度指的是两篇文档之间的相似程度,也被称为文档距离。文档相似度通常是文本聚类、信息检索等NLP任务的基础,常见的计算文档距离的方法包括simhash和余弦距离。

    simhash算法

    simhash是由Charikar在2002年提出来的,论文名为《Similarity estimation techniques from rounding algorithms》。Google基于simhash在海量网页中进行相似度计算并去重。通常对比两个文档是否相同时,会计算对应的hash值,常见的算法包括md5和sha256。实际使用中,对于检测文档是否被篡改时,使用hash值具有不错的表现。但是当文档内容因为修改少许文字,插入广告甚至只是修改了标点符合和错别字,都会导致hash值改变,可是文档的核心内容并未发生改变。如何使用数学的方法表征这种文档相似性呢?simhash的设计初衷就是使用一种所谓局部hash的方法,可以既可以敏感的识别文档的少许修改又可以识别出文档的大多数内容相同。

    simhash的一种典型实现就是将一个文档最后转换成一个64位的字节的特征字或者说simhash值,然后判断重复只需要判断他们的特征字的距离是不是小于3,就可以判断两个文档是否相似。这个距离使用海明距离,即两个simhash值取异或后二进制中1的个数。大家可以结合自身业务特点修改simhash值的位数以及判断文档相似性的海明距离的值。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FIn50zQA-1597211237758)(https://ws4.sinaimg.cn/large/006tNc79gy1g2kf406c05j30hs0byq3q.jpg)]

    如图所示,计算6位simhash值典型的实现算法为:

    • 将Doc分词和计算权重,抽取出n个(关键词,权重)对,即图中的(feature, weight)
    • 计算关键词的hash,生成图中的(hash,weight),并将hash和weight相乘,这一过程是对hash值加权
    • 将hash和weight相乘的值相加,比如图中的[13, 108, -22, -5, -32, 55],并最终转换成simhash值110001,转换的规则为正数为1负数为0

    simhash库

    simhash具有多种实现,常用的一种已经部署在pip源上了,直接安装即可。

    pip install simhash
    

    有兴趣的读者也可以使用源码安装。

    git clone https://github.com/leonsim/simhash
    cd simhash/
    python setup.py 
    python setup.py install
    

    数据集

    数据集依然使用搜狗实验室提供的"搜狐新闻数据",该数据来自搜狐新闻2012年6月—7月期间国内,国际,体育,社会,娱乐等18个频道的新闻数据,提供URL和正文信息。 对应的网址为:

    为了处理方便,我们提取其中前1万条的正文信息,保存到如下文件中:

    …/data/news_sohusite_content_10000.txt

    数据清洗

    为了避免开发环境的编码方式对结果的影响,设置环境的默认编码方式为utf8.

    reload(sys)
    sys.setdefaultencoding('utf8')
    

    加载加载搜狐新闻语料.

    def load_sougou_content():
        #with open("../data/news_sohusite_content.txt") as F:
        # 测试阶段仅加载前1w条记录
        with open("../data/news_sohusite_content_10000.txt") as F:
            content=F.readlines()
            F.close()
        return content
    

    选择其第88篇文章为测试文章,在剩下的语料中寻找与其相似的文档。

    #加载搜狐新闻语料
    content=load_sougou_content()
    
    #设置测试文章
    print "select test data:"
    test_news=content[88]
    print test_news
    

    测试文档的内容如下:

    南方日报 讯   ( 记者 / 黄少宏   实习生 / 朱子 煜   通讯员 / 成广伟 ) “ 学习 台北 垃圾 分类 模式 ” 要 全面铺开 , 部分 小区 试行 垃圾 费 “ 按袋 计量 征收 ” , 厨余 垃圾 专袋 收运 . . . . . . 这是 记者 昨日 从 广州市 城 管委 庆祝 建党 9 1 周年 暨 争先 创优 表彰大会 上 获悉 的 。 据 广州市 城 管委 主任 李廷贵 透露 , 7 月 1 0 日 将 召开 垃圾 分类 全市 动员大会 , 并 推出 一系列 政策 。 在 昨日 的 大会 上 , 针对 垃圾 围城 难题 , 李廷贵 透露 , 广州市委 、 市政府 已经 形成 决议 , 初步 决定 在 7 月 1 0 日 , 在 中山纪念堂 召开 动员大会 , 进行 全面 部署 , 全面 动员 , 正式 启动 垃圾 分类 , 并 将 形成 一整套 法律法规 和 规范 文件 、 配套 实施方案 。 李廷贵 提到 , 要 采取 5 种 垃圾 分类 技术 路线 , 其中 包括 按袋 计量 。 据介绍 , 广州 将 于 今年年底 前 选择 1 - 2 个 生活 小区 试点 “ 垃圾 费 按袋 计量 收费 ” 模式 , 厨余 垃圾 排放 免费 , 其他 垃圾 排放 计量 收费 。 至于 “ 垃圾 费 按袋 计量 收费 ” 政策 , 将 以 专用 垃圾袋 作为 收费 的 工具 , 市民 丢弃 垃圾 , 必须 购买 政府 制作 、 在 指定 地点 发售 的 专用 垃圾袋 盛装 , 再交 垃圾车 收运 。 产生 多少 垃圾 付 多少 钱 , 垃圾 越 少 , 缴费 就 越少 。 除 台北 “ 垃圾 不 落地 ” 模式 将 在 广州 进一步 推广 外 , “ 垃圾袋 实名制 、 垃圾 费 随袋 征收 ” 政策 也 将 在 广州 试点 运行 。 那么 , 垃圾袋 实名制 将 如何 推行 呢 ? 据介绍 , 广州 将 在 政府 特制 的 分类 垃圾袋 上 , 印 上 居民 的 住宅 地段 号 和 房号 , 以此 作为 识别 垃圾袋 出自 那家 哪户 的 标志 , 根据 该 标志 , 可以 追查 垃圾 投放 的 源头 。 如果 居民 没有 按照 规定 对 垃圾 分类 , 将 根据 标记 信息 追查 到 居民 个人 。

    数据清洗过程,加载我们积累的中文停用词。

    def load_stopwords():
        with open("stopwords.txt") as F:
            stopwords=F.readlines()
            F.close()
        return [word.strip() for word in stopwords]
    

    为了避免停用词的影响,清洗阶段我们从数据集中删除停用词。

    # 加载积累的stopwords
    stopwords = load_stopwords()
    
    # 切割token并清除stopwords
    x = [[word for word in line.split() if word not in stopwords] for line in content]
    
    # 切割token并清除stopwords
    test_news = [word for word in test_news.split() if word not in stopwords]
    
    # 计算simhash
    test_news_hash = Simhash(test_news)
    

    计算simhash值

    依次计算语料库中每条记录的simhash,并记录下与测试数据的距离。

    sim=[]
    # 遍历语料计算simhash值
    for news in x:
        hash = Simhash(news)
        score=test_news_hash.distance(hash)
        sim.append( score)
    

    选择距离最短的6的文档和序号并打印,因为需要按照score正序排列,需要设置key参数。

    for index, score in sorted(enumerate(sim), key=lambda item: item[1])[:6]:
        print   "index:%d similarities:%f content:%s" % (index, score, content[index])
    

    排名第一的是距离为0的第88号文档,正好就是原文,排名第二的是序号为5644的文档,距离为4,可以发现讲的也是垃圾回收的内容。

    垃圾袋 印 房号 可追溯 源头 , 按袋 计量 收费 广州 将 试点 垃圾袋 实名制 垃圾袋 印 房号 可追溯 源头 , 按袋 计量 收费 “ 学习 台北 垃圾 分类 模式 ” 要 全面铺开 , 部分 小区 试行 垃圾 费 “ 按袋 计量 征收 ” , 厨余 垃圾 专袋 收运 … … 这是 记者 近日 从 广州市 城 管委 庆祝 建党 9 1 周年 暨 争先 创优 表彰大会 上 获悉 的 。 据 广州市 城 管委 主任 李廷贵 透露 , 7 月 1 0 日 将 召开 垃圾 分类 全市 动员大会 , 并 推出 一系列 政策 。 针对 垃圾 围城 难题 , 李廷贵 透露 , 广州市委 、 市政府 已经 形成 决议 , 初步 决定 在 7 月 1 0 日 , 在 中山纪念堂 召开 动员大会 , 进行 全面 部署 , 全面 动员 , 正式 启动 垃圾 分类 , 并 将 形成 一整套 法律法规 和 规范 文件 、 配套 实施方案 。 李廷贵 提到 , 要 采取 5 种 垃圾 分类 技术 路线 , 其中 包括 按袋 计量 。 据介绍 , 广州 将 于 今年年底 前 选择 1 - 2 个 生活 小区 试点 “ 垃圾 费 按袋 计量 收费 ” 模式 , 厨余 垃圾 排放 免费 , 其他 垃圾 排放 计量 收费 。 至于 “ 垃圾 费 按袋 计量 收费 ” 政策 , 将 以 专用 垃圾袋 作为 收费 的 工具 , 市民 丢弃 垃圾 , 必须 购买 政府 制作 、 在 指定 地点 发售 的 专用 垃圾袋 盛装 , 再交 垃圾车 收运 。 产生 多少 垃圾 付 多少 钱 , 垃圾 越 少 , 缴费 就 越少 。

    余弦距离

    余弦距离,又称为余弦相似性,是通过计算两个向量的夹角余弦值来评估他们的相似度。余弦相似度将向量根据坐标值,绘制到向量空间中,如最常见的二维空间。假设向量a、b的坐标分别为(x1,y1)、(x2,y2) ,则对应的余弦距离为:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NIPK3MMP-1597211237760)(https://ws3.sinaimg.cn/large/006tNc79gy1g2kgnqmlpcj305k01hq2q.jpg)]

    设向量 A = (A1,A2,…,An),B = (B1,B2,…,Bn) 。推广到多维:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DrEm6nYZ-1597211237762)([外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e1Hb5A1u-1597211238249)(evernotecid://B17C42DD-6BDC-4F75-93FC-07ADC43AEA8D/appyinxiangcom/11012738/ENResource/p2159)]])

    夹角越小,余弦值越接近于1,它们的方向更加吻合,则越相似。可见余弦距离在0和1之间且约接近1说明越两者越相似。

    数据集

    数据集也和simhash使用相同的数据集。

    数据清洗

    数据清洗方式与simhash类似,只不过多了一个TFIDF处理。

    # 加载积累的stopwords
    stopwords = load_stopwords()
    
    # 切割token并清除stopwords
    x = [[word for word in line.split() if word not in stopwords] for line in content]
    
    # 获取词袋
    dictionary = corpora.Dictionary(x)
    
    # 制作语料
    corpus = [dictionary.doc2bow(doc) for doc in x]
    
    # 进行TFIDF处理
    tfidf = models.TfidfModel(corpus)
    
    # 把测试文章转换成tfidf
    test_news_vec = [word for word in test_news.split() if word not in stopwords]
    
    test_news_vec = tfidf[dictionary.doc2bow(test_news_vec)]
    

    词袋提取使用的是gensim的库,生成的矩阵为稀疏矩阵。

    计算余弦距离

    gensim库封装实现了针对稀疏矩阵计算余弦距离的类,直接调用即可。由于需要按照score的倒序排列,所以使用key参数。

    index = similarities.SparseMatrixSimilarity(tfidf[corpus], num_features=len(dictionary.keys()))
    sim = index[tfidf[test_news_vec]]
    
    for index, score in sorted(enumerate(sim), key=lambda item: -item[1])[:6]:
     	print   "index:%d similarities:%f content:%s" % (index, score, content[index])
    

    排名第一的是距离为0.965616的第88号文档,正好就是原文,排名第二的是序号为5644的文档,距离为40.907202,可以发现讲的也是垃圾回收的内容。

    参考文献

    • http://yanyiwu.com/work/2014/01/30/simhash-shi-xian-xiang-jie.html
    展开全文
  • 我们不可避免地应用到自然语言处理(NLP)技术去解决问题,比如智能问答系统、资讯舆情分析等……在自然语言处理中,很多实际应用具有共性问题,本文就以文本相似度的计算为例介绍自然语言处理解决问题思路。...
  • 文本相似度,顾名思义是指两个文本(文章)之间相似度,在搜索引擎、推荐系统、论文鉴定、机器翻译、自动应答、命名实体识别、拼写纠错等领域有广泛应用。 与之相对应,还有一个概念——文本距离——指是两...
  • 编辑距离,又称Levenshtein距离. 表示从字符串1到字符串2,需要增删改操作最小次数 编辑距离实现原理是动态规划算法,leetcode...Levenshtein.distance("自然语言处理","自然语言处理技术") Levenshtein.distance("自
  • NLP自然语言处理的文本相似度

    千次阅读 多人点赞 2019-09-03 22:28:40
    1. 背景介绍 ...希望读完本文,大家可以对文本相似度有一个完整而深刻理解,最好能在非代码维度上超过开发人员(达到了这种水平,输出需求自然会得到开发同学最大尊重和认同)。 文本相似度,顾名...
  • 前言 人与计算机交互过程中,如果能提供人类自然语言形式来进行交流,那么人与计算机就能更加亲密友好。而要实现这一机制就需要自然语言处理来处理,一般来说自然语言处理...
  • 文本相似度,顾名思义是指两个文本(文章)之间相似度,在搜索引擎、推荐系统、论文鉴定、机器翻译、自动应答、命名实体识别、拼写纠错等领域有广泛应用。 与之相对应,还有一个概念——文本距离——指是两...
  • 自然语言处理(五 文本相似度

    千次阅读 2017-12-16 12:40:36
    LMSentence Embedding表示简单共有词判断模型假设现在有文本A和B,Num(A∩B)Num(A\cap B) 表示A和B中相同词数量,Num(A∪B)Num(A\cup B)表示A和B中所有词数量。那么定义A和B相似程度为: Similarity(A,B)=Num...
  • 自然语言处理中,我们经常需要判定两个东西是否相似。 比如,在微博热点话题推荐那里,我们需要比较微博之间的相似度,让相似度微博聚集在一起形成一个簇,提出一个主题。 在问答系统中,比如说人工客服,...
  • 文章目录文本相似度和分类文本相似度案例:文本分类TF-IDF (词频-逆文档频率)案例: 文本相似度和分类 度量文本间相似性 使用词频表示文本特征 文本中单词出现频率或次数 NLTK实现词频统计 文本相似度案例:...
  • 目录 1. 文本相似度问题与应用 ...文本相似度问题包含:词与词、句与句、段落与段落、篇章与篇章之间相似度问题;以及词与句、句与段落、段落与篇章等之类相似度问题,这里相似指是语义...
  • 文章目录自然语言处理系列三十文本相似度算法余弦相似度Java代码实现总结 自然语言处理系列三十 文本相似度算法 在自然语言处理中,我们经常需要判定两个东西是否相似。比如,在微博热点话题推荐那里,我们需要...
  • 在这个链接这里介绍了和文本相似度检测有关:https://paperswithcode.com/task/semantic-textual-similarity paperwithcode是一个很好网站 然后github上关于Semantic Textual Similarity信息综合帖,...
  • 文章目录自然语言处理系列二十九文本相似度算法余弦相似度算法原理总结 自然语言处理系列二十九 文本相似度算法 在自然语言处理中,我们经常需要判定两个东西是否相似。比如,在微博热点话题推荐那里,我们需要...
  • 文章目录自然语言处理系列三十一文本相似度算法余弦相似度Python代码实现总结 自然语言处理系列三十一 文本相似度算法 在自然语言处理中,我们经常需要判定两个东西是否相似。比如,在微博热点话题推荐那里,我们...
  • ​ 在做自然语言处理的过程中,我们经常会遇到需要找出相似语句的场景,或者找出句子的近似表达,这时候就需要把类似的句子归到一起,这里面就涉及到句子相似度计算的问题。 基本方法 句子相似度计算一共归类了以下...
  • 文本相似度计算在信息检索、数据挖掘、机器翻译、文档复制检测等领域有着广泛应用。文本相似度常用计算方法有TF-IDF、LSI、LDA等。本文分别用上述3种算法来对同一批文本计算相似度,并分析比较不同算法优劣之...
  • 自然语言处理(NLP)之使用TF-IDF模型计算文本相似度 所用数据集:ChnSentiCorp_htl_all.csv 语料库即存放稀疏向量列表。 要注意是,搜索文本text与被检索文档共用一个特征词词典。 代码主要使用gensim库...
  • 在NLP领域,语义相似度的计算一直是个难题:搜索场景下query和Doc语义相似度、feeds场景下Doc和Doc语义相似度、机器翻译场景下A句子和B句子语义相似度等等。本文通过介绍DSSM、CNN-DSSM、LSTM-DSSM等深度学习...
  • 从本文开始要讲一个非常重要问题:文本相似度问题,通过计算两个文本相似度,以达到文本判重目的。它应用有很多,比如文本去重、搜索引擎网页判重、论文反抄袭等。解决文本相似度问题算法有很多,本文就...
  • 句子的相似度有非常广泛应用,比如文本搜索、问答系统等。今天我们来看下如何计算两个句子之间的相似度
  • 文章目录自然语言处理系列二十七文本相似度算法字符串编辑距离Java代码实现总结 自然语言处理系列二十七 文本相似度算法 在自然语言处理中,我们经常需要判定两个东西是否相似。比如,在微博热点话题推荐那里,...
  • 文章目录自然语言处理系列二十八文本相似度算法字符串编辑距离Python代码实现总结 自然语言处理系列二十八 文本相似度算法 在自然语言处理中,我们经常需要判定两个东西是否相似。比如,在微博热点话题推荐那里,...

空空如也

空空如也

1 2 3 4 5 ... 17
收藏数 331
精华内容 132
关键字:

自然语言处理的文本相似度