当前位置:   article > 正文

NLP(自然语言处理)--新浪新闻文本分类(tensorflow+RNN)详细解释_cnews.train.txt

cnews.train.txt

github链接:https://github.com/gaussic/text-classification-cnn-rnn(结构化编程)

以下将以上结构化编程统一起来,并对每行代码进行了解释。

 数据集

数据集下载链接: https://pan.baidu.com/s/1oLZZF4AHT5X_bzNl2aF2aQ 提取码: 5sea
下载压缩文件cnews.zip完成后,选择解压到cnews

cnew文件夹中有4个文件:
1.训练集文件cnews.train.txt
2.测试集文件cnew.test.txt
3.验证集文件cnews.val.txt
4.词汇表文件cnews.vocab.txt
共有10个类别,65000个样本数据,其中训练集50000条,测试集10000条,验证集5000条。

代码文件需要放到和cnews文件夹同级目录

 

代码解释

  1. import warnings
  2. warnings.filterwarnings('ignore') #ignore中文叫做忽略,即不打印警告信息;
  3. import time
  4. startTime = time.time() #把程序开始时间赋值给变量startTime;
  5. def printUsedTime(): #定义printUsedTime函数,作用是打印程序运行时间
  6. used_time = time.time() - startTime
  7. print('used time: %.2f seconds' %used_time)
  8. with open('./cnews/cnews.train.txt', encoding='utf8') as file: #调用open方法打开文本文件
  9. line_list = [k.strip() for k in file.readlines()] #使用列表推导式得到文本文件中的行内容列表赋值给变量label_list
  10. train_label_list = [k.split()[0] for k in line_list] #得到训练集的标签列表赋值给变量train_label_list
  11. train_content_list = [k.split(maxsplit=1)[1] for k in line_list] #得到训练集的内容列表赋值给变量train_content_list
  12. with open('./cnews/cnews.vocab.txt', encoding='utf8') as file: #得到词汇表文件cnews.vocab.txt中的词汇列表赋值给变量vocabulary_list
  13. vocabulary_list = [k.strip() for k in file.readlines()]
  14. print('0.load train data finished') #表示加载训练集数据完成
  15. printUsedTime() #打印程序运行至此步使用的时间
  16. word2id_dict = dict([(b, a) for a, b in enumerate(vocabulary_list)]) #使用列表推导式得到词汇及其id对应的列表,并调用dict方法将列表强制转换为字典
  17. list(word2id_dict.items())[:5] #打印变量word2id_dict的前5
  18. content2idList = lambda content : [word2id_dict[word] for word in content if word in word2id_dict] #使用列表推导式和匿名函数定义函数content2idlist,函数作用是将文章中的每个字转换为id
  19. train_idlist_list = [content2idList(content) for content in train_content_list] #使用列表推导式得到的结果是列表的列表,总列表train_idlist_list中的元素是每篇文章中的字对应的id列表
  20. vocabolary_size = 5000 # 词汇表大小
  21. sequence_length = 150 # 序列长度
  22. embedding_size = 64 # 词向量大小
  23. num_hidden_units = 256 # LSTM细胞隐藏层大小
  24. num_fc1_units = 64 #第1个全连接下一层的大小
  25. dropout_keep_probability = 0.5 # dropout保留比例
  26. num_classes = 10 # 类别数量
  27. learning_rate = 1e-3 # 学习率
  28. batch_size = 64 # 每批训练大小
  29. import tensorflow.contrib.keras as kr #获得能够用于模型训练的特征矩阵和预测目标值
  30. train_X = kr.preprocessing.sequence.pad_sequences(train_idlist_list, sequence_length) #将每个样本统一长度为seq_length,即600
  31. from sklearn.preprocessing import LabelEncoder
  32. labelEncoder = LabelEncoder() #实例化LabelEncoder对象
  33. train_y = labelEncoder.fit_transform(train_label_list) #调用LabelEncoder对象的fit_transform方法做标签编码
  34. train_Y = kr.utils.to_categorical(train_y, num_classes) #调用keras.untils库的to_categorical方法将标签编码的结果再做Ont-Hot编码
  35. import tensorflow as tf
  36. tf.reset_default_graph() #重置tensorflow图,加强代码的健壮性
  37. X_holder = tf.placeholder(tf.int32, [None, sequence_length]) #将每次训练的特征矩阵X和预测目标值Y赋值给变量X_holder和Y_holder
  38. Y_holder = tf.placeholder(tf.float32, [None, num_classes])
  39. print('1.data preparation finished') #数据准备完成
  40. printUsedTime() #运行至此步使用的时间
  41. #搭建神经网络
  42. embedding = tf.get_variable('embedding',
  43. [vocabolary_size, embedding_size]) #get_variable方法实例化可以更新的模型参数embedding,矩阵形状为vocabulary_size*embedding_size,即5000*64
  44. embedding_inputs = tf.nn.embedding_lookup(embedding,
  45. X_holder) #embedding_inputs的形状为batch_size*sequence_length*embedding_size,即50*100*64
  46. gru_cell = tf.contrib.rnn.GRUCell(num_hidden_units) #调用tf.contrib.rnn.GRUCell方法实例化GRU细胞对象
  47. outputs, state = tf.nn.dynamic_rnn(gru_cell,
  48. embedding_inputs,
  49. dtype=tf.float32) #动态计算循环神经网络中的结果,outputs是每个细胞的h的结果,state是最后一个细胞的h和c的结果,LSTM网络中h是短时记忆矩阵,c是长时记忆矩阵
  50. last_cell = outputs[:, -1, :] #获取最后一个细胞的h,即最后一个细胞的短时记忆矩阵,等价于state.h
  51. full_connect1 = tf.layers.dense(last_cell,
  52. num_fc1_units) #添加全连接层,tf.layers.dense方法结果赋值给变量full_connect1,形状为batch_size*num_fc1_units,即50*128
  53. full_connect1_dropout = tf.contrib.layers.dropout(full_connect1,
  54. dropout_keep_probability)
  55. full_connect1_activate = tf.nn.relu(full_connect1_dropout)
  56. full_connect2 = tf.layers.dense(full_connect1_activate,
  57. num_classes)
  58. predict_Y = tf.nn.softmax(full_connect2)
  59. cross_entropy = tf.nn.softmax_cross_entropy_with_logits_v2(labels=Y_holder,
  60. logits=full_connect2)
  61. loss = tf.reduce_mean(cross_entropy) #使用交叉熵作为损失函数
  62. optimizer = tf.train.AdamOptimizer(learning_rate)
  63. train = optimizer.minimize(loss)
  64. isCorrect = tf.equal(tf.argmax(Y_holder,1), tf.argmax(predict_Y, 1)) #计算预测准确率
  65. accuracy = tf.reduce_mean(tf.cast(isCorrect, tf.float32))
  66. print('2.build model finished') #表示搭建神经网络完成
  67. printUsedTime()
  68. #参数初始化
  69. init = tf.global_variables_initializer()
  70. session = tf.Session()
  71. session.run(init)
  72. print('3.initialize variable finished')
  73. printUsedTime()
  74. #获取文本文件cnews.test.txt,即测试集中的数据
  75. with open('./cnews/cnews.test.txt', encoding='utf8') as file:
  76. line_list = [k.strip() for k in file.readlines()]
  77. test_label_list = [k.split()[0] for k in line_list]
  78. test_content_list = [k.split(maxsplit=1)[1] for k in line_list]
  79. test_idlist_list = [content2idList(content) for content in test_content_list]
  80. test_X = kr.preprocessing.sequence.pad_sequences(test_idlist_list, sequence_length)
  81. test_y = labelEncoder.transform(test_label_list)
  82. test_Y = kr.utils.to_categorical(test_y, num_classes)
  83. print('4.load test data finished')
  84. printUsedTime()
  85. print('5.begin model training')
  86. import random
  87. for i in range(5000):
  88. selected_index = random.sample(list(range(len(train_y))), k=batch_size) #从训练集中选取batch_size大小,即50个样本做批量梯度下降
  89. batch_X = train_X[selected_index]
  90. batch_Y = train_Y[selected_index]
  91. session.run(train, {X_holder:batch_X, Y_holder:batch_Y}) #每运行1次,表示模型训练1
  92. step = i + 1 #记录当前步数,赋值给变量step
  93. if step % 100 == 0:
  94. selected_index = random.sample(list(range(len(test_y))), k=200) #从测试集中随机选取200个样本
  95. batch_X = test_X[selected_index]
  96. batch_Y = test_Y[selected_index]
  97. #计算损失值loss_value、准确率accuracy_value
  98. loss_value, accuracy_value = session.run([loss, accuracy], {X_holder:batch_X, Y_holder:batch_Y})
  99. print('step:%d loss:%.4f accuracy:%.4f' %(step, loss_value, accuracy_value))
  100. printUsedTime()
  101. #以上已经完成循环神经网络的训练
  102. ##词汇表
  103. '''
  104. 本项目已提供词汇表文件cnews.vocab.txt,但在实践中需要自己统计语料的词汇表。
  105. 下面代码可以由内容列表content_list产生词汇表:
  106. from collections import Counter
  107. def getVocabularyList(content_list, vocabulary_size):
  108. allContent_str = ''.join(content_list)
  109. counter = Counter(allContent_str)
  110. vocabulary_list = [k[0] for k in counter.most_common(vocabulary_size)]
  111. return vocabulary_list
  112. def makeVocabularyFile(content_list, vocabulary_size):
  113. vocabulary_list = getVocabularyList(content_list, vocabulary_size)
  114. with open('vocabulary.txt', 'w', encoding='utf8') as file:
  115. for vocabulary in vocabulary_list:
  116. file.write(vocabulary + '\n')
  117. makeVocabularyFile(train_content_list, 5000)
  118. 本段代码产生的文件,与提供的词汇表文件cnews.vocab.txt稍有不同。
  119. 造成原因有2点:
  120. 1.词汇表文件的第1个字<PAD>是补全字,无实际含义,与kr.preprocessing.sequence.pad_sequences方法补全的0对应;
  121. 2.源代码作者使用了训练集、验证集、测试集作为总语料库,上面一段代码只使用了训练集作为语料库。
  122. '''
  123. ##计算混淆矩阵
  124. import numpy as np
  125. import pandas as pd
  126. from sklearn.metrics import confusion_matrix
  127. def predictAll(test_X, batch_size=100):
  128. predict_value_list = []
  129. for i in range(0, len(test_X), batch_size):
  130. selected_X = test_X[i: i + batch_size]
  131. predict_value = session.run(predict_Y, {X_holder:selected_X})
  132. predict_value_list.extend(predict_value)
  133. return np.array(predict_value_list)
  134. Y = predictAll(test_X)
  135. y = np.argmax(Y, axis=1)
  136. predict_label_list = labelEncoder.inverse_transform(y)
  137. pd.DataFrame(confusion_matrix(test_label_list, predict_label_list),
  138. columns=labelEncoder.classes_,
  139. index=labelEncoder.classes_ )
  140. #从混淆矩阵的结果可以看出哪些分类效果较差。
  141. ##报告表
  142. #下面一段代码能够成功运行的前提是已经运行混淆矩阵代码。
  143. import numpy as np
  144. from sklearn.metrics import precision_recall_fscore_support
  145. def eval_model(y_true, y_pred, labels):
  146. # 计算每个分类的Precision, Recall, f1, support
  147. p, r, f1, s = precision_recall_fscore_support(y_true, y_pred)
  148. # 计算总体的平均Precision, Recall, f1, support
  149. tot_p = np.average(p, weights=s)
  150. tot_r = np.average(r, weights=s)
  151. tot_f1 = np.average(f1, weights=s)
  152. tot_s = np.sum(s)
  153. res1 = pd.DataFrame({
  154. u'Label': labels,
  155. u'Precision': p,
  156. u'Recall': r,
  157. u'F1': f1,
  158. u'Support': s
  159. })
  160. res2 = pd.DataFrame({
  161. u'Label': ['总体'],
  162. u'Precision': [tot_p],
  163. u'Recall': [tot_r],
  164. u'F1': [tot_f1],
  165. u'Support': [tot_s]
  166. })
  167. res2.index = [999]
  168. res = pd.concat([res1, res2])
  169. return res[['Label', 'Precision', 'Recall', 'F1', 'Support']]
  170. eval_model(test_label_list, predict_label_list, labelEncoder.classes_)
  171. '''
  172. 1.本项目数据共有65000条。
  173. 2.分类模型的评估指标F1score为0.89左右,总体来说这个分类模型比CNN模型效果差,而且训练时间更久;
  174. 3.本文为了节省实验时间,设置sequence_length为150,迭代5000次总共花费1123秒,即18分43秒;
  175. 4.如果设置sequence_length为300,迭代5000次总共花费时间2184秒,即36分24秒,评估指标F1score为0.9282。
  176. '''

 

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号