最近由于做论文的补充实验,需要在rnn上做一下算法验证。找了一下这个博客写的挺好的,但是也有一些bug,暂时先记录一下。

使用循环神经网络(RNN)实现影评情感分类

作为对循环神经网络的实践,我用循环神经网络做了个影评情感的分类,即判断影评的感情色彩是正面的,还是负面的。

选择使用RNN来做情感分类,主要是因为影评是一段文字,是序列的,而RNN对序列的支持比较好,能够“记忆”前文。虽然可以提取特征词向量,然后交给传统机器学习模型或全连接神经网络去做,也能取得很好的效果,但只从端对端的角度来看的话,RNN无疑是最合适的。

以下介绍实现过程。

转载请注明出处:https://blog.csdn.net/aaronjny/article/details/79561115

一、数据预处理

本文中使用的训练数据集为https://www.cs.cornell.edu/people/pabo/movie-review-data/上的sentence polarity dataset v1.0,包含正负面评论各5331条。可以点击进行下载。

数据下载下来之后需要进行解压,得到rt-polarity.negrt-polarity.pos文件,这两个文件是Windows-1252编码的,先将它转成unicode处理起来会更方便。

补充一下小知识,当我们打开一个文件,发现乱码,却又不知道该文件的编码是什么的时候,可以使用python
chardet类库进行判断,这里的Windows-1252就是使用该类库检测出来的。

在数据预处理部分,我们要完成如下处理过程:

1.转码

即将文件转为unicode编码,方便我们后续操作。读取文件,转换编码,重新写入到新文件即可。不存在技术难点。

2.生成词汇表

读取训练文件,提取出所有的单词,并统计各个单词出现的次数。为了避免低频词的干扰,同时减少模型参数,我们只保留部分高频词,比如这里我只保存出现次数前9999个,同时将低频词标识符<unkown>加入到词汇表中。

3.借助词汇表将影评转化为词向量

单词是没法直接输入给模型的,所以我们需要将词汇表中的每个单词对应于一个编号,将影评数据转化成词向量。方便后面生成词嵌入矩阵。

4.填充词向量并转化为np数组

因为不同评论的长度是不同的,我们要组成batch进行训练,就需要先将其长度统一。这里我选择以最长的影评为标准,对其他较短的影评的空白部分进行填充。然后将其转化成numpy的数组。

5.按比例划分数据集

按照机器学习的惯例,数据集应被划分为三份,即训练集、开发集和测试集。当然,有时也会只划分两份,即只包括训练集和开发集。

这里我划分成三份,训练集、开发集和测试集的占比为[0.8,0.1,0.1]。划分的方式为轮盘赌法,在numpy中可以使用cumsumsearchsorted来简洁地实现轮盘赌法。

6.打乱数据集,写入文件

为了取得更好的训练效果,将数据集随机打乱。为了保证在训练和模型调整的过程中训练集、开发集、测试集不发生改变,将三个数据集写入到文件中,使用的时候从文件中读取。

下面贴上数据预处理的代码,注释写的很细,就不多说了。

