使用 CNN 进行句子分类的自然语言处理

2021-11-19 15:24:57 浏览数 (1)


磐创AI分享

作者 | nilanjan6182121

编译 | Flin

来源 | analyticsvidhya

概述

句子 分类是最简单的NLP任务之一,具有广泛的应用,包括文档分类、垃圾邮件过滤和情感分析。一个句子在句子分类中被分类到一个类中。

本文将使用问题数据库,每个问题都将标明问题的内容。例如,“谁是亚伯拉罕·林肯”将是一个问题,其标签将是“人”。

我们将使用这个数据集 - http://cogcomp.org/Data/QA/QC/

CNN基础知识

让我们看看 CNN 背后的基本思想,而不涉及太多技术细节。CNN 是一堆层,类似于卷积层、池化层和全连接层。我们将讨论这些中的每一个,以了解它们在 CNN 中的作用。

首先,输入连接到一组卷积层。这些卷积层在输入上滑动一个权重块,并通过卷积操作产生输出。卷积层使用少量权重,这些权重被组织成仅覆盖每层中的一小部分输入,并且这些权重分布在某些维度上(例如,图像的宽度和高度维度)。

除此之外,CNN 使用卷积运算来共享权重,通过滑动这组权重和所需维度来形成输出。我们从这个卷积操作中得到的结果如图所示。如果卷积滤波器中存在的模式存在于图像的补丁中,则卷积将在该位置具有高值输出,否则将输出低值。并且,通过对整个图像进行卷积,我们得到的矩阵表明某个位置是否存在模式。

最后,我们将得到一个矩阵作为卷积输出:

