本文是基于TensorFlow使用RNN进行的中文文本分类的一篇学习笔记,作为初学者,参考别人的例子基本是重复写了一遍,刚开始遇到了很多问题,各种查资料,看代码,个人觉得自己动手写完一个小项目是很有效的学习方式。
首先简单说一下方法(这个例子很多人都做过,可作为初学者学习的入手Project)
代码地址:snow123321/Text-Classification-RNN
1、 RNN-中文文本分类
环境
Python 3
TensorFlow
数据集
使用THUCNews的一个子集进行训练与测试,数据集划分如下:
训练集cnews.train.txt 50000条
验证集cnews.val.txt 5000条
测试集cnews.test.txt 10000条
共分为10个类别:"体育","财经","房产","家居","教育","科技","时尚","时政","游戏","娱乐"。
cnews.vocab.txt为词汇表,字符级,大小为5000,根据频次选择的。
文件说明
data_loader.py:文本数据处理
lstmrnn_model.py:RNN模型,实验的基本配置参数
run_RNN.py:主函数文件
结果
在3epoch时停止训练,测试集上准确率85%,可继续通过调参提升准确率。

2、学习过程中的问题
(由于是刚开始学,也是参考的别人的例子然后自己基本是重复写了一遍,这个过程中刚开始有很多不明白的地方,通过查资料最后才弄明白)
2.1、padding及embedding
词汇表中第一个词为手动添加的“<PAD>”,这样转换时word_id为0表示<PAD>,这个词在实际语料中是不存在的。是因为后面会把所有句子都padding为同样的长度,padding填充的是0,这样在后面训练词向量的时候,所有句子padding的部分的词向量都是一样的。
此次实验用的是字符级词向量(char embedding),调用tensorflow的API实现。
embedding = tf.get_variable("embedding",shape=[self.config.vocab_size,self.config.embendding_dim])
embedding_inputs = tf.nn.embedding_lookup(embedding,self.input_x)
embedding是在最开始随机初始化,然后在模型训练过程中一起训练的!tf.nn.embedding_lookup的作用是在embedding中根据输入的词id查找对应的向量。这里也可以使用预训练好的词向量,在训练时就不再训练词向量了,这样还可以设置输入序列长度可变,后面准备试试这种方法。
2.2、几个函数
(1)
self.logits = tf.layers.dense(fc,self.config.num_classes,name = "softmax")
self.y_pred = tf.argmax(self.logits,1)
这里logits是每个样本在各个类别上的概率,形状为[样本数*类别数];
tf.argmax(input, axis=None),返回最大值所在的索引,axis=0返回每一列最大值的索引,axis=1返回每一行最大值的索引。
(2)outputs,和states
outputs, states = tf.nn.dynamic_rnn(rnn_cells,inputs = embedding_inputs,dtype = tf.float32)
last_outputs = outputs[:,-1,:] #取最后一个时序输出结果
outputs大小为[batch_size,n_steps,n_inputs],即和输入X大小一样;
states为最终状态,一般情况下大小为[batch_size,cell.output_size],但当cell为lstm时,大小为[2,batch_size,cell.output_size],分别对应lstm的cell state和hidden state。
当有多个隐藏层时,outputs是最后一层的输出,states是每一层最终状态的输出