textcnn文本词向量_文本分类模型之TextCNN

本文详细介绍了TextCNN模型在文本分类中的应用,强调其利用不同卷积核尺寸提取N-gram信息,并通过最大池化突出关键特征。预训练词嵌入与卷积、池化层结合,有效捕捉文本特征。讨论了TextCNN的优缺点,如信息丢失问题,并提出了可能的改进策略。
摘要由CSDN通过智能技术生成

5ae13dcd054a80a9285cd27b3c74549c.png
六年的大学生涯结束了,目前在搜索推荐岗位上继续进阶,近期正好在做类目预测多标签分类的项目,因此把相关的模型记录总结一下,便于后续查阅总结。

一、理论篇:
在我们的场景中,文本数据量比较大,因此直接采用深度学习模型来预测文本类目的多标签,而TextCNN向来以速度快,准确率高著称。TextCNN的核心思想是抓取文本的局部特征:通过不同的卷积核尺寸(确切的说是卷积核高度)来提取文本的N-gram信息,然后通过最大池化操作来突出各个卷积操作提取的最关键信息(颇有一番Attention的味道),拼接后通过全连接层对特征进行组合,最后通过交叉熵损失函数来训练模型。

e7d6f34565a454472e5c9cfd3af7d100.png

bf38719a9b27669c7755e0a7b64e13f3.png

模型的第一层就是Embedding层,预训练的词嵌入可以利用其它语料库得到更多的先验知识,经过模型训练后能够抓住与当前任务最相关的文本特征。在我们的应用场景中,使用预训练的Embedding比随机初始化带来的效果不是特别显著。第二层为卷积层,CV中常见的卷积尺寸通常是正方形,而本文的卷积尺寸与之不同,本文的卷积宽度等于文本Embedding后的维度,保持不变,因为每个词或字相当于一个最小的单元,不可进一步分割。而卷积核的高度可以自定义,在向下滑动的过程中,通过定义不同的窗口来提取不同的特征向量,有点类似于N-gram过程。这样不同的kernel可以获取不同范围内词的关系,获得的是纵向的差异信息,也就是在一个句子中不同范围的词出现会带来什么信息。比如可以使用3,4,5个词数分别作为卷积核的大小),每个卷积尺寸下又有多个相同的卷积核(原因是卷积神经网络学习的是卷积核中的参数,每个filter都有自己的关注点,它们可以从同一个窗口学习相互之间互补的特征,这样多个卷积核就能学习到不同的信息,比如可以设置size为3的filter有4个卷积核)。

第三层是最大池化层,即为从每个滑动窗口产生的特征向量中筛选出一个最大的特征,然后将这些特征拼接起来构成向量表示。也可以选用K-Max池化(选出每个特征向量中最大的K个特征),或者平均池化(将特征向量中的每一维取平均)等,达到的效果都是将不同长度的句子通过池化得到一个定长的向量表示。在短文本分类场景中,每条文本中都会有一些对分类无用的信息,而最大池化可以突出最重要的关键词以帮助模型更容易找到对应的类目。

接下来的几层就跟具体的任务相关了,一般都会拼接特征,在通过全连接层自由组合提取出来的特征实现分类。在损失函数上,二分类和多标签分类可以采用基于Sigmoid函数的交叉熵损失函数binary_crossentropy多分类任务可以采用基于Softmax的多类别交叉熵损失函数(categorical_crossentropy)。

二、代码部分:

def textcnn(hyper_parameters):
    input = Input(shape=(hyper_parameters.max_len,))
    if hyper_parameters.embedding_matrix is None:
        embedding = Embedding(input_dim=hyper_parameters.vocab + 1,
                              output_dim=hyper_parameters.emd_dim,
                              input_length=hyper_parameters.MAX_LEN,
                              trainable=True)(input)
    else:  # 使用预训练矩阵初始化Embedding
        embedding = Embedding(input_dim=hyper_parameters.vocab + 1,
                              output_dim=hyper_parameters.emd_dim,
                              weights=[hyper_parameters.embedding_matrix],
                              input_length=hyper_parameters.MAX_LEN,
                              trainable=False)(input)

    convs = []
    for kernel_size in hyper_parameters.kernel_size:
        conv = Conv1D(hyper_parameters.conv_code, kernel_size,
                      activation=hyper_parameters.relu)(embedding)
        pool = MaxPooling1D()(conv)
        convs.append(pool)
    concat = Concatenate()(convs)
    flattern = Flatten()(concat)
    dropout = Dropout(hyper_parameters.dropout)(flattern)
    output = Dense(hyper_parameters.classes, activation=hyper_parameters.sigmoid)(dropout)
    model = Model(input, output)
    model.compile(loss='binary_crossentropy',
                  optimizer='adam',
                  metrics=['accuracy'])

    return model