![](http://qiniu.aihubs.net/17157Screenshot (180).png)

CNN结构

我们将对文本文档进行如下操作:

  • 将句子转换为可以由 CNN 轻松处理的首选格式。
  • 为句子分类执行卷积和池化操作。

数据转换

让我们考虑这个例子以便更好地理解:

  • Bob and Mary are friends.
  • Bob plays Soccer.
  • Mary likes to sing in the choir.

第三句话的字数最多。因此,n=7。现在,让我们对这些单词进行独热编码。有 13(k=13) 个不同的词。

  • Bob – 1,0,0,0,0,0,0,0,0,0,0,0,0
  • and – 0,1,0,0,0,0,0,0,0,0,0,0,0
  • Mary – 0,0,1,0,0,0,0,0,0,0,0,0,0

同样,对于 3 个句子,我们将有一个 3713 的三维矩阵。

![](http://qiniu.aihubs.net/60835Screenshot (167).png)

图 2 – 使用 TensorFlow 的 NLP,作者:Thushan Ganegedara

卷积操作

假设我们一次只处理一个句子,那么会有一个 k 矩阵,其中 n 是填充后每个句子的单词数,k 是单个单词的维度。在上面的例子中,这将是 713。

现在定义了大小为 m*k 的矩阵的权重,

其中 m 是一维卷积运算的滤波器大小。

通过将大小为 n * k 的输入 x 与大小为 m * k 的权重矩阵 W 进行卷积,我们将产生大小为 l * n 的 h 输出,如下所示:

![](http://qiniu.aihubs.net/11910Screenshot (169).png)图 3 – 使用 TensorFlow 的

这里,wi,j 是W 的 第(i,j)个元素,我们将用零填充 x,使 h 的大小为 l*n。

h=W*x b

这里,* 表示卷积操作(连同填充)并添加了额外的标量偏差 b。

![](http://qiniu.aihubs.net/87712Screenshot (171).png)

图 4 – 使用 TensorFlow 的 NLP,作者:Thushan Ganegedara

对于丰富的特征集,使用具有不同卷积滤波器大小的并行层。

每个卷积层给出一个大小为 ln 的隐藏向量,这些输出连接起来形成大小为 qn 的下一层的输入,其中 q 是并行层的数量。较大的 q 值有更好的性能。

池化操作

池化操作的目的是对之前讨论的并行卷积层的输出进行二次采样。

为此,我们假设最后一层 h 的输出大小为 qn。然后,池化层将给出输出 h' 和大小 ql 的输出。

![](http://qiniu.aihubs.net/38526Screenshot (173)_LI.jpg)

图 4 – 使用 TensorFlow 的 NLP,作者:Thushan Ganegedara

![](http://qiniu.aihubs.net/69307Screenshot (175).png)

图 5 – 使用 TensorFlow 的 NLP,作者:Thushan Ganegedara

结合这些操作,我们终于得到了这个架构

![](http://qiniu.aihubs.net/23540Screenshot (177).png)

图 6 – 使用 TensorFlow 的 NLP,作者:Thushan Ganegedara

用代码实现

首先,我们将定义输入和输出。一批句子将作为我们的输入,我们将用独热编码的词向量来表示单词。

代码语言:javascript复制
sent_inputs = tf.placeholder(shape=
[batch_size,sent_length,vocabulary_size],dtype=tf.fl
oat32,name='sentence_inputs')
sent_labels = tf.placeholder(shape=
[batch_size,num_classes],dtype=tf.float32,name='sent
ence_labels') 

然后,我们将定义三个不同的一维卷积层以及三个不同大小的滤波器及其各自的偏差:

代码语言:javascript复制
w1 =
tf.Variable(tf.truncated_normal([filter_sizes[0],voc
abulary_size,1],stddev=0.02,dtype=tf.float32),name='
weights_1')
b1 =
tf.Variable(tf.random_uniform([1],0,0.01,dtype=tf.fl
oat32),name='bias_1')
w2 =
tf.Variable(tf.truncated_normal([filter_sizes[1],voc
abulary_size,1],stddev=0.02,dtype=tf.float32),name='
weights_2')
b2 =
tf.Variable(tf.random_uniform([1],0,0.01,dtype=tf.fl
oat32),name='bias_2')
w3 =
tf.Variable(tf.truncated_normal([filter_sizes[2],voc
abulary_size,1],stddev=0.02,dtype=tf.float32),name='
weights_3')
b3 =
tf.Variable(tf.random_uniform([1],0,0.01,dtype=tf.fl
oat32),name='bias_3')

然后,我们将计算三个输出,每个输出都属于一个卷积层。我们将使用 1 步长和零填充来确保输出包含与输入相同的大小:

代码语言:javascript复制
h1_1 =
tf.nn.relu(tf.nn.conv1d(sent_inputs,w1,stride=1,padd
ing='SAME')   b1)
h1_2 =
tf.nn.relu(tf.nn.conv1d(sent_inputs,w2,stride=1,padd
ing='SAME')   b2)
h1_3 =
tf.nn.relu(tf.nn.conv1d(sent_inputs,w3,stride=1,padd
ing='SAME')   b3)

然后,我们需要在 TensorFlow 中编写基本函数来执行此操作,以便随着时间的推移计算最大池化,因为 TensorFlow 没有内置函数来执行此操作。我

们将计算每个卷积层产生的每个隐藏输出的最大值。这将为每一层提供一个标量:

代码语言:javascript复制
h2_1 = tf.reduce_max(h1_1,axis=1)
h2_2 = tf.reduce_max(h1_2,axis=1)
h2_3 = tf.reduce_max(h1_3,axis=1)

然后我们将连接在 axis 1 上产生的输出,以给出大小为 batchsize*q 的输出

代码语言:javascript复制
h2 = tf.concat([h2_1,h2_2,h2_3],axis=1)

然后,我们将定义全连接层,它们将完全连接到池化层产生的输出。

在这种情况下,这里有一个全连接层,这也将是我们的输出层:

代码语言:javascript复制
w_fc1 = tf.Variable(tf.truncated_normal([len(filter_sizes),n
um_classes],stddev=0.5,dtype=tf.float32),name='weigh
ts_fulcon_1')
b_fc1 =
tf.Variable(tf.random_uniform([num_classes],0,0.01,d
type=tf.float32),name='bias_fulcon_1')

此处定义的函数将生成 logits,然后将其用于计算网络的损失:

代码语言:javascript复制
logits = tf.matmul(h2,w_fc1)   b_fc1

然后,通过将 softmax 激活应用于 logits,我们将得到预测:

代码语言:javascript复制
predictions =
tf.argmax(tf.nn.softmax(logits),axis=1)

然后,我们将定义损失函数,即交叉熵损失:

代码语言:javascript复制
loss =
tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logi
ts_v2(labels=sent_labels,logits=logits))
代码语言:javascript复制
optimizer =
tf.train.MomentumOptimizer(learning_rate=0.01,moment
um=0.9).minimize(loss)

为了优化模型,使用了 MomentumOptimizer,它是 TensorFlow 的内置优化器。

执行这些操作来优化 CNN 并评估测试数据,在这个句子分类任务中为我们提供了大约 90%(500 个测试句子)的测试准确率。

结束笔记

在本文中,我们讨论了以下内容:

  • 一维卷积操作与时间池化的组合可用于实现基于 CNN 架构的句子分类器。
  • 使用 TensorFlow 实现这样的 CNN 及其性能。
  • 在现实生活中,它可以以这种方式使用 - 例如,如果我们想搜索 Julius Ceasar,而不从一份包含罗马历史的大型文件中阅读整个文件的情况下。句子分类器对于这些类型的任务非常有用。
  • 句子分类可用于其他任务,如电影评论分类和电影评级自动化。

参考

写这篇文章的想法来自于Thushan Ganegedara的NLP with Tensorflow。

图片来源

  1. 图 1 – https://books.google.co.in/books/about/Natural_Language_Processing_with_TensorF.html?id=trhwswEACAAJ&redir_esc=y
  2. 图 2 – https://books.google.co.in/books/about/Natural_Language_Processing_with_TensorF.html?id=trhwswEACAAJ&redir_esc=y
  3. 图 3 – https://books.google.co.in/books/about/Natural_Language_Processing_with_TensorF.html?id=trhwswEACAAJ&redir_esc=y
  4. 图 4 – https://books.google.co.in/books/about/Natural_Language_Processing_with_TensorF.html?id=trhwswEACAAJ&redir_esc=y
  5. 图 5 – https://books.google.co.in/books/about/Natural_Language_Processing_with_TensorF.html?id=trhwswEACAAJ&redir_esc=y
  6. 图 6 – https://books.google.co.in/books/about/Natural_Language_Processing_with_TensorF.html?id=trhwswEACAAJ&redir_esc=y

原文链接:https://www.analyticsvidhya.com/blog/2021/09/natural-language-processing-using-cnns-for-sentence-classification/

0 人点赞