【深度学习-NLP】文本表示方法简介

264 阅读12分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第1天

词嵌入

词嵌入(Word Embedding)是一种将文本中的词转换成数字向量的方法,为了使用标准机器学习算法来对它们进行分析,就需要把这些被转换成数字的向量以数字形式作为输入。词嵌入过程就是把一个维数为所有词数量的高维空间嵌入到一个维数低得多的连续向量空间中,每个单词或词组被映射为实数域上的向量,词嵌入的结果就生成了词向量。

词向量是各种NLP任务中文本向量化的首选技术,如词性标注、命名实体识别、文本分类、文档聚类、情感分析、文档生成、问答系统等。

One-Hot编码

One-hot编码(独热码或独热编码)的词向量。他是一位有效编码,主要是采用N位状态寄存器来对N个状态来进行编码,每个状态都由他独立的寄存器位,并且在任意时候只有一位有效。是分类变量作为二进制向量的表示。One-hot编码是最基本的向量方法。One-hot编码通过词汇大小的向量表示文本中的词,其中只有对应于该词的项是1而所有其他的项都是零。

One-hot编码的主要缺点是不能表示词之间的相似性。在任何给定的语料库中,我们会期望诸如(猫、狗)之类的词具有一些相似性,使用点积计算向量之间的相似性。点积是向量元素乘法的总和。在One-hot编码中,语料库中任何两个词之间的点积总是为零。

在处理数据特征的时候,我们经常会遇到这种分类特征:(1)性别特征:【男,女】,根据one-hot定义,我们需要将该性别特征改编为 10-男,01-女 (2)国家特征:【中国,美国,法国】,根据one-hot改编为 100-中国,010-美国,001-法国

juejin1.png

使用one-hot的好处:

  • 解决了分类器不好解决属性分类的问题
  • 扩充特征

关于离散数据:

分类问题中,损失函数经常呗定义为预测值和真实值的误差平方和。离散数字编码之后,3被预测为1的损失是比3被预测为2有着更大的损失,而onehot编码保证了不同类别的距离相同,所以onehot对于不同的分类更合适。

bags of words

Bag of Words(词袋表示),也称为Count Vectors,每个文档的字/词可以使用其出现次数来进行表示。 举例:

juejin2.png

在转换之前需要先构建一个字典:

{“我”:1,“爱”:2,“北”:3,“京”:4,“天”:5,“安”:6,“门”:7,“喜”: 8,“欢”:9,“上”:10,“海”}

  • 使用机器学习算法实现
from sklearn.feature_extraction.text import CountVectorizer
corpus = [
    'This is the first document.',
    'This document is the second document.',
    'And this is the third one.',
    'Is this the first document?',
]
vectorizer = CountVectorizer()
vectorizer.fit_transform(corpus).toarray()

N-Gram

N-Gram是一种基于统计语言模型的算法,基本思想是将文本里面的内容按照字节进行大小为N的滑动窗口操作,形成一个长度为N的字节片段的序列。

每一个字节片段称为Gram,对所有gram的出现频度进行统计,并且按照事先设定好的阈值进行过滤,形成关键gram列表,也就是这个文本的向量特征空间,列表中的每一种gram就是一个特征向量维度。

该模型有这样一种前提,第N个词的出现只与前面N-1个词相关,而与其他任何词都不相关,整句的概率就是各个词出现概率的乘积,这些概率可以通过直接从语料中统计N个词同时出现的次数得到,常用的是二元的Bi-Gram和三元的Tri-Gram。

N-Gram是一句一个语料库中,对于单词的统计来计算。N-Gram常见的有一元模型,二元模型,和三元模型。在语义上只人为相近的几个词有关联。

  • 一元模型: 比如语句:“猫,跳上,椅子”p(A="猫",B="跳上",C="椅子") = p("猫")p("跳上")P("椅子");其中各个词的数量是语料库中统计的数量。

juejin3.png 依据这个可以计算出p(A,B,C) = p(A)p(B)p(C)

  • 二元模型 每个词都与他左侧最近的词有关联,即P(A,B,C) = P(A)P(B|A)P(C|B),比如语句:“猫,跳上,椅子” ,P(A="猫",B="跳上",C="椅子") = P("猫")P(“跳上”|“猫”)P("椅子"|“跳上”);其中各个词的数量数语料库中统计的数量

juejin4.png

P(A,B,C) = P(A)P(B|A)P(C|B)

p(A) = 13/M

P(B|A) =9/13

