用于NLP的Python:使用Keras的多标签文本LSTM神经网络分类|附代码数据
全文下载链接:http://tecdat.cn/?p=8640
在本文中,我们将看到如何开发具有多个输出的文本分类模型。我们开发一个文本分类模型,该模型可分析文本注释并预测与该注释关联的多个标签。多标签分类问题实际上是多个输出模型的子集。在本文结尾,您将能够对数据执行多标签文本分类。
数据集
数据集包含来自Wikipedia对话页编辑的评论。评论可以属于所有这些类别,也可以属于这些类别的子集,这是一个多标签分类问题。
现在,我们导入所需的库并将数据集加载到我们的应用程序中。以下脚本导入所需的库:
import pandas as pdimport numpy as npimport reimport matplotlib.pyplot as plt
现在,将数据集加载到内存中:
toxic\_comments = pd.read\_csv("/comments.csv")
以下脚本显示数据集的维度,并显示数据集的标题:
print(toxic_comments.shape)
toxic_comments.head()
输出:
(159571,8)
数据集包含159571条记录和8列。数据集的标题如下所示:
让我们删除所有记录中任何行包含空值或空字符串的记录。
filter = toxic\_comments\["comment\_text"\] != ""toxic\_comments = toxic\_comments\[filter\]
toxic\_comments = toxic\_comments.dropna()
该comment_text
列包含文本注释。
print(toxic\_comments\["comment\_text"\]\[168\])
输出:
You should be fired, you're a moronic wimp who is too lazy to do research. It makes me sick that people like you exist in this world.
让我们看一下与此注释相关的标签:
print("Toxic:" + str(toxic_comments\["toxic"\]\[168\]))
print("Severe\_toxic:" + str(toxic\_comments\["severe_toxic"\]\[168\]))
print("Obscene:" + str(toxic_comments\["obscene"\]\[168\]))
print("Threat:" + str(toxic_comments\["threat"\]\[168\]))
print("Insult:" + str(toxic_comments\["insult"\]\[168\]))
print("Identity\_hate:" + str(toxic\_comments\["identity_hate"\]\[168\]))
输出:
Toxic:1Severe\_toxic:0Obscene:0Threat:0Insult:1Identity\_hate:0
我们将首先过滤所有标签或输出列。
toxic\_comments\_labels = toxic\_comments\[\["toxic", "severe\_toxic", "obscene", "threat", "insult", "identity_hate"\]\]
toxic\_comments\_labels.head()
输出:
使用toxic_comments_labels
数据框,我们将绘制条形图,来显示不同标签的总注释数。
输出:
您可以看到,“有毒”评论的出现频率最高,其次是 “侮辱”。
点击标题查阅往期内容
python用于NLP的seq2seq模型实例:用Keras实现神经网络机器翻译
左右滑动查看更多
01
02
03
04
创建多标签文本分类模型
创建多标签分类模型的方法有两种:使用单个密集输出层和多个密集输出层。
在第一种方法中,我们可以使用具有六个输出的单个密集层,并具有S型激活函数和二进制交叉熵损失函数。
在第二种方法中,我们将为每个标签创建一个密集输出层。
具有单输出层的多标签文本分类模型
在本节中,我们将创建具有单个输出层的多标签文本分类模型。
在下一步中,我们将创建输入和输出集。输入是来自该comment_text
列的注释。
这里我们不需要执行任何一键编码,因为我们的输出标签已经是一键编码矢量的形式。
下一步,我们将数据分为训练集和测试集:
我们需要将文本输入转换为嵌入式向量。
我们将使用GloVe词嵌入将文本输入转换为数字输入。
以下脚本创建模型。我们的模型将具有一个输入层,一个嵌入层,一个具有128个神经元的LSTM层和一个具有6个神经元的输出层,因为我们在输出中有6个标签。
LSTM\_Layer\_1 = LSTM(128)(embedding_layer)
dense\_layer\_1 = Dense(6, activation='sigmoid')(LSTM\_Layer\_1)
model = Model()
让我们输出模型摘要:
print(model.summary())
输出:
_________________________________________________________________Layer (type) Output Shape Param #
=================================================================input\_1 (InputLayer) (None, 200) 0\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_embedding\_1 (Embedding) (None, 200, 100) 14824300\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_lstm\_1 (LSTM) (None, 128) 117248\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_dense_1 (Dense) (None, 6) 774
=================================================================Total params: 14,942,322
Trainable params: 118,022
Non-trainable params: 14,824,300
以下脚本输出了我们的神经网络的结构:
plot\_model(model, to\_file='model\_plot4a.png', show\_shapes=True, show\_layer\_names=True)
输出:
从上图可以看到,输出层仅包含1个具有6个神经元的密集层。现在让我们训练模型:
可以用更多的时间训练模型,看看结果是好是坏。
结果如下:
rain on 102124 samples, validate on 25532 samplesEpoch 1/5102124/102124 \[==============================\] - 245s 2ms/step - loss: 0.1437 - acc: 0.9634 - val\_loss: 0.1361 - val\_acc: 0.9631Epoch 2/5102124/102124 \[==============================\] - 245s 2ms/step - loss: 0.0763 - acc: 0.9753 - val\_loss: 0.0621 - val\_acc: 0.9788Epoch 3/5102124/102124 \[==============================\] - 243s 2ms/step - loss: 0.0588 - acc: 0.9800 - val\_loss: 0.0578 - val\_acc: 0.9802Epoch 4/5102124/102124 \[==============================\] - 246s 2ms/step - loss: 0.0559 - acc: 0.9807 - val\_loss: 0.0571 - val\_acc: 0.9801Epoch 5/5102124/102124 \[==============================\] - 245s 2ms/step - loss: 0.0528 - acc: 0.9813 - val\_loss: 0.0554 - val\_acc: 0.9807
现在让我们在测试集中评估模型:
print("Test Score:", score\[0\])
print("Test Accuracy:", score\[1\])
输出:
31915/31915 \[==============================\] - 108s 3ms/stepTest Score: 0.054090796736467786Test Accuracy: 0.9810642735274182
我们的模型实现了约98%的精度 。
最后,我们将绘制训练和测试集的损失和准确度,以查看我们的模型是否过拟合。
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(\['train','test'\], loc='upper left')
plt.show()
输出:
您可以看到模型在验证集上没有过拟合。
具有多个输出层的多标签文本分类模型
在本节中,我们将创建一个多标签文本分类模型,其中每个输出标签将具有一个 输出密集层。让我们首先定义预处理功能:
def preprocess_text(sen):
# 删除标点符号和数字
# 单字符删除
# 删除多个空格
sentence = re.sub(r'\\s+', ' ', sentence)
return sentence
第二步是为模型创建输入和输出。该模型的输入将是文本注释,而输出将是六个标签。以下脚本创建输入层和组合的输出层:
y = toxic\_comments\[\["toxic", "severe\_toxic", "obscene", "threat", "insult", "identity_hate"\]\]
让我们将数据分为训练集和测试集:
X\_train, X\_test, y\_train, y\_test = train\_test\_split(X, y, test\_size=0.20, random\_state=42)
该y
变量包含6个标签的组合输出。但是,我们要为每个标签创建单独的输出层。我们将创建6个变量,这些变量存储来自训练数据的各个标签,还有6个变量,分别存储测试数据的各个标签值。
下一步是将文本输入转换为嵌入的向量。
X\_train = pad\_sequences(X_train, padding='post', maxlen=maxlen)
X\_test = pad\_sequences(X_test, padding='post', maxlen=maxlen)
我们将再次使用GloVe词嵌入:
embedding\_matrix = zeros((vocab\_size, 100))
我们的模型将具有一层输入层,一层嵌入层,然后一层具有128个神经元的LSTM层。LSTM层的输出将用作6个密集输出层的输入。每个输出层具有1个具有S型激活功能的神经元。
以下脚本创建我们的模型:
model = Model()以下脚本输出模型的摘要:
``````
print(model.summary())
输出:
__________________________________________________________________________________________________Layer (type) Output Shape Param # Connected to
==================================================================================================input\_1 (InputLayer) (None, 200) 0\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_embedding\_1 (Embedding) (None, 200, 100) 14824300 input\_1\[0\]\[0\]\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_lstm\_1 (LSTM) (None, 128) 117248 embedding\_1\[0\]\[0\]\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_dense\_1 (Dense) (None, 1) 129 lstm\_1\[0\]\[0\]\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_dense\_2 (Dense) (None, 1) 129 lstm\_1\[0\]\[0\]\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_dense\_3 (Dense) (None, 1) 129 lstm\_1\[0\]\[0\]\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_dense\_4 (Dense) (None, 1) 129 lstm\_1\[0\]\[0\]\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_dense\_5 (Dense) (None, 1) 129 lstm\_1\[0\]\[0\]\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_dense\_6 (Dense) (None, 1) 129 lstm_1\[0\]\[0\]
==================================================================================================Total params: 14,942,322
Trainable params: 118,022
Non-trainable params: 14,824,300
以下脚本显示了我们模型的体系结构:
plot\_model(model, to\_file='model\_plot4b.png', show\_shapes=True, show\_layer\_names=True)
输出:
您可以看到我们有6个不同的输出层。上图清楚地说明了我们在上一节中创建的具有单个输入层的模型与具有多个输出层的模型之间的区别。
现在让我们训练模型:
history = model.fit(x=X\_train, y=\[y1\_train, y2\_train, y3\_train, y4\_train, y5\_train, y6\_train\], batch\_size=8192, epochs=5, verbose=1, validation_split=0.2)
训练过程和结果如下所示:
输出:
Train on 102124 samples, validate on 25532 samplesEpoch 1/5102124/102124 \[==============================\] - 24s 239us/step - loss: 3.5116 - dense\_1\_loss: 0.6017 - dense\_2\_loss: 0.5806 - dense\_3\_loss: 0.6150 - dense\_4\_loss: 0.5585 - dense\_5\_loss: 0.5828 - dense\_6\_loss: 0.5730 - dense\_1\_acc: 0.9029 - dense\_2\_acc: 0.9842 - dense\_3\_acc: 0.9444 - dense\_4\_acc: 0.9934 - dense\_5\_acc: 0.9508 - dense\_6\_acc: 0.9870 - val\_loss: 1.0369 - val\_dense\_1\_loss: 0.3290 - val\_dense\_2\_loss: 0.0983 - val\_dense\_3\_loss: 0.2571 - val\_dense\_4\_loss: 0.0595 - val\_dense\_5\_loss: 0.1972 - val\_dense\_6\_loss: 0.0959 - val\_dense\_1\_acc: 0.9037 - val\_dense\_2\_acc: 0.9901 - val\_dense\_3\_acc: 0.9469 - val\_dense\_4\_acc: 0.9966 - val\_dense\_5\_acc: 0.9509 - val\_dense\_6\_acc: 0.9901Epoch 2/5102124/102124 \[==============================\] - 20s 197us/step - loss: 0.9084 - dense\_1\_loss: 0.3324 - dense\_2\_loss: 0.0679 - dense\_3\_loss: 0.2172 - dense\_4\_loss: 0.0338 - dense\_5\_loss: 0.1983 - dense\_6\_loss: 0.0589 - dense\_1\_acc: 0.9043 - dense\_2\_acc: 0.9899 - dense\_3\_acc: 0.9474 - dense\_4\_acc: 0.9968 - dense\_5\_acc: 0.9510 - dense\_6\_acc: 0.9915 - val\_loss: 0.8616 - val\_dense\_1\_loss: 0.3164 - val\_dense\_2\_loss: 0.0555 - val\_dense\_3\_loss: 0.2127 - val\_dense\_4\_loss: 0.0235 - val\_dense\_5\_loss: 0.1981 - val\_dense\_6\_loss: 0.0554 - val\_dense\_1\_acc: 0.9038 - val\_dense\_2\_acc: 0.9900 - val\_dense\_3\_acc: 0.9469 - val\_dense\_4\_acc: 0.9965 - val\_dense\_5\_acc: 0.9509 - val\_dense\_6\_acc: 0.9900Epoch 3/5102124/102124 \[==============================\] - 20s 199us/step - loss: 0.8513 - dense\_1\_loss: 0.3179 - dense\_2\_loss: 0.0566 - dense\_3\_loss: 0.2103 - dense\_4\_loss: 0.0216 - dense\_5\_loss: 0.1960 - dense\_6\_loss: 0.0490 - dense\_1\_acc: 0.9043 - dense\_2\_acc: 0.9899 - dense\_3\_acc: 0.9474 - dense\_4\_acc: 0.9968 - dense\_5\_acc: 0.9510 - dense\_6\_acc: 0.9915 - val\_loss: 0.8552 - val\_dense\_1\_loss: 0.3158 - val\_dense\_2\_loss: 0.0566 - val\_dense\_3\_loss: 0.2074 - val\_dense\_4\_loss: 0.0225 - val\_dense\_5\_loss: 0.1960 - val\_dense\_6\_loss: 0.0568 - val\_dense\_1\_acc: 0.9038 - val\_dense\_2\_acc: 0.9900 - val\_dense\_3\_acc: 0.9469 - val\_dense\_4\_acc: 0.9965 - val\_dense\_5\_acc: 0.9509 - val\_dense\_6\_acc: 0.9900Epoch 4/5102124/102124 \[==============================\] - 20s 198us/step - loss: 0.8442 - dense\_1\_loss: 0.3153 - dense\_2\_loss: 0.0570 - dense\_3\_loss: 0.2061 - dense\_4\_loss: 0.0213 - dense\_5\_loss: 0.1952 - dense\_6\_loss: 0.0493 - dense\_1\_acc: 0.9043 - dense\_2\_acc: 0.9899 - dense\_3\_acc: 0.9474 - dense\_4\_acc: 0.9968 - dense\_5\_acc: 0.9510 - dense\_6\_acc: 0.9915 - val\_loss: 0.8527 - val\_dense\_1\_loss: 0.3156 - val\_dense\_2\_loss: 0.0558 - val\_dense\_3\_loss: 0.2074 - val\_dense\_4\_loss: 0.0226 - val\_dense\_5\_loss: 0.1951 - val\_dense\_6\_loss: 0.0561 - val\_dense\_1\_acc: 0.9038 - val\_dense\_2\_acc: 0.9900 - val\_dense\_3\_acc: 0.9469 - val\_dense\_4\_acc: 0.9965 - val\_dense\_5\_acc: 0.9509 - val\_dense\_6\_acc: 0.9900Epoch 5/5102124/102124 \[==============================\] - 20s 197us/step - loss: 0.8410 - dense\_1\_loss: 0.3146 - dense\_2\_loss: 0.0561 - dense\_3\_loss: 0.2055 - dense\_4\_loss: 0.0213 - dense\_5\_loss: 0.1948 - dense\_6\_loss: 0.0486 - dense\_1\_acc: 0.9043 - dense\_2\_acc: 0.9899 - dense\_3\_acc: 0.9474 - dense\_4\_acc: 0.9968 - dense\_5\_acc: 0.9510 - dense\_6\_acc: 0.9915 - val\_loss: 0.8501 - val\_dense\_1\_loss: 0.3153 - val\_dense\_2\_loss: 0.0553 - val\_dense\_3\_loss: 0.2069 - val\_dense\_4\_loss: 0.0226 - val\_dense\_5\_loss: 0.1948 - val\_dense\_6\_loss: 0.0553 - val\_dense\_1\_acc: 0.9038 - val\_dense\_2\_acc: 0.9900 - val\_dense\_3\_acc: 0.9469 - val\_dense\_4\_acc: 0.9965 - val\_dense\_5\_acc: 0.9509 - val\_dense\_6_acc: 0.9900
对于每个时期,我们在输出中的所有6个密集层都有 精度 。
现在让我们评估模型在测试集上的性能:
print("Test Score:", score\[0\])
print("Test Accuracy:", score\[1\])
输出:
31915/31915 \[==============================\] - 111s 3ms/stepTest Score: 0.8471985269747015Test Accuracy: 0.31425264998511726
通过多个输出层只能达到31%的精度。
以下脚本绘制了第一密集层的训练和验证集的损失和准确值。
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(\['train','test'\], loc='upper left')
plt.show()
输出:
从输出中可以看到,在第一个时期之后,测试(验证)的准确性并未收敛。
结论
多标签文本分类是最常见的文本分类问题之一。在本文中,我们研究了两种用于多标签文本分类的深度学习方法。在第一种方法中,我们使用具有多个神经元的单个密集输出层,其中每个神经元代表一个标签。
在第二种方法中,我们为每个带有一个神经元的标签创建单独的密集层。结果表明,在我们的情况下,具有多个神经元的单个输出层比多个输出层的效果更好。
本文摘选《用于NLP的Python:使用Keras的多标签文本LSTM神经网络分类》 ,点击“阅读原文”获取全文完整资料。
点击标题查阅往期内容
【视频】Python用LSTM长短期记忆神经网络对不稳定降雨量时间序列进行预测分析|数据分享
深度学习实现自编码器Autoencoder神经网络异常检测心电图ECG时间序列
NLP自然语言处理—主题模型LDA案例:挖掘人民网留言板文本数据
Python主题建模LDA模型、t-SNE 降维聚类、词云可视化文本挖掘新闻组数据集
自然语言处理NLP:主题LDA、情感分析疫情下的新闻文本数据
用于NLP的Python:使用Keras进行深度学习文本生成
R语言文本挖掘tf-idf,主题建模,情感分析,n-gram建模研究
用于NLP的Python:使用Keras的多标签文本LSTM神经网络分类
R语言中的LDA模型:对文本数据进行主题模型topic modeling分析
R语言文本主题模型之潜在语义分析(LDA:Latent Dirichlet Allocation)
Python中TensorFlow的长短期记忆神经网络(LSTM)、指数移动平均法预测股票市场和可视化
RNN循环神经网络 、LSTM长短期记忆网络实现时间序列长期利率预测
结合新冠疫情COVID-19股票价格预测:ARIMA,KNN和神经网络时间序列分析
深度学习:Keras使用神经网络进行简单文本分类分析新闻组数据
PYTHON用LSTM长短期记忆神经网络的参数优化方法预测时间序列洗发水销售数据
Python用Keras神经网络序列模型回归拟合预测、准确度检查和结果可视化
R语言深度学习卷积神经网络 (CNN)对 CIFAR 图像进行分类:训练与结果评估可视化
深度学习:Keras使用神经网络进行简单文本分类分析新闻组数据
Python用LSTM长短期记忆神经网络对不稳定降雨量时间序列进行预测分析
R语言深度学习Keras循环神经网络(RNN)模型预测多输出变量时间序列
R语言KERAS用RNN、双向RNNS递归神经网络、LSTM分析预测温度时间序列、 IMDB电影评分情感
Python用Keras神经网络序列模型回归拟合预测、准确度检查和结果可视化
Python用LSTM长短期记忆神经网络对不稳定降雨量时间序列进行预测分析
R语言中的神经网络预测时间序列:多层感知器(MLP)和极限学习机(ELM)数据分析报告
R语言深度学习:用keras神经网络回归模型预测时间序列数据
Matlab用深度学习长短期记忆(LSTM)神经网络对文本数据进行分类
R语言KERAS深度学习CNN卷积神经网络分类识别手写数字图像数据(MNIST)
Python中用PyTorch机器学习神经网络分类预测银行客户流失模型
SAS使用鸢尾花(iris)数据集训练人工神经网络(ANN)模型
【视频】R语言实现CNN(卷积神经网络)模型进行回归数据分析
R语言用神经网络改进Nelson-Siegel模型拟合收益率曲线分析
matlab使用长短期记忆(LSTM)神经网络对序列数据进行分类
使用PYTHON中KERAS的LSTM递归神经网络进行时间序列预测