# -*- coding: utf-8 -*-
# @Time    : 18-3-14 下午2:28
# @Author  : AaronJny
# @Email   : Aaron__7@163.com
import sys
reload(sys)
sys.setdefaultencoding('utf8')
import collections
import settings
import utils
import numpy as np
def create_vocab():"""创建词汇表,写入文件中:return:"""# 存放出现的所有单词word_list = []# 从文件中读取数据,拆分单词with open(settings.NEG_TXT, 'r') as f:f_lines = f.readlines()for line in f_lines:words = line.strip().split()word_list.extend(words)with open(settings.POS_TXT, 'r') as f:f_lines = f.readlines()for line in f_lines:words = line.strip().split()word_list.extend(words)# 统计单词出现的次数counter = collections.Counter(word_list)sorted_words = sorted(counter.items(), key=lambda x: x[1], reverse=True)# 选取高频词word_list = [word[0] for word in sorted_words]word_list = ['<unkown>'] + word_list[:settings.VOCAB_SIZE - 1]# 将词汇表写入文件中with open(settings.VOCAB_PATH, 'w') as f:for word in word_list:f.write(word + '\n')
def create_vec(txt_path, vec_path):"""根据词汇表生成词向量:param txt_path: 影评文件路径:param vec_path: 输出词向量路径:return:"""# 获取单词到编号的映射word2id = utils.read_word_to_id_dict()# 将语句转化成向量vec = []with open(txt_path, 'r') as f:f_lines = f.readlines()for line in f_lines:tmp_vec = [str(utils.get_id_by_word(word, word2id)) for word in line.strip().split()]vec.append(tmp_vec)# 写入文件中with open(vec_path, 'w') as f:for tmp_vec in vec:f.write(' '.join(tmp_vec) + '\n')
def cut_train_dev_test():"""使用轮盘赌法,划分训练集、开发集和测试集打乱,并写入不同文件中:return:"""# 三个位置分别存放训练、开发、测试data = [[], [], []]labels = [[], [], []]# 累加概率 rate [0.8,0.1,0.1]  cumsum_rate [0.8,0.9,1.0]rate = np.array([settings.TRAIN_RATE, settings.DEV_RATE, settings.TEST_RATE])cumsum_rate = np.cumsum(rate)# 使用轮盘赌法划分数据集with open(settings.POS_VEC, 'r') as f:f_lines = f.readlines()for line in f_lines:tmp_data = [int(word) for word in line.strip().split()]tmp_label = [1, ]index = int(np.searchsorted(cumsum_rate, np.random.rand(1) * 1.0))data[index].append(tmp_data)labels[index].append(tmp_label)with open(settings.NEG_VEC, 'r') as f:f_lines = f.readlines()for line in f_lines:tmp_data = [int(word) for word in line.strip().split()]tmp_label = [0, ]index = int(np.searchsorted(cumsum_rate, np.random.rand(1) * 1.0))data[index].append(tmp_data)labels[index].append(tmp_label)# 计算一下实际上分割出来的比例print '最终分割比例', np.array([map(len, data)], dtype=np.float32) / sum(map(len, data))# 打乱数据,写入到文件中shuffle_data(data[0], labels[0], settings.TRAIN_DATA)shuffle_data(data[1], labels[1], settings.DEV_DATA)shuffle_data(data[2], labels[2], settings.TEST_DATA)
def shuffle_data(x, y, path):"""填充数据,生成np数组打乱数据,写入文件中:param x: 数据:param y: 标签:param path: 保存路径:return:"""# 计算影评的最大长度maxlen = max(map(len, x))# 填充数据data = np.zeros([len(x), maxlen], dtype=np.int32)for row in range(len(x)):data[row, :len(x[row])] = x[row]label = np.array(y)# 打乱数据state = np.random.get_state()np.random.shuffle(data)np.random.set_state(state)np.random.shuffle(label)# 保存数据np.save(path + '_data', data)np.save(path + '_labels', label)
def decode_file(infile, outfile):"""将文件的编码从'Windows-1252'转为Unicode:param infile: 输入文件路径:param outfile: 输出文件路径:return:"""with open(infile, 'r') as f:txt = f.read().decode('Windows-1252')with open(outfile, 'w') as f:f.write(txt)
if __name__ == '__main__':# 解码文件decode_file(settings.ORIGIN_POS, settings.POS_TXT)decode_file(settings.ORIGIN_NEG, settings.NEG_TXT)# 创建词汇表create_vocab()# 生成词向量create_vec(settings.NEG_TXT, settings.NEG_VEC)create_vec(settings.POS_TXT, settings.POS_VEC)# 划分数据集cut_train_dev_test()

二、模型编写

数据处理好之后,开始模型的编写。这里选用循环神经网络,建模过程大致如下:

1.使用embedding构建词嵌入矩阵

