Task5 基于深度学习的文本分类2

Task5 基于深度学习的文本分类2

传统的机器学习方法通常是特征过程+分类器,而深度学习可以使用词表示、句子表示、篇章表示来代替繁琐的特征工程。这一节尝试寻找更优的深度学习的文本分类模型。

5.1 学习目标

1.学习Word2Vec的使用和基础原理
2.学习使用TextCNN、TextRNN进行文本分类。
3.学习使用HAN网络结构完成文本分类。

5.2 文本表示方法part3
5.2.1 词向量

本节通过word2vec学习词向量。word2vec模型背后的基本思想是对出现在上下文环境里的词进行预测。具体做法是对于每一条输入文本,选取一个上下文窗口和一个中心词,并基于这个中心词去预测窗口里其他词出现的概率。word2vec模型可以方便地从新增语料中学习到新增词的向量表达,是一种高效的在线学习算法(online learning)。
word2vec的主要思路:通过单词和上下文彼此预测,对应的两个算法分别为:
1.Skip-gram(SG):预测上下文
2.Continuous Bag of Words(CBOW):预测目标单词。
另外还有两种更高效的训练方法:
1.Hierarchical softmax(分层softmax)
2.Negative sampling(负采样)

5.2.1.1 Skip-gram原理和网络结构

从直观上理解,Skip-gram是给定input word来预测上下文。而CBOW是给定上下文,来预测input word。
在这里插入图片描述
word2vec模型实际上分为两个部分:
1.建立模型。
2.通过模型获取嵌入词向量。
建模过程与自编码器(auto-encoder)的思想类似:先基于训练数据构建一个神经网络,训练好模型后,并不会将其用于处理新的任务,因为我们只需要该模型通过训练所学得的参数,例如隐藏层的权重矩阵——这些权重在word2vec中其实就是我们试图去学习的“word vectors”。
PS:上面提到的这种方法实际上会在无监督特征学习(unsupervised feature learning)中见到,最常见的就是自编码器(auto-encoder):通过在隐层将输入进行编码压缩,继而在输出层将数据解码恢复初始状态,训练完成后,我们会将输出层“砍掉”,仅保留隐层。
Skip-gram过程:
假定句子为“The dog barked at the mailman”。
1.首先选择句子中的一个词作为输入词,这里我们选择“dog”作为input word;
2.接着定义skip_window参数,代表从当前input word的一侧(左边或右边)选取词的数量。如果设置skip_window = 2,那么最终获得窗口中的词(包含input word)就是[‘The’, ‘dog’, ‘barked’,‘at’],skip_window = 2表示选取input左侧两个词以及右侧两个词进入窗口(这里‘dog’左侧只有‘The’),所以窗口的大小span = 2×2 = 4。我们还要定义另一个参数num_skips,代表从窗口中选取多少个不同的词作为output,当skip_window = 2,num_skips = 2时,即从窗口中获得两组(input word, output word)形式的训练数据,即(‘dog’, ‘barked’),(‘dog’ ,‘the’)。
3.神经网络基于这些训练数据会输出一个概率分布,代表词典中每个词作为input word的output word的概率。
比如说我们使用了‘dog’作为input word,那么模型通过学习2中得到的训练数据,可以告诉我们词汇表中除去“dog”外每个单词作为output的可能性。
也就是说模型的输出概率代表词典中每个词与input word同时出现的可能性。比如说向模型中输入一个单词“Soviet”,那么模型的最终输出中,像‘Union’,‘Russia’这种相关词的概率将远高于像‘watermelon’,‘kangaroo’这样的非相关词的概率。因为一般而言,‘Union’,‘Russia’更可能在“Soviet”的窗口中出现。
所以我们就是通过将文本中成对的单词输入到神经网络中来进行训练,完成上述的概率计算。下面给出一个例子,选定句子为“The quick brown fox jumps over lazy dog”,设定窗口大小window_size = 2,也就是选择输入词的前后两个词与输入词进行组合。下图中,蓝色代表input word,方框表示位于窗口内的单词。
在这里插入图片描述
模型将从每对单词出现的次数习得统计结果。在模型中可能会更多地得到类似(“Soviet”, “Union”)这样的训练样本对,而(“Soviet”, “Sasquatch”)这样的组合出现的就会较少。因此,模型完成训练后,如果给定“Soviet”作为输入,输出结果中 "Union"会比"Sasquatch"被赋予更高的概率。
此外,input word 和output word都会被进行one-hot编码,因为神经网络只能接受数值输入,我们不可能把一个单词字符串作为输入。因此最常用的办法就是基于训练文档来构建我们自己的词汇表(vocabulary)再对单词进行one-hot编码。
假设从训练文档中抽取出10000个唯一不重复的单词组成词汇表。我们对这10000个单词进行one-hot编码,得到的每个单词都是一个10000维的向量,向量每个维度的值只有0或者1,假如单词ants在词汇表中的出现位置为第3个,那么ants的向量就是一个第三维度取值为1,其他维都为0的10000维的向量(ants = [0,0,1,0,…,0])。
对于上述的句子,可以构建一个大小为5的词汇表(忽略大小写和标点符号):(“the”, “dog”, “barked”, “at”, “mailman”),我们对这个词汇表的单词进行编号0-4。那么”dog“就可以被表示为一个5维向量[0, 1, 0, 0, 0]。
模型的输入如果为一个10000维的向量,那么输出也是一个10000维度(词汇表的大小)的向量,它包含了10000个概率,每一个概率代表着当前词是输入样本中output word的概率大小。
word2vec模型其实就是一个简单的神经网络结构:
在这里插入图片描述

