基于 TextCNN 的分类模型

基于 TextCNN 的分类模型

实验环境

  • 操作系统:ubuntu 20.4.3
  • 运行环境:Python 3.9
  • 框架环境:TensorFlow 2.6.0

实验数据

  • 训练数据集:57680
  • 验证数据集:18003
  • 测试数据集:14570

模型表现

  • 训练集表现:loss: 0.0669 – acc: 0.9752
  • 验证集表现:loss: 0.1563 – acc: 0.9475
  • 测试集表现:loss: 0.1583 – acc: 0.9442

模型概览

在这里插入图片描述

代码实现

import sys
import pandas as pd
import tensorflow as tf
import matplotlib.pyplot as plt
from keras.layers import Dense, Embedding, Conv1D, GlobalMaxPool1D, Dropout
sys.path.append("/home/laowang/PycharmProjects/DeepLearning/classification(RNN_TextCNN_BERT)/Untils")
from D_01_TxtEncoder import TextEncoder
# 词语总量
word_size = 2117
# 每个文本最大输出长度
out_txt_len = 512
# 单词维度
word_dim = 128
cnn_filters = 50
dnn_units = 512
epochs_times = 10
droup_rate = 0.5
txtEncoder = TextEncoder("../Data/09_文本当中出现的所有字.txt", word_size, out_txt_len)
词库加载完成
['', '[UNK]', 'z', 'y', 'x', 'w', 'v', 'u', 't', 's', 'r', 'q', 'p', 'o', 'n', 'm', 'l', 'k', 'j', 'i', 'h', 'g', 'f', 'e', 'd', 'c', 'b', 'a', '~', ';', ':', ',', ')', '(', '龚', '龙', '龄', '齿', '齐', '鼓', '鼎', '默', '黔', '黑', '黎', '黄', '麻', '麦', '麟', '麓', '麒', '鹿', '鹰', '鹤', '鹏', '鹄', '鸿', '鸥', '鸣', '鸡', '鸟', '鲲', '鲜', '鲍', '鲁', '鱼', '魔', '魏', '魁', '高', '骨', '骥', '骏', '验', '骆', '骅', '骄', '驿', '驾', '驻', '驶', '驱', '驰', '马', '馨', '香', '首', '馆', '饶', '饲', '饰', '饮', '饭', '餐', '食', '飞', '风', '额', '颜', '题']
# 加载数据
data_train = pd.read_csv("../Data/10_文本数据_字分隔_Train.txt")
x_train = data_train.iloc[:, 1:2]
y_train = data_train.iloc[:, 2:]

data_val = pd.read_csv("../Data/10_文本数据_字分隔_Test.txt")
x_val = data_val.iloc[:, 1:2]
y_val = data_val.iloc[:, 2:]

data_test = pd.read_csv("../Data/05_验证数据_原数据.csv")
x_test = data_test.iloc[:, 0:1]
y_test = data_test.iloc[:, 1:]

print(f"训练集数量:{len(data_train)}")
print(f"验证集数量:{len(data_val)}")
print(f"测试集数量:{len(data_test)}")

print(f'x:{x_train.iloc[0][0]},  y:{y_train.iloc[0][0]}')
print(f'x:{x_train.iloc[1][0]},  y:{y_train.iloc[1][0]}')
print(f'x:{x_train.iloc[10][0]},  y:{y_train.iloc[10][0]}')
训练集数量:57680
验证集数量:18003
测试集数量:14570
x:曾 明 军 , 阿 贝 妮 创 始 人,  y:0.0
x:3 0 年 乳 业 经 验 , 曾 就 业 于 利 乐 、 爱 克 林 、 阿 菲 金 等 公 司 。,  y:1.0
x:1 9 8 3 年 7 月 生 , 中 国 国 籍 , 无 境 外 永 久 居 留 权 , 博 士 研 究 生 学 历 , 高 级 工 程 师 , 安 徽 省 战 略 性 新 兴 产 业 技 术 领 军 人 才 , “ 安 徽 省 特 支 计 划 ” 创 新 领 军 人 才 。 2 0 0 8 年 就 读 博 士 期 间 参 与 发 行 人 第 一 台 工 业 机 器 人 ( Q H 1 6 5 机 器 人 ) 的 研 制 , 主 要 负 责 机 器 人 本 体 正 向 设 计 及 机 器 人 控 制 算 法 的 研 究 与 开 发 。 2 0 1 1 年 1 1 月 正 式 入 职 埃 夫 特 , 2 0 1 1 年 1 1 月 至 2 0 1 4 年 1 2 月 担 任 机 器 人 事 业 部 总 工 程 师 ; 2 0 1 4 年 1 2 月 至 2 0 1 6 年 5 月 担 任 公 司 董 事 及 总 工 程 师 ; 2 0 1 6 年 5 月 至 2 0 1 9 年 4 月 担 任 公 司 董 事 、 常 务 副 总 经 理 及 总 工 程 师 ; 2 0 1 9 年 4 月 起 任 公 司 董 事 、 总 经 理 及 总 工 程 师 。 自 任 职 以 来 , 带 领 发 行 人 牵 头 承 接 了 发 改 委 、 工 信 部 、 科 技 部 等 多 个 部 委 的 科 研 和 产 业 化 项 目 。 2 0 1 4 年 作 为 项 目 首 席 专 家 主 持 了 国 家 8 6 3 计 划 先 进 制 造 技 术 领 域 “ 面 向 恶 劣 生 产 环 境 下 经 济 型 工 业 机 器 人 及 成 套 系 统 的 应 用 示 范 ” ( 2 0 1 4 A A 0 4 1 6 0 0 ) 主 题 项 目 。,  y:3.0
# 转化成独热
y_train_one_hot = tf.keras.utils.to_categorical(y_train, dtype='int')
y_val_one_hot = tf.keras.utils.to_categorical(y_val, dtype='int')
y_test_one_hot = tf.keras.utils.to_categorical(y_test, dtype='int')

