前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >文本在计算机中的表示方法总结

文本在计算机中的表示方法总结

作者头像
AI研习社
发布2019-10-29 17:00:49
2.9K0
发布2019-10-29 17:00:49
举报
文章被收录于专栏:AI研习社AI研习社

本文为 AI 研习社社区用户 @Dendi 独家投稿内容,欢迎扫描底部社区名片访问 @Dendi 的主页,查看更多内容。

阅读提示

本文约 8900 字,预计阅读时间 23 分钟

1

概述

文本表示( text representation)是NLP任务中非常基础,同时也非常重要的一部分。目前常用的文本表示方式分为:

  1. 离散式表示(Discrete Representation);
  2. 分布式表示(Distributed Representation);

本文旨在介绍这两类常用的文本表示方式。

2

离散式表示(Discrete Representation

2.1 One-Hot

One-Hot 编码又称为“独热编码”或“哑编码”,是最传统、最基础的词(或字)特征表示方法。这种编码将词(或字)表示成一个向量,该向量的维度是词典(或字典)的长度(该词典是通过语料库生成的),该向量中,当前词的位置的值为1,其余的位置为0。

文本使用one-hot 编码步骤:

  1. 根据语料库创建 词典(vocabulary),并创建词和索引的 映射(stoi,itos);
  2. 将句子转换为用索引表示;
  3. 创建OneHot 编码器;
  4. 使用OneHot 编码器对句子进行编码;

Demo

class OneHotEncoder(object):
    def __init__(self, corpus=[]):
        # 统计词频
        word_counter = {}
        for sentence in corpus:
            for item in sentence.split():
                if item in word_counter.keys():
                    word_counter[item] += 1
                else:
                    word_counter[item] = 1
        # 按词频排序
        word_counter_sort = sorted(word_counter, key=word_counter.__getitem__, reverse=True)
        # 词典
        self.vocab = set(word_counter_sort)
        # 创建词和索引的映射
        self.stoi = {}
        self.itos = {}
        for index, word in enumerate(word_counter_sort):
            self.stoi[word] = index
            self.itos[index + 1] = word
    # 句子编码
    def sentence_encoder(self, sentence):
        result = []
        for i in range(0, len(sentence.split())):
            result.append([0] * len(self.vocab))

        for index, item in enumerate(sentence.split()):
            result[index][self.stoi[item]] = 1
        return result
    # 单词编码
    def word_encoder(self, word):
        result = [0] * len(self.vocab)
        result[self.stoi[word]] = 1
        return result

if __name__ == '__main__':
    corpus = [
        "CNN LSTM TRANSFORMER",
        "This is NLP, NLP is a every good task",
        "This is a sample",
        "This is anthor example anthor example",
        "CNN module is very useful",
        "That is pytorch"
    ]
    one_hot_enc = OneHotEncoder(corpus)
    print('词索引:')
    print(one_hot_enc.stoi)
    print('“is” 的one-hot编码:{}'.format(one_hot_enc.word_encoder('is')))
    print('“This” 的one-hot编码:{}'.format(one_hot_enc.word_encoder('This')))
    print('{}:one-hot 编码结果:'.format(corpus[0]))
    print(one_hot_enc.sentence_encoder(corpus[0]))

结果:

# 词索引:
{'is': 0, 'This': 1, 'CNN': 2, 'a': 3, 'anthor': 4, 'example': 5, 'LSTM': 6, 'TRANSFORMER': 7, 'NLP,': 8, 'NLP': 9, 'every': 10, 'good': 11, 'task': 12, 'sample': 13, 'module': 14, 'very': 15, 'useful': 16, 'That': 17, 'pytorch': 18}

# “is” 的one-hot编码:
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
# “This” 的one-hot编码:
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

# CNN LSTM TRANSFORMER:one-hot 编码结果:
[
    [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
    [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
    [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]

如结果所示,One-Hot 编码的特点如下:

  1. 词向量长度是词典长度;
  2. 在向量中,该单词的索引位置的值为 1 ,其余的值都是 0 ;
  3. 使用One-Hot 进行编码的文本,得到的矩阵是稀疏矩阵(sparse matrix

缺点:

  1. 不同词的向量表示互相正交,无法衡量不同词之间的关系;
  2. 该编码只能反映某个词是否在句中出现,无法衡量不同词的重要程度;
  3. 使用One-Hot 对文本进行编码后得到的是高维稀疏矩阵,会浪费计算和存储资源;

2.2 词袋模型(Bag Of Word,BOW

例句:

  1. Jane wants to go to Shenzhen.
  2. Bob wants to go to Shanghai.

在词袋模型中不考虑语序和词法的信息,每个单词都是相互独立的,将词语放入一个“袋子”里,统计每个单词出现的频率。

Demo

class BagOfWords(object):
    def __init__(self, corpus=[]):
        # 统计词频
        word_counter = {}
        for sentence in corpus:
            for item in sentence.split():
                if item in word_counter.keys():
                    word_counter[item] += 1
                else:
                    word_counter[item] = 1
        # 按词频排序
        word_counter_sort = sorted(word_counter, key=word_counter.__getitem__, reverse=True)
        # 词典
        self.vocab = set(word_counter_sort)
        # 创建词和索引的映射
        self.stoi = {}
        self.itos = {}
        for index, word in enumerate(word_counter_sort):
            self.stoi[word] = index
            self.itos[index + 1] = word

    def sentence_encoder(self, sentence):
        result = [0] * len(self.vocab)
        for item in sentence.split():
            result[self.stoi[item]] += 1
        return result

if __name__ == '__main__':
    corpus = [
        'Jane wants to go to Shenzhen',
        'Bob wants to go to Shanghai'
    ]
    bow = BagOfWords(corpus)
    print('词索引:')
    print(bow.stoi)
    print('{} 编码:'.format(corpus[0]))
    print(bow.sentence_encoder(corpus[0]))
    print('{} 编码:'.format(corpus[1]))
    print(bow.sentence_encoder(corpus[1]))

结果:

# 词索引:
{'to': 0, 'wants': 1, 'go': 2, 'Jane': 3, 'Shenzhen': 4, 'Bob': 5, 'Shanghai': 6}
# Jane wants to go to Shenzhen 编码:
[2, 1, 1, 1, 1, 0, 0]
# Bob wants to go to Shanghai 编码:
[2, 1, 1, 0, 0, 1, 1]

词袋模型编码特点:

  1. 词袋模型是对文本(而不是字或词)进行编码;
  2. 编码后的向量长度是词典的长度;
  3. 该编码忽略词出现的次序;
  4. 在向量中,该单词的索引位置的值为单词在文本中出现的次数;如果索引位置的单词没有在文本中出现,则该值为 0 ;

缺点

  1. 该编码忽略词的位置信息,位置信息在文本中是一个很重要信息,词的位置不一样语义会有很大的差别(如 “猫爱吃老鼠” 和 “老鼠爱吃猫” 的编码一样);
  2. 该编码方式虽然统计了词在文本中出现的次数,但仅仅通过“出现次数”这个属性无法区分常用词(如:“我”、“是”、“的”等)和关键词(如:“自然语言处理”、“NLP ”等)在文本中的重要程度;

2.3 TF-IDF(词频-逆文档频率)

为了解决词袋模型无法区分常用词(如:“是”、“的”等)和专有名词(如:“自然语言处理”、“NLP ”等)对文本的重要性的问题,TF-IDF 算法应运而生。

TF-IDF 全称是:term frequency–inverse document frequency 又称 词频-逆文本频率。其中:

  1. TF Term Frequency :某个词在当前文本中出现的频率,频率高的词语或者是重要的词(如:“自然语言处理”)或者是常用词(如:“我”、“是”、“的”等);
  2. IDF Inverse Document frequency :逆文本频率。文本频率是指:含有某个词的文本在整个语料库中所占的比例。逆文本频率是文本频率的倒数;

公式

优点

  1. 实现简单,算法容易理解且解释性较强;
  2. IDF 的计算方法可以看出常用词(如:“我”、“是”、“的”等)在语料库中的很多文章都会出现,故IDF的值会很小;而关键词(如:“自然语言处理”、“NLP ”等)只会在某领域的文章出现,IDF 的值会比较大;故:TF-IDF 在保留文章的重要词的同时可以过滤掉一些常见的、无关紧要的词;

缺点

  1. 不能反映词的位置信息,在对关键词进行提取时,词的位置信息(如:标题、句首、句尾的词应该赋予更高的权重);
  2. IDF 是一种试图抑制噪声的加权,本身倾向于文本中频率比较小的词,这使得IDF 的精度不高;
  3. TF-IDF 严重依赖于语料库(尤其在训练同类语料库时,往往会掩盖一些同类型的关键词;如:在进行TF-IDF 训练时,语料库中的 娱乐 新闻较多,则与 娱乐 相关的关键词的权重就会偏低 ),因此需要选取质量高的语料库进行训练;

3

分布式表示(Distributed Representation

理论基础:

  • 1954年,Harris提出分布式假说(distributional hypothesis)奠定了这种方法的理论基础:A word’s meaning is given by the words that frequently appear close-by(上下文相似的词,其语义也相似);
  • 1957年,Firth对分布式假说做出进一步的阐述和明确:A word is characterized by the company it keeps(词的语义由其上下文决定);

3.1 n-gram

n-gram 是一种 语言模型(Language Model, LM)。语言模型是一种基于概率的判别式模型,该模型的输入是一句话(单词的序列),输出的是这句话的概率,也就是这些单词的联合概率(joint probability)。(备注:语言模型就是判断一句话是不是正常人说的。)

语言模型中的概率计算:

n-gram模型中的概率计算:

n-gram 是对语言模型的一个简化(马尔科夫假设 Markov Assumption):一个词的出现仅与它之前出现的若干(n)个词有关。

  • 当 n=1 时,表示当前词的出现仅与它前面出现的词语有关,成该模型为:bi-gram:
  • 当 n=2 时,表示当前词的出现仅与它前面出现的词语有关,成该模型为:tri-gram:

备注:在 n=gram 中并不是 n 取值越大越好,一般取 n=1 或 n=2。

3.2 共现矩阵(Co-Occurrence Matrix

首先指定窗口大小,然后统计窗口(和对称窗口)内词语共同出现的次数作为词的向量(vector)。

语料库:

  1. I like deep learning.
  2. I like NLP.
  3. I enjoy flying.

备注: 指定窗口大小为1(即:左右的 window_length=1,相当于 bi-gram)统计数据如下:(I, like),(Iike, deep),(deep, learning),(learning, .),(I, like),(like, NLP),(NLP, .),(I, enjoy),(enjoy, flying), (flying, .)。则语料库的共现矩阵如下表所示:

从以上的共现矩阵可以看出,单词 like 和 enjoy 都在单词 I 附件出现且统计数目大概相等,则它们在 语义 和 语法 上的含义大概相同。

优点

  1. 考虑了句子中词的顺序;

缺点

  1. 词表的长度很大,导致词的向量长度也很大;
  2. 共现矩阵也是稀疏矩阵(可以使用 SVDPCA 等算法进行降维,但是计算量很大);

3.3 Word2Vec

word2vec 模型是Google团队在2013年发布的 word representation 方法。该方法一出让 预训练词向量 的使用在NLP 领域遍地开花。

模型

word2vec有两种模型:CBOWSKIP-GRAM

  • CBOW:利用上下文的词预测中心词;
  • SKIP-GRAM:利用中心词预测上下文的词;

效果

用 word2vec 训练 中国 得到的词向量(150维)如下所示。

中国 0.695267 0.024923 0.373858 0.069021 
-0.117292 -0.556426 0.432008 0.254941 
0.586677 -0.254549 1.003527 -0.222197 
0.185688 0.083037 -0.058732 0.323542 
1.258338 0.164693 -0.188106 -0.250684 
-0.080654 -0.151610 -0.412507 0.285773 
0.052821 0.102732 -0.270337 -0.111756 
-0.498646 -0.186227 -0.293205 -0.095415 
0.127587 0.344156 -0.381316 -0.480463 
0.223322 -0.497338 0.027069 0.011063 
-0.114940 0.390520 -0.585619 0.699663 
0.274457 0.169250 -0.218244 -0.451712 
-0.687161 -0.706266 -0.142516 -0.017635 
-0.063381 0.591093 -0.032082 0.093772 
0.516114 -0.283159 -0.097458 0.145825 
-0.068391 0.100854 -0.114780 0.348797 
-0.063897 -0.194472 0.221520 -0.610716 
-0.470367 -0.771020 -0.060092 0.089194 
0.666474 0.088972 -0.066155 -0.374819 
-0.251768 0.296184 0.057016 0.082267 
0.148182 -0.088706 -0.562667 0.730473 
-0.106829 0.278102 -0.068409 0.271573 
-0.321527 -0.046518 -0.109408 -0.594494 
0.364192 -0.826890 0.293684 0.301737 
0.083754 -0.350486 -0.638416 -0.272567 
-0.252318 0.335563 -0.225580 0.158646 
-0.649817 -0.177225 -0.164084 0.016909 
-0.336381 0.385419 0.237850 0.618375 
-0.240223 -0.464445 -0.247453 -0.699201 
0.328400 0.790493 -0.093674 0.899263 
0.362883 0.443218 -0.124069 0.950863 
0.079109 0.246814 -0.344305 -0.672262 
-0.266110 0.146369 -0.067152 -0.508636 
0.355758 -0.807643 -0.135210 0.114947 
0.297123 0.047535 -0.061851 -0.305667 
-0.053594 0.075912 0.536091 -0.482222 
0.419101 0.261491 1.181885 0.723524 
-0.788293 0.393409

* 注:为便于显示,此处进行了换行处理。

1. 这个过程就是word embedding,跟离散式表示方法相比,word2vec得到的向量不是稀疏向量,此外维度一般在100到300维,不像one-hot、bow、tf-idf算法得到的词向量维度(词汇表的大小)那么大;

2. 将得到的word embedding(本例子中为150维)再进行降维后进行可是话表示,如下图所示:

可以发现:
  • nine、zero、three、two 等数字词汇聚合在一起;
  • tuesday、saturday 等日期词汇聚合在一起;
  • google、yahoo 等搜索引擎词汇聚合在一起;

3. 此外还有一个有意思的现象,可以用数学公式表示:

优点

  1. 考虑到词语的上下文,学习到了语义和语法的信息;
  2. 得到的词向量维度小,节省存储和计算资源;
  3. 通用性强,可以应用到各种NLP 任务中;

缺点

  1. 词和向量是一对一的关系,无法解决多义词的问题;
  2. word2vec是一种静态的模型,虽然通用性强,但无法真的特定的任务做动态优化;

3.4 GloVe

GloVe 是斯坦福大学Jeffrey、Richard 等提供的一种词向量表示算法,GloVe 的全称是Global Vectors for Word Representation,是一个基于全局词频统计(count-based & overall staticstics)的词表征(word representation)算法。该算法综合了global matrix factorization(全局矩阵分解) 和 local context window(局部上下文窗口) 两种方法的优点。

备注:Glove模型的推导公式比较复杂,在这里不做详细推导,具体可以查看官网(https://nlp.stanford.edu/projects/glove/)。

效果

优点

  1. 考虑到词语的上下文、和全局语料库的信息,学习到了语义和语法的信息;
  2. 得到的词向量维度小,节省存储和计算资源;
  3. 通用性强,可以应用到各种NLP 任务中;

缺点

  1. 词和向量是一对一的关系,无法解决多义词的问题;
  2. glove也是一种静态的模型,虽然通用性强,但无法真的特定的任务做动态优化;

3.5 ELMO

word2vec 和 glove 算法得到的词向量都是静态词向量(静态词向量会把多义词的语义进行融合,训练结束之后不会根据上下文进行改变),静态词向量无法解决多义词的问题(如:“我今天买了7斤苹果” 和 “我今天买了苹果7” 中的 苹果 就是一个多义词)。而ELMO模型进行训练的词向量可以解决多义词的问题。

ELMO 的全称是“ Embedding from Language Models ”,这个名字不能很好的反映出该模型的特点,提出ELMO 的论文题目可以更准确的表达出该算法的特点“ Deep contextualized word representation ”。

该算法的精髓是:用语言模型训练神经网络,在使用word embedding 时,单词已经具备上下文信息,这个时候神经网络可以根据上下文信息对word embedding 进行调整,这样经过调整之后的word embedding 更能表达在这个上下文中的具体含义,这就解决了静态词向量无法表示多义词的问题。

网络模型

过程

  1. 上图中的结构使用字符级卷积神经网络(convolutional neural network, CNN)来将文本中的词转换成原始词向量(raw word vector) ;
  2. 将原始词向量输入双向语言模型中第一层 ;
  3. 前向迭代中包含了该词以及该词之前的一些词汇或语境的信息(即上文);
  4. 后向迭代中包含了该词以及该词之后的一些词汇或语境的信息(即下文) ;
  5. 这两种迭代的信息组成了中间词向量(intermediate word vector);
  6. 中间词向量被输入到模型的下一层 ;
  7. 最终向量就是原始词向量和两个中间词向量的加权和;

效果

如上图所示:

  • 使用glove训练的词向量中,与 play 相近的词大多与体育相关,这是因为语料中与play相关的语料多时体育领域的有关;
  • 在使用elmo训练的词向量中,当 play 取 演出 的意思时,与其相近的也是 演出 相近的句子;

4

结语

  1. 现在深度学习在NLP 领域中使用的大多是分布式词向量;
  2. 分布式词向量的理论基础是语言模型;
  3. 在进行词向量选择时,要考虑到具体任务的特性,word2vec、glove、elmo训练的词向量各有优缺点,并没有哪一种比另两种效果好很多。

* 封面图来源:https://pixabay.com/images/id-4166221/

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-10-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AI研习社 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 2.1 One-Hot
    • Demo
      • 缺点:
      • 2.2 词袋模型(Bag Of Word,BOW)
        • Demo
          • 缺点
          • 2.3 TF-IDF(词频-逆文档频率)
            • 公式
              • 优点
                • 缺点
                • 3.1 n-gram
                • 3.2 共现矩阵(Co-Occurrence Matrix)
                  • 优点
                    • 缺点
                    • 3.3 Word2Vec
                      • 模型
                        • 效果
                          • 优点
                            • 缺点
                            • 3.4 GloVe
                              • 效果
                                • 优点
                                  • 缺点
                                  • 3.5 ELMO
                                    • 网络模型
                                      • 过程
                                        • 效果
                                        相关产品与服务
                                        NLP 服务
                                        NLP 服务(Natural Language Process,NLP)深度整合了腾讯内部的 NLP 技术,提供多项智能文本处理和文本生成能力,包括词法分析、相似词召回、词相似度、句子相似度、文本润色、句子纠错、文本补全、句子生成等。满足各行业的文本智能需求。
                                        领券
                                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档