在数据预处理中,我们将影评处理成了一个个单词编号构成的向量,也就是说,一条影评,对应于一个由单词编号构成的向量。

将这样的向量进行embedding,即可构建出词嵌入矩阵。在词嵌入矩阵中,每个词由一个向量表示,矩阵中不同向量之间的差异对应于它们表示的词之间的差异。

2.使用LSTM作为循环神经网络的基本单元

长短时记忆网络(LSTM)能够自动完成前文信息的“记忆”和“遗忘”,在循环神经网络中表现良好,已经成为在循环神经网络中大部分人的首选。这里我选择使用LSTM作为循环神经网络的基本单元。

3.对embedding和LSTM进行随机失活(dropout)

为了提高模型的泛化能力,并减少参数,我对embedding层和LSTM单元进行dropout。

4.建立深度为2的深度循环神经网络

为了提高模型的拟合能力,使用深度循环神经网络,我选择的深度为2。

5.给出二分类概率

对深度循环神经网络的最后节点的输出做逻辑回归,通过sigmoid使结果落到0-1之间,代表结果是正类的概率。

损失函数使用交叉熵,优化器选择Adam。

此部分代码如下(注:代码中装饰器的作用为划分命名空间以及保证张量运算只被定义一次):

# -*- coding: utf-8 -*-
# @Time    : 18-3-14 下午2:57
# @Author  : AaronJny
# @Email   : Aaron__7@163.com
import tensorflow as tf
import functools
import settings
HIDDEN_SIZE = 128
NUM_LAYERS = 2
def doublewrap(function):@functools.wraps(function)def decorator(*args, **kwargs):if len(args) == 1 and len(kwargs) == 0 and callable(args[0]):return function(args[0])else:return lambda wrapee: function(wrapee, *args, **kwargs)return decorator
@doublewrap
def define_scope(function, scope=None, *args, **kwargs):attribute = '_cache_' + function.__name__name = scope or function.__name__@property@functools.wraps(function)def decorator(self):if not hasattr(self, attribute):with tf.variable_scope(name, *args, **kwargs):setattr(self, attribute, function(self))return getattr(self, attribute)return decorator
class Model(object):def __init__(self, data, lables, emb_keep, rnn_keep):"""神经网络模型:param data:数据:param lables: 标签:param emb_keep: emb层保留率:param rnn_keep: rnn层保留率"""self.data = dataself.label = lablesself.emb_keep = emb_keepself.rnn_keep = rnn_keepself.predictself.lossself.global_stepself.emaself.optimizeself.acc@define_scopedef predict(self):"""定义前向传播过程:return:"""# 词嵌入矩阵权重embedding = tf.get_variable('embedding', [settings.VOCAB_SIZE, HIDDEN_SIZE])# 使用dropout的LSTMlstm_cell = [tf.nn.rnn_cell.DropoutWrapper(tf.nn.rnn_cell.BasicLSTMCell(HIDDEN_SIZE), self.rnn_keep) for _ inrange(NUM_LAYERS)]# 构建循环神经网络cell = tf.nn.rnn_cell.MultiRNNCell(lstm_cell)# 生成词嵌入矩阵,并进行dropoutinput = tf.nn.embedding_lookup(embedding, self.data)dropout_input = tf.nn.dropout(input, self.emb_keep)# 计算rnn的输出outputs, last_state = tf.nn.dynamic_rnn(cell, dropout_input, dtype=tf.float32)# 做二分类问题,这里只需要最后一个节点的输出last_output = outputs[:, -1, :]# 求最后节点输出的线性加权和weights = tf.Variable(tf.truncated_normal([HIDDEN_SIZE, 1]), dtype=tf.float32, name='weights')bias = tf.Variable(0, dtype=tf.float32, name='bias')logits = tf.matmul(last_output, weights) + biasreturn logits@define_scopedef ema(self):"""定义移动平均:return:"""ema = tf.train.ExponentialMovingAverage(settings.EMA_RATE, self.global_step)return ema@define_scopedef loss(self):"""定义损失函数,这里使用交叉熵:return:"""loss = tf.nn.sigmoid_cross_entropy_with_logits(labels=self.label, logits=self.predict)loss = tf.reduce_mean(loss)return loss@define_scopedef global_step(self):"""step,没什么好说的,注意指定trainable=False:return:"""global_step = tf.Variable(0, trainable=False)return global_step@define_scopedef optimize(self):"""定义反向传播过程:return:"""# 学习率衰减learn_rate = tf.train.exponential_decay(settings.LEARN_RATE, self.global_step, settings.LR_DECAY_STEP,settings.LR_DECAY)# 反向传播优化器optimizer = tf.train.AdamOptimizer(learn_rate).minimize(self.loss, global_step=self.global_step)# 移动平均操作ave_op = self.ema.apply(tf.trainable_variables())# 组合构成训练opwith tf.control_dependencies([optimizer, ave_op]):train_op = tf.no_op('train')return train_op@define_scopedef acc(self):"""定义模型acc计算过程:return:"""# 对前向传播的结果求sigmoidoutput = tf.nn.sigmoid(self.predict)# 真负类ok0 = tf.logical_and(tf.less_equal(output, 0.5), tf.equal(self.label, 0))# 真正类ok1 = tf.logical_and(tf.greater(output, 0.5), tf.equal(self.label, 1))# 一个数组,所有预测正确的都为True,否则Falseok = tf.logical_or(ok0, ok1)# 先转化成浮点型,再通过求平均来计算accacc = tf.reduce_mean(tf.cast(ok, dtype=tf.float32))return acc

