什么是 Word2vec?

在聊 Word2vec 之前,先聊聊 NLP (自然语言处理)。NLP 里面,最细粒度的是 词语,词语组成句子,句子再组成段落、篇章、文档。所以处理 NLP 的问题,首先就要拿词语开刀。

举个简单例子,判断一个词的词性,是动词还是名词。用机器学习的思路,我们有一系列样本(x,y),这里 x 是词语,y 是它们的词性,我们要构建 f(x)->y 的映射,但这里的数学模型 f(比如神经网络、SVM)只接受数值型输入,而 NLP 里的词语,是人类的抽象总结,是符号形式的(比如中文、英文、拉丁文等等),所以需要把他们转换成数值形式,或者说——嵌入到一个数学空间里,这种嵌入方式,就叫词嵌入(word embedding),而 Word2vec,就是词嵌入( word embedding) 的一种

我在前作『都是套路: 从上帝视角看透时间序列和数据挖掘』提到,大部分的有监督机器学习模型,都可以归结为:

f(x)->y
在 NLP 中,把 x 看做一个句子里的一个词语,y 是这个词语的上下文词语,那么这里的 f,便是 NLP 中经常出现的『语言模型』(language model),这个模型的目的,就是判断 (x,y) 这个样本,是否符合自然语言的法则,更通俗点说就是:词语x和词语y放在一起,是不是人话。

Word2vec 正是来源于这个思想,但它的最终目的,不是要把 f 训练得多么完美,而是只关心模型训练完后的副产物——模型参数(这里特指神经网络的权重),并将这些参数,作为输入 x 的某种向量化的表示,这个向量便叫做——词向量(这里看不懂没关系,下一节我们详细剖析)。

我们来看个例子,如何用 Word2vec 寻找相似词:

对于一句话:『她们 夸 吴彦祖 帅 到 没朋友』,如果输入 x 是『吴彦祖』,那么 y 可以是『她们』、『夸』、『帅』、『没朋友』这些词
现有另一句话:『她们 夸 我 帅 到 没朋友』,如果输入 x 是『我』,那么不难发现,这里的上下文 y 跟上面一句话一样
从而 f(吴彦祖) = f(我) = y,所以大数据告诉我们:我 = 吴彦祖(完美的结论)
3.2. Skip-gram 和 CBOW 模型
上面我们提到了语言模型

如果是用一个词语作为输入,来预测它周围的上下文,那这个模型叫做『Skip-gram 模型』
而如果是拿一个词语的上下文作为输入,来预测这个词语本身,则是 『CBOW 模型』
3.2.1 Skip-gram 和 CBOW 的简单情形
我们先来看个最简单的例子。上面说到, y 是 x 的上下文,所以 y 只取上下文里一个词语的时候,语言模型就变成:

用当前词 x 预测它的下一个词 y
但如上面所说,一般的数学模型只接受数值型输入,这里的 x 该怎么表示呢? 显然不能用 Word2vec,因为这是我们训练完模型的产物,现在我们想要的是 x 的一个原始输入形式。

答案是:one-hot encoder

所谓 one-hot encoder,其思想跟特征工程里处理类别变量的 one-hot 一样(参考我的前作『数据挖掘比赛通用框架』、『深挖One-hot和Dummy背后的玄机』)。本质上是用一个只含一个 1、其他都是 0 的向量来唯一表示词语。

我举个例子,假设全世界所有的词语总共有 V 个,这 V 个词语有自己的先后顺序,假设『吴彦祖』这个词是第1个词,『我』这个单词是第2个词,那么『吴彦祖』就可以表示为一个 V 维全零向量、把第1个位置的0变成1,而『我』同样表示为 V 维全零向量、把第2个位置的0变成1。这样,每个词语都可以找到属于自己的唯一表示。

OK,那我们接下来就可以看看 Skip-gram 的网络结构了,x 就是上面提到的 one-hot encoder 形式的输入,y 是在这 V 个词上输出的概率,我们希望跟真实的 y 的 one-hot encoder 一样。

首先说明一点:隐层的激活函数其实是线性的,相当于没做任何处理(这也是 Word2vec 简化之前语言模型的独到之处),我们要训练这个神经网络,用反向传播算法,本质上是链式求导,在此不展开说明了,

