中文短文本分类实例三-TextCNN(Convolutional Neural Networks for Sentence Classification)

一.概述

        TextCNN(Convolutional Neural Networks for Sentence Classification) by Yoon Kim作为CNN在NLP文本分类任务上的经典之作,诞生于深度学习和卷积神经网络成为图像任务明星的2012年之后的2014年,让人不得不感慨时势的神奇。

        TextCNN提出的目的在于,希望将CNN在图像领域中所取得的成就复制于自然语言处理NLP任务中,以后来人的眼光来看,这无疑是比较成功的,虽然现在仍然很多难点和遗憾。

        在TextCNN之前,支持向量机SVM一家独大,模型称霸图像、文本等各种领域,直至2012年图像领域的AlexNet横空出世,撕开了笼罩在人工智能的神秘面纱,深度学习从此开始了它那辉煌的时代。2014年,TextCNN在文本领域的一声狂啸,发出了对文本分类SVM老大位置的挑战,虽然当时TextCNN模型效果没有完全超过SVM,但CNN的热潮,把它推得老高老高,成为NLP文本分类任务的经典模型。

        TextCNN是一种采用卷积神经网络(CNN)提取文本n-gram特征,最大池化,全连接然后进行分类的一种新型模型。

        为什么TextCNN强于传统的分类模型呢?

        图像答约:人工神经网络,更具体地说,是深度网络,因为深度网络能够学习更复杂的特征。

        文本答约:  我只有四层(输入、卷积、池化、输出),不算深度模型吧!

        回答:         1.  可以算是了,因为NLP任务模型神经网络本来就不深。

                         2.  另一种说法 ,全局优化大于局部优化、分层优化。具体说来,传统机器学习的做法一般是构建选择文本特征、然后分类;而深度学习的做法是不需要手动构建特征,神经网络会自己构建、选择特征,然后分类,二者是端到端的训练,可以达到一种联动,全局优化,而不是像传统机器学习那样,构建好特征,然后训练的二步模式,局部最优。               

 模型github:  https://github.com/yongzhuo/Keras-TextClassification/blob/master/keras_textclassification/m02_TextCNN/graph.py

        只实现了CNN-rand,随机初始化词向量,训练中调整变化。

                

二.TextCNN网络

        2.1 首先放Yoon Kim的TextCNN开山之作震楼:

                                       

        从上图可以发现,TextCNN由输入层,卷积层,最大池化层,全连接层等四层构成; 

        1. 输入层: 一般由是onehot处理后的非负整数构成的向量,这里使用word2vec预训练好的词向量构建(或者随机初始化)。一般都会定义最大文本长度(25啊,50啊什么的),padding实现;

        2. 卷积层: 上图中是双通道2*3=6个卷积核,卷积核大小为 卷积大小(n-gram) * 词向量维度(embed) = 2 * 300 = 600,一般卷积大小设2,3,4,5等。论文中实现的是a. CNN-rand(随机初始化词向量);b.CNN-static(word2vec预训练词向量,训练过程中不变);c. CNN-no-static(word2vec预训练词向量,训练过程中微调);d. CNN-multichannel(多个通道,论文中使用的是双通道,即b和c)

           现在一般不直接用词向量,会构建Embedding层嵌入。

        3. 池化层:  池化层工作与卷积层大同小异,不同于卷积层将卷积核中数据相加;池化层的池化核将池化核中数据求平均或者是只保留最大值。论文中采用的是最大池化,然后级联。

        4. 全连接层: 也叫输出层,是池化后级联,再使用图像领域中首先提出的的dropout,防止过拟合(也可加l2正则化b),然后使用激活函数分类输出。

        2.2 然后是Ye Zhang关于TextCNN模型的调参

                                              

        主要是调参,单层CNN调参说明:

        1. 词向量维度: 影响不大,动态预训练词向量>静态预训练词向量>随机初始化,word2vec比glove好一点点,词向量维度是300,用别人预训练好的模型;

        2. 卷积核尺寸: 影响较大, 一般取1-10。论文中有数据集取7最优,也有取3最优的。最后各种实验得出,首先选出单个最优的,然后再加上它们的相邻数实验,比如说3就是【3,4,5】,7就是【7,8,9】;

        3. 卷积核个数: 影响比较大,选择100-600,最好接近600,默认600个卷积核数量;

        4. 激活函数:     tanh>Iden>relu>sigmod

        5. polling池化: 最大池化>平均池化和k-max池化

        6. 防止过拟合: dropout设置0.3-0.5,不要超过0.5;l2正则化效果不明确

        7. 交叉验证

三.TextCNN实例

        1. 代码实现并不难,就一个embedding,conv和pool,超级简单;

         github:https://github.com/yongzhuo/Keras-TextClassification/blob/master/keras_textclassification/m02_TextCNN/graph.py

        2.主体代码

def create_model(self, hyper_parameters):
        """
            构建神经网络
        :param hyper_parameters:json,  hyper parameters of network
        :return: tensor, moedl
        """
        super().create_model(hyper_parameters)
        embedding = self.word_embedding.output
        embedding_reshape = Reshape((self.len_max, self.embed_size, 1))(embedding)
        # 提取n-gram特征和最大池化, 一般不用平均池化
        conv_pools = []
        for filter in self.filters:
            conv = Conv2D(filters = self.kernel_size,
                          kernel_size = (filter, self.embed_size),
                          padding = 'valid',
                          kernel_initializer = 'normal',
                          activation = 'relu',
                          )(embedding_reshape)
            pooled = MaxPool2D(pool_size = (self.len_max - filter + 1, 1),
                               strides = (1, 1),
                               padding = 'valid',
                               )(conv)
            conv_pools.append(pooled)
        # 拼接
        x = Concatenate(axis=1)(conv_pools)
        x = Flatten()(x)
        x = Dropout(self.dropout)(x)
        output = Dense(units=self.label, activation=self.activate_classify)(x)
        self.model = Model(inputs=self.word_embedding.input, outputs=output)
        self.model.summary(120)

希望对你有所帮助!

发布了96 篇原创文章 · 获赞 72 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/rensihui/article/details/91691099
今日推荐