赞
踩
了解TextCNN,看这一篇就够了。
我们之前提到CNN时,通常会认为属于CV领域,是用于解决计算机视觉方向问题的模型,但是在2014年,Yoon Kim针对CNN的输入层做了一些变形,提出了文本分类模型TextCNN。与传统图像的CNN网络相比,TextCNN 在网络结构上没有任何变化(甚至更加简单了),从图1可以看出TextCNN 其实只有一层卷积,一层max-pooling,最后将输出外接softmax来n分类。
与图像当中CNN的网络相比,textCNN 最大的不同便是在输入数据的不同:图像是二维数据,图像的卷积核是从左到右,从上到下进行滑动来进行特征抽取。自然语言是一维数据,虽然经过word embedding生成了二维向量,但是对词向量做从左到右滑动来进行卷积没有意义。比如 “今天” 对应的向量[0, 0, 0, 0, 1],按窗口大小为 1* 2 从左到右滑动得到[0,0],[0,0],[0,0],[0, 1]这四个向量,对应的都是"今天"这个词汇,这种滑动没有帮助。
TextCNN的成功,不是网络结构的成功,而是通过引入已经训练好的词向量来在多个数据集上达到了超越benchmark的表现,进一步证明了构造更好的embedding,是提升nlp各项任务的关键能力,后面会专门讲解目前流行的embedding算法。
{"的": 1, "是": 2, ……}
,词向量文件的作用是,在对输入文本进行切词后,需要获取每个词的向量表征,则先通过词向量文件获取词对应的索引,再通过索引在词向量矩阵中获取词的向量表征。这时再理解词向量矩阵,就简单多了,词向量矩阵的作用,是用于获取输入文本的向量表征,说的通俗点,就是用向量将文本表现出来,以用于模型中的数值计算(例如后续的卷积、池化等操作)。词向量矩阵的每一行,是某个词对应的向量,也就是说,我们通过词向量文件中的索引,可以在词向量矩阵中获取词的向量表征。再简单介绍下词向量矩阵及词向量文件生成的两种方式。
self.embedding = torch.nn.Embedding(vocab_size, embed_dim)
命令直接随机生成个初始化的词向量矩阵,此时的向量值符合正态分布N(0,1),这里的vocab_size
是指词向量矩阵能表征的词的个数,这个数值即是词向量文件中词的数量加1(加1的原因是,如果某个词在词向量文件中不存在,则获取不到索引,也就无法在词向量矩阵中获取对应的向量,这时我们默认这个词的索引为0,即将词向量的第一行作为这个词的向量表征。使用预训练的词向量文件时,这个方法同样适用),embed_dim
是指表征每个词时,向量的维度(可自定义,如256)。对于随机初始化词向量矩阵的方式,词向量文件的生成方式一般是将当前所有的文本数据(包括训练数据、验证数据、测试数据)进行切词,再对所有词进行聚合统计,保留词的数量大于某个阈值(比如3)的词,并进行索引编号(编号从1开始,0作为上面提到的不在词向量文件中的其他词的索引),进而生成词向量文件。顺便提一句,词向量矩阵的初始化的方式也有很多种,比如Xavier、Kaiming初始化方法。gensim
工具包进行加载,具体命令是wvmodel = gensim.models.KeyedVectors.load_word2vec_format(word2vec_file, binary=False, encoding='utf-8', unicode_errors='ignore')
,加载后,可通过wvmodel.key_to_index
获取词向量文件(要对词向量文件中的词索引进行重新编号,原索引从0开始,调整为从1开始,0作为不在词向量文件中的词的索引),通过wvmodel.get_vector("xxx")
获取词向量文件中每个词对应的向量,将词向量文件中所有词对应的向量聚合在一起后(聚合的方式是,每个词的向量表征,按照词的索引,填充在词向量矩阵对应的位置),生成预训练词向量矩阵weight
,再通过self.embedding = torch.nn.Embedding.from_pretrained(weight, freeze=False)
完成词向量矩阵的初始化,参数freeze
的作用,是指明训练时是否更新词向量矩阵的权重值,True
为不更新,默认为True
,等同于self.embedding.weight.requires_grad = False
)。wvmodel.get_vector("xxx")
,获取预训练词向量矩阵weight
,最后进行后续的词向量矩阵初始化过程。这样操作之后,由于词向量文件中词的数量减少,词向量矩阵的行数减少,内存占用会随之减少很多。另外,生成词向量的预训练方法还有很多,参见【通俗易懂的词向量】。池化层
池化层也很容易理解,我们同样介绍一些细节。池化层的输入是卷积层的输出,卷积层输出的通道数m等于卷积核的数量,每个通道都是一列。池化的操作就是对这些输出通道进行池化计算,目前存在两种计算方式,平均池化和最大值池化。
torch.nn.functional.avg_pool1d
命令即可实现。torch.nn.functional.max_pool1d
命令即可实现。不管是平均池化还是最大池化,最终都会生成m个数值,将这m个数值拼接后,进入最后的全连接层。
torch.nn.Linear(input_num, num_class)
即可定义全连接层,其中input_num
是池化层输出的维数,即m,num_class
是分类任务的类别数量。简简单单!!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。