三、组织数据集

我编写了一个类用于组织数据,方便训练和验证使用。代码很简单,就不多说了,直接贴代码:

# -*- coding: utf-8 -*-
# @Time    : 18-3-14 下午3:33
# @Author  : AaronJny
# @Email   : Aaron__7@163.com
import numpy as np
import settings
class Dataset(object):def __init__(self, data_kind=0):"""生成一个数据集对象:param data_kind: 决定了使用哪种数据集 0-训练集 1-开发集 2-测试集"""self.data, self.labels = self.read_data(data_kind)self.start = 0  # 记录当前batch位置self.data_size = len(self.data)  # 样例数def read_data(self, data_kind):"""从文件中加载数据:param data_kind:数据集种类 0-训练集 1-开发集 2-测试集:return:"""# 获取数据集路径data_path = [settings.TRAIN_DATA, settings.DEV_DATA, settings.TEST_DATA][data_kind]# 加载data = np.load(data_path + '_data.npy')labels = np.load(data_path + '_labels.npy')return data, labelsdef next_batch(self, batch_size):"""获取一个大小为batch_size的batch:param batch_size: batch大小:return:"""start = self.startend = min(start + batch_size, self.data_size)self.start = end# 当遍历完成后回到起点if self.start >= self.data_size:self.start = 0# 返回一个batch的数据和标签return self.data[start:end], self.labels[start:end]

四、模型训练

训练过程中,额外操作主要有两个:

1.使用移动平均

我使用移动平均的主要目的是使loss曲线尽量平滑,以及提升模型的泛化能力。

2.使用学习率指数衰减

目的是保证前期学习率足够大,能够快速降低loss,后期学习率变小,能更好地逼近最优解。

当然,就是说说而已,这次的训练数据比较简单,学习率衰减发挥的作用不大。

训练过程中,定期保存模型,以及checkpoint。这样可以在训练的同时,在验证脚本中读取最新模型进行验证。

此部分具体代码如下:

