• Python实现卷积神经网络的Text-CNN文本分类


    利用卷积神经网络的Text-CNN 文本分类

    简介

    TextCNN 是利用卷积神经网络对文本进行分类的算法,由 Yoon Kim 在 “Convolutional Neural Networks for Sentence Classification” 一文 (见参考[1]) 中提出. 是 2014 年的算法.

    图 1-1 参考[1] 中的论文配图

    在这里插入图片描述

    以下是阅读 TextCNN 后的理解

    步骤:

    1.先对句子进行分词,一般使用“jieba”库进行分词。

    2.在原文中,用了 6 个卷积核对原词向量矩阵进行卷积。

    卷积具有局部特征提取的功能, 所以可用 CNN 来提取句子中类似 n-gram 的关键信息.

    个卷积核大小:2 个 46、2 个 36 和 2 个 2*6,如上图所示;然后进行池化,对相同卷积核产生的特征图进行连接;再进行 softmax 输出 2 个类别。

    1).这里对 no-static 进行阐述,采用不固定的词向量,这样更加贴近自然生活中,不同长度的句子代表的意思不同,所以在我看来采用 no-static 比 static 更加的贴近语义。

    2).对一个词向量进行卷积和池化后,产生的特征只有一个 1*1 的向量,所以说不管采用 static 和 no-static 得到的特征都只有一个,对本生网络没什么影响。

    为什么采用不同大小的卷积核,不同的感受视野,卷积核的宽取词汇表的纬度,有利于语义的提取。

    体现在代码中

    tf.flags.DEFINE_string("filter_sizes", "3,4,5", "Comma-separated filter sizes (default: '3,4,5')")
    filter_sizes=list(map(int, FLAGS.filter_sizes.split(","))),
    
    • 1
    • 2

    是一个 list

    5.研究证明为什么要采用字,而不采用字,原因是词粒度准确率 > 字粒度准确率。存在两种模型,一种是词袋模型,第二种是词向量模型。下面对词向量模型来进行讲述。

    词向量模型:

    一般开始为高纬度,高稀疏向量,利用嵌入层对其进行降维,增加稠密性。

    使用词向量进行文本分类的步骤为:

    ①.先使用分词工具提取词汇表。

    ②.将要分类的内容转换为词向量。

    a.分词

    b.将每个词转换为 word2vec 向量。

    c.按顺序组合 word2vec,那么久组合成了一个词向量。

    d.降维,由原来的高纬度降维为我们设定的低纬度。

    e.卷积、池化和连接,然后进行分类。

    6.嵌入层

    通过一个隐藏层将 word2vec 高纬度的词向量转换到低纬度空间的词向量,这个层的本质是特征提取,提取高纬度词向量的特征到低纬度,这样可以使语义相近的词映射到低维空间以后,欧式距离更近。

    参数与超参数

    sequence_length
    Q: 对于 CNN, 输入与输出都是固定的,可每个句子长短不一, 怎么处理?
    A: 需要做定长处理, 比如定为 n, 超过的截断, 不足的补 0. 注意补充的 0 对后面的结果没有影响,因为后面的 max-pooling 只会输出最大值,补零的项会被过滤掉.

    num_classes
    多分类, 分为几类.

    vocabulary_size
    语料库的词典大小, 记为 |D|.

    embedding_size
    将词向量的维度, 由原始的 |D| 降维到 embedding_size.

    filter_size_arr
    多个不同 size 的 filter.

    Embedding Layer

    首先用 VocabularyProcessor 将 每一句话 转为 词 id 向量

    在这里插入图片描述

    然后定义了词嵌入矩阵,将输入的词 id 转化成词向量,这里的词嵌入矩阵是可以训练的,我们希望得到的是训练完以后,输入经过 W 矩阵转换得到的固定维度的隐藏层,及词向量矩阵通过一个词嵌入矩阵, 将 编码的词投影到一个低维空间中.

    本质上是特征提取器,在指定维度中编码语义特征. 这样, 语义相近的词, 它们的欧氏距离或余弦距离也比较近.

    self.embedded_chars=tf.nn.embedding_lookup(W,self.input_x)

    在这里插入图片描述

    如果先用 word2vec_helpers 处理完,然后代用 textCNN 的情况下,这里的 embeding 层是不是就不要了?

    原始的在没有预先使用 word2vec 的情况下:在网络层有 embeding 层

    在这里插入图片描述

    而预先使用了 word2vec_helpers 处理完之后,

    在这里插入图片描述

    Convolution Layer
    
    • 1

    为不同尺寸的 filter 都建立一个卷积层. 所以会有多个 feature map.
    图像是像素点组成的二维数据, 有时还会有 RGB 三个通道, 所以它们的卷积核至少是二维的.
    从某种程度上讲, word is to text as pixel is to image, 所以这个卷积核的 size 与 stride 会有些不一样.

    xixi
    xi∈Rkxi∈Rk, 一个长度为 n 的句子中, 第 i 个词语的词向量, 维度为 k.

    xi:jxi:j
    xi:j=xi⊕xi+1⊕…⊕xjxi:j=xi⊕xi+1⊕…⊕xj
    表示在长度为 n 的句子中, 第 [i,j] 个词语的词向量的拼接.

    hh
    卷积核所围窗口中单词的个数, 卷积核的尺寸其实就是 hkhk.

    ww
    w∈Rhkw∈Rhk, 卷积核的权重矩阵.

    cici
    ci=f(wxi:i+h1+b)ci=f(wxi:i+h1+b), 卷积核在单词 i 位置上的输出.b∈RKb∈RK, 是 bias.ff 是双曲正切之类的激活函数.

    c=[c1,c2,…,cnh+1]c=[c1,c2,…,cnh+1]
    filter 在句中单词上进行所有可能的滑动, 得到的 featuremapfeaturemap.

    Max-Pooling Layer
    
    • 1

    max-pooling 只会输出最大值, 对输入中的补 0 做过滤.

    SoftMax 分类 Layer

    最后接一层全连接的 softmax 层,输出每个类别的概率。

    • 小的变种

    • 在 word representation 处理上会有一些变种.

    • CNN-rand
      设计好 embedding_size 这个 Hyperparameter 后, 对不同单词的向量作随机初始化, 后续 BP 的时候作调整.

    • static
      拿 pre-trained vectors from word2vec, FastText or GloVe 直接用, 训练过程中不再调整词向量. 这也算是迁移学习的一种思想.

    • non-static

    • pre-trained vectors + fine tuning , 即拿 word2vec 训练好的词向量初始化, 训练过程中再对它们微调.

    • multiple channel
      类比于图像中的 RGB 通道, 这里也可以用 static 与 non-static 搭两个通道来搞.

    一些结果表明,max-pooling 总是优于 average-pooling ,理想的 filter sizes 是重要的,但具体任务具体考量,而用不用正则化似乎在 NLP 任务中并没有很大的不同。

    Text CNN 的 tf 实现
    图 8-1 Text CNN 网络中的卷积与池化 结构

    需要注意的细节有。
    tf.nn.embedding_lookup()

    与 LeNet 作比较

    在这里插入图片描述

    figure LeNet-5 网络结构

    # LeNet5
    conv1_weights = tf.get_variable(
                        "weight",
                        [CONV1_SIZE, CONV1_SIZE, NUM_CHANNELS, CONV1_DEEP],
                        initializer=tf.truncated_normal_initializer(stddev=0.1))
                    tf.nn.conv2d(
                        input_tensor,
                        conv1_weights,
                        strides=[1, 1, 1, 1],
                        padding='SAME')
                    tf.nn.max_pool(
                        relu1,
                        ksize = [1,POOL1_SIZE,POOL1_SIZE,1],
                        strides=[1,POOL1_SIZE,POOL1_SIZE,1],
                        padding="SAME")
    # TextCNN
                    conv1_weights = tf.get_variable(
                                        "weight",
                                        [FILTER_SIZE, EMBEDDING_SIZE, 1, NUM_FILTERS],
                                        initializer=tf.truncated_normal_initializer(stddev=0.1))
                                    tf.nn.conv2d(
                                        self.embedded_chars_expanded,
                                        conv1_weights,
                                        strides=[1, 1, 1, 1],
                                        padding="VALID")
                                    tf.nn.max_pool(
                                        h,
                                        ksize=[1, SEQUENCE_LENGTH - FILTER_SIZE + 1, 1, 1],
                                        strides=[1, 1, 1, 1],
                                        padding='VALID')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    先来比较卷积

    LeNet 的 filter 是正方形的, 且每一层都只用了同一种尺寸的卷积核. Text-CNN 中, filter 是矩形, 矩形的长度有好几种, 一般取 (2,3,4), 而矩形的宽度是定长的, 同 word 的 embedding_size 相同. 每种尺寸都配有 NUM_FILTERS 个数目, 类比于 LeNet 中的 output_depth,所以得到的 feature_map 是长条状, 宽度为 1.
    因为是卷积, 所以 stride 每个维度都是 1.

    再说池化层.

    池化处理, 也叫下采样. 这里依旧可以对比 LeNet 网络.
    LeNet 的 kernel 是正方形, 一般也是 2*2 等, 所以会把卷积后的 feature_map 尺寸缩小一半.
    Text-CNN 的 kernel 依旧是长方形, 将整个 feature_map 映射到一个点上. 一步到位, 只有一个池化层.

    全连接层

    都是多分类, 这一步的处理比较类似. 将池化后的矩阵 reshape 为二维, 用 tf.nn.sparse_softmax_cross_entropy_with_logits() 计算损失.

    TextCNN 论文中的网络结构

    windows size 分别取 (3,4,5), 每个尺寸都会有 100 个 filter.

    Hyperparameters and Training
    For all datasets we use:
    rectified linear units, filter
    windows (h) of 3, 4, 5 with 100 feature maps each,
            dropout rate (p) of 0.5, l2 constraint (s) of 3, and
            mini-batch size of 50. These values were chosen
            via a grid search on the SST-2 dev set.
            1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 相关阅读:
    我,在日本开密室逃脱,钱还没赚,人进“橘子”了……
    质量管理 | QC、QA、QM,去QA化与降本增效
    qt6 多媒体开发代码分析(三、音频采集)
    LeetCode每日一题:1123. 最深叶节点的最近公共祖先(2023.9.6 C++)
    gradle迁移到gradle.kts(复制可用)
    部分准备金银行已经过时
    Java对象内存空间大小计算
    2022杭电多校10(总结+补题)
    网络编程(五)
    【基于C的排序算法】插入排序之直接插入排序
  • 原文地址:https://blog.csdn.net/newlw/article/details/126069948