当模型训练完后,最后得到的其实是神经网络的权重,比如现在输入一个 x 的 one-hot encoder: [1,0,0,…,0],对应刚说的那个词语『吴彦祖』,则在输入层到隐含层的权重里,只有对应 1 这个位置的权重被激活,这些权重的个数,跟隐含层节点数是一致的,从而这些权重组成一个向量 vx 来表示x,而因为每个词语的 one-hot encoder 里面 1 的位置是不同的,所以,这个向量 vx 就可以用来唯一表示 x。

注意:上面这段话说的就是 Word2vec 的精髓!!

此外,我们刚说了,输出 y 也是用 V 个节点表示的,对应V个词语,所以其实,我们把输出节点置成 [1,0,0,…,0],它也能表示『吴彦祖』这个单词,但是激活的是隐含层到输出层的权重,这些权重的个数,跟隐含层一样,也可以组成一个向量 vy,跟上面提到的 vx 维度一样,并且可以看做是词语『吴彦祖』的另一种词向量。而这两种词向量 vx 和 vy,正是 Mikolov 在论文里所提到的,『输入向量』和『输出向量』,一般我们用『输入向量』。

需要提到一点的是,这个词向量的维度(与隐含层节点数一致)一般情况下要远远小于词语总数 V 的大小,所以 Word2vec 本质上是一种降维操作——把词语从 one-hot encoder 形式的表示降维到 Word2vec 形式的表示。

Skip-gram 更一般的情形

上面讨论的是最简单情形,即 y 只有一个词,当 y 有多个词时,网络结构如下:

可以看成是 单个x->单个y 模型的并联,cost function 是单个 cost function 的累加(取log之后)
如果你想深入探究这些模型是如何并联、 cost function 的形式怎样,不妨仔细阅读参考资料4. 在此我们不展开。

3.2.3 CBOW 更一般的情形
跟 Skip-gram 相似,只不过:

Skip-gram 是预测一个词的上下文,而 CBOW 是用上下文预测这个词
网络结构如下

更 Skip-gram 的模型并联不同,这里是输入变成了多个单词,所以要对输入处理下(一般是求和然后平均),输出的 cost function 不变,在此依然不展开,建议你阅读参考资料4.

Word2vec 的训练trick

相信很多初次踩坑的同学,会跟我一样陷入 Mikolov 那篇论文(参考资料1.)里提到的 hierarchical softmax 和 negative sampling 里不能自拔,但其实,它们并不是 Word2vec 的精髓,只是它的训练技巧,但也不是它独有的训练技巧。 Hierarchical softmax 只是 softmax 的一种近似形式(详见参考资料7.),而 negative sampling 也是从其他方法借鉴而来。

为什么要用训练技巧呢? 如我们刚提到的,Word2vec 本质上是一个语言模型,它的输出节点数是 V 个,对应了 V 个词语,本质上是一个多分类问题,但实际当中,词语的个数非常非常多,会给计算造成很大困难,所以需要用技巧来加速训练。

这里我总结了一下这两个 trick 的本质,有助于大家更好地理解,在此也不做过多展开,有兴趣的同学可以深入阅读参考资料1.~7.

hierarchical softmax
本质是把 N 分类问题变成 log(N)次二分类

negative sampling
本质是预测总体类别的一个子集

利用cnn和rnn分类文本

