zoukankan      html  css  js  c++  java
  • 词袋模型和句子相似度

    词袋模型和句子相似度

    词袋模型(bag of words ,BOW)

    词袋模型能够把一个句子转化为向量表示,是比较简单直白的一种方法,它不考虑句子中单词的顺序,只考虑此表中单词在这个句子中的出现的次数。

    "John likes to watch movies, Mary likes movies too"
    
    "John also likes to watch football games"
    

    对于这两个句子,我们要用词袋模型把它转化为向量表示,这两个句子形成的词表(不去停用词)为:

    [‘also’, ‘football’, ‘games’, ‘john’, ‘likes’, ‘mary’, ‘movies’, ‘to’, ‘too’, ‘watch’]
    

    因此,它们的向量表示为:

    scikit-learn实现

    from sklearn.feature_extraction.text import CountVectorizer
    corpus = [
        "John likes to watch movies, Mary likes movies too",
        "John also likes to watch football games",
    ]
    vectorizer = CountVectorizer()
    X = vectorizer.fit_transform(corpus)
    print(vectorizer.get_feature_names())
    print(X.toarray())
    

    手动实现

    通常nlp无法一下子处理完整的段落或句子,因此,第一步往往是分句和分词。这里只有句子,因此只需分词。对于英语句子,可以使用NLTK中的word_tokenize函数,对于中文句子,则可使用jieba模块。故第一步是分词,代码如下:

    from nltk import word_tokenize
    sents = [sent1, sent2]
    texts = [[word for word in word_tokenize(sent)] for sent in sents]
    

    输出的结果是:

    [['I', 'love', 'sky', ',', 'I', 'love', 'sea', '.'], ['I', 'like', 'running', ',', 'I', 'love', 'reading', '.']]
    

    分词完毕。下一步构建语料库,即所有句子中出现的单词和标点。代码如下:

    all_list = []
    for text in texts:
        all_list += text
    corpus = set(all_list)
    print(corpus)
    

    输出如下:

    {'love', 'running', 'reading', 'sky', '.', 'I', 'like', 'sea', ','}
    

    接下来,对语料库中的单词及标点建立数字映射,便于后续的句子的向量表示。代码如下:

    corpus_dict = dict(zip(corpus, range(len(corpus))))
    print(corpus_dict)
    

    输出如下:

    {'running': 1, 'reading': 2, 'love': 0, 'sky': 3, '.': 4, 'I': 5, 'like': 6, 'sea': 7, ',': 8}
    

    虽然单词及标点并没有按照它们出现的顺序来建立数字映射,不过这并不会影响句子的向量表示及后续的句子间的相似度。
      下一步,也就是词袋模型的关键一步,就是建立句子的向量表示。这个表示向量并不是简单地以单词或标点出现与否来选择0,1数字,而是把单词或标点的出现频数作为其对应的数字表示,结合刚才的语料库字典,句子的向量表示的代码如下:

    # 建立句子的向量表示
    def vector_rep(text, corpus_dict):
        vec = []
        for key in corpus_dict.keys():
            if key in text:
                vec.append((corpus_dict[key], text.count(key)))
            else:
                vec.append((corpus_dict[key], 0))
    
        vec = sorted(vec, key= lambda x: x[0])
    
        return vec
    
    vec1 = vector_rep(texts[0], corpus_dict)
    vec2 = vector_rep(texts[1], corpus_dict)
    print(vec1)
    print(vec2)
    

    输出如下:

    [(0, 2), (1, 0), (2, 0), (3, 1), (4, 1), (5, 2), (6, 0), (7, 1), (8, 1)]
    [(0, 1), (1, 1), (2, 1), (3, 0), (4, 1), (5, 2), (6, 1), (7, 0), (8, 1)]
    

    真实的向量:

    [2, 0, 0, 1, 1, 2, 0, 1, 1]
    [1, 1, 1, 0, 1, 2, 1, 0, 1]
    

    以上便是词袋模型。

    接下来是计算两个句子的相似度,一般会选择用余弦相似度来作为句子相似度。向量的余弦相似度即为两个向量的夹角的余弦值。代码如下:

    from math import sqrt
    def similarity_with_2_sents(vec1, vec2):
        inner_product = 0
        square_length_vec1 = 0
        square_length_vec2 = 0
        for tup1, tup2 in zip(vec1, vec2):
            inner_product += tup1[1]*tup2[1]
            square_length_vec1 += tup1[1]**2
            square_length_vec2 += tup2[1]**2
    
        return (inner_product/sqrt(square_length_vec1*square_length_vec2))
    
    
    cosine_sim = similarity_with_2_sents(vec1, vec2)
    print('两个句子的余弦相似度为: %.4f。'%cosine_sim)
    
  • 相关阅读:
    Silverlight 4.0添加鼠标右键菜单和Silverlight全屏模式的进入退出
    获取天气服务
    Silverlight 数据绑定 (1):怎样实现数据绑定 &&Silverlight 数据绑定 (2):Source to Target
    调用根据IP查看城市WebService
    Silverlight中的Binding使用(一、二、三)
    使用Prism实现的WPF MVVM点餐Demo
    [Silverlight入门系列]实现局部元素全屏(Element部分全屏)
    silverlight 上下标
    动画教程(动态注册/静态注册)
    Silverlight数据验证
  • 原文地址:https://www.cnblogs.com/jimlau/p/13118255.html
Copyright © 2011-2022 走看看