【AI达人创造营第二期】 一文读懂双向循环神经网络 BRNN
时间:2025-07-31 14:12:19
本研究全面解析了RNN与BRNN的基础知识、架构及各自的利弊,并通过一个案例展示了基于vanilla RNN、LSTM、BiLSTM、GRU以及BiGRU模型的谣言识别应用实例。
一、项目简介
本文详述了RNN、BRNN的结构与训练过程中的反向传播、梯度消失与爆炸的原因及它们的优点与不足。通过一个利用vanilla RNN、LSTM、BiLSTM、GRU和Bigru模型进行谣言检测项目的例子,帮助读者更好地理解这些神经网络模型。
二、RNN
2.1 RNN简介
循环神经网络简称RNN,是一种特殊的神经网络,用于处理时间序列数据。它通过假设当前状态与先前状态和输入信号相关联来实现这一目标。
假设已有数据如下所示
x={x1,x2,...,xT}y={y1,y2,...,yT}x={x1,x2,...,xT}y={y1,y2,...,yT}
ht=f1(xt,ht1;θ)yt=f2(ht;)ht=f1(xt,ht1;θ)yt=f2(ht;)
yt=f2(f1(xt,ht1;θ);)yt=f2(f1(xt,ht1;θ);)
y3=f2(f1(x3,f2(f1(x2,f2(f1(x1,h0;θ););θ););θ);)y3=f2(f1(x3,f2(f1(x2,f2(f1(x1,h0;θ););θ););θ);)
神经网络主要由权重、偏置及激活函数构成,具体表示方式灵活多样。例如,上述htht和ytyt公式可变通为(此处展示形式各异,根据需求变动)。
ht=tanh(Uxt+Wht1)y=softmax(Vht)ht=tanh(Uxt+Wht1)y=softmax(Vht)
训练RNN需要用到基于时间的反向传播(BPTT),在此我们假设预测误差EE,权重矩阵ww,样本xx的正确标签ll,样本xx的预测标签yy,损失函数LL为均方差。 举例:以普通链式法则求Ew3w3E
可以变形为
在hthjhjht中,需增加tj+副本。将它们聚合为单一RNN,计算各前一步的梯度,最终更新此网络。
这样随着序列的增长,我们依旧向后计算固定数量的导数,不会使计算成本变得过大。
2.5 RNN的梯度消失与爆炸
在实际的任务训练中,RNN遇到的一个主要挑战是其对长序列数据处理的局限性。当输入文本很长时,网络中的长期依赖关系会导致过多的内部状态信息积累,这可能会导致输出结果变得不可靠和不一致。为了克服这一问题,研究人员开始探索其他深度学习模型,如Transformer,它们在处理长序列任务方面表现更好。
假设标准RNN隐藏状态计算公式为,激活函数σσ是sigmoid ,WW是权重矩阵
ht=σ(Wxxt+Whht1)ht=σ(Wxxt+Whht1)
为了简化计算,忽略与当前输入相关的项,重点放在循环部分
ht=σ(Whht1)ht=σ(Whht1)
结合链式法则对ht求偏导得到
hthtk=∏i=0k1Whσ(Whhtk+i)(1σ(Whhtk+i))htkht=i=0∏k1Whσ(Whhtk+i)(1σ(Whhtk+i))
提取出k个权重矩阵
hthtk=Whk∏i=0k1σ(Whhtk+i)(1σ(Whhtk+i))htkht=Whki=0∏k1σ(Whhtk+i)(1σ(Whhtk+i))
通过数学公式可以总结出以下特点: 当计算 $ \frac{\partial h_t}{\partial h_{t-k}}$ 的值接近于,通常会观察到梯度消失现象。 在 W_h 和 W_h 的权重因子较大时,其激活函数 $\sigma(W_hh_{t-k+i})$ 则更接近于相反地,当 W_h 和 W_h 的权重过小或过大时,该值则逐渐向近。此时,通过连续的 $k$ 个连乘计算, $ \frac{\partial h_t}{\partial h_{t-k}}$ 也将趋于同样产生梯度消失。 此外,如果 Whk 和 Whk 的初始化设置不当(过小或过大),也会引发梯度消失或梯度爆炸的问题。
BRNN意为双向循环神经网络,是一种常见的提升RNN预测质量的方法。之前介绍RNN时假设了当前时间步是由前面的较早时间步和当前输入决定的。然而,当输入序列是文本时,句子的当前时间步也可能是由后面的时间步决定的。例如: 我晚上不能喝___,因为要开车回家。
其结构与RNN相似,由两个反向的RNN叠加而成,HtHt代表隐藏状态,包含正向和反向隐藏状态,即Ht→Ht→正向隐藏状态和Ht←Ht←反向隐藏状态,输入为x,输出为O,权重矩阵为W,偏置矩阵为b。
Ht→=σ(XtWxh(f)+Ht1→Whh(f)+bh(f))Ht→=σ(XtWxh(f)+Ht1→Whh(f)+bh(f))
Ht←=σ(XtWxh(b)+Ht1←Whh(b)+bh(b))Ht←=σ(XtWxh(b)+Ht1←Whh(b)+bh(b))
Ht=(Ht→,Ht←)Ht=(Ht→,Ht←)
Ot=HtWhq+bqOt=HtWhq+bq
在深度学习领域中,对于两个方向的隐藏层之间的连接方法是通过concat来实现的。这种设计使得系统能够同时处理来自不同维度的信息,并根据图中的表现方式可以认为信息从一个方向上传播到另一个方向进行传递。与RNN(循环神经网络)类似的是,在这种架构中每个方向上的隐藏单元的数量保持不变,从而实现了信息的高效传递。然而,这也导致了由于梯度爆炸或消失的问题。尽管这些在RNN中是常见的问题,但是在新的设计中并没有直接讨论和解决这些问题的方法。这可能是因为这些具体的细节没有被纳入讨论的核心框架内,或者因为这是一个新的研究方向而未涉及。
四、RNN以及其变体在项目中的运用
4.1.项目介绍
揭秘零起点如何构建成功:利用微博数据集,采用深度学习框架中的RNN、LSTM、BiLSTM、GRU和BigRU模型,实现谣言检测任务的完美解决方案。
4.1.1 什么是谣言检测任务
在传统谣言检测模型中,主要依靠人工构建的特征进行分析,这种方法存在考虑片面、人力消耗大等缺点。此次实践采用基于循环神经网络(RNN)的谣言检测方法,将文本中的谣言事件向量化处理,并通过RNN的学习来挖掘文本深层特征,避免了特征手工构造的缺陷,同时捕捉到难以被其他方式发现的独特特征,实现了更优异的效果。
4.2、数据集
4.2.1 数据集概览
本次实践采用的数据源是来自新浪微博的不实信息举报平台的中文谣言样本,共计包括了谣言与非谣言信息。以下是图示化的详细信息:每条数据均以JSON格式呈现,其中text字段代表微博原文的文字内容。
更多数据集介绍请参考https://github.com/thunlp/Chinese_Rumor_Dataset。
4.2.2 数据集处理
(1)解压数据,读取并解析数据,生成all_data.txt
(2)生成数据字典,即dict.txt
(3)生成数据列表,并进行训练集与验证集的划分,train_list.txt 、eval_list.txt
(4)定义训练数据集提供器train_reader和验证数据集提供器eval_reader In [1]
#解压原始数据集,将Rumor_Dataset.zip解压至data目录下import zipfileimport osimport randomfrom PIL import Imagefrom PIL import ImageEnhanceimport json src_path="/home/aistudio/data/data20519/Rumor_Dataset.zip"target_path="/home/aistudio/data/Chinese_Rumor_Dataset-master"if(not os.path.isdir(target_path)): z = zipfile.ZipFile(src_path, 'r') z.extractall(path=target_path) z.close()登录后复制 In [2]
#分别为谣言数据、非谣言数据、全部数据的文件路径rumor_class_dirs = os.listdir(target_path+"/Chinese_Rumor_Dataset-master/CED_Dataset/rumor-repost/") non_rumor_class_dirs = os.listdir(target_path+"/Chinese_Rumor_Dataset-master/CED_Dataset/non-rumor-repost/") original_microblog = target_path+"/Chinese_Rumor_Dataset-master/CED_Dataset/original-microblog/"#谣言标签为0,非谣言标签为1rumor_label="0"non_rumor_label="1"#分别统计谣言数据与非谣言数据的总数rumor_num = 0non_rumor_num = 0all_rumor_list = [] all_non_rumor_list = []#解析谣言数据for rumor_class_dir in rumor_class_dirs: if(rumor_class_dir != '.DS_Store'): #遍历谣言数据,并解析 with open(original_microblog + rumor_class_dir, 'r') as f: rumor_content = f.read() rumor_dict = json.loads(rumor_content) all_rumor_list.append(rumor_label+"\t"+rumor_dict["text"]+"\n") rumor_num +=1#解析非谣言数据for non_rumor_class_dir in non_rumor_class_dirs: if(non_rumor_class_dir != '.DS_Store'): with open(original_microblog + non_rumor_class_dir, 'r') as f2: non_rumor_content = f2.read() non_rumor_dict = json.loads(non_rumor_content) all_non_rumor_list.append(non_rumor_label+"\t"+non_rumor_dict["text"]+"\n") non_rumor_num +=1 print("谣言数据总量为:"+str(rumor_num))print("非谣言数据总量为:"+str(non_rumor_num))登录后复制
谣言数据总量为:1538 非谣言数据总量为:1849登录后复制 In [3]
- 首先清空all_data.txt文件;然后将正负样本列表相加,并使用random.shuffle函数打乱顺序;接着打开file进行写入操作,一行一个样本。
# 导入必要的包%matplotlib inlineimport osfrom multiprocessing import cpu_countimport numpy as npimport shutilimport paddleimport paddle.fluid as fluidfrom PIL import Imageimport matplotlib.pyplot as pltfrom matplotlib.font_manager import FontProperties font = FontProperties(fname='simhei.ttf', size=16)登录后复制 In [5]
# all_data_path= data_list_path + "all_data.txt"# data_list_path="/home/aistudio/data/"# dict_path = data_list_path + "dict.txt"# 生成数据字典def create_dict(data_path, dict_path): dict_set = set() # 创建一个无序不重复元素集,集合 # 读取全部数据 with open(data_path, 'r', encoding='utf-8') as f: lines = f.readlines() # with open('data/test_lines.txt', 'w', encoding='utf-8') as f: # f.write(str(lines)) #print(lines) # 把数据生成一个元组 for line in lines: content = line.split('\t')[-1].replace('\n', '') # 以\t为分隔符,取最后一段。去掉每一行的换行符 # print(line,content) for s in content: dict_set.add(s) # print(s,dict_set) #将每一个字加入到一个无序不重复元素集中(元组) # 把集合转换成字典,一个字对应一个数字 dict_list = [] i = 0 for s in dict_set: dict_list.append([s, i]) i += 1 # print(dict_list) # 添加未知字符 dict_txt = dict(dict_list) # list转字典 end_dict = {"<unk>": i} dict_txt.update(end_dict) # 把这些字典保存到本地中 with open(dict_path, 'w', encoding='utf-8') as f: f.write(str(dict_txt)) print("数据字典生成完成!") # 获取字典的长度def get_dict_len(dict_path): with open(dict_path, 'r', encoding='utf-8') as f: line = eval(f.readlines()[0]) return len(line.keys()) create_dict('data/all_data.txt','data/dict.txt') get_dict_len('data/dict.txt')登录后复制
数据字典生成完成!登录后复制
- 录后复制 In [6]
# 创建序列化表示的数据,并按照一定比例划分训练数据与验证数据def create_data_list(data_list_path): #在生成数据之前,首先将eval_list.txt和train_list.txt清空 with open(os.path.join(data_list_path, 'eval_list.txt'), 'w', encoding='utf-8') as f_eval: f_eval.seek(0) f_eval.truncate() with open(os.path.join(data_list_path, 'train_list.txt'), 'w', encoding='utf-8') as f_train: f_train.seek(0) f_train.truncate() with open(os.path.join(data_list_path, 'dict.txt'), 'r', encoding='utf-8') as f_data: dict_txt = eval(f_data.readlines()[0]) # print(dict_txt) with open(os.path.join(data_list_path, 'all_data.txt'), 'r', encoding='utf-8') as f_data: lines = f_data.readlines() # print(lines) i = 0 with open(os.path.join(data_list_path, 'eval_list.txt'), 'a', encoding='utf-8') as f_eval,open(os.path.join(data_list_path, 'train_list.txt'), 'a', encoding='utf-8') as f_train: for line in lines: # print(line) words = line.split('\t')[-1].replace('\n', '') label = line.split('\t')[0] labs = "" if i % 8 == 0: for s in words: lab = str(dict_txt[s]) labs = labs + lab + ',' labs = labs[:-1] labs = labs + '\t' + label + '\n' f_eval.write(labs) else: for s in words: lab = str(dict_txt[s]) labs = labs + lab + ',' labs = labs[:-1] labs = labs + '\t' + label + '\n' f_train.write(labs) i += 1 print("数据列表生成完成!") create_data_list('/home/aistudio/data/')登录后复制
数据列表生成完成!登录后复制 In [7]
#dict_path为数据字典存放路径#all_data_path = data_list_path + all_data.txt#data_list_path=~/aistudio/data/#dict_path = data_list_path + dict.txt#创建数据字典,位置:dict.txt。生成前清空#with open(dict_path, 'w') as f: f.seek( f.truncate#create_dict(all_data_path, dict_path)#创建数据列表,分别位于train_list.txt和eval_list.txt。
数据字典生成完成! 数据列表生成完成!登录后复制 In [8]
def data_mapper(sample): data, label = sample data = [int(data) for data in data.split(',')] return data, int(label)#定义数据读取器def data_reader(data_path): def reader(): with open(data_path, 'r') as f: lines = f.readlines() for line in lines: data, label = line.split('\t') yield data, label return paddle.reader.xmap_readers(data_mapper, reader, cpu_count(), 1024)登录后复制 In [9]
# 获取训练数据读取器和测试数据读取器,设置超参数# data_list_path="/home/aistudio/data/"BATCH_SIZE = 256train_list_path = data_list_path+'train_list.txt'eval_list_path = data_list_path+'eval_list.txt'train_reader = paddle.batch( reader=data_reader(train_list_path), batch_size=BATCH_SIZE) eval_reader = paddle.batch( reader=data_reader(eval_list_path), batch_size=BATCH_SIZE)登录后复制
4.3、模型组网
完成数据准备后,我们接着构建循环神经网络,用于从文本中提取特征,并开发算法以识别虚假信息。
4.3.1 搭建网络
4.3.1.1 rnn
In [10]
def rnn_net(ipt, input_dim): #循环神经网络 # 以数据的IDs作为输入, ipt 输入 数据集 emb = fluid.layers.embedding(input=ipt, size=[input_dim, 128],is_sparse=True) drnn = fluid.layers.DynamicRNN() with drnn.block(): # 将embedding标记为RNN的输入,每个时间步取句子中的一个字进行处理 word=drnn.step_input(emb) # 将memory初始化为一个值为0的常量Tensor,shape=[batch_size, 200],其中batch_size由输入embedding决定 memory = drnn.memory(shape=[200]) hidden = fluid.layers.fc(input=[word, memory], size=200, act='relu') # 用hidden更新memory drnn.update_memory(ex_mem=memory, new_mem=hidden) # 将hidden标记为RNN的输出 drnn.output(hidden) # 最大序列池操作 fc = fluid.layers.sequence_pool(input=drnn(), pool_type='max') # 以softmax作为全连接的输出层,大小为2,也就是正负面 out = fluid.layers.fc(input=fc, size=2, act='softmax') return out登录后复制
4.3.1.2 lstm
In [11]
def lstm_net(ipt, input_dim): # 长短期记忆网络 # 以数据的ID作为输入 emb = fluid.layers.embedding(input=ipt, size=[input_dim, , is_sparse=True) # 第一全连接层 fc= fluid.layers.fc(input=emb, size= # 进行长短期记忆操作 lstm _ = fluid.layers.dynamic_lstm(input=fc size= # 返回:隐藏状态和LSTM神经元状态 # 第一个最大序列池操作 fc= fluid.layers.sequence_pool(input=emb, pool_type='max') # 第二个最大序列池操作 lstm= fluid.layers.sequence_pool(input=lstm pool_type='max') # 以softmax作为全连接层的输出,大小为表示正负面情感 out = fluid.layers.fc(input=[fc lstm, size= act='softmax') return out
4.3.1.3 bilstm
In [12]
def bilstm_net(ipt, input_dim): # 双向长短期神经网络 # 以数据的IDs作为输入 emb = fluid.layers.embedding(input=ipt, size=[input_dim, 128], is_sparse=True) # 第一个全连接层 fc1_f = fluid.layers.fc(input=emb, size=128) fc1_b = fluid.layers.fc(input=emb, size=128) # 进行一个长短期记忆操作 lstm1_f, _ = fluid.layers.dynamic_lstm(input=fc1_f, #返回:隐藏状态(hidden state),LSTM的神经元状态 size=128) #size=4*hidden_size lstm1_b, _ = fluid.layers.dynamic_lstm(input=fc1_b, #返回:隐藏状态(hidden state),LSTM的神经元状态 is_reverse = True, size=128) #size=4*hidden_size # 第一个最大序列池操作 fc2_f = fluid.layers.sequence_pool(input=fc1_f, pool_type='max') fc2_b = fluid.layers.sequence_pool(input=fc1_b, pool_type='max') # 第二个最大序列池操作 lstm2_f = fluid.layers.sequence_pool(input=lstm1_f, pool_type='max') lstm2_b = fluid.layers.sequence_pool(input=lstm1_b, pool_type='max') lstm2 = fluid.layers.concat(input=[lstm2_f, lstm2_b], axis=1) fc2 = fluid.layers.concat(input=[fc2_f, fc2_b], axis=1) # 以softmax作为全连接的输出层,大小为2,也就是正负面 out = fluid.layers.fc(input=[fc2, lstm2], size=2, act='softmax') return out登录后复制
4.3.1.4 gru
In [13]
def gru_net(ipt, input_dim): # 门控循环单元 # 以数据的IDs作为输入 emb = fluid.layers.embedding(input=ipt, size=[input_dim, 128], is_sparse=True) # 第一个全连接层 fc1 = fluid.layers.fc(input=emb, size=384) # 进行一个长短期记忆操作 gru1= fluid.layers.dynamic_gru(input=fc1,size=128) # 第一个最大序列池操作 fc2 = fluid.layers.sequence_pool(input=fc1, pool_type='max') # 第二个最大序列池操作 gru2 = fluid.layers.sequence_pool(input=gru1, pool_type='max') # 以softmax作为全连接的输出层,大小为2,也就是正负面 out = fluid.layers.fc(input=[fc2, gru2], size=2, act='softmax') return out登录后复制
4.3.1.5 bigru
In [14]
def bigru_net(ipt, input_dim): # 双向门控循环单元 # 以数据的IDs作为输入 emb = fluid.layers.embedding(input=ipt, size=[input_dim, 128], is_sparse=True) # 第一个全连接层 fc1_f = fluid.layers.fc(input=emb, size=384) fc1_b = fluid.layers.fc(input=emb, size=384) # 进行一个长短期记忆操作 gru1_f= fluid.layers.dynamic_gru(input=fc1_f,size=128) gru1_b= fluid.layers.dynamic_gru(input=fc1_b,size=128,is_reverse=True) # 第一个最大序列池操作 fc2_f = fluid.layers.sequence_pool(input=fc1_f, pool_type='max') fc2_b = fluid.layers.sequence_pool(input=fc1_b, pool_type='max') # 第二个最大序列池操作 gru2_f = fluid.layers.sequence_pool(input=gru1_f, pool_type='max') gru2_b = fluid.layers.sequence_pool(input=gru1_b, pool_type='max') gru2 = fluid.layers.concat(input=[gru2_f, gru2_b], axis=1) fc2 = fluid.layers.concat(input=[fc2_f, fc2_b], axis=1) # 以softmax作为全连接的输出层,大小为2,也就是正负面 out = fluid.layers.fc(input=[fc2, gru2], size=2, act='softmax') return out登录后复制
4.3.2 定义数据层
In [15]
# 定义输入数据, lod_level不为0指定输入数据为序列数据paddle.enable_static() words = fluid.data(name='words', shape=[None,1], dtype='int64', lod_level=1) label = fluid.data(name='label', shape=[None,1], dtype='int64')登录后复制
4.3.3 获取分类器
In [16]
# 获取数据字典长度dict_dim = get_dict_len(dict_path)# 获取分类器# model = rnn_net(words, dict_dim) # model = lstm_net(words, dict_dim) model = bilstm_net(words, dict_dim) # model = gru_net(words, dict_dim) # model = bigru_net(words, dict_dim)登录后复制
4.3.4 定义损失函数和准确率
定义了一个损失函数之后,还有对它求平均值,因为定义的是一个Batch的损失值。
同时我们还可以定义一个准确率函数,这个可以在我们训练的时候输出分类的准确率。 In [17]
# 获取损失函数和准确率cost = fluid.layers.cross_entropy(input=model, label=label) avg_cost = fluid.layers.mean(cost) acc = fluid.layers.accuracy(input=model, label=label)# 获取预测程序test_program = fluid.default_main_program().clone(for_test=True)登录后复制
4.3.5 定义优化方法
In [18]
# 定义优化方法optimizer = fluid.optimizer.AdagradOptimizer(learning_rate=0.001) opt = optimizer.minimize(avg_cost)登录后复制
4.4、训练网络
4.4.1 创建Executor
In [19]
# use_cuda为False,表示运算场所为CPU;use_cuda为True,表示运算场所为GPU use_cuda = True place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace() exe = fluid.Executor(place) # 进行参数初始化exe.run(fluid.default_startup_program())登录后复制
W0221 21:51:10.279976 21097 device_context.cc:447] Please NOTE: device: 0, GPU Compute Capability: 7.0, Driver API Version: 10.1, Runtime API Version: 10.1 W0221 21:51:10.283764 21097 device_context.cc:465] device: 0, cuDNN Version: 7.6.登录后复制
[]登录后复制
4.4.2 定义数据映射器
DataFeeder负责将数据提供器(train_reader,test_reader)返回的数据转成一种特殊的数据结构,使其可以输入到Executor中。
feed_list设置向模型输入的向变量表或者变量表名 In [20]
# 定义数据映射器feeder = fluid.DataFeeder(place=place, feed_list=[words, label])登录后复制
4.4.3 展示模型训练曲线
In [21]
all_train_iter=0all_train_iters=[] all_train_costs=[] all_train_accs=[] all_eval_iter=0all_eval_iters=[] all_eval_costs=[] all_eval_accs=[]def draw_process(title,iters,costs,accs,label_cost,lable_acc): plt.title(title, fontsize=24) plt.xlabel("iter", fontsize=20) plt.ylabel("cost/acc", fontsize=20) plt.plot(iters, costs,color='red',label=label_cost) plt.plot(iters, accs,color='green',label=lable_acc) plt.legend() plt.grid() plt.show()登录后复制
4.4.4 训练并保存模型
当Executor收到程序时,会依据输入映射表feed_map并将数据作为输入提供给程序;同时也会根据结果获取表fetch_list加载数据以供程序使用,并通过添加相应的feed和fetch操作符来处理这些信息。
feed map为该program提供输入数据。fetch_list提供program训练结束后用户预期的变量。
每一轮训练结束之后,再使用验证集进行验证,并求出相应的损失值Cost和准确率acc。 In [22]
在EPOCH_NUM = 次中,对模型进行训练。每批次输出一次当前的进度信息,并记录总批次数和成本、准确率等数据。通过验证集评估模型性能,并计算平均预测损失与准确率。若未存在目标路径,则创建目录用于保存模型;最后完成模型保存操作。
epoch: 1 Pass:0, Batch:0, Cost:0.69911, Acc:0.47266 Pass:0, Batch:10, Cost:0.66337, Acc:0.56250 Test:0, Cost:0.66470, ACC:0.53683 epoch: 2 Pass:1, Batch:0, Cost:0.65396, Acc:0.55469 Pass:1, Batch:10, Cost:0.63739, Acc:0.62500 Test:1, Cost:0.64528, ACC:0.63030 epoch: 3 Pass:2, Batch:0, Cost:0.63112, Acc:0.70703 Pass:2, Batch:10, Cost:0.61620, Acc:0.71875 Test:2, Cost:0.62902, ACC:0.69699 epoch: 4 Pass:3, Batch:0, Cost:0.61294, Acc:0.77344 Pass:3, Batch:10, Cost:0.59836, Acc:0.76953 Test:3, Cost:0.61558, ACC:0.71670 epoch: 5 Pass:4, Batch:0, Cost:0.59646, Acc:0.78906 Pass:4, Batch:10, Cost:0.58233, Acc:0.79688 Test:4, Cost:0.60275, ACC:0.73047 epoch: 6 Pass:5, Batch:0, Cost:0.58203, Acc:0.80078 Pass:5, Batch:10, Cost:0.56806, Acc:0.81250 Test:5, Cost:0.59103, ACC:0.76581 epoch: 7 Pass:6, Batch:0, Cost:0.56877, Acc:0.81641 Pass:6, Batch:10, Cost:0.55464, Acc:0.81250 Test:6, Cost:0.57990, ACC:0.77269 epoch: 8 Pass:7, Batch:0, Cost:0.55748, Acc:0.82422 Pass:7, Batch:10, Cost:0.54018, Acc:0.83984 Test:7, Cost:0.57005, ACC:0.78162 epoch: 9 Pass:8, Batch:0, Cost:0.54539, Acc:0.83203 Pass:8, Batch:10, Cost:0.52911, Acc:0.85156 Test:8, Cost:0.56025, ACC:0.78757 epoch: 10 Pass:9, Batch:0, Cost:0.53370, Acc:0.83594 Pass:9, Batch:10, Cost:0.52003, Acc:0.85547 Test:9, Cost:0.55105, ACC:0.79846 epoch: 11 Pass:10, Batch:0, Cost:0.52343, Acc:0.84375 Pass:10, Batch:10, Cost:0.50598, Acc:0.87500 Test:10, Cost:0.54268, ACC:0.79548 epoch: 12 Pass:11, Batch:0, Cost:0.51352, Acc:0.84375 Pass:11, Batch:10, Cost:0.49801, Acc:0.87891 Test:11, Cost:0.53439, ACC:0.80134 epoch: 13 Pass:12, Batch:0, Cost:0.50305, Acc:0.84766 Pass:12, Batch:10, Cost:0.48714, Acc:0.89453 Test:12, Cost:0.52690, ACC:0.80627 epoch: 14 Pass:13, Batch:0, Cost:0.49415, Acc:0.83984 Pass:13, Batch:10, Cost:0.47674, Acc:0.89844 Test:13, Cost:0.51935, ACC:0.81017 epoch: 15 Pass:14, Batch:0, Cost:0.48502, Acc:0.84375 Pass:14, Batch:10, Cost:0.46768, Acc:0.89844 Test:14, Cost:0.51199, ACC:0.82199 epoch: 16 Pass:15, Batch:0, Cost:0.47742, Acc:0.85156 Pass:15, Batch:10, Cost:0.45791, Acc:0.89844 Test:15, Cost:0.50501, ACC:0.82394 epoch: 17 Pass:16, Batch:0, Cost:0.46781, Acc:0.85938 Pass:16, Batch:10, Cost:0.45186, Acc:0.89844 Test:16, Cost:0.49864, ACC:0.82394 epoch: 18 Pass:17, Batch:0, Cost:0.45989, Acc:0.86328 Pass:17, Batch:10, Cost:0.44218, Acc:0.89453 Test:17, Cost:0.49238, ACC:0.82292 epoch: 19 Pass:18, Batch:0, Cost:0.45258, Acc:0.85938 Pass:18, Batch:10, Cost:0.43367, Acc:0.89453 Test:18, Cost:0.48672, ACC:0.82487 epoch: 20 Pass:19, Batch:0, Cost:0.44533, Acc:0.85547 Pass:19, Batch:10, Cost:0.42680, Acc:0.89453 Test:19, Cost:0.48060, ACC:0.82096 训练模型保存完成!登录后复制
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/cbook/__init__.py:2349: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working if isinstance(obj, collections.Iterator): /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/cbook/__init__.py:2366: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working return list(data) if isinstance(data, collections.MappingView) else data登录后复制
<Figure size 432x288 with 1 Axes>登录后复制登录后复制
<Figure size 432x288 with 1 Axes>登录后复制登录后复制
4.5、模型预测
In [23]
# 用训练好的模型进行预测并输出预测结果# 创建执行器place = fluid.CPUPlace() infer_exe = fluid.Executor(place) infer_exe.run(fluid.default_startup_program()) save_path = '/home/aistudio/work/infer_model/'# 从模型中获取预测程序、输入数据名称列表、分类器[infer_program, feeded_var_names, target_var] = fluid.io.load_inference_model(dirname=save_path, executor=infer_exe)# 获取数据def get_data(sentence): # 读取数据字典 with open('/home/aistudio/data/dict.txt', 'r', encoding='utf-8') as f_data: dict_txt = eval(f_data.readlines()[0]) dict_txt = dict(dict_txt) # 把字符串数据转换成列表数据 keys = dict_txt.keys() data = [] for s in sentence: # 判断是否存在未知字符 if not s in keys: s = '<unk>' data.append(int(dict_txt[s])) return data data = []# 获取图片数据data1 = get_data('兴仁县今天抢小孩没抢走,把孩子母亲捅了一刀,看见这车的注意了,真事,车牌号辽HFM055!!!!!赶紧散播! 都别带孩子出去瞎转悠了 尤其别让老人自己带孩子出去 太危险了 注意了!!!!辽HFM055北京现代朗动,在各学校门口抢小孩!!!110已经 证实!!全市通缉!!') data2 = get_data('重庆真实新闻:2016年6月1日在重庆梁平县袁驿镇发生一起抢儿童事件,做案人三个中年男人,在三中学校到镇街上的一条小路上,把小孩直接弄晕(儿童是袁驿新幼儿园中班的一名学生),正准备带走时被家长及时发现用棒子赶走了做案人,故此获救!请各位同胞们以此引起非常重视,希望大家有爱心的人传递下') data3 = get_data('@尾熊C 要提前预习育儿知识的话,建议看一些小巫写的书,嘻嘻') data.append(data1) data.append(data2) data.append(data3)# 获取每句话的单词数量base_shape = [[len(c) for c in data]]# 生成预测数据tensor_words = fluid.create_lod_tensor(data, base_shape, place)# 执行预测result = exe.run(program=infer_program, feed={feeded_var_names[0]: tensor_words}, fetch_list=target_var)# 分类名称names = [ '谣言', '非谣言']# 获取结果概率最大的labelfor i in range(len(data)): lab = np.argsort(result)[0][i][-1] print('预测结果标签为:%d, 分类为:%s, 概率为:%f' % (lab, names[lab], result[0][i][lab]))登录后复制
预测结果显示: - 标签为分类为谣言,概率为 - 标签为分类为谣言,概率为 - 标签为分类为非谣言,概率为录后可复制这段信息
代码解释
五、总结
展示的项目使用了RNN,LSTM,BiLSTM,GRU和BiGRU分别进行谣言分类
相比与vanilla RNN(原始RNN),其变体(LSTM,GRU)在实际项目中运用比较广泛
双向循环神经网络不仅能更好融合文本信息,参数量增多导致训练效率降低。
采用其他网络的谣言检测任务可以在本项目的基础上修改实现
以上就是【AI达人创造营第二期】 一文读懂双向循环神经网络 BRNN的详细内容,更多请关注其它相关文章!
热门推荐
-
【AI达人创造营第二期】 一文读懂双向循环神经网络 BRNN本研究全面解析了RNN与BRNN的基础知识、架构及各自的利弊,并通过一个案例展示了基于vanillaRNN、LSTM、BiLSTM、GRU以及BiGRU模型的谣言
-
【AI达人特训营第三期】:PaddleSeg助力自动驾驶场景分割本文介绍使用PaddleSeg工具处理基于ADE数据集场景解析的过程。首先,解压相关软件及数据集,并加载并预处理它们
-
永劫无间无法进入大厅 老司机教你几招,秒变排队达人铁友们,不要急着吐槽“永劫无间无法进入大厅”的困扰了!别忘了喝杯热茶暖暖身子,我们坐下来好好聊聊。今天,我打算把这事儿说透彻,绝对干货满满,让你看得懂、记得住
-
汉字达人爱心宠物店怎么过_汉字达人爱心宠物店将宠物店的价格砍到最低通关攻略汉字达人爱心宠物店将宠物店的价格砍到最低通关攻略:在汉字达人游戏很多关卡还是挺多的,当然这些关卡玩起来也是非常有意思的。小编整理了爱心宠物店关卡如何玩呢?下面一起来看看相关的信息。
-
《创造与魔法》兑换码2022永久坐骑12月汇总在创造与魔法这款游戏中,官方每个月会给小伙伴发放兑换码的福利,小伙伴能够经过兑换码来兑换获取奖励,不过兑换码通常都是有期限的,那么本年12月份的兑换码是甚么呢。好
-
《创造与魔法》精烹食品大全 精烹食品制作攻略在创造与魔法中有很多种食物,网友能够阐发自个的想象力自在制造,部分玩家想知道游戏中的精烹食物要怎样做,接下来小编就给网友带来了创造与魔法精烹食物大全,期望可以或许
-
创造与魔法精烹夏季水果沙拉怎么做 精烹水果沙拉配方分享迩来有很多网友们都在问创造与魔法精烹夏日生果沙拉怎样做,为此本站的小编整理好了创造与魔法精烹生果沙拉配方分享,有必要的话没关系一块出去瞧瞧干系内容的讲解吧。创造与
-
创造与魔法月息壤在哪里获得 创造与魔法月息壤获取途径创造与魔法月息壤在哪里得到?创造与魔法月息壤怎样弄?接下来一起来瞧瞧周详的玩法讲解吧!得到攻略1、月息壤主要是挖月岩得到,月岩分两种。第一种普及的,挖完以后能够拿
-
创造与魔法精烹食品配方大全创造与魔法精烹食物配方是甚么?创造与魔法精烹食物还是许多的,网友能够依据接下来供给的菜谱完成对于美食的制造的,接下来便是小编带来的创造与魔法精烹食物配方一览,好奇
-
抓大鹅第二关怎么过-抓大鹅第二关通关教程抓大鹅第二关怎么过?目前,抓大鹅这款微信小程序的游戏可以说是十分火爆的,这款小程序游戏和羊了个羊是有异曲同工之妙的
-
我在《剑星》玩《胜利女神》 这波双向联动可太懂玩家了ShiftUp重量级作品剑星(StellarBlade)PC版现已开放预购,国区标准版售价,豪华版;游戏预定全球同步推出,支持中文与配音
-
迷你世界循环电路怎么做 迷你世界循环电路教程迷你世界循环电路怎么制作?很多小伙伴在建造自动化装置时需要用到循环电路,但不知道具体操作方法。本站小编整理了迷你世界循环电路的详细制作步骤,其实只要掌握几个关键点
-
死亡循环黑屏进不去怎么办 死亡循环黑屏解决方案在黑礁岛的一日轮回中,玩家需要面对死亡循环以“时间循环+第一人称刺杀”为核心玩法。如果你遭遇了黑屏无法进入的情况,首先建议你从硬件连接、驱动文件和网络环境等维度进
-
死亡循环延迟掉线掉帧怎么解决 死亡循环卡顿丢包怎么办死亡循环作为一款结合了时间循环与多人射击元素的游戏,在追求沉浸式体验的同时,对玩家的网络延迟和帧率稳定性提出了极高要求
-
循环镜像文件是什么循环镜像文件具有内部包含指向自身的链接或引用的特征,检测此现象的方法包括:通过`dd`和`file`命令分析文件结构;利用高级文件系统工具进行检查
-
汉字找茬王找出网络热梗攻略图文-找梗怎么过关抖音小游戏《汉字找茬王》是抖音上现在很火的精美益智烧脑解谜闯关游戏,游戏中关卡找梗怎样过,这一关需求找出网络热梗!下面是小编给大伙带来的抖音小游戏《汉字找茬王》找出网络热梗通关攻略,好奇的小伙伴们一起来看看吧。
-
dinner是什么梗-dinner是什么网络用语对于从型学习英文的我们都晓得,dinner便是晚饭的意思,不外跟着时期的进展,越来越多的词也有了本身特别的意义,并且由于网络环境的问题,很多的词都会被谐和,所以网友们就想出了谐音的办法。接下来小编就为列位带来dinner是甚么梗的先容,一起来看看吧!
-
《抖音》网络热梗泰酷辣介绍泰裤辣是甚么梗?能够又有玩家不知道这是甚么。这个梗来自于小鬼王琳凯歌曲中的念白,也是他音乐节的口头禅,下面是小编带来的网络热梗泰酷辣讲解,好奇的玩家必定不要错过哦
-
为什么抖音总是显示网络错误 为什么抖音总是显示网络错误安卓抖音总是显示网络错误是因为网络不好或者关闭了网络的功能。有以下3种处理方法如下:1、开启WLAN+,开启WLAN的按键下方就有一个选项:WLAN+,开启WLAN+后不仅可以有效提高网络质量,还可以智能切换WLAN与移动数据。2、开启LTE载波聚合,LTE载波聚合可以有效提高上下行传输速率,从而提升我们的网络、通话的速度与稳定。3、先打开飞行模式,再关闭飞行模式,看看网络能不能恢复正常。
-
天猫精灵重新配对网络方法天猫精灵是需要连接网络后才能使用相关功能的,否则很多功能都无法正常实现。那么连接了网络之后,如果我们想要重新配对网络该如何操作呢?下面小编就为大家带来了天猫精灵重新配对网络的方法介绍,我们一起来了解下吧!