#!/usr/bin/python
# -*- coding: utf-8 -*-from __future__ import print_functionimport os
import sys
import time
from datetime import timedeltaimport numpy as np
import tensorflow as tf
from sklearn import metricsfrom cnn_model import TCNNConfig, TextCNN
from data.test import read_vocab, read_category, batch_iter, process_file, build_vocabbase_dir = r'C:\Users\zhang\Desktop\doubledata\tiss\CNN\layer2\tiab'
train_dir = os.path.join(base_dir, 'train_6.txt')
test_dir = os.path.join(base_dir, 'test_6.txt')
val_dir = os.path.join(base_dir, 'val_6.txt')
vocab_dir = os.path.join(base_dir, 'vocab_6.txt')save_dir = 'checkpoints/textcnn'
save_path = os.path.join(save_dir, 'best_validation')  # 最佳验证结果保存路径def get_time_dif(start_time):"""获取已使用时间"""end_time = time.time()time_dif = end_time - start_timereturn timedelta(seconds=int(round(time_dif)))def feed_data(x_batch, y_batch, keep_prob):feed_dict = {model.input_x: x_batch,model.input_y: y_batch,model.keep_prob: keep_prob}return feed_dictdef evaluate(sess, x_, y_):"""评估在某一数据上的准确率和损失"""data_len = len(x_)batch_eval = batch_iter(x_, y_, 128)total_loss = 0.0total_acc = 0.0for x_batch, y_batch in batch_eval:batch_len = len(x_batch)feed_dict = feed_data(x_batch, y_batch, 1.0)loss, acc = sess.run([model.loss, model.acc], feed_dict=feed_dict)total_loss += loss * batch_lentotal_acc += acc * batch_lenreturn total_loss / data_len, total_acc / data_lendef train():print("Configuring TensorBoard and Saver...")# 配置 Tensorboard,重新训练时,请将tensorboard文件夹删除,不然图会覆盖tensorboard_dir = 'tensorboard/textcnn'if not os.path.exists(tensorboard_dir):os.makedirs(tensorboard_dir)#显示标量信息tf.summary.scalar("loss", model.loss)tf.summary.scalar("accuracy", model.acc)#merge_all 可以将所有summary全部保存到磁盘merged_summary = tf.summary.merge_all()#指定一个文件用来保存图writer = tf.summary.FileWriter(tensorboard_dir)# 配置 Saver# 将训练好的模型参数保存起来,以便以后进行验证或测试。saver = tf.train.Saver()if not os.path.exists(save_dir):os.makedirs(save_dir)print("Loading training and validation data...")# 载入训练集与验证集start_time = time.time()x_train, y_train = process_file(train_dir, word_to_id, cat_to_id, config.seq_length)x_val, y_val = process_file(val_dir, word_to_id, cat_to_id, config.seq_length)time_dif = get_time_dif(start_time)print("Time usage:", time_dif)# 创建session# Session提供了Operation执行和Tensor求值的环境session = tf.Session()session.run(tf.global_variables_initializer())writer.add_graph(session.graph)print('Training and evaluating...')start_time = time.time()total_batch = 0  # 总批次best_acc_val = 0.0  # 最佳验证集准确率last_improved = 0  # 记录上一次提升批次require_improvement = 1000  # 如果超过1000轮未提升,提前结束训练flag = Falsefor epoch in range(config.num_epochs):print('Epoch:', epoch + 1)batch_train = batch_iter(x_train, y_train, config.batch_size)for x_batch, y_batch in batch_train:feed_dict = feed_data(x_batch, y_batch, config.dropout_keep_prob)if total_batch % config.save_per_batch == 0:# 每多少轮次将训练结果写入tensorboard scalars = session.run(merged_summary, feed_dict=feed_dict)writer.add_summary(s, total_batch)if total_batch % config.print_per_batch == 0:# 每多少轮次输出在训练集和验证集上的性能feed_dict[model.keep_prob] = 1.0loss_train, acc_train = session.run([model.loss, model.acc], feed_dict=feed_dict)loss_val, acc_val = evaluate(session, x_val, y_val)  # todoif acc_val > best_acc_val:# 保存最好结果best_acc_val = acc_vallast_improved = total_batchsaver.save(sess=session, save_path=save_path)improved_str = '*'else:improved_str = ''time_dif = get_time_dif(start_time)msg = 'Iter: {0:>6}, Train Loss: {1:>6.2}, Train Acc: {2:>7.2%},' \+ ' Val Loss: {3:>6.2}, Val Acc: {4:>7.2%}, Time: {5} {6}'print(msg.format(total_batch, loss_train, acc_train, loss_val, acc_val, time_dif, improved_str))feed_dict[model.keep_prob] = config.dropout_keep_probsession.run(model.optim, feed_dict=feed_dict)  # 运行优化total_batch += 1if total_batch - last_improved > require_improvement:# 验证集正确率长期不提升,提前结束训练print("No optimization for a long time, auto-stopping...")flag = Truebreak  # 跳出循环if flag:  # 同上breakprint(best_acc_val)with open(r'C:\Users\zhang\Desktop\doubledata\tiss\CNN\layer2\tiab\6_cnn_layer1.txt', 'a+') as f:now = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))f.write('=' * 60)f.write('\nTime: {}\n'.format(now))f.write('best_acc_val:\n')f.write(str(best_acc_val))def test():print("Loading test data...")start_time = time.time()x_test, y_test = process_file(test_dir, word_to_id, cat_to_id, config.seq_length)session = tf.Session()session.run(tf.global_variables_initializer())saver = tf.train.Saver()saver.restore(sess=session, save_path=save_path)  # 读取保存的模型print('Testing...')loss_test, acc_test = evaluate(session, x_test, y_test)msg = 'Test Loss: {0:>6.2}, Test Acc: {1:>7.2%}'print(msg.format(loss_test, acc_test))batch_size = 128data_len = len(x_test)num_batch = int((data_len - 1) / batch_size) + 1y_test_cls = np.argmax(y_test, 1)y_pred_cls = np.zeros(shape=len(x_test), dtype=np.int32)  # 保存预测结果for i in range(num_batch):  # 逐批次处理start_id = i * batch_sizeend_id = min((i + 1) * batch_size, data_len)feed_dict = {model.input_x: x_test[start_id:end_id],model.keep_prob: 1.0}y_pred_cls[start_id:end_id] = session.run(model.y_pred_cls, feed_dict=feed_dict)print(y_pred_cls)# 评估print("Precision, Recall and F1-Score...")print(metrics.classification_report(y_test_cls, y_pred_cls, target_names=categories))# 混淆矩阵print("Confusion Matrix...")cm = metrics.confusion_matrix(y_test_cls, y_pred_cls)print(cm)time_dif = get_time_dif(start_time)print("Time usage:", time_dif)with open(r'C:\Users\zhang\Desktop\doubledata\tiss\CNN\layer2\tiab\6_cnn_layer1.txt', 'a+') as f:now = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))f.write('=' * 60)f.write('\nTime: {}\n'.format(now))msg = 'Test Loss: {0:>6.2}, Test Acc: {1:>7.2%}\n'f.write(msg.format(loss_test, acc_test))f.write(metrics.classification_report(y_test_cls, y_pred_cls, target_names=categories))f.write('y_pred\n')for i in range(len(y_pred_cls)):f.write(str(y_pred_cls[i]))f.write('\n')if __name__ == '__main__':if len(sys.argv) != 2 or sys.argv[1] not in ['train', 'test']:raise ValueError("""usage: python run_cnn.py [train / test]""")print('Configuring CNN model...')config = TCNNConfig()if not os.path.exists(vocab_dir):  # 如果不存在词汇表,重建build_vocab(train_dir, vocab_dir, config.vocab_size)categories, cat_to_id = read_category()words, word_to_id = read_vocab(vocab_dir)config.vocab_size = len(words)model = TextCNN(config)if sys.argv[1] == 'train':train()else:test()
# coding: utf-8import tensorflow as tfclass TCNNConfig(object):"""CNN配置参数"""embedding_dim =96#向量维度seq_length =96#序列长度num_classes = 2 # 类别数 7 4 8 3 2 2num_filters = 256  # 卷积核数目kernel_size = 5  # 卷积核尺寸vocab_size = 5000  # 词汇表达小hidden_dim = 128  # 全连接层神经元dropout_keep_prob = 0.5  # dropout保留比例learning_rate = 1e-3  # 学习率batch_size = 64  # 每批训练大小num_epochs = 10  # 总迭代轮次print_per_batch = 100  # 每多少轮输出一次结果save_per_batch = 10  # 每多少轮存入tensorboardclass TextCNN(object):"""文本分类,CNN模型"""def __init__(self, config):self.config = config# 三个待输入的数据self.input_x = tf.placeholder(tf.int32, [None, self.config.seq_length], name='input_x')self.input_y = tf.placeholder(tf.float32, [None, self.config.num_classes], name='input_y')self.keep_prob = tf.placeholder(tf.float32, name='keep_prob')self.cnn()def cnn(self):"""CNN模型"""# 词向量映射with tf.device('/cpu:0'):embedding = tf.get_variable('embedding', [self.config.vocab_size, self.config.embedding_dim])embedding_inputs = tf.nn.embedding_lookup(embedding, self.input_x)with tf.name_scope("cnn"):# CNN layerconv = tf.layers.conv1d(embedding_inputs, self.config.num_filters, self.config.kernel_size, name='conv')# global max pooling layergmp = tf.reduce_max(conv, reduction_indices=[1], name='gmp')with tf.name_scope("score"):# 全连接层,后面接dropout以及relu激活fc = tf.layers.dense(gmp, self.config.hidden_dim, name='fc1')fc = tf.contrib.layers.dropout(fc, self.keep_prob)fc = tf.nn.relu(fc)# 分类器self.logits = tf.layers.dense(fc, self.config.num_classes, name='fc2')self.y_pred_cls = tf.argmax(tf.nn.softmax(self.logits), 1)  # 预测类别with tf.name_scope("optimize"):# 损失函数,交叉熵cross_entropy = tf.nn.softmax_cross_entropy_with_logits(logits=self.logits, labels=self.input_y)self.loss = tf.reduce_mean(cross_entropy)# 优化器self.optim = tf.train.AdamOptimizer(learning_rate=self.config.learning_rate).minimize(self.loss)with tf.name_scope("accuracy"):# 准确率correct_pred = tf.equal(tf.argmax(self.input_y, 1), self.y_pred_cls)self.acc = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
# coding: utf-8from __future__ import print_functionimport os
import sys
import time
from datetime import timedeltaimport numpy as np
import tensorflow as tf
from sklearn import metricsfrom rnn_model import TRNNConfig, TextRNN
from data.test import read_vocab, read_category, batch_iter, process_file, build_vocabbase_dir = r'C:\Users\zhang\Desktop\doubledata\tiss\CNN\layer2\1'
train_dir = os.path.join(base_dir, 'train.txt')
test_dir = os.path.join(base_dir, 'test.txt')
val_dir = os.path.join(base_dir, 'val.txt')
vocab_dir = os.path.join(base_dir, 'vocab.txt')save_dir = r'C:\Users\zhang\Desktop\doubledata\tiss\CNN\layer2\1'
save_path = os.path.join(save_dir, 'best_validation')  # 最佳验证结果保存路径def get_time_dif(start_time):"""获取已使用时间"""end_time = time.time()time_dif = end_time - start_timereturn timedelta(seconds=int(round(time_dif)))def feed_data(x_batch, y_batch, keep_prob):feed_dict = {model.input_x: x_batch,model.input_y: y_batch,model.keep_prob: keep_prob}return feed_dictdef evaluate(sess, x_, y_):"""评估在某一数据上的准确率和损失"""data_len = len(x_)batch_eval = batch_iter(x_, y_, 128)total_loss = 0.0total_acc = 0.0for x_batch, y_batch in batch_eval:batch_len = len(x_batch)feed_dict = feed_data(x_batch, y_batch, 1.0)loss, acc = sess.run([model.loss, model.acc], feed_dict=feed_dict)total_loss += loss * batch_lentotal_acc += acc * batch_lenreturn total_loss / data_len, total_acc / data_lendef train():print("Configuring TensorBoard and Saver...")# 配置 Tensorboard,重新训练时,请将tensorboard文件夹删除,不然图会覆盖tensorboard_dir = 'tensorboard/textrnn'if not os.path.exists(tensorboard_dir):os.makedirs(tensorboard_dir)tf.summary.scalar("loss", model.loss)tf.summary.scalar("accuracy", model.acc)merged_summary = tf.summary.merge_all()writer = tf.summary.FileWriter(tensorboard_dir)# 配置 Saversaver = tf.train.Saver()if not os.path.exists(save_dir):os.makedirs(save_dir)print("Loading training and validation data...")# 载入训练集与验证集start_time = time.time()x_train, y_train = process_file(train_dir, word_to_id, cat_to_id, config.seq_length)x_val, y_val = process_file(val_dir, word_to_id, cat_to_id, config.seq_length)time_dif = get_time_dif(start_time)print("Time usage:", time_dif)# 创建sessionsession = tf.Session()session.run(tf.global_variables_initializer())writer.add_graph(session.graph)print('Training and evaluating...')start_time = time.time()total_batch = 0  # 总批次best_acc_val = 0.0  # 最佳验证集准确率last_improved = 0  # 记录上一次提升批次require_improvement = 1000  # 如果超过1000轮未提升,提前结束训练flag = Falsefor epoch in range(config.num_epochs):print('Epoch:', epoch + 1)batch_train = batch_iter(x_train, y_train, config.batch_size)for x_batch, y_batch in batch_train:feed_dict = feed_data(x_batch, y_batch, config.dropout_keep_prob)if total_batch % config.save_per_batch == 0:# 每多少轮次将训练结果写入tensorboard scalars = session.run(merged_summary, feed_dict=feed_dict)writer.add_summary(s, total_batch)if total_batch % config.print_per_batch == 0:# 每多少轮次输出在训练集和验证集上的性能feed_dict[model.keep_prob] = 1.0loss_train, acc_train = session.run([model.loss, model.acc], feed_dict=feed_dict)loss_val, acc_val = evaluate(session, x_val, y_val)  # todoif acc_val > best_acc_val:# 保存最好结果best_acc_val = acc_vallast_improved = total_batchsaver.save(sess=session, save_path=save_path)improved_str = '*'else:improved_str = ''time_dif = get_time_dif(start_time)msg = 'Iter: {0:>6}, Train Loss: {1:>6.2}, Train Acc: {2:>7.2%},' \+ ' Val Loss: {3:>6.2}, Val Acc: {4:>7.2%}, Time: {5} {6}'print(msg.format(total_batch, loss_train, acc_train, loss_val, acc_val, time_dif, improved_str))feed_dict[model.keep_prob] = config.dropout_keep_probsession.run(model.optim, feed_dict=feed_dict)  # 运行优化total_batch += 1if total_batch - last_improved > require_improvement:# 验证集正确率长期不提升,提前结束训练print("No optimization for a long time, auto-stopping...")flag = Truebreak  # 跳出循环if flag:  # 同上breakprint(best_acc_val)with open(r'C:\Users\zhang\Desktop\doubledata\tiss\CNN\layer2\1\rnn_layer2.txt', 'a+') as f:now = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))f.write('best_acc_val:' )f.write(str(best_acc_val))def test():print("Loading test data...")start_time = time.time()x_test, y_test = process_file(test_dir, word_to_id, cat_to_id, config.seq_length)session = tf.Session()session.run(tf.global_variables_initializer())saver = tf.train.Saver()saver.restore(sess=session, save_path=save_path)  # 读取保存的模型print('Testing...')loss_test, acc_test = evaluate(session, x_test, y_test)msg = 'Test Loss: {0:>6.2}, Test Acc: {1:>7.2%}'print(msg.format(loss_test, acc_test))batch_size = 128data_len = len(x_test)num_batch = int((data_len - 1) / batch_size) + 1y_test_cls = np.argmax(y_test, 1)y_pred_cls = np.zeros(shape=len(x_test), dtype=np.int32)  # 保存预测结果for i in range(num_batch):  # 逐批次处理start_id = i * batch_sizeend_id = min((i + 1) * batch_size, data_len)feed_dict = {model.input_x: x_test[start_id:end_id],model.keep_prob: 1.0}y_pred_cls[start_id:end_id] = session.run(model.y_pred_cls, feed_dict=feed_dict)# 评估print("Precision, Recall and F1-Score...")print(metrics.classification_report(y_test_cls, y_pred_cls, target_names=categories))# 混淆矩阵print("Confusion Matrix...")cm = metrics.confusion_matrix(y_test_cls, y_pred_cls)print(cm)time_dif = get_time_dif(start_time)print("Time usage:", time_dif)with open(r'C:\Users\zhang\Desktop\doubledata\tiss\CNN\layer2\1\rnn_layer2.txt', 'a+') as f:now = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))f.write('=' * 60)f.write('\nTime: {}\n'.format(now))msg = 'Test Loss: {0:>6.2}, Test Acc: {1:>7.2%}\n'f.write(msg.format(loss_test, acc_test))f.write(metrics.classification_report(y_test_cls, y_pred_cls, target_names=categories))for i in range(len(y_pred_cls)):f.write(str(y_pred_cls[i]))f.write('\n')if __name__ == '__main__':if len(sys.argv) != 2 or sys.argv[1] not in ['train', 'test']:raise ValueError("""usage: python run_rnn.py [train / test]""")print('Configuring RNN model...')config = TRNNConfig()if not os.path.exists(vocab_dir):  # 如果不存在词汇表,重建build_vocab(train_dir, vocab_dir, config.vocab_size)categories, cat_to_id = read_category()words, word_to_id = read_vocab(vocab_dir)config.vocab_size = len(words)model = TextRNN(config)if sys.argv[1] == 'train':train()else:test()
#!/usr/bin/python
# -*- coding: utf-8 -*-import tensorflow as tfclass TRNNConfig(object):"""RNN配置参数"""# 模型参数embedding_dim = 96      # 词向量维度seq_length = 96        # 序列长度num_classes = 5       # 类别数 5 4 8 3 2 2vocab_size = 5000       # 词汇表达小num_layers= 2           # 隐藏层层数hidden_dim = 128        # 隐藏层神经元rnn = 'gru'             # lstm 或 grudropout_keep_prob = 0.8 # dropout保留比例learning_rate = 1e-3    # 学习率batch_size = 128         # 每批训练大小num_epochs = 10          # 总迭代轮次print_per_batch = 100    # 每多少轮输出一次结果save_per_batch = 10      # 每多少轮存入tensorboardclass TextRNN(object):"""文本分类,RNN模型"""def __init__(self, config):self.config = config# 三个待输入的数据self.input_x = tf.placeholder(tf.int32, [None, self.config.seq_length], name='input_x')self.input_y = tf.placeholder(tf.float32, [None, self.config.num_classes], name='input_y')self.keep_prob = tf.placeholder(tf.float32, name='keep_prob')self.rnn()def rnn(self):"""rnn模型"""def lstm_cell():   # lstm核return tf.contrib.rnn.BasicLSTMCell(self.config.hidden_dim, state_is_tuple=True)def gru_cell():  # gru核return tf.contrib.rnn.GRUCell(self.config.hidden_dim)def dropout(): # 为每一个rnn核后面加一个dropout层if (self.config.rnn == 'lstm'):cell = lstm_cell()else:cell = gru_cell()return tf.contrib.rnn.DropoutWrapper(cell, output_keep_prob=self.keep_prob)# 词向量映射with tf.device('/cpu:0'):embedding = tf.get_variable('embedding', [self.config.vocab_size, self.config.embedding_dim])embedding_inputs = tf.nn.embedding_lookup(embedding, self.input_x)with tf.name_scope("rnn"):# 多层rnn网络cells = [dropout() for _ in range(self.config.num_layers)]rnn_cell = tf.contrib.rnn.MultiRNNCell(cells, state_is_tuple=True)_outputs, _ = tf.nn.dynamic_rnn(cell=rnn_cell, inputs=embedding_inputs, dtype=tf.float32)last = _outputs[:, -1, :]  # 取最后一个时序输出作为结果with tf.name_scope("score"):# 全连接层,后面接dropout以及relu激活fc = tf.layers.dense(last, self.config.hidden_dim, name='fc1')fc = tf.contrib.layers.dropout(fc, self.keep_prob)fc = tf.nn.relu(fc)# 分类器self.logits = tf.layers.dense(fc, self.config.num_classes, name='fc2')self.y_pred_cls = tf.argmax(tf.nn.softmax(self.logits), 1)  # 预测类别with tf.name_scope("optimize"):# 损失函数,交叉熵cross_entropy = tf.nn.softmax_cross_entropy_with_logits(logits=self.logits, labels=self.input_y)self.loss = tf.reduce_mean(cross_entropy)# 优化器self.optim = tf.train.AdamOptimizer(learning_rate=self.config.learning_rate).minimize(self.loss)with tf.name_scope("accuracy"):# 准确率correct_pred = tf.equal(tf.argmax(self.input_y, 1), self.y_pred_cls)self.acc = tf.reduce_mean(tf.cast(correct_pred, tf.float32))