隐层没有使用任何激活函数,但是输出层使用了sotfmax。
编码后只有一个位置为1,其余维度都是0,也就是说得到一个相当稀疏的向量,如果我们将一个1×10000的向量与10000×300的矩阵相乘,耗费的计算资源是相当大的,为了高效计算,模型只会选择矩阵中对应向量维度值为1的索引行进行计算:
在这里插入图片描述

5.2.1.2 Skip-gram训练

从上一部分可以知道,word2vec模型是一个权重矩阵规模庞大的神经网络。比如说,对于一个有10000个单词的词汇表,如果想嵌入300维的词向量,那么输入-隐藏层权重矩阵以及隐藏层-输出层权重矩阵都会有10000×300 = 300W个权重,在这样庞大的神经网络中进行梯度下降自然会相当缓慢。此外,还需要大量的训练数据来调整这些权重并且避免过拟合,百万数量级的权重矩阵和亿万数量级的训练样本意味着训练这个模型将会是个灾难。
解决方案:
1.将常见的单词组合(word pairs)或者词组作为单个“words”来处理。
2.对高频词单词进行抽样来减少训练样本的个数。
3.对优化目标采样“negative sampling”方法,让训练样本的训练只更新一小部分的模型权重,从而降低计算负担。
(1)Word pairs and “phase”
一些词组的含义和拆开的后每个单词具有完全不同的意义。比如“Boston Globe”是一个报刊的名字,而单独的“Boston”和“Globe”却体现不出这样的含义。因此,只要文章中出现“Boston Globe”,我们就可以把它当做一个单独的词来生成词向量,而不是把它拆开。同样的例子还有“New York”,“United Stated”。
在Google发布的模型中,本身的训练样本有来自Google News数据集中的1000亿的单词,但是除去单个单词,单词组合也有300万之多。
(2)对高频词抽样
在上一部分中,对于原始文本为“The quick brown fox jumps over the lazy dog”。如果使用窗口大小为2,那么可以得到下图中的训练样本:
在这里插入图片描述
但是该句含有“the”这样常用的高频词汇,这样的处理方式存在以下两个问题:
1.当我们得到成对的单词训练样本时,(“fox”,“the”)这样的训练样本无法提供关于“fox”更多的语义信息,因为“the”在每个单词的上下文中几乎都会出现。
2.由于在文本中“the”这样的常用词出现概率很大,也就是会出现大量的(“the”,…)这样的训练样本,但是学习“the”这个词向量并不需要这么多的训练样本。
word2vec通过“抽样”模式来解决这种高频词问题:对于训练样本中遇到的每一个单词,都存在一定的概率会被输出,这个删除的概率与单词的频率相关。
定义x是一个单词,Z(x)是x这个单词在所有语料中出现的频次。比如单词“peanut”在10亿规模大小的语料中出现了1000次,那么Z(peanut) = 1000 / 10亿 = 1e-6。
P(x)则代表保留某个单词的概率:
在这里插入图片描述
在这里插入图片描述
x轴代表单词在语料中出现的频率,y轴代表某个单词被保留的概率。
(3)negative sampling
训练一个神经网络意味着输入训练样本并并不断调整神经元的权重,从而不断提高对目标预测的准确度。每当神经网络进行一个训练样本的训练,就会调整一次权重。
正如上面所讨论的,词典的大小决定了Skip-gram神经网络的权重矩阵的规模。如果权重需要通过数以亿计的训练样本来进行调整,这是非常消耗计算资源的,并且实际训练起来会非常慢。
负采样(negative sampling)可以解决这个问题,它是用来提高训练速度并且改善词向量质量的一种方法。不同于原本每个训练样本都需要更新权重,负采样每次让训练样本仅仅更新一小部分的权重,这样就会降低梯度下降过程中的计算量。
使用训练样本(“fox”,“quick”)来训练神经网络时,“fox”和“quick”都需要进行one-hot编码,。如果词典大小为10000,那么在输出层,对应“quick”的神经元结点输出为1,其余的9999个输出为0,这9999个神经元结点称为“negative word”。
负采样时,随机选择一小部分的negative word(比如说5个)来更新对应的权重。当然也会对positive word进行权重更新(在这个例子中positive word就是:quick)。
在论文中,作者指出指出对于小规模数据集,选择5-20个negative words会比较好,对于大规模数据集可以仅选择2-5个negative words。
回忆一下我们的隐层-输出层拥有300 x 10000的权重矩阵。如果使用了负采样的方法我们仅仅去更新我们的positive word-“quick”的和我们选择的其他5个negative words的结点对应的权重,共计6个输出神经元,相当于每次只更新300×6=1800个权重。对于3百万的权重来说,相当于只计算了0.06%的权重,这样计算效率就大幅度提高。
选择“negative word”的方式是“一元模型分布(unigram distribution)”,出现频次越高的单词越容易被选作negative words。
每个单词被选作negative words的概率计算公式:
在这里插入图片描述
f为单词w_i出现的频次,开3/4的根号基于经验得出。