# -*- coding: utf-8 -*-
# @Time    : 18-3-14 下午4:41
# @Author  : AaronJny
# @Email   : Aaron__7@163.com
import settings
import tensorflow as tf
import models
import dataset
import os
BATCH_SIZE = settings.BATCH_SIZE
# 数据
x = tf.placeholder(tf.int32, [None, None])
# 标签
y = tf.placeholder(tf.float32, [None, 1])
# emb层的dropout保留率
emb_keep = tf.placeholder(tf.float32)
# rnn层的dropout保留率
rnn_keep = tf.placeholder(tf.float32)
# 创建一个模型
model = models.Model(x, y, emb_keep, rnn_keep)
# 创建数据集对象
data = dataset.Dataset(0)
saver = tf.train.Saver()
with tf.Session() as sess:# 全局初始化sess.run(tf.global_variables_initializer())# 迭代训练for step in range(settings.TRAIN_TIMES):# 获取一个batch进行训练x, y = data.next_batch(BATCH_SIZE)loss, _ = sess.run([model.loss, model.optimize],{model.data: x, model.label: y, model.emb_keep: settings.EMB_KEEP_PROB,model.rnn_keep: settings.RNN_KEEP_PROB})# 输出lossif step % settings.SHOW_STEP == 0:print 'step {},loss is {}'.format(step, loss)# 保存模型if step % settings.SAVE_STEP == 0:saver.save(sess, os.path.join(settings.CKPT_PATH, settings.MODEL_NAME), model.global_step)

五、验证模型

加载最新模型进行验证,通过修改数据集对象的参数可以制定训练/开发/测试集进行验证。

加载模型的时候,使用移动平均的影子变量覆盖对应变量。

代码如下:

# -*- coding: utf-8 -*-
# @Time    : 18-3-14 下午5:09
# @Author  : AaronJny
# @Email   : Aaron__7@163.com
import settings
import tensorflow as tf
import models
import dataset
import os
import time
# 为了在使用GPU训练的同时,使用CPU进行验证
os.environ['CUDA_VISIBLE_DEVICES'] = ''
BATCH_SIZE = settings.BATCH_SIZE
# 数据
x = tf.placeholder(tf.int32, [None, None])
# 标签
y = tf.placeholder(tf.float32, [None, 1])
# emb层的dropout保留率
emb_keep = tf.placeholder(tf.float32)
# rnn层的dropout保留率
rnn_keep = tf.placeholder(tf.float32)
# 创建一个模型
model = models.Model(x, y, emb_keep, rnn_keep)
# 创建一个数据集对象
data = dataset.Dataset(1)  # 0-训练集 1-开发集 2-测试集
# 移动平均变量
restore_variables = model.ema.variables_to_restore()
# 使用移动平均变量进行覆盖
saver = tf.train.Saver(restore_variables)
with tf.Session() as sess:while True:# 加载最新的模型ckpt = tf.train.get_checkpoint_state(settings.CKPT_PATH)saver.restore(sess, ckpt.model_checkpoint_path)# 计算并输出accacc = sess.run([model.acc],{model.data: data.data, model.label: data.labels, model.emb_keep: 1.0, model.rnn_keep: 1.0})print 'acc is ', acctime.sleep(1)

六、对词汇表进行操作的几个方法

把对词汇表进行操作的几个方法提取出来了,放到了utils.py文件中。

# -*- coding: utf-8 -*-
# @Time    : 18-3-14 下午2:44
# @Author  : AaronJny
# @Email   : Aaron__7@163.com
import settings
def read_vocab_list():"""读取词汇表:return:由词汇表中所有单词组成的列表"""with open(settings.VOCAB_PATH, 'r') as f:vocab_list = f.read().strip().split('\n')return vocab_list
def read_word_to_id_dict():"""生成一个单词到编号的映射:return:单词到编号的字典"""vocab_list = read_vocab_list()word2id = dict(zip(vocab_list, range(len(vocab_list))))return word2id
def read_id_to_word_dict():"""生成一个编号到单词的映射:return:编号到单词的字典"""vocab_list = read_vocab_list()id2word = dict(zip(range(len(vocab_list)), vocab_list))return id2word
def get_id_by_word(word, word2id):"""给定一个单词和字典,获得单词在字典中的编号:param word: 给定单词:param word2id: 单词到编号的映射:return: 若单词在字典中,返回对应的编号 否则,返回word2id['<unkown>']"""if word in word2id:return word2id[word]else:return word2id['<unkown>']