# 对数据进行编码
x_train = txtEncoder.encoder(x_train)
x_val = txtEncoder.encoder(x_val)
x_test = txtEncoder.encoder(x_test)

# 定义各层
embedding = Embedding(txtEncoder.get_size(), word_dim)
# 定义TextCNN卷积层,分别是 2,3,4 步长(参考TextCNN论文)
cnn_layer1 = Conv1D(filters=cnn_filters,
                    kernel_size=2,
                    padding="valid",
                    activation="relu")
cnn_layer2 = Conv1D(filters=cnn_filters,
                    kernel_size=3,
                    padding="valid",
                    activation="relu")
cnn_layer3 = Conv1D(filters=cnn_filters,
                    kernel_size=4,
                    padding="valid",
                    activation="relu")
# 池化层
pool = GlobalMaxPool1D()

dense_1 = Dense(units=dnn_units, activation="relu")
dropout = Dropout(rate=droup_rate)
output_dense = Dense(units=4, activation="softmax")

# ************************************
# !!!!!!!!!构建模型!!!!!!!!!!
inputs = tf.keras.Input(shape=(out_txt_len,))
layer = embedding(inputs)

l_1 = cnn_layer1(layer)
l_1 = pool(l_1)

l_2 = cnn_layer2(layer)
l_2 = pool(l_2)

l_3 = cnn_layer3(layer)
l_3 = pool(l_3)

# 将所有卷积数据拼接在一起
concatenated = tf.concat([l_1, l_2, l_3], axis=-1)  # (batch_size, 3 * cnn_filters)
concatenated = dense_1(concatenated)
concatenated = dropout(concatenated)
model_output = output_dense(concatenated)

model = tf.keras.Model(inputs=inputs, outputs=model_output)

model.summary()
Model: "model"
__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_1 (InputLayer)            [(None, 512)]        0                                            
__________________________________________________________________________________________________
embedding (Embedding)           (None, 512, 128)     265984      input_1[0][0]                    
__________________________________________________________________________________________________
conv1d (Conv1D)                 (None, 511, 50)      12850       embedding[0][0]                  
__________________________________________________________________________________________________
conv1d_1 (Conv1D)               (None, 510, 50)      19250       embedding[0][0]                  
__________________________________________________________________________________________________
conv1d_2 (Conv1D)               (None, 509, 50)      25650       embedding[0][0]                  
__________________________________________________________________________________________________
global_max_pooling1d (GlobalMax (None, 50)           0           conv1d[0][0]                     
                                                                 conv1d_1[0][0]                   
                                                                 conv1d_2[0][0]                   
__________________________________________________________________________________________________
tf.concat (TFOpLambda)          (None, 150)          0           global_max_pooling1d[0][0]       
                                                                 global_max_pooling1d[1][0]       
                                                                 global_max_pooling1d[2][0]       
__________________________________________________________________________________________________
dense (Dense)                   (None, 512)          77312       tf.concat[0][0]                  
__________________________________________________________________________________________________
dropout (Dropout)               (None, 512)          0           dense[0][0]                      
__________________________________________________________________________________________________
dense_1 (Dense)                 (None, 4)            2052        dropout[0][0]                    
==================================================================================================
Total params: 403,098
Trainable params: 403,098
Non-trainable params: 0
__________________________________________________________________________________________________
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['acc'])

history = model.fit(x_train, y_train_one_hot, epochs=epochs_times, batch_size=1000,
                        validation_data=(x_val, y_val_one_hot))
Epoch 1/10