5.2.1.3 Hierarchical Softmax

(1)霍夫曼树
输入:权值为(w1,w2,…,wn)的n个节点。
输出:对应的霍夫曼树。
建立霍夫曼树的步骤:
1.将(w1,w2,…,wn)看做是有n颗树的森林,每个树仅有一个节点;
2.在森林中选取根节点权值最小的两棵树进行合并,得到一颗新树,这两棵树分别作为新树的左右子树。新树的根节点权值为左右子树的根节点权值之和;
3.在森林中删除根节点权值最小的两棵树,把新树加入森林;
4.重复步骤2,3直到森林只有一棵树为止。
举例说明:有(a,b,c,d,e,f)6个节点,节点对应的权值分布为(16,4,8,6,20,3)。
首先将权值最小的b和f合并,得到新树根节点权值为7,删除b,f的权值,加入新树,此时森林为5棵树,权值分别为(16,8,6,20,7)。
然后将权值最小的6,7合并,得到新树根节点权值为13…以此类推,最终获得下面的霍夫曼树。
在这里插入图片描述
得到霍夫曼树后,可以对叶子结点进行霍夫曼编码。因为权重高的叶子结点越靠近根节点,而权重低的叶子结点会远离根节点,所以高权重节点编码值较短,而低权重编码值较长。这样就保证了树的带权路径最短,也符合我们的信息论——希望越常用的词拥有更短的编码。一般约定左子树编码为0,右子树编码为1。
在word2vec中,约定编码方式为左子树编码为1,右子树编码为0,同时左子树的权重不小于右子树的权重。
(2)Hierarchical Softmax过程
为了避免计算所有词的softmax概率,word2vec采用了霍夫曼树来代替从隐藏层到输出softmax层的映射。
霍夫曼树的建立:
1.根据标签(label)和频率建立霍夫曼树(label出现的频率越高,霍夫曼树的路径越短);
2.霍夫曼树中每一个叶子结点代表一个label。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
此时的theta为待定系数。
在这里插入图片描述
使用gensim训练word2vec:

from gensim.models.word2vec import Word2Vec
model = Word2Vec(sentences, workers=num_workers, size=num_features)
5.2.2 TextCNN