参考:
https://zhuanlan.zhihu.com/p/26306795

Task5 基于深度学习的文本分类相关推荐

  1. Datawhale NLP入门:Task5 基于深度学习的文本分类2

    Task5 基于深度学习的文本分类2 在上一章节,我们通过FastText快速实现了基于深度学习的文本分类模型,但是这个模型并不是最优的.在本章我们将继续深入. 基于深度学习的文本分类 本章将继续学习 ...

  2. Task5 基于深度学习的文本分类2

    Task5 基于深度学习的文本分类2 在上一章节,我们通过FastText快速实现了基于深度学习的文本分类模型,但是这个模型并不是最优的.在本章我们将继续深入. 基于深度学习的文本分类 本章将继续学习 ...

  3. Datawhale零基础入门NLP day5/Task5基于深度学习的文本分类2

    基于深度学习的文本分类 本章将继续学习基于深度学习的文本分类. 学习目标 学习Word2Vec的使用和基础原理 学习使用TextCNN.TextRNN进行文本表示 学习使用HAN网络结构完成文本分类 ...

  4. Datawhale零基础入门NLP赛事 - Task5 基于深度学习的文本分类2

    在上一章节,我们通过FastText快速实现了基于深度学习的文本分类模型,但是这个模型并不是最优的.在本章我们将继续深入. 基于深度学习的文本分类 本章将继续学习基于深度学习的文本分类. 学习目标 学 ...

  5. DataWhale NLP组队学习 Task5 基于深度学习的文本分类2

    文章目录 文本表示方法 Part3 词向量 TextCNN TextRNN 基于TextCNN.TextRNN的文本表示 TextCNN TextRNN 使用HAN用于文本分类 本章小结 本章作业 后 ...

  6. 新闻文本分类--任务5 基于深度学习的文本分类2

    Task5 基于深度学习的文本分类2 在上一章节,我们通过FastText快速实现了基于深度学习的文本分类模型,但是这个模型并不是最优的.在本章我们将继续深入. 基于深度学习的文本分类 本章将继续学习 ...

  7. NLP以赛代练 Task5:基于深度学习的文本分类 2

    基于深度学习的文本分类 2 学习目标 文本表示方法 Part3 词向量 1. Skip-grams原理和网络结构 2. Skip-grams训练 2.1 Word pairs and "ph ...

  8. 基于深度学习的文本分类1

    基于深度学习的文本分类 与传统机器学习不同,深度学习既提供特征提取功能,也可以完成分类的功能.从本章开始我们将学习如何使用深度学习来完成文本表示. 现有文本表示方法的缺陷 在上一章节,我们介绍几种文本 ...

  9. 综述:基于深度学习的文本分类 --《Deep Learning Based Text Classification: A Comprehensive Review》总结(一)

    文章目录 综述:基于深度学习的文本分类 <Deep Learning Based Text Classification: A Comprehensive Review>论文总结(一) 总 ...

