在之前的文章中,我介绍了撩一发深度文本分类之RNN via Attention,解决有毒评论文本分类问题。然而,在工业界,RNN、LSTM、GRU等循环神经网络不能并行计算,尽管研究者提出了一些其他的模型,如SRU等。CNN尽管效果在某些时候会稍逊RNN以及RNN的变体,但是CNN在速度方面却有着无可比拟的效果,且由于它的可并行性广被工业界喜爱。
在本文中,我将介绍 「TextCNN」 算法,帮助有需要的朋友入门深度学习自然语言处理。关于TextCNN算法,有两篇不错的paper可供参考:
(1) Convolutional Neural Networks for Sentence Classification
(2) A Sensitivity Analysis of (and Practitioners’ Guide to) Convolutional Neural Networks for Sentence Classification
卷积神经网络(CNN),做过图像的朋友都知道,比如图像分类、目标检测、分割等,很多都是利用CNN提取图像的深层次图像表征,并且取得了state-of-the-art performance,在图像领域大放异彩。那么在文本领域是否也可以提取文本的特征呢?2014年Yoon Kim这位大佬揭晓了答案,完全可以,而且也可以取得不错的效果。在文本中,并不是所有的文本都是全部依赖,正如我们在之前一篇文章中利用TFIDF+LR 来解决这个问题一样,我们利用ngram信息,捕捉文本的局部相关性特征。CNN的原理也是如此,我们可以通过卷积核,来补捉文本的局部相关性特征。同时,我们也可以使用多个不同的卷积核,来捕捉多个ngram信息。
下面我以一张经典的图来简单介绍了以下TextCNN模型。在2014年提出,Yoon Kim使用了卷积 + 最大池化这两个在图像领域非常成功的好基友组合。我们先看一下他的结构。如下图所示,示意图中第一层输入为7*5的词向量矩阵,其中词向量维度为5,句子长度为7,然后第二层使用了3组宽度分别为2、3、4的卷积核,图中每种宽度的卷积核使用了两个。其中每个卷积核在整个句子长度上滑动,得到n个激活值,图中卷积核滑动的过程中没有使用padding,因此宽度为4的卷积核在长度为7的句子上滑动得到4个特征值。然后出场的就是卷积的好基友全局池化了,每一个卷积核输出的特征值列向量通过在整个句子长度上取最大值得到了6个特征值组成的feature map来供后级分类器作为分类的依据。
在本文中,我将借助有毒评论分类比赛数据https://www.kaggle.com/c/jigsaw-toxic-comment-classification-challenge,来实现下TextCNN,帮助有需要的朋友入门深度自然语言处理。
上面简单介绍了下TextCNN的结构,我将借助有毒评论分类比赛数据https://www.kaggle.com/c/jigsaw-toxic-comment-classification-challenge,来实现下TextCNN。有毒评论问题我们在上几篇文章中已经分析了文本的一些特征,这里我就不下详细描述了,大家有兴趣的话,可以看我之前的几篇文章。
本文的主要动机是为了解决RNN的不可并行性,利用CNN的高速并行性。因此,在performance上可以会有些差。话不多说,下面就是我们TextCNN的架构,采用keras简单实现了下,和原始论文的模型有些不一样。
def TextCNN(maxlen):
inp = Input(shape=(maxlen,))
x = Embedding(max_features, embed_size, weights=[embedding_matrix])(inp)
conv1 = Conv1D(filters=64, kernel_size=1, padding=same)(x)
conv1 = MaxPool1D(pool_size=32)(conv1)
conv2 = Conv1D(filters=64, kernel_size=2, padding=same)(x)
conv2 = MaxPool1D(pool_size=32)(conv2)
conv3 = Conv1D(filters=64, kernel_size=3, padding=same)(x)
conv3 = MaxPool1D(pool_size=32)(conv3)
conv4 = Conv1D(filters=64, kernel_size=4, padding=same)(x)
conv4 = MaxPool1D(pool_size=32)(conv4)
cnn = concatenate([conv1, conv2, conv3, conv4], axis=-1)
flat = Flatten()(cnn)
x = Dense(50, activation=relu)(flat)
x = Dropout(0.1)(x)
x = Dense(6, activation=sigmoid)(x)
model = Model(inputs=inp, outputs=x)
model.compile(loss=binary_crossentropy, optimizer=adam, metrics=[accuracy])
model.summary()
return model
model=TextCNN(maxlen)
model.fit(X_t, y, batch_size=32, epochs=2, validation_split=0.1)
submission = pd.DataFrame.from_dict({id: test[id]})
y_test = model.predict([X_te], batch_size=1024, verbose=1)
submission[list_classes] = pd.DataFrame(y_test)
上面就是一个非常粗糙的TextCNN模型,我提交了下,效果有点不太理想。如果想要提升下模型效果,可以考虑增加多层卷积,或者残差卷积等等。这仅仅作为入门的一个baseline。如果你想要运行完整代码可以参考我的github: https://github.com/hecongqing/TextClassification
推荐阅读
大幅减少GPU显存占用:可逆残差网络(The Reversible Residual Network)
AINLP-DBC GPU 云服务器租用平台建立,价格足够便宜
关于AINLP
AINLP 是一个有趣有AI的自然语言处理社区,专注于 AI、NLP、机器学习、深度学习、推荐算法等相关技术的分享,主题包括文本摘要、智能问答、聊天机器人、机器翻译、自动生成、知识图谱、预训练模型、推荐系统、计算广告、招聘信息、求职经验分享等,欢迎关注!加技术交流群请添加AINLP君微信(id:AINLP2),备注工作/研究方向+加群目的。