七、对模型进行配置

模型的配置参数大多数都被提取出来,单独放到了settings.py文件中,可以在这里对模型进行配置。

# -*- coding: utf-8 -*-
# @Time    : 18-3-14 下午2:44
# @Author  : AaronJny
# @Email   : Aaron__7@163.com
# 源数据路径
ORIGIN_NEG = 'data/rt-polarity.neg'
ORIGIN_POS = 'data/rt-polarity.pos'
# 转码后的数据路径
NEG_TXT = 'data/neg.txt'
POS_TXT = 'data/pos.txt'
# 词汇表路径
VOCAB_PATH = 'data/vocab.txt'
# 词向量路径
NEG_VEC = 'data/neg.vec'
POS_VEC = 'data/pos.vec'
# 训练集路径
TRAIN_DATA = 'data/train'
# 开发集路径
DEV_DATA = 'data/dev'
# 测试集路径
TEST_DATA = 'data/test'
# 模型保存路径
CKPT_PATH = 'ckpt'
# 模型名称
MODEL_NAME = 'model'
# 词汇表大小
VOCAB_SIZE = 10000
# 初始学习率
LEARN_RATE = 0.0001
# 学习率衰减
LR_DECAY = 0.99
# 衰减频率
LR_DECAY_STEP = 1000
# 总训练次数
TRAIN_TIMES = 2000
# 显示训练loss的频率
SHOW_STEP = 10
# 保存训练模型的频率
SAVE_STEP = 100
# 训练集占比
TRAIN_RATE = 0.8
# 开发集占比
DEV_RATE = 0.1
# 测试集占比
TEST_RATE = 0.1
# BATCH大小
BATCH_SIZE = 64
# emb层dropout保留率
EMB_KEEP_PROB = 0.5
# rnn层dropout保留率
RNN_KEEP_PROB = 0.5
# 移动平均衰减率
EMA_RATE = 0.99

八、运行模型

至此,模型构建完成。模型的运行步骤大致如下:

1.确保数据文件放在了对应路径中,运行python process_data对数据进行预处理。

2.运行python train.py对模型进行训练,训练好的模型会自动保存到对应的路径中。

3.运行python eval.py读取保存的最新模型,对训练/开发/测试集进行验证。

我简单跑了一下,由于数据集较小,模型的泛化能力不是很好。

当训练集、开发集、测试集的分布为[0.8,0.1,0.1],训练2000个batch_size=64的mini_batch时,模型在各数据集上的acc表现大致如下:

  • 训练集 0.95

  • 开发集 0.79

  • 测试集 0.80

更多

转行做机器学习,要学的还很多,文中如有错误纰漏之处,恳请诸位大佬拍砖指教…

项目GitHub地址:https://github.com/AaronJny/emotional_classification_with_rnn

补充

2018.5.4

有朋友说希望我发一下网络结构图,所以就抽个时间随便画了一下,比较简陋,凑合着看吧=。=


其实你如果安装了python2,tensorflow1.5左右,应该问题不大。但是我这里使用了python3,tensorflow gpu模式。你可能会有以下几个问题:
1、print与sys以及编码encode与decode的报错
2、CUBLAS_STATUS_ALLOC_FAILED
3、模型准确率不够高,过拟合严重

其实想跑通代码,就需要解决这几个问题,python2与python3
的区别,其次就是安装对应的python包,配置合适的显卡驱动,保证足够的显存与显卡调用技巧。
其次,就是优化网络结构与参数,来提高准确率了,不得不说作者用的网络结构较大,数据集较小,最后的过拟合很严重,想知道更多,也可以阅读一下原文,作者还是用风格独特的装饰器,还不错。
https://blog.csdn.net/aaronjny/article/details/79561115

我这里提供一个可以跑的示例:


