如何用词向量做文本分类(embedding+cnn)

本文介绍如何利用GloVe词向量和卷积神经网络对20Newsgroup数据集进行文本分类,包括数据预处理、词向量加载及模型训练等步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、数据简介

本文使用的数据集是著名的”20 Newsgroup dataset”。该数据集共有20种新闻文本数据,我们将实现对该数据集的文本分类任务。数据集的说明和下载请参考(http://www.cs.cmu.edu/afs/cs.cmu.edu/project/theo-20/www/data/news20.html)。本文使用GloVe词向量。GloVe 是 “Global Vectors for Word Representation”的缩写,一种基于共现矩阵分解的词向量。本文所使用的GloVe词向量是在2014年的英文维基百科上训练的,有400k个不同的词,每个词用100维向量表示。链接(http://nlp.stanford.edu/data/glove.6B.zip) (友情提示,词向量文件大小约为822M)

2、数据预处理

我们首先遍历下语料文件下的所有文件夹,获得不同类别的新闻以及对应的类别标签,代码如下所示

texts = []  # list of text samples
labels_index = {}  # dictionary mapping label name to numeric id
labels = []  # list of label ids
import os
TEXT_DATA_DIR = 'e:/textm/20_newsgroup'
for name in sorted(os.listdir(TEXT_DATA_DIR)):
    path = os.path.join(TEXT_DATA_DIR, name)
    if os.path.isdir(path):
        label_id = len(labels_index)
        labels_index[name] = label_id
        if label_id == 2:
            break
        for fname in sorted(os.listdir(path)):
            if fname.isdigit():
                fpath = os.path.join(path, fname)
                f = open(fpath,'r',encoding='latin-1')
                texts.append(f.read().strip())
                f.close()
                labels.append(label_id)


print('Found %s texts.' % len(texts))
print(texts[0])
print(labels)

之后,我们可以新闻样本转化为神经网络训练所用的张量。所用到的Keras库是keras.preprocessing.text.Tokenizer和keras.preprocessing.sequence.pad_sequences。代码如下所示

######,我们可以新闻样本转化为神经网络训练所用的张量。
# 所用到的Keras库是keras.preprocessing.text.Tokenizer和keras.preprocessing.sequence.pad_sequences。代码如下所示
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences
import numpy as np
tokenizer = Tokenizer()
tokenizer.fit_on_texts(texts)
sequences = tokenizer.texts_to_sequences(texts)

word_index = tokenizer.word_index
print('Found %s unique tokens.' % len(word_index))

data = pad_sequences(sequences)
# from keras.utils import np_utils
# labels = np_utils.to_categorical(np.asarray(labels))
print('Shape of data tensor:', data.shape)



# split the data into a training set and a validation set
indices = np.arange(data.shape[0])
np.random.shuffle(indices)
data = data[indices]
labels_new = []
for i in indices:
    labels_new.append(labels[i])

nb_validation_samples = int(0.8 * data.shape[0])

x_train = data[:-nb_validation_samples]
y_train = labels_new[:-nb_validation_samples]
x_val = data[-nb_validation_samples:]
y_val = labels_new[-nb_validation_samples:]
print(x_train[0])

接下来,我们从GloVe文件中解析出每个词和它所对应的词向量,并用字典的方式存储

###############读取词向量

embeddings_index = {}
f = open(os.path.join('E:\\textm', 'glove.6B.100d.txt'),'r',encoding='utf-8')
for line in f.readlines():
    values = line.split()
    word = values[0]
    coefs = np.asarray(values[1:], dtype='float32')
    embeddings_index[word] = coefs
f.close()

print('Found %s word vectors.' % len(embeddings_index))

此时,我们可以根据得到的字典生成上文所定义的词向量矩阵

#############我们可以根据得到的字典生成上文所定义的词向量矩阵
embedding_matrix = np.zeros((len(word_index) + 1, 100))
for word, i in word_index.items():
    embedding_vector = embeddings_index.get(word)
    if embedding_vector is not None:
        # words not found in embedding index will be all-zeros.
        embedding_matrix[i] = embedding_vector

print(embedding_matrix)
#########我们将这个词向量矩阵加载到Embedding层中,注意,我们设置trainable=False使得这个编码层不可再训练。
from keras.layers import Embedding

embedding_layer = Embedding(len(word_index) + 1,
                            100,
                            weights=[embedding_matrix],
                            input_length=10036,

                            trainable=False)

3、训练模型

用到了三层卷积

from keras.models import *
from keras.layers import *
from keras.applications import *
from keras.preprocessing.image import *
sequence_input = Input(shape=(10036,), dtype='int32')
embedded_sequences = embedding_layer(sequence_input)
x = Conv1D(128, 5, activation='relu')(embedded_sequences)
x = MaxPooling1D(5)(x)
x = Conv1D(128, 5, activation='relu')(x)
x = MaxPooling1D(5)(x)
x = Conv1D(128, 5, activation='relu')(x)
x = MaxPooling1D(35)(x)  # global max pooling
x = Flatten()(x)
x = Dense(128, activation='relu')(x)
preds = Dense(1, activation='sigmoid')(x)

model = Model(sequence_input, preds)
model.compile(loss='binary_crossentropy',
              optimizer='rmsprop',
              metrics=['acc'])

# happy learning!
model.fit(x_train, y_train, validation_data=(x_val, y_val),
          nb_epoch=4, batch_size=128)
model.save('e:/mymodel.h5')

全部代码如下

texts = []  # list of text samples
labels_index = {}  # dictionary mapping label name to numeric id
labels = []  # list of label ids
import os
TEXT_DATA_DIR = 'e:/textm/20_newsgroup'
for name in sorted(os.listdir(TEXT_DATA_DIR)):
    path = os.path.join(TEXT_DATA_DIR, name)
    if os.path.isdir(path):
        label_id = len(labels_index)
        labels_index[name] = label_id
        if label_id == 2:
            break
        for fname in sorted(os.listdir(path)):
            if fname.isdigit():
                fpath = os.path.join(path, fname)
                f = open(fpath,'r',encoding='latin-1')
                texts.append(f.read().strip())
                f.close()
                labels.append(label_id)


print('Found %s texts.' % len(texts))
print(texts[0])
print(labels)

######,我们可以新闻样本转化为神经网络训练所用的张量。
# 所用到的Keras库是keras.preprocessing.text.Tokenizer和keras.preprocessing.sequence.pad_sequences。代码如下所示
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences
import numpy as np
tokenizer = Tokenizer()
tokenizer.fit_on_texts(texts)
sequences = tokenizer.texts_to_sequences(texts)

word_index = tokenizer.word_index
print('Found %s unique tokens.' % len(word_index))

data = pad_sequences(sequences)
# from keras.utils import np_utils
# labels = np_utils.to_categorical(np.asarray(labels))
print('Shape of data tensor:', data.shape)



# split the data into a training set and a validation set
indices = np.arange(data.shape[0])
np.random.shuffle(indices)
data = data[indices]
labels_new = []
for i in indices:
    labels_new.append(labels[i])

nb_validation_samples = int(0.8 * data.shape[0])

x_train = data[:-nb_validation_samples]
y_train = labels_new[:-nb_validation_samples]
x_val = data[-nb_validation_samples:]
y_val = labels_new[-nb_validation_samples:]
print(x_train[0])

###############读取词向量

embeddings_index = {}
f = open(os.path.join('E:\\textm', 'glove.6B.100d.txt'),'r',encoding='utf-8')
for line in f.readlines():
    values = line.split()
    word = values[0]
    coefs = np.asarray(values[1:], dtype='float32')
    embeddings_index[word] = coefs
f.close()

print('Found %s word vectors.' % len(embeddings_index))

#############我们可以根据得到的字典生成上文所定义的词向量矩阵
embedding_matrix = np.zeros((len(word_index) + 1, 100))
for word, i in word_index.items():
    embedding_vector = embeddings_index.get(word)
    if embedding_vector is not None:
        # words not found in embedding index will be all-zeros.
        embedding_matrix[i] = embedding_vector

print(embedding_matrix)
#########我们将这个词向量矩阵加载到Embedding层中,注意,我们设置trainable=False使得这个编码层不可再训练。
from keras.layers import Embedding

embedding_layer = Embedding(len(word_index) + 1,
                            100,
                            weights=[embedding_matrix],
                            input_length=10036,

                            trainable=False)


from keras.models import *
from keras.layers import *
from keras.applications import *
from keras.preprocessing.image import *
sequence_input = Input(shape=(10036,), dtype='int32')
embedded_sequences = embedding_layer(sequence_input)
x = Conv1D(128, 5, activation='relu')(embedded_sequences)
x = MaxPooling1D(5)(x)
x = Conv1D(128, 5, activation='relu')(x)
x = MaxPooling1D(5)(x)
x = Conv1D(128, 5, activation='relu')(x)
x = MaxPooling1D(35)(x)  # global max pooling
x = Flatten()(x)
x = Dense(128, activation='relu')(x)
preds = Dense(1, activation='sigmoid')(x)

model = Model(sequence_input, preds)
model.compile(loss='binary_crossentropy',
              optimizer='rmsprop',
              metrics=['acc'])

# happy learning!
model.fit(x_train, y_train, validation_data=(x_val, y_val),
          nb_epoch=4, batch_size=128)
model.save('e:/mymodel.h5')

4、参考文献

http://keras-cn.readthedocs.io/en/latest/blog/word_embedding/

<think>嗯,用户想了解如何结合DCNN、双向GRU和朴素贝叶斯来构建垃圾邮件分类模型。首先,我需要回忆一下这些模型各自的特点以及如何将它们结合起来。 DCNN主要用于提取局部特征,比如在文本中的n-gram特征。双向GRU可以捕捉文本的上下文信息,因为双向结构能同时考虑过去和未来的信息。而朴素贝叶斯作为传统算法,可能在特征处理或后处理阶段发挥作用。不过,如何将深度学习和概率模型结合呢?常见的方法可能是用深度学习模型提取特征,然后将这些特征输入朴素贝叶斯进行分类,或者进行模型融合,比如加权平均概率。 接下来,我需要考虑模型的结构流程。可能的步骤是:首先用词嵌入层处理文本,然后通过DCNN提取局部特征,再用双向GRU捕捉序列依赖,将两者的输出融合,比如拼接起来。之后可能需要全连接层进行分类。但朴素贝叶斯的位置呢?可能需要将深度模型输出的特征作为输入到朴素贝叶斯中,或者单独处理文本的统计特征,再与深度特征结合。 另外,示例代码部分需要选择合适的框架,比如TensorFlow或PyTorch。用户可能希望看到具体的层构建和训练过程。需要注意的是,朴素贝叶斯通常处理的是离散特征,而深度学习模型输出的是连续特征,可能需要特殊处理,比如离散化或者使用不同的融合方式。 还要考虑如何引用提供的参考文献。比如引用[^1]提到CNN-RNN模型结合,可以借鉴他们的结构。引用[^3]关于训练神经网络的方法,可能会涉及到反向传播和梯度下降的应用。引用[^4]中CNN的特征提取能力,可以说明DCNN部分的作用。 可能的问题是如何处理不同模型之间的输入输出兼容性,以及训练过程中的协调。比如,是否要联合训练所有组件,还是分阶段训练。联合训练可能更有效,但需要处理不同模型的优化方法差异。朴素贝叶斯通常是生成式模型,而深度学习是判别式,联合训练可能需要将贝叶斯部分转化为判别式框架,或者使用集成方法。 最后,确保回答结构清晰,分步骤说明方法,并给出代码示例。同时,生成相关问题需要考虑用户可能感兴趣的后续问题,比如性能优化、对比实验或实际应用中的调整。</think>### 方法步骤说明 #### 1. **模型设计思路** - **DCNN**:提取文本局部特征(如n-gram模式),通过卷积核捕捉关键短语,例如$W_{\text{conv}} * x_{i:i+k}$,输出特征图后通过最大池化提取显著特征。 - **双向GRU**:建模文本的长期依赖关系,正向和反向GRU分别处理序列,输出拼接后得到上下文感知的语义表示,公式为: $$h_t = \text{GRU}(x_t, h_{t-1}) \quad \text{和} \quad h'_t = \text{GRU}(x_t, h'_{t+1})$$ - **朴素贝叶斯**:作为补充分类器,可处理词频、句法等统计特征,与深度学习特征融合。例如,对DCNN-GRU输出的概率与贝叶斯的概率进行加权平均。 #### 2. **实现流程** 1. **输入处理**:文本分词后通过词嵌入层(如Word2Vec或BERT)转换为向量序列。 2. **特征提取**: - DCNN:多尺寸卷积核(如3/4/5-gram)并行提取特征,池化后拼接。 - 双向GRU:输出最终隐藏状态或序列所有时间步的均值。 3. **特征融合**:将DCNN和GRU的输出拼接为$F_{\text{combined}} = [F_{\text{DCNN}}; F_{\text{GRU}}]$。 4. **混合分类**: - 方案一:将$F_{\text{combined}}$输入全连接层生成概率$P_{\text{NN}}$,同时用朴素贝叶斯计算$P_{\text{NB}}$,最终分类概率为$\alpha P_{\text{NN}} + (1-\alpha)P_{\text{NB}}$。 - 方案二:将朴素贝叶斯的特征(如TF-IDF)与$F_{\text{combined}}$拼接后输入分类层。 #### 3. **示例代码(TensorFlow框架)** ```python import tensorflow as tf from tensorflow.keras.layers import Embedding, Conv1D, GlobalMaxPooling1D, Bidirectional, GRU, Concatenate, Dense from sklearn.naive_bayes import MultinomialNB # 文本预处理和词嵌入 vocab_size = 10000 max_len = 200 embedding_dim = 128 inputs = tf.keras.Input(shape=(max_len,)) x = Embedding(vocab_size, embedding_dim)(inputs) # DCNN分支 conv_3 = Conv1D(64, 3, activation='relu')(x) pool_3 = GlobalMaxPooling1D()(conv_3) conv_4 = Conv1D(64, 4, activation='relu')(x) pool_4 = GlobalMaxPooling1D()(conv_4) conv_5 = Conv1D(64, 5, activation='relu')(x) pool_5 = GlobalMaxPooling1D()(conv_5) dcnn_output = Concatenate()([pool_3, pool_4, pool_5]) # 双向GRU分支 gru_output = Bidirectional(GRU(64, return_sequences=False))(x) # 特征融合 combined = Concatenate()([dcnn_output, gru_output]) # 神经网络分类输出 nn_output = Dense(1, activation='sigmoid')(combined) model = tf.keras.Model(inputs=inputs, outputs=nn_output) # 朴素贝叶斯分支(需单独处理统计特征) # 假设X_nb为TF-IDF特征,y为标签 nb_model = MultinomialNB() nb_model.fit(X_nb, y) # 混合预测(示例) def hybrid_predict(text_sequences, X_nb_features): nn_probs = model.predict(text_sequences) nb_probs = nb_model.predict_proba(X_nb_features)[:, 1] final_probs = 0.7 * nn_probs + 0.3 * nb_probs # 权重可调整 return (final_probs > 0.5).astype(int) ``` #### 4. **关键点说明** - **训练顺序**:建议先单独训练DCNN-GRU模型和朴素贝叶斯模型,再固定参数进行混合预测,或设计端到端的联合训练(需自定义损失函数)[^3]。 - **特征对齐**:确保神经网络和朴素贝叶斯的输入样本ID一一对应。 - **权重调整**:混合权重$\alpha$可通过验证集网格搜索确定。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值