在Embedding部分,如果有条件可以使用自己预训练的文本信息来初始化Embedding矩阵,效果可能会比随机初始化Embedding提升一点。

三、几点思考:

1.TextCNN能用于文本分类的主要原因是什么?

除了预训练文本外,TextCNN通过利用不同的卷积核尺寸并行提取文本的信息(类似N-gram),并通过最大池化来突出最重要的关键词来实现分类。

2.TextCNN的缺点:

2.1. TextCNN的卷积和池化操作会丢失文本序列中的词汇顺序和位置信息等内容,但也可利用这一点来增强文本,例如白色旅游鞋,可以添加旅游鞋白色数据等,分词后白色和旅游鞋位置就可以互换来丰富语料 。

2.2. 在长文本使用TextCNN效果可能没有在短文本中效果好(具体还需要实践确认),原因同上,因此可以尝试使用Top k池化替代最大池化提取更多的文本信息。

https://arxiv.org/pdf/1408.5882.pdf​arxiv.org 小占同学:深入TextCNN(一)详述CNN及TextCNN原理​zhuanlan.zhihu.com
75d437d15eae7774b0f14f171921468e.png
以下是一个简单的 TextCNN 文本分类模型的代码示例: ```python import tensorflow as tf from tensorflow.keras.layers import Input, Embedding, Conv1D, GlobalMaxPooling1D, Dense from tensorflow.keras.models import Model class TextCNN: def __init__(self, max_seq_len, vocab_size, embedding_dim, num_filters, filter_sizes, num_classes): self.max_seq_len = max_seq_len self.vocab_size = vocab_size self.embedding_dim = embedding_dim self.num_filters = num_filters self.filter_sizes = filter_sizes self.num_classes = num_classes def build_model(self): inputs = Input(shape=(self.max_seq_len,)) embedding = Embedding(input_dim=self.vocab_size, output_dim=self.embedding_dim, input_length=self.max_seq_len)(inputs) conv_outputs = [] for filter_size in self.filter_sizes: conv = Conv1D(filters=self.num_filters, kernel_size=filter_size, activation='relu')(embedding) pool = GlobalMaxPooling1D()(conv) conv_outputs.append(pool) concat = tf.keras.layers.concatenate(conv_outputs, axis=1) outputs = Dense(units=self.num_classes, activation='softmax')(concat) model = Model(inputs=inputs, outputs=outputs) return model ``` 在上面的代码中,我们定义了一个名为 `TextCNN` 的类,它接收参数 `max_seq_len`、`vocab_size`、`embedding_dim`、`num_filters`、`filter_sizes` 和 `num_classes`。这些参数分别指定了输入序列的最大长度、词汇表大小、词向量维度、卷积核数量、卷积核大小列表和类别数。 我们在 `build_model` 方法中建立了模型。首先,我们使用 Keras 的 `Input` 层定义了输入张量。接着,我们使用 `Embedding` 层将每个单词映射为一个词向量,并且使用 `Conv1D` 层对词向量进行卷积操作。我们使用多个不同大小的卷积核来捕捉不同长度的 n-gram 特征。然后,我们使用 `GlobalMaxPooling1D` 层对每个卷积层的输出进行最大池化操作。最后,我们将所有卷积层的输出连接起来,并通过一个全连接层输出分类结果。 使用 TextCNN 模型进行文本分类时,需要将文本序列转换为数字序列,并将它们填充到相同的长度。可以使用 Keras 的 `Tokenizer` 类将文本序列转换为数字序列,并使用 Keras 的 `pad_sequences` 函数将它们填充到相同的长度。然后,使用 `model.fit` 函数训练模型即可。 注:以上代码仅为示例,实际应用中可能需要根据具体情况进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值