p(C|B) = 15/16

  • 三元模型和以上类似
  • 困惑度评估

juejin5.png

  • 注意:上述中的pp为困惑度(perplexity),是一种评估语言模型好坏的指标。

TF-IDF

TF-IDF(term frequency–inverse document frequency,词频-逆向文件频率)是一种用于信息检索(information retrieval)与文本挖掘的常用加权技术。

TF-IDF是一种统计方法,用来评估一个字词对于一个文件或一个语料库中的一份文件的重要程度,字词的重要性随着他在文件中出现的次数成正比增加,但同时也会随着他在语料库中出现的频率成反比下降。

主要思想是:如果某个单词在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。

一.TF是词频

词频表示词条在文本中出现的频率,这个数字通常会被归一化(一般是词频除以文章总词数),以防止它偏向长的文件。

juejin6.png 其中,nij表示该词在文件dj中出现的次数,分母则是文件dj中所有词汇出现的次数总和。

二.IDF是逆向文件频率

逆向文件频率:某一特定词语的IDF,可以由总文件数目除以包含该词语的文件的数目,再将得到的商取对数得到,如果包含词条t的文档越少,IDF越大,则说明词条具有很好的类别区分能力。

juejhin7.png

其中,|D|是语料库中的文件总数,|{j:ti∈dj}| 表示包含词语ti的文件数目,(即ni,j!=0的文件数目)如果该词语不在语料库中,就会导致分母为零,因此一般情况下使用{j:ti∈dj}|,即:

juejin8.png

三.TF-IDF实际上是:TF*IDF

某一特定文件内的高词语频率,以及该词语在整个文件集合上的文件频率,可以产生出高权重的TF-IDF,因此,TF-IDF倾向于过滤掉常见的词语,保留重要的词语。

juejin9.png 注意:该算法没有考虑词语的语义信息,无法处理一词多义与一义多词的情况。

  • 使用sklearn实现
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
 
x_train = ['TF-IDF 主要 思想 是','算法 一个 重要 特点 可以 脱离 语料库 背景',
           '如果 一个 网页 被 很多 其他 网页 链接 说明 网页 重要']
x_test=['原始 文本 进行 标记','主要 思想']
 
#该类会将文本中的词语转换为词频矩阵,矩阵元素a[i][j] 表示j词在i类文本下的词频
vectorizer = CountVectorizer(max_features=10)
#该类会统计每个词语的tf-idf权值
tf_idf_transformer = TfidfTransformer()
#将文本转为词频矩阵并计算tf-idf
tf_idf = tf_idf_transformer.fit_transform(vectorizer.fit_transform(x_train))
#将tf-idf矩阵抽取出来,元素a[i][j]表示j词在i类文本中的tf-idf权重
x_train_weight = tf_idf.toarray()
 
#对测试集进行tf-idf权重计算
tf_idf = tf_idf_transformer.transform(vectorizer.transform(x_test))
x_test_weight = tf_idf.toarray()  # 测试集TF-IDF权重矩阵
 
print('输出x_train文本向量:')
print(x_train_weight)
print('输出x_test文本向量:')
print(x_test_weight)
  • jieba实现
import jieba.analyse
 
text='关键词是能够表达文档中心内容的词语,常用于计算机系统标引论文内容特征、
信息检索、系统汇集以供读者检阅。关键词提取是文本挖掘领域的一个分支,是文本检索、
文档比较、摘要生成、文档分类和聚类等文本挖掘研究的基础性工作'
 
keywords=jieba.analyse.extract_tags(text, topK=5, withWeight=False, allowPOS=())
print(keywords)

不足:

  • 没有考虑特征词的位置因素对文本的区分度,词条出现在文档的不同位置时,对区分度的贡献大小是不一样的。

  • 按照传统TF-IDF,往往一些生僻词的IDF(反文档频率)会比较高、因此这些生僻词常会被误认为是文档关键词。

  • 传统TF-IDF中的IDF部分只考虑了特征词与它出现的文本数之间的关系,而忽略了特征项在一个类别中不同的类别间的分布情况。

  • 对于文档中出现次数较少的重要人名、地名信息提取效果不佳。

BOW

BOW是词袋Bag of Words的简称,BOW是文本分类中常用的文本向量化的方法,它忽略了顺序和语法,将文本看成词汇的集合,且词汇间相互独立,如同把词放进了一个袋子。在分类任务中使用BOW时,就是根据各个词义综合分析文本的类型,常用于感情色彩分类等领域。