TextCNN利用CNN(卷积神经网络)进行文本特征提取,不同大小的卷积核分别抽取n-gram特征,卷积计算出的特征图经过MaxPooling保留最大的特征值,然后拼接成一个向量作为文本的表示。
基于TextCNN原始论文的设定,分别采用100个大小为2,3,4的卷积核,最后得到的文本向量大小为100*3=300维。
在这里插入图片描述
详细过程原理图:
在这里插入图片描述
Embedding:第一层是图中最左边的7乘5的句子矩阵,每行是词向量,维度=5,这个可以类比为图像中的原始像素点。
Convolution:然后经过 kernel_sizes=(2,3,4) 的一维卷积层,每个kernel_size 有两个输出 channel。
MaxPolling:第三层是一个1-max pooling层,这样不同长度句子经过pooling层之后都能变成定长的表示。
FullConnection and Softmax:最后接一层全连接的 softmax 层,输出每个类别的概率。
通道(Channels):
图像中可以利用 (R, G, B) 作为不同channel;
文本的输入的channel通常是不同方式的embedding方式(比如 word2vec或Glove),实践中也有利用静态词向量和fine-tunning词向量作为不同channel的做法。
一维卷积(conv-1d):
图像是二维数据;
文本是一维数据,因此在TextCNN卷积用的是一维卷积(在word-level上是一维卷积;虽然文本经过词向量表达后是二维数据,但是在embedding-level上的二维卷积没有意义)。一维卷积带来的问题是需要通过设计不同 kernel_size 的 filter 获取不同宽度的视野。

5.2.3 TextRNN

TextRNN利用RNN(循环神经网络)进行文本特征提取,由于文本是一种序列,而LSTM天然适合建模序列数据。TextRNN将句子中每个单词的词向量依次输入到双向双层LSTM,分别将两个方向最后一个有效的隐藏层拼接成一个向量作为文本的表示。
在这里插入图片描述

5.3 基于TextCNN、TextRNN的文本表示
5.3.1 TextCNN
#TextCNN
#1.模型搭建
self.filter_sizes = [2, 3, 4] # n-gram window
self.out_channel = 100
self.convs = nn.ModuleList([nn.Conv2d(1, self.out_channel, (filter_size, input_size), bias=True)
for filter_size in self.filter_sizes])

#2.前向传播
pooled_outputs = []
for i in range(len(self.filter_sizes)):
    filter_height = sent_len - self.filter_sizes[i] + 1
    conv = self.convs[i](batch_embed)
    hidden = F.relu(conv) # sen_num x out_channel x filter_height x 1
    mp = nn.MaxPool2d((filter_height, 1)) # (filter_height, filter_width)
    # sen_num x out_channel x 1 x 1 -> sen_num x out_channel
    pooled = mp(hidden).reshape(sen_num, self.out_channel)
    pooled_outputs.append(pooled)
5.3.2 TextRNN
#TextRNN
#1.模型搭建
input_size = config.word_dims
self.word_lstm = LSTM(
    input_size=input_size,
    hidden_size=config.word_hidden_size,
    num_layers=config.word_num_layers,
    batch_first=True,
    bidirectional=True,
    dropout_in=config.dropout_input,
    dropout_out=config.dropout_hidden,
)

#2.前向传播
hiddens, _ = self.word_lstm(batch_embed, batch_masks) # sent_len x sen_num x hidden*2
hiddens.transpose_(1, 0) # sen_num x sent_len x hidden*2

if self.training:
    hiddens = drop_sequence_sharedmask(hiddens, self.dropout_mlp)
5.4 使用HAN用于文本分类

Hierarchical Attention Network for Document Classification(HAN)基于层级注意力,在词和句子级别分别编码并基于注意力获得文档的表示,也就是说词级别和句子级别使模型给与篇章中重要性不同的句子和词以不同的注意力,然后经过softmax进行分类。其中word encoder的作用是获得句子的表示,可以替换为上节提到的TextCNN和TextRNN,也可以替换为下节的BERT。
在这里插入图片描述
在注意力机制中,首先会初始化一个向量,然后将其与每一个词或者每一个句子进行点积,然后通过一个softmax,以一个概率的形式表达每个词或句子不同的注意力。

5.5 小结

本章介绍了word2vec模型学习词向量的方法,以及TextCNN、TextRNN的原理和训练,最后介绍了用于长文档分类的HAN。

5.6 作业

1.尝试通过word2vec训练词向量;
2.尝试使用TextCNN、TextRNN完成文本分类;
3.尝试使用HAN完成文本分类。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值