# -*- coding: utf-8 -*-
# @Time    : 18-3-14 下午4:41
# @Author  : AaronJny
# @Email   : Aaron__7@163.com
import settings
import tensorflow as tf
import models
import dataset
import osBATCH_SIZE = settings.BATCH_SIZE# 数据
x = tf.placeholder(tf.int32, [None, None])
# 标签
y = tf.placeholder(tf.float32, [None, 1])
# emb层的dropout保留率
emb_keep = tf.placeholder(tf.float32)
# rnn层的dropout保留率
rnn_keep = tf.placeholder(tf.float32)# 创建一个模型
model = models.Model(x, y, emb_keep, rnn_keep)# 创建数据集对象
data = dataset.Dataset(0)saver = tf.train.Saver()gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.333)
with tf.Session(config=tf.ConfigProto(gpu_options=gpu_options)) as sess:# 全局初始化sess.run(tf.global_variables_initializer())gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.333)# 迭代训练for step in range(settings.TRAIN_TIMES):# 获取一个batch进行训练x, y = data.next_batch(BATCH_SIZE)loss, _ = sess.run([model.loss, model.optimize],{model.data: x, model.label: y, model.emb_keep: settings.EMB_KEEP_PROB,model.rnn_keep: settings.RNN_KEEP_PROB})# 输出lossif step % settings.SHOW_STEP == 0:print ('step {},loss is {}'.format(step, loss))# 保存模型if step % settings.SAVE_STEP == 0:saver.save(sess, os.path.join(settings.CKPT_PATH, settings.MODEL_NAME), model.global_step)

程序员,不懂就查,debug就行了。

参考链接:

http://www.mamicode.com/info-detail-2806323.html
https://blog.csdn.net/qq236237606/article/details/105347236/
https://www.cnblogs.com/blogpro/p/11343791.html
https://www.it1352.com/678688.html
https://www.jb51.net/article/176105.htm
https://blog.csdn.net/weixin_42989523/article/details/81873874
https://www.thinbug.com/q/2014069
https://blog.csdn.net/qq_45290890/article/details/101672879
https://blog.csdn.net/Tiger_lin1/article/details/103651631
https://blog.csdn.net/qq_45290890/article/details/101672879
https://blog.csdn.net/u013314786/article/details/50980425
https://blog.csdn.net/shangxiaqiusuo1/article/details/84336339
https://blog.csdn.net/Amigo_1997/article/details/88832587
https://blog.csdn.net/qq_17556191/article/details/83447590
https://blog.csdn.net/weixin_42769131/article/details/84372952
https://blog.csdn.net/zhangyumengs/article/details/80551633

