关于数据挖掘:用于NLP的Python使用Keras的多标签文本LSTM神经网络分类

27次阅读

共计 13119 个字符,预计需要花费 33 分钟才能阅读完成。

原文链接: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 数据框,咱们将绘制条形图,来显示不同标签的总正文数。

输入:

您能够看到,“有毒”评论的呈现频率最高,其次是“羞辱”。

创立多标签文本分类模型

创立多标签分类模型的办法有两种:应用单个密集输入层和多个密集输入层。

在第一种办法中,咱们能够应用具备六个输入的单个密集层,并具备 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()

输入:

从输入中能够看到,在第一个期间之后,测试(验证)的准确性并未收敛。

论断

多标签文本分类是最常见的文本分类问题之一。在本文中,咱们钻研了两种用于多标签文本分类的深度学习办法。在第一种办法中,咱们应用具备多个神经元的单个密集输入层,其中每个神经元代表一个标签。

在第二种办法中,咱们为每个带有一个神经元的标签创立独自的密集层。结果表明,在咱们的状况下,具备多个神经元的单个输入层比多个输入层的成果更好。


最受欢迎的见解

1. 探析大数据期刊文章钻研热点

2.618 网购数据盘点 - 剁手族在关注什么

3.r 语言文本开掘 tf-idf 主题建模,情感剖析 n -gram 建模钻研

4.python 主题建模可视化 lda 和 t -sne 交互式可视化

5. 疫情下的新闻数据察看

6.python 主题 lda 建模和 t -sne 可视化

7.r 语言中对文本数据进行主题模型 topic-modeling 剖析

8. 主题模型:数据凝听人民网留言板的那些“网事”

9.python 爬虫进行 web 抓取 lda 主题语义数据分析

正文完
 0