最新文章

  1. 使用pytorch搭建 RNN线性神经网络
  2. 百分点宣布完成C轮融资2500万美元 将进一步开放云平台应用
  3. SQL Server事务
  4. 转: ajax跨域之JSONP
  5. 为什么我们不要 .NET 程序员
  6. 【渝粤教育】国家开放大学2019年春季 776员工招聘与管理 参考试题
  7. yolov4Linux,基于Darknet的YOLOv4目标检测
  8. win10锁屏c语言,怎样在Win10锁屏界面打开任意应用程序?
  9. Linux shell - 按时间和文件大小排序显示文件(ll)
  10. Python中的正则表达式找到所有符合要求的字符串
  11. linux下的nginx+tomcat配置
  12. 拉格朗日乘子法 那些年学过的高数
  13. NAT穿越技术详细介绍
  14. 手把手教你实现——Python文字(汉字)转语音教程,举一反三~
  15. Navicat 8 用户与注册码
  16. 鸿蒙超级终端使用教程,超级终端怎么用(超级终端使用配置教程)
  17. 基于单片机指纹考勤机仿真系统-毕设资料
  18. layui 勾选不联动父项 树形控件_layui树形组件重现勾选过程的办法
  19. 芯片分享——MS9601A
  20. 关于风向的u、v分量,及根据uv计算风向公式

热门文章

  1. 计算机专业文献,最新大学计算机专业参考文献 大学计算机专业论文参考文献哪里找...
  2. Xilisoft.Audio.Converter.v6.4.0.20120801.Multilanguage-LAXiTY
  3. 火焰检测的一些名词解释
  4. 滑模变结构控制的几种切换函数
  5. 没想到!是数据中台,“助燃”数字化转型热潮
  6. 深度相机(四)--Realsense概览
  7. Canvas绘制鱼儿游水动画
  8. 电学仪器自动化计量软件|无线电自动校准软件|仪器校准计量系统NSAT-3010
  9. windows7计算机配置要求,Windows7最低配置要求是什么 windows7的版本介绍
  10. 趋势安全大师 for Mac(杀毒软件) v2.3.0中文破解版