使用循环神经网络(RNN)实现影评情感分类相关推荐

  1. 循环神经网络LSTM实现电影情感分类

    循环神经网络LSTM实现电影情感分类 一.数据集: 为了对word embedding这种常用的文本向量化的方法进行巩固,这里我们会完成一个文本情感分类的案例 现在我们有一个经典的数据集IMDB数据集 ...

  2. python输出一首诗_基于循环神经网络(RNN)的古诗生成器

    基于循环神经网络(RNN)的古诗生成器,具体内容如下 之前在手机百度上看到有个"为你写诗"功能,能够随机生成古诗,当时感觉很酷炫= = 在学习了深度学习后,了解了一下原理,打算自己 ...

  3. TensorFlow练手项目二:基于循环神经网络(RNN)的古诗生成器

    基于循环神经网络(RNN)的古诗生成器 2019.01.02更新: 代码比较老了,当时的开发环境为Python 2.7 + TensorFlow 1.4,现在可能无法直接运行了.如果有兴趣,可以移步我 ...

  4. [Python人工智能] 十二.循环神经网络RNN和LSTM原理详解及TensorFlow编写RNN分类案例

    从本专栏开始,作者正式开始研究Python深度学习.神经网络及人工智能相关知识.前一篇讲解了TensorFlow如何保存变量和神经网络参数,通过Saver保存神经网络,再通过Restore调用训练好的 ...

  5. [译] RNN 循环神经网络系列 2:文本分类

    原文地址:RECURRENT NEURAL NETWORKS (RNN) – PART 2: TEXT CLASSIFICATION 原文作者:GokuMohandas 译文出自:掘金翻译计划 本文永 ...

  6. [深度学习-原理篇]什么是循环神经网络RNN与LSTM

    1. 什么是 RNN 循环神经网络(Recurrent Neural Network,RNN)是一种以序列数据为输入来进行建模的深度学习模型,它是 NLP 中最常用的模型. 2. RNN 的结构 RN ...

  7. 【NLP】 深度学习NLP开篇-循环神经网络(RNN)

    从这篇文章开始,有三AI-NLP专栏就要进入深度学习了.本文会介绍自然语言处理早期标志性的特征提取工具-循环神经网络(RNN).首先,会介绍RNN提出的由来:然后,详细介绍RNN的模型结构,前向传播和 ...

  8. 「NLP」 深度学习NLP开篇-循环神经网络(RNN)

    https://www.toutiao.com/a6714260714988503564/ 从这篇文章开始,有三AI-NLP专栏就要进入深度学习了.本文会介绍自然语言处理早期标志性的特征提取工具-循环 ...

  9. 时序数据采样、原始循环神经网络RNN、RNN梯度爆炸原因推导

    时序数据的采样 随机采样 每个样本是原始序列上任意截取的一段序列.相邻的两个随机小批量在原始序列上的位置不一定相毗邻.因此,我们无法用一个小批量最终时间步的隐藏状态来初始化下一个小批量的隐藏状态.在训 ...

最新文章

  1. LeetCode: 929. Unique Email Addresses
  2. python cnn图像分类_关于CNN图像分类的一份综合设计指南
  3. 从Java到Ruby——我的最近一次技术转型
  4. mysql 关联数组_在PHP / MySQL查询中创建关联数组
  5. 程序员删库被判 6 年,公司损失近亿,云原生时代如何打造安全防线?
  6. 多特征自动植物病害识别与检测
  7. 1031 查验身份证 (15 分)—PAT (Basic Level) Practice (中文)
  8. PHP读取PDF内容方法
  9. html是乱码怎么解决,如何解决html乱码问题
  10. 阿里java面试流程_阿里巴巴JAVA开发工程师面试经验
  11. 华为机试:统计射击比赛成绩
  12. windows xp iis5.1服务器安装
  13. 中国移动北京公司携未来电视、UWA、爱奇艺开启超高清新时代
  14. 通讯测试工具和博图仿真机的连接教程
  15. 2019-2020-1 1823《程序设计与数据结构》每周成绩
  16. ICC布局布线 实践课
  17. [oh-my-zsh] 提示检测到不安全的完成相关目录的问题解决
  18. PlusFo解析“梭哈”逻辑
  19. 一文学会,三款黑客必备的抓包工具教学(实在太强了,总有一款适合你)
  20. 近期完成了PHPWIND的树形论坛改版(PHPWIND的树型论坛结构)

热门文章

  1. pytorch系列8 --self.modules() 和 self.children()的区别
  2. vue3 - 网页大转盘抽奖功能,支持后端接口确定最终奖品,可自定义轮盘宽高、颜色、字号、按钮等等(超详细的示例代码及注释开箱即用,稍微改改就能应用到你的项目中)
  3. Android手机拍照或从本地相册选取图片设置头像。适配小米、华为、7.0
  4. mybatis mysql 关于调用存储过程获取查询结果
  5. 教你如何把一张图片做成一段视频
  6. BZOJ4872 [SHOI2017]分手是祝愿
  7. 课后练习--制作美联英语在线VIP页面——学伴
  8. 你觉得自己牛逼在哪儿?
  9. 更改计算机网络,终于理会如何更改计算机网络ip
  10. MySQL5.5 的安装与配置