CBOW

CBOW是连续词袋模型Continuous Bag-of-Word Model的简称,它常用于上下文词来预测中间词。

juejin10.png

如图所示,使用前两个和后两个词(共C=4个)预测中间的词w,其中每个词被映射成V维的词向量;每个词向量乘以参数矩阵A(V-N维矩阵),转换成N维数据,然后将所有词对应的N维的数据相加取均值,计算出N维的隐藏层Hidden;再用隐藏层乘参数矩阵B(N-V维),计算待预测的词w对应的V维词向量;最终用预测出的w与真实的w作比较计算误差函数,然后用梯度下降调整A,B两个参数矩阵。由此,使用简单的神经网络就完成了预测任务。

fasttext

fasttext简介

fastText是一个快速文本分类算法,与基于神经网络的分类算法相比有两大优点:

  • fastText在保持高精度的情况下加快了训练速度和测试速度

  • fastText不需要预训练好的词向量,fastText会自己训练词向量

  • fastText两个重要的优化:Hierarchical Softmax、N-gram

在文本分类问题中,早期的算法一般将词袋BOW作为输入,使用线性模型作为算法计算类别,这种方法在类别不均衡时效果不好,后来用将线性分类器分解为低秩矩阵或者多层网络的方法解决这一问题。

模型架构

juejin11.png

fasttext模型与CBOW模型有些类似,其中输入是文档中的词,使用词嵌入方法,和CBOW一样,通过乘A矩阵转换到Hidden,再乘B矩阵转换到输出层,与CBOW不同的是它的输出不是空缺的单词,而是分类的类别。

loss损失函数使用负对数似然函数

juejin12.png

其中N是文档数,xn是文档中的词特征。yn是标签,A和B是权重矩阵,A用于转换到文本表示,B用于线性变换计算类别,f是一个softmax函数用于计算最终分类的概率。

当分类的类别较多时,计算的时间复杂度是O(hk),其中k是类别的个数,h是文本表示的维度。Fasttext使用了基于霍夫曼编码树的分级softmax,使训练的时间复杂度降为O(hlog2(k))。每一个节点的概率大小与从树根到该节点经过的路径有关,例如某节点深度为l+1,它的父节点分别是n1…n2,则它的概率是:

juejin13.png

word2vec

word embedding(词嵌入): 即将高维词向量嵌入到一个低维空间。词嵌入的时候保持两个原则:

(1)这个映射是单设(不懂的概念自行搜索);
(2)映射之后的向量不会丢失之前的那种向量所含的信息。

word2vec模型其实就是简单的神经网络模型,

juejin14.png

输入是One-Hot Vector,Hidden Layer没有激活函数,也就是线性的单元。Output Layer维度跟Input Layer的维度一样,用的是Softmax回归。当这个模型训练好以后,我们并不会用这个训练好的模型处理新的任务,我们真正需要的是这个模型通过训练数据所学得的参数,例如隐层的权重矩阵。

该模型定义输入和输出有两种方式:CBOW和Skip-Gram模型。CBOW模型的训练输入是某一个特征词的上下文相关的词对应的词向量,而输出就是这特定的一个词的词向量。 Skip-Gram模型输入是特定的一个词的词向量,而输出是特定词对应的上下文词向量。CBOW对小型数据库比较合适,而Skip-Gram在大型语料中表现更好。

CBOW

juejin15.png

  • 输出层:上下文单词的one-hot(假设单词向量空间dim为V,上下文单词个数为C)

  • 所有one-hot分别乘以共享的输入权重矩阵W,(V*N矩阵,N为自己设定的数,初始化权重矩阵W)

  • 所得的向量(因为是onehot所以为向量),相加求平均作为隐层向量,size为1N

  • 乘以输出权重矩阵W`(N-V)

  • 得到向量(1*V)激活函数处理得到V-dim概率分布

  • 概率最大的index所指示的单词就是预测出的中间层词,与true label的onehot做比较,误差越小越好。(根据误差更新权重矩阵)

所以,需要定义损失函数(一般为交叉熵代价函数),采用梯度下降算法更新W和W'。训练完毕后,输入层的每个单词与矩阵W相乘得到的向量的就是我们想要的词向量(word embedding),有了W矩阵就可以免去训练过程直接查表得到单词的词向量了。

skip-Gram

该模型与CBOW相反,由预测词的上下文作为输入,模型的输出概率代表着到我们词典中每个词有多大可能性跟input word同时出现。