2023-09-13 16:00:31.064755: I tensorflow/stream_executor/cuda/cuda_dnn.cc:369] Loaded cuDNN version 8100
2023-09-13 16:00:31.956121: I tensorflow/stream_executor/cuda/cuda_blas.cc:1760] TensorFloat-32 will be used for the matrix multiplication. This will only be logged once.


58/58 [==============================] - 4s 46ms/step - loss: 0.6870 - acc: 0.7582 - val_loss: 0.4322 - val_acc: 0.8390
Epoch 2/10
58/58 [==============================] - 2s 40ms/step - loss: 0.3279 - acc: 0.8805 - val_loss: 0.2591 - val_acc: 0.9037
Epoch 3/10
58/58 [==============================] - 2s 40ms/step - loss: 0.2400 - acc: 0.9068 - val_loss: 0.2167 - val_acc: 0.9129
Epoch 4/10
58/58 [==============================] - 2s 40ms/step - loss: 0.1989 - acc: 0.9215 - val_loss: 0.1895 - val_acc: 0.9245
Epoch 5/10
58/58 [==============================] - 2s 40ms/step - loss: 0.1678 - acc: 0.9346 - val_loss: 0.1695 - val_acc: 0.9314
Epoch 6/10
58/58 [==============================] - 2s 40ms/step - loss: 0.1384 - acc: 0.9479 - val_loss: 0.1583 - val_acc: 0.9379
Epoch 7/10
58/58 [==============================] - 2s 40ms/step - loss: 0.1140 - acc: 0.9563 - val_loss: 0.1533 - val_acc: 0.9428
Epoch 8/10
58/58 [==============================] - 2s 40ms/step - loss: 0.0964 - acc: 0.9629 - val_loss: 0.1504 - val_acc: 0.9455
Epoch 9/10
58/58 [==============================] - 2s 39ms/step - loss: 0.0792 - acc: 0.9697 - val_loss: 0.1532 - val_acc: 0.9473
Epoch 10/10
58/58 [==============================] - 2s 39ms/step - loss: 0.0669 - acc: 0.9752 - val_loss: 0.1563 - val_acc: 0.9475
plt.title('loss')
plt.plot(history.epoch, history.history.get('loss'), color='red')
plt.plot(history.epoch, history.history.get('val_loss'), color='blue')
plt.legend(['train', 'validation'], loc='upper right')
plt.show()

在这里插入图片描述

plt.title('acc')
plt.plot(history.epoch, history.history.get('acc'), color='red')
plt.plot(history.epoch, history.history.get('val_acc'), color='blue')
plt.legend(['train', 'validation'], loc='upper right')
plt.show()

在这里插入图片描述

# 测试模型情况
loss, accuracy = model.evaluate(x=x_test, y=y_test_one_hot)

print(f'测试集损失: {loss}')
print(f'测试集准确度: {accuracy}')
456/456 [==============================] - 1s 2ms/step - loss: 0.1583 - acc: 0.9443
测试集损失: 0.15834568440914154
测试集准确度: 0.944269061088562
以下是基于Pytorch实现textcnn文本分类模型的代码,其中使用了CNN对文本进行卷积和池化,再经过全连接层进行分类。具体代码如下: ```python import torch import torch.nn as nn import torch.nn.functional as F class TextCNN(nn.Module): def __init__(self, vocab_size, embedding_dim, num_classes, filter_sizes, num_filters): super(TextCNN, self).__init__() self.embeddings = nn.Embedding(vocab_size, embedding_dim) self.convs = nn.ModuleList([ nn.Conv2d(1, num_filters, (fs, embedding_dim)) for fs in filter_sizes ]) self.fc = nn.Linear(num_filters * len(filter_sizes), num_classes) def forward(self, x): x = self.embeddings(x) # (batch_size, seq_len, embedding_dim) x = x.unsqueeze(1) # (batch_size, 1, seq_len, embedding_dim) x = [F.relu(conv(x)).squeeze(3) for conv in self.convs] # [(batch_size, num_filters, seq_len - filter_size + 1), ...] x = [F.max_pool1d(conv, conv.shape[2]).squeeze(2) for conv in x] # [(batch_size, num_filters), ...] x = torch.cat(x, 1) # (batch_size, num_filters * len(filter_sizes)) x = self.fc(x) # (batch_size, num_classes) return x ``` 其中,`vocab_size`表示词汇表大小,`embedding_dim`表示词向量维度,`num_classes`表示分类数目,`filter_sizes`表示卷积核大小,`num_filters`表示卷积核个数。 在`forward`函数中,首先将输入的文本通过词向量层进行转换,得到(batch_size, seq_len, embedding_dim)的张量。然后通过卷积层和池化层对文本进行特征提取,得到形状为(batch_size, num_filters * len(filter_sizes))的张量,最后通过全连接层进行分类
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值