文本分类:Keras+RNN vs 传统机器学习
摘要:本文通过 Keras 实现了一个 RNN 文本分类学习的案例,并详细介绍了循环神经网络原理知识及与机器学习对比。
本文分享自华为云社区《基于Keras+RNN的文本分类vs基于传统机器学习的文本分类》,作者: eastmount 。
一.RNN 文本分类
1.RNN
循环神经网络英文是 Recurrent Neural Networks,简称 RNN。RNN 的本质概念是利用时序信息,在传统神经网络中,假设所有的输入(以及输出)都各自独立。但是,对于很多任务而言,这非常局限。举个例子,假如你想根据一句没说完的话,预测下一个单词,最好的办法就是联系上下文的信息。而 RNN(循环神经网络)之所以是“循环”,是因为它们对序列的每个元素执行相同的任务,而每次的结果都独立于之前的计算。
假设有一组数据 data0、data1、data2、data3,使用同一个神经网络预测它们,得到对应的结果。如果数据之间是有关系的,比如做菜下料的前后步骤,英文单词的顺序,如何让数据之间的关联也被神经网络学习呢?这就要用到——RNN。
比如存在 ABCD 数字,需要预测下一个数字 E,会根据前面 ABCD 顺序进行预测,这就称为记忆。预测之前,需要回顾以前的记忆有哪些,再加上这一步新的记忆点,最终输出 output,循环神经网络(RNN)就利用了这样的原理。
首先,让我们想想人类是怎么分析事物之间的关联或顺序的。人类通常记住之前发生的事情,从而帮助我们后续的行为判断,那么是否能让计算机也记住之前发生的事情呢?
在分析 data0 时,我们把分析结果存入记忆 Memory 中,然后当分析 data1 时,神经网络(NN)会产生新的记忆,但此时新的记忆和老的记忆没有关联,如上图所示。在 RNN 中,我们会简单的把老记忆调用过来分析新记忆,如果继续分析更多的数据时,NN 就会把之前的记忆全部累积起来。
下面是一个典型的 RNN 结果模型,按照时间点 t-1、t、t+1,每个时刻有不同的 x,每次计算会考虑上一步的 state 和这一步的 x(t),再输出 y 值。在该数学形式中,每次 RNN 运行完之后都会产生 s(t),当 RNN 要分析 x(t+1)时,此刻的 y(t+1)是由 s(t)和 s(t+1)共同创造的,s(t)可看作上一步的记忆。多个神经网络 NN 的累积就转换成了循环神经网络,其简化图如下图的左边所示。例如,如果序列中的句子有 5 个单词,那么,横向展开网络后将有五层神经网络,一层对应一个单词。
总之,只要你的数据是有顺序的,就可以使用 RNN,比如人类说话的顺序,电话号码的顺序,图像像素排列的顺序,ABC 字母的顺序等。RNN 常用于自然语言处理、机器翻译、语音识别、图像识别等领域。
2.文本分类
文本分类旨在对文本集按照一定的分类体系或标准进行自动分类标记,属于一种基于分类体系的自动分类。文本分类最早可以追溯到上世纪 50 年代,那时主要通过专家定义规则来进行文本分类;80 年代出现了利用知识工程建立的专家系统;90 年代开始借助于机器学习方法,通过人工特征工程和浅层分类模型来进行文本分类。现在多采用词向量以及深度神经网络来进行文本分类。
牛亚峰老师将传统的文本分类流程归纳如下图所示。在传统的文本分类中,基本上大部分机器学习方法都在文本分类领域有所应用。主要包括:
Naive Bayes
KNN
SVM
集合类方法
最大熵
神经网络
利用 Keras 框架进行文本分类的基本流程如下:
步骤 1:文本的预处理,分词->去除停用词->统计选择 top n 的词做为特征词
步骤 2:为每个特征词生成 ID
步骤 3:将文本转化成 ID 序列,并将左侧补齐
步骤 4:训练集 shuffle
步骤 5:Embedding Layer 将词转化为词向量
步骤 6:添加模型,构建神经网络结构
步骤 7:训练模型
步骤 8:得到准确率、召回率、F1 值
注意,如果使用 TFIDF 而非词向量进行文档表示,则直接分词去停后生成 TFIDF 矩阵后输入模型。本文将采用词向量、TFIDF 两种方式进行实验。
深度学习文本分类方法包括:
卷积神经网络(TextCNN)
循环神经网络(TextRNN)
TextRNN+Attention
TextRCNN(TextRNN+CNN)
推荐牛亚峰老师的文章:基于 word2vec 和 CNN 的文本分类 :综述 & 实践
二.基于传统机器学习贝叶斯算法的文本分类
1.MultinomialNB+TFIDF 文本分类
数据集采用基基伟老师的自定义文本,共 21 行数据,包括 2 类(小米手机、小米粥)。其基本流程是:
获取数据集 data 和 target
调用 Jieba 库实现中文分词
计算 TF-IDF 值,将词频矩阵转换为 TF-IDF 向量矩阵
调用机器学习算法进行训练和预测
实验评估及可视化分析
完整代码如下:
输出结果如下所示:
6 个预测数据的 accuracy ===> 0.67
绘制图形如下图所示:
2.GaussianNB+Word2Vec 文本分类
该方法与前面不同之处是采用 Word2Vec 进行词向量计算,将每行数据集分词,并计算每个特征词的词向量,接着转换为词向量矩阵,比如 15 行数据,每行数据 40 个特征词,每个特征词用 20 维度的词向量表示,即(15, 40, 20)。同时,由于词向量存在负数,所以需要使用 GaussianNB 算法替代 MultinomialNB 算法。
Word2Vec 详见作者前文:[Python人工智能] 九.gensim词向量Word2Vec安装及《庆余年》中文短文本相似度计算
sentences:传入的数据集序列(list of lists of tokens),默认值为 None
size:词向量维数,默认值为 100
window:同句中当前词和预测词的最大距离,默认值为 5
min_count:最低词频过滤,默认值为 5
workers:线程数,默认值为 3
sg:模型参数,其值为 0 表示 CBOW,值为 1 表示 skip-gram,默认值为 0
hs:模型参数,其值为 0 表示负例采样,值为 1 表示层次 softmax,默认值为 0
negative:负例样本数,默认值为 5
ns_exponent:用于形成负例样本的指数,默认值为 0.75
cbow_mean:上下文词向量参数,其值为 0 表示上下文词向量求和值,值为 1 表示上下文词向量平均值,默认值为 1
alpha:初始学习率,默认值为 0.025
min_alpha:最小学习率,默认值为 0.0001
完整代码如下:
输出结果如下所示:
6 个预测数据的 accuracy ===> 0.83
三.Keras 实现 RNN 文本分类
1.IMDB 数据集和序列预处理
(1) IMDB 数据集 Keras 框架为我们提供了一些常用的内置数据集。比如,图像识别领域的手写识别 MNIST 数据集、文本分类领域的电影影评 imdb 数据集等等。这些数据库可以用一条代码就可以调用:
(trainX, trainY), (testX, testY) = imdb.load_data(path=“imdb.npz”, num_words=max_features)
这些数据集是通过https://s3.amazonaws.com进行下载的,但有时该网站不能使用,需要下载数据至本地,再进行调用分析。Keras 数据集百度云链接:
作者将下载后的数据放在 C:\Users\Administrator.keras\datasets 文件夹下,如下图所示。
该数据集是互联网电影资料库(Internet Movie Database,简称 IMDb),它是一个关于电影演员、电影、电视节目、电视明星和电影制作的在线数据库。
imdb.npz 文件中数据和格式如下:
每个 list 是一个句子,句子中每个数字表示单词的编号。那么,怎么获取编号对应的单词?此时需要使用 imdb_word_index.json 文件,其文件格式如下:
共有 88584 个单词,采用 key-value 格式存放,key 代表单词,value 代表(单词)编号。词频(单词在语料中出现次数)越高编号越小,例如, “the:1”出现次数最高,编号为 1。
(2) 序列预处理在进行深度学习向量转换过程中,通常需要使用 pad_sequences()序列填充。其基本用法如下:
参数含义如下:
sequences:浮点数或整数构成的两层嵌套列表
maxlen:None 或整数,为序列的最大长度。大于此长度的序列将被截短,小于此长度的序列将在后部填 0
dtype:返回的 numpy array 的数据类型
padding:pre 或 post,确定当需要补 0 时,在序列的起始还是结尾补 0
truncating:pre 或 post,确定当需要截断序列时,从起始还是结尾截断
value:浮点数,此值将在填充时代替默认的填充值 0
返回值是个 2 维张量,长度为 maxlen
基本用法如下所示:
在自然语言中一般和分词器一起使用。
2.词嵌入模型训练
此时我们将通过词嵌入模型进行训练,具体流程包括:
导入 IMDB 数据集
数据集转换为序列
创建 Embedding 词嵌入模型
神经网络训练
完整代码如下:
输出结果如下所示:
显示矩阵如下图所示:
3.RNN 文本分类
RNN 对 IMDB 电影数据集进行文本分类的完整代码如下所示:
输出结果如下所示,三个 Epoch 训练。
训练数据的 accuracy ===> 0.9075
评估数据的 val_accuracy ===> 0.7844
Epoch 可以用下图进行形象的表示。
绘制的 accuracy 和 val_accuracy 曲线如下图所示:
loss: 0.2329 - accuracy: 0.9075 - val_loss: 0.5050 - val_accuracy: 0.7844
四.RNN 实现中文数据集的文本分类
1.RNN+Word2Vector 文本分类
第一步,导入文本数据集并转换为词向量。
此时输出结果如下所示:
第二步,建立 RNN 神经网络结构,使用 Bi-GRU 模型,并进行训练与预测。
输出结果如下图所示,发现 accuracy 和 val_accuracy 值非常不理想。怎么解决呢?
神经网络模型和 Epoch 训练结果如下图所示:
test loss: 0.7160684466362
test accuracy: 0.33333334
这里补充一个知识点——EarlyStopping。EarlyStopping 是 Callbacks 的一种,callbacks 用于指定在每个 epoch 开始和结束的时候进行哪种特定操作。Callbacks 中有一些设置好的接口,可以直接使用,如 acc、val_acc、loss 和 val_loss 等。EarlyStopping 则是用于提前停止训练的 callbacks,可以达到当训练集上的 loss 不在减小(即减小的程度小于某个阈值)的时候停止继续训练。上面程序中,当我们 loss 不在减小时就可以调用 Callbacks 停止训练。推荐文章:[深度学习] keras的EarlyStopping使用与技巧 - zwqjoy
最后给出该部分的完整代码:
2.LSTM+Word2Vec 文本分类
接着我们使用 LSTM 和 Word2Vec 进行文本分类。整个神经网络的结构很简单,第一层是嵌入层,将文本中的单词转化为向量;之后经过一层 LSTM 层,使用 LSTM 中最后一个时刻的隐藏状态;再接一个全连接层,即可完成整个网络的构造。
注意矩阵形状的变换。
X_train = X_train.reshape(len(y_train), maxlen*max_features)
X_test = X_test.reshape(len(y_test), maxlen*max_features)
完整代码如下所示:
输出结果如下所示,仍然不理想。
test loss: 0.712007462978363
test accuracy: 0.33333334
对应的图形如下所示。
3.LSTM+TFIDF 文本分类
同时,补充 LSTM+TFIDF 文本分类代码。
输出结果如下所示:
test loss: 0.7694947719573975
test accuracy: 0.33333334
对应图形如下:
4.机器学习和深度学习对比分析
最终结果我们进行简单对比,发现机器学习比深度学习好,这是为什么呢?我们又能做哪些提升呢?
MultinomialNB+TFIDF:test accuracy = 0.67
GaussianNB+Word2Vec:test accuracy = 0.83
RNN+Word2Vector:test accuracy = 0.33333334
LSTM+Word2Vec:test accuracy = 0.33333334
LSTM+TFIDF:test accuracy = 0.33333334
作者结合大佬们的文章及自己的经验对其进行简单分析,原因如下:
一是 数据集预处理的原因,上述代码没有进行停用词过滤,大量标点符号和停用词影响了文本分类效果。同时词向量的维度设置也需要进行调试。
二是 数据集大小的原因。数据量少的情况下,推荐使用 CNN,RNN 的过拟合会让你欲哭无泪。如果数据量多,也许 RNN 效果会更好。如果为了创新,RLSTM 和 RCNN 等都是近几年不错的选择。但如果仅仅是为了应用,用普通的机器学习方法已经足够优秀了(特别是新闻数据集),如果考虑上时间成本,贝叶斯无疑才是真正的最好选择。
三是 CNN 和 RNN 适用性不同。CNN 擅长空间特征的学习和捕获,RNN 擅长时序特征的捕获。从结构来讲,RNN 更胜一筹。主流的 NLP 问题,比如翻译、生成文本,seq2seq(俩独立 RNN)的引入突破了很多之前的 benchmark。Attention 的引入是为了解决长句问题,其本质就是外挂了额外的一个 softmax 去学词和词的映射关系,有点像外挂存储,其根源来自一篇名为“neural turing machine”的 paper。
四是 不同的数据集适应不同的方法,各种方法各有所长。有的情感分析 GRU 好于 CNN,而新闻分类、文本分类竞赛 CNN 可能会有优势。CNN 具有速度优势,基本比较大的数据上 CNN 能加大参数,拟合更多种类的 local phrase frequency,获得更好的效果。如果你是想做系统,两个算法又各有所长,就是 ensemble 登场的时候了。
五是 在文本情感分类领域,GRU 是要好于 CNN,并且随着句子长度的增长,GRU 的这一优势会进一步放大。当句子的情感分类是由整个句子决定的时候,GRU 会更容易分类正确, 当句子的情感分类是由几个局部的 key-phrases 决定的时候,CNN 会更容易分类正确。
总之,我们在真实的实验中,尽量选择适合我们数据集的算法,这也是实验中的一部分,我们需要对比各种算法、各种参数、各种学习模型,从而找到一个更好的算法。后续作者会进一步学习 TextCNN、Attention、BiLSTM、GAN 等算法,希望能与大家一起进步。
参考及推荐文章:请问对于中文长文本分类,是CNN效果好,还是RNN效果好?- 知乎
五.总结
写道这里,这篇文章就结束了。希望对您有所帮助,同时文章中不足或错误的地方,欢迎读者提出。这些实验都是我在做论文研究或项目评价常见的一些问题,希望读者带着这些问题,结合自己的需求进行深入的思考,更希望大家能学以致用。
总之,本文通过 Keras 实现了一个 RNN 文本分类学习的案例,并详细介绍了循环神经网络原理知识及与机器学习对比。最后,作为人工智能的菜鸟,我希望自己能不断进步并深入,后续将它应用于图像识别、网络安全、对抗样本等领域,指导大家撰写简单的学术论文,一起加油!
感恩能与大家在华为云遇见!希望能与大家一起在华为云社区共同成长。原文地址:https://blog.csdn.net/Eastmount/article/details/105165164(By:娜璋之家 Eastmount 2021-11-09 夜于武汉)
参考文献:
再次感谢参考文献前辈和老师们的贡献,同时也参考了作者的 Python 人工智能和数据分析系列文章,源码请在 github 下载。
[1] Keras的imdb和MNIST数据集无法下载问题解决 - 摸金青年v
[2] 官网实例详解4.42(imdb.py)-keras学习笔记四 - wyx100
[4] TextCNN文本分类(keras实现)- 强推Asia-Lee老师的文章
[5] Keras 之文本分类实现 - 强推知乎王奕磊老师的文章
[6 ]自然语言处理入门(二)–Keras实现BiLSTM+Attention新闻标题文本分类 - ilivecode
[7] 用深度学习(CNN RNN Attention)解决大规模文本分类问题 - 综述和实践 - 知乎清凇
[8] 基于 word2vec 和 CNN 的文本分类 :综述 & 实践 - 牛亚峰 serena
[9] https://github.com/keras-team/keras
[10] [深度学习] keras的EarlyStopping使用与技巧 - zwqjoy
[11] 深度学习为什么会出现validation accuracy大于train accuracy的现象?- ICOZ
[12] Keras实现CNN文本分类 - vivian_ll
[13] Keras文本分类实战(上)- weixin_34351321
[14] 请问对于中文长文本分类,是CNN效果好,还是RNN效果好?- 知乎
版权声明: 本文为 InfoQ 作者【华为云开发者社区】的原创文章。
原文链接:【http://xie.infoq.cn/article/b75db0a88001f3a35b4b84893】。文章转载请联系作者。
评论