关键词:
【自然语言处理(NLP)】基于LSTM的谣言检测
(文章目录)
前言
(一)、任务描述
本次实践使用基于循环神经网络(RNN)的谣言检测模型,将文本中的谣言事件向量化,通过循环神经网络的学习训练来挖掘表示文本深层的特征,避免了特征构建的问题,并能发现那些不容易被人发现的特征,从而产生更好的效果。
数据集介绍:
本次实践所使用的数据是从新浪微博不实信息举报平台抓取的中文谣言数据,数据集中共包含1538条谣言和1849条非谣言。如下图所示,每条数据均为json格式,其中text字段代表微博原文的文字内容。
更多数据集介绍请参考https://github.com/thunlp/Chinese_Rumor_Dataset
(二)、环境配置
本示例基于飞桨开源框架2.0版本。
import paddle
import numpy as np
import matplotlib.pyplot as plt
print(paddle.__version__)
输出结果如下图1所示:
一、数据准备
(1)解压数据,读取并解析数据,生成all_data.txt
(2)生成数据字典,即dict.txt
(3)生成数据列表,并进行训练集与验证集的划分,train_list.txt 、eval_list.txt
(4)定义训练数据集提供器
(一)、解压数据
import os, zipfile
src_path="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()
import io
import random
import json
#谣言数据文件路径
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,非谣言标签为1
rumor_label="0"
non_rumor_label="1"
#分别统计谣言数据与非谣言数据的总数
rumor_num = 0
non_rumor_num = 0
all_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))
输出结果如下图2所示:
(二)、写入all_data.txt
#全部数据进行乱序后写入all_data.txt
data_list_path="/home/aistudio/data/"
all_data_path=data_list_path + "all_data.txt"
all_data_list = all_rumor_list + all_non_rumor_list
random.shuffle(all_data_list)
#在生成all_data.txt之前,首先将其清空
with open(all_data_path, w) as f:
f.seek(0)
f.truncate()
with open(all_data_path, a) as f:
for data in all_data_list:
f.write(data)
(三)、生成数据字典
# 生成数据字典
def create_dict(data_path, dict_path):
with open(dict_path, w) as f:
f.seek(0)
f.truncate()
dict_set = set()
# 读取全部数据
with open(data_path, r, encoding=utf-8) as f:
lines = f.readlines()
# 把数据生成一个元组
for line in lines:
content = line.split(\\t)[-1].replace(\\n, )
for s in content:
dict_set.add(s)
# 把元组转换成字典,一个字对应一个数字
dict_list = []
i = 0
for s in dict_set:
dict_list.append([s, i])
i += 1
# 添加未知字符
dict_txt = dict(dict_list)
end_dict = "<unk>": i
dict_txt.update(end_dict)
end_dict = "<pad>": i+1
dict_txt.update(end_dict)
# 把这些字典保存到本地中
with open(dict_path, w, encoding=utf-8) as f:
f.write(str(dict_txt))
print("数据字典生成完成!")
(四)、数据集划分
# 创建序列化表示的数据,并按照一定比例划分训练数据train_list.txt与验证数据eval_list.txt
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(0)
f_eval()
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])
with open(os.path.join(data_list_path, all_data.txt), r, encoding=utf-8) as f_data:
lines = f_data.readlines()
i = 0
maxlen = 0
with open(os.path.join(data_list_path, eval(os.path.join(data_list_path, train_list.txt), a, encoding=utf-8) as f_train:
for line in lines:
words = line.split(\\t)[-1].replace(\\n, )
maxlen = max(maxlen, len(words))
label = line.split(\\t)[0]
labs = ""
# 每8个 抽取一个数据用于验证
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(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("数据列表生成完成!")
print("样本最长长度:" + str(maxlen))
# 把生成的数据列表都放在自己的总类别文件夹中
data_root_path = "/home/aistudio/data/"
data_path = os.path.join(data_root_path, all_data.txt)
dict_path = os.path.join(data_root_path, "dict.txt")
# 创建数据字典
create_dict(data_path, dict_path)
# 创建数据列表
create_data_list(data_root_path)
输出结果如下图3所示:
(五)、定义训练数据集提供器
def load_vocab(file_path):
fr = open(file_path, r, encoding=utf8)
vocab = eval(fr.read()) #读取的str转换为字典
fr.close()
return vocab
# 打印前2条训练数据
vocab = load_vocab(os.path.join(data_root_path, dict.txt))
def ids_to_str(ids):
words = []
for k in ids:
w = list(vocab.keys())[list(vocab.values()).index(int(k))]
words.append(w if isinstance(w, str) else w.decode(ASCII))
return " ".join(words)
file_path = os.path.join(data_root_path, train_list.txt)
with io.open(file_path, "r", encoding=utf8) as fin:
i = 0
for line in fin:
i += 1
cols = line.strip().split("\\t")
if len(cols) != 2:
sys.stderr.write("[NOTICE] Error Format Line!")
continue
label = int(cols[1])
wids = cols[0].split(",")
print(str(i)+":")
print(sentence list id is:, wids)
print(sentence list is: , ids_to_str(wids))
print(sentence label id is:, label)
print(---------------------------------)
if i == 2: break
输出结果如下图4所示:
vocab = load_vocab(os.path.join(data_root_path, dict.txt))
class RumorDataset(paddle.io.Dataset):
def __init__(self, data_dir):
self.data_dir = data_dir
self.all_data = []
with io.open(self.data_dir, "r", encoding=utf8) as fin:
for line in fin:
cols = line.strip().split("\\t")
if len(cols) != 2:
sys.stderr.write("[NOTICE] Error Format Line!")
continue
label = []
label.append(int(cols[1]))
wids = cols[0].split(",")
if len(wids)>=150:
wids = np.array(wids[:150]).astype(int64)
else:
wids = np.concatenate([wids, [vocab["<pad>"]]*(150-len(wids))]).astype(int64)
label = np.array(label).astype(int64)
self.all_data.append((wids, label))
def __getitem__(self, index):
data, label = self.all_data[index]
return data, label
def __len__(self):
return len(self.all_data)
batch_size = 32
train_dataset = RumorDataset(os.path.join(data_root_path, train_list.txt))
test_dataset = RumorDataset(os.path.join(data_root_path, eval_list.txt))
train_loader = paddle.io.DataLoader(train_dataset, places=paddle.CPUPlace(), return_list=True,
shuffle=True, batch_size=batch_size, drop_last=True)
test_loader = paddle.io.DataLoader(test_dataset, places=paddle.CPUPlace(), return_list=True,
shuffle=True, batch_size=batch_size, drop_last=True)
#check
print(=============train_dataset =============)
for data, label in train_dataset:
print(data)
print(np.array(data).shape)
print(label)
break
print(=============test_dataset =============)
for data, label in test_dataset:
print(data)
print(np.array(data).shape)
print(label)
break
输出结果如下图5所示:
二、模型配置
import paddle
from paddle.nn import Conv2D, Linear, Embedding
from paddle import to_tensor
import paddle.nn.functional as F
class RNN(paddle.nn.Layer):
def __init__(self):
super(RNN, self).__init__()
self.dict_dim = vocab["<pad>"]
self.emb_dim = 128
self.hid_dim = 128
self.class_dim = 2
self.embedding = Embedding(
self.dict_dim + 1, self.emb_dim,
sparse=False)
self._fc1 = Linear(self.emb_dim, self.hid_dim)
self.lstm = paddle.nn.LSTM(self.hid_dim, self.hid_dim)
self.fc2 = Linear(19200, self.class_dim)
def forward(self, inputs):
# [32, 150]
emb = self.embedding(inputs)
# [32, 150, 128]
fc_1 = self._fc1(emb)
# [32, 150, 128]
x = self.lstm(fc_1)
x = paddle.reshape(x[0], [0, -1])
x = self.fc2(x)
x = paddle.nn.functional.softmax(x)
return x
rnn = RNN()
paddle.summary(rnn,(32,150),"int64")
输出结果如下图6所示:
三、模型训练
# 构建迁移网络,使用ERNIE的token-level输出
query = outputs["sequence_output"]
title = outputs[sequence_output_2]
# 创建pointwise文本匹配任务
pointwise_matching_task = hub.PointwiseTextMatchingTask(
dataset=dataset,
query_feature=query,
title_feature=title,
tokenizer=tokenizer,
config=config)
四、开始Finetune
def draw_process(title,color,iters,data,label):
plt.title(title, fontsize=24)
plt.xlabel("iter", fontsize=20)
plt.ylabel(label, fontsize=20)
plt.plot(iters, data,color=color,label=label)
plt.legend()
plt.grid()
plt.show()
def train(model):
model.train()
opt = paddle.optimizer.Adam(learning_rate=0.002, parameters=model.parameters())
steps = 0
Iters, total_loss, total_acc = [], [], []
for epoch in range(3):
for batch_id, data in enumerate(train_loader):
steps += 1
sent = data[0]
label = data[1]
logits = model(sent)
loss = paddle.nn.functional.cross_entropy(logits, label)
acc = paddle.metric.accuracy(logits, label)
if batch_id % 50 == 0:
Iters.append(steps)
total_loss.append(loss.numpy()[0])
total_acc.append(acc.numpy()[0])
print("epoch: , batch_id: , loss is: ".format(epoch, batch_id, loss.numpy()))
loss.backward()
opt.step()
opt.clear_grad()
# evaluate model after one epoch
model.eval()
accuracies = []
losses = []
for batch_id, data in enumerate(test_loader):
sent = data[0]
label = data[1]
logits = model(sent)
loss = paddle.nn.functional.cross_entropy(logits, label)
acc = paddle.metric.accuracy(logits, label)
accuracies.append(acc.numpy())
losses.append(loss.numpy())
avg_acc, avg_loss = np.mean(accuracies), np.mean(losses)
print("[validation] accuracy: , loss: ".format(avg_acc, avg_loss))
model.train()
paddle.save(model.state_dict(),"model_final.pdparams")
draw_process("trainning loss","red",Iters,total_loss,"trainning loss")
draw_process("trainning acc","green",Iters,total_acc,"trainning acc")
model = RNN()
train(model)
输出结果如下图7、8、9所示:
五、模型评估
模型评估
model_state_dict = paddle.load(model_final.pdparams)
model = RNN()
model.set_state_dict(model_state_dict)
model.eval()
label_map = 0:"是", 1:"否"
samples = []
predictions = []
accuracies = []
losses = []
for batch_id, data in enumerate(test_loader):
sent = data[0]
label = data[1]
logits = model(sent)
for idx,probs in enumerate(logits):
# 映射分类label
label_idx = np.argmax(probs)
labels = label_map[label_idx]
predictions.append(labels)
samples.append(sent[idx].numpy())
loss = paddle.nn.functional.cross_entropy(logits, label)
acc = paddle.metric.accuracy(logits, label)
accuracies.append(acc.numpy())
losses.append(loss.numpy())
avg_acc, avg_loss = np.mean(accuracies), np.mean(losses)
print("[validation] accuracy: , loss: ".format(avg_acc, avg_loss))
print(数据: \\n\\n是否谣言: .format(ids_to_str(samples[0]), predictions[0]))
输出结果如下图10所示:
总结
本系列文章内容为根据清华社出版的《自然语言处理实践》所作的相关笔记和感悟,其中代码均为基于百度飞桨开发,若有任何侵权和不妥之处,请私信于我,定积极配合处理,看到必回!!!
最后,引用本次活动的一句话,来作为文章的结语~( ̄▽ ̄~)~:
【**学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。**】
自然语言处理(nlp)基于lstm的命名实体识别(代码片段)
【自然语言处理(NLP)】基于LSTM的命名实体识别(文章目录)前言(一)、任务描述命名实体识别任务主要识别文本中的实体,并且给识别出的实体进行分类,比如人名、地名、机构名或其它类型。本质上,对于给定的文本,只需要... 查看详情
自然语言处理(nlp)基于注意力机制的英文新闻标题生成(代码片段)
【自然语言处理(NLP)】基于注意力机制的英文新闻标题生成(文章目录)前言(一)、任务描述我们将会使用飞桨提供的LSTM的API,组建一个sequencetosequencewithattention的自动文摘的模型,并在示例的数据集上完成从英文文章生成英文摘... 查看详情
自然语言处理(nlp)基于paddlehub的文本审核(代码片段)
【自然语言处理(NLP)】基于PaddleHub的文本审核(文章目录)前言(一)、任务描述在2017年之前,工业界和学术界对NLP文本处理依赖于序列模型RecurrentNeuralNetwork(RNN).近年来随着深度学习的发展,模型参数数量飞速增长,为了训练这些... 查看详情
自然语言处理(nlp)基于squad的机器阅读理解(代码片段)
【自然语言处理(NLP)】基于SQuAD的机器阅读理解(文章目录)前言(一)、任务描述机器阅读理解(MachingReadingComprehension,MRC)是一项基于文本的问答任务(Text-QA),也是非常重要和经典的自然语言处理任务之一。机器阅读理解旨... 查看详情
自然语言处理(nlp)基于transformer的英文自动文摘(代码片段)
【自然语言处理(NLP)】基于Transformer的英文自动文摘(文章目录)前言(一)、任务描述本示例教程介绍如何使用飞桨完成一个机器翻译任务。我们将会使用飞桨提供的开源框架完成基于Transformer的英文文本自动文摘模型。飞桨框架... 查看详情
自然语言处理(nlp)基于ernie语言模型的文本语义匹配(代码片段)
【自然语言处理(NLP)】基于ERNIE语言模型的文本语义匹配(文章目录)前言(一)、任务描述文本匹配一直是自然语言处理(NLP)领域一个基础且重要的方向,一般研究两段文本之间的关系。文本相似度计算、自然语言推理、问答系... 查看详情
自然语言处理(nlp)基于bilstm的关系抽取(代码片段)
【自然语言处理(NLP)】基于BiLSTM的关系抽取(文章目录)前言(一)、任务描述关系抽取是信息抽取的重要子任务,其主要目的是将非结构化获半结构化描述的自然语言文本转化成结构化数据,关系抽取主要负责对文本中抽取出的... 查看详情
自然语言处理(nlp)基于bi-daf的机器阅读理解(代码片段)
【自然语言处理(NLP)】基于Bi-DAF的机器阅读理解(文章目录)前言(一)、任务描述在机器阅读理解(MRC)任务中,我们会给定一个问题(Q)以及一个或多个段落(P)/文档(D),然后利用机器在给定的段落中寻找正确答案(A),即Q+PorD=>A.机... 查看详情
自然语言处理(nlp)基于bilstm+crf的事件抽取(代码片段)
【自然语言处理(NLP)】基于BiLSTM+CRF的事件抽取(文章目录)前言(一)、任务描述事件抽取技术是从非结构化信息中抽取出用户感兴趣的事件,并以结构化呈现给用户。事件抽取任务可分解为4个子任务:触发词识别、事件类型分类... 查看详情
毕业设计之-基于cnn实现谣言检测(代码片段)
...;这里是丹成学长,今天向大家介绍一个深度学习项目基于CNN实现谣言检测大家可用于毕业设计1.1背景社交媒体的发展在加速信息传播的同时,也带来了虚假谣言信息的泛滥,往往会引发诸多不安定因素,并对经济... 查看详情
做项目一定用得到的nlp资源分类版
...翻译数字转换指代消解文本聚类文本分类知识推理可解释自然语言处理文本对抗攻击文本可视化文本标注工具语言检测综合工具有趣搞笑工具课程报告面试等比赛金融自然语言处理医疗自然语言处理法律自然语言处理其他备注原... 查看详情
自然语言处理(nlp)基于gru实现情感分类(代码片段)
【自然语言处理(NLP)】基于GRU实现情感分类@TOC前言任务描述任务描述:本示例教程演示如何在IMDB数据集上用GRU网络完成文本分类的任务。IMDB数据集是一个对电影评论标注为正向评论与负向评论的数据集,共有25000条文本数据... 查看详情
自然语言处理(nlp)基于transformer的中-英机器翻译(代码片段)
【自然语言处理(NLP)】基于Transformer的中-英机器翻译(文章目录)前言(一)、任务描述飞桨框架实现了Transformer的基本层,因此可以直接调用:TransformerEncoderLayer类定义了编码器端的一个层,包括多头注意力子层及逐位前馈网络子... 查看详情
自然语言处理(nlp)bert与lstm结合
参考技术A自然语言处理(NLP)在深度学习领域是一大分支(其他:CV、语音),经过这些年的发展NLP发展已经很成熟,同时在工业界也慢慢开始普及,谷歌开放的Bert是NLP前进的又一里程碑。本篇文章结合Bert与Lstm,对文本数据进... 查看详情
自然语言处理(nlp)基于循环神经网络实现情感分类(代码片段)
【自然语言处理(NLP)】基于循环神经网络实现情感分类@TOC任务描述本示例教程演示如何在IMDB数据集上用RNN网络完成文本分类的任务。IMDB数据集是一个对电影评论标注为正向评论与负向评论的数据集,共有25000条文本数据作为... 查看详情
自然语言处理(nlp)基于paddlenlp的短文本相似度计算(代码片段)
【自然语言处理(NLP)】基于PaddleNLP的短文本相似度计算(文章目录)前言(一)、任务描述短文本语义匹配(SimailarityNet,SImNet)是一个计算短文本相似度的框架,可以根据用户输入的两个文本,计算出相似度得分。SimNet框架在百度各产... 查看详情
自然语言处理(nlp)基于fnn网络的电影评论情感分析(代码片段)
【自然语言处理(NLP)】基于FNN网络的电影评论情感分析作者简介:在校大学生一枚,华为云享专家,阿里云专家博主,腾云先锋(TDP)成员,云曦智划项目总负责人,全国高等学校计算机... 查看详情
中文nlp笔记:11. 基于 lstm 生成古诗
...古诗1.语料准备 一共四万多首古诗,一行一首诗2.预处理 将汉字表示为One-Hot的形式 在每行末尾加上]符号是为了标识这首诗已经结束,说明]符号之前的语句和之后的语句是没有关联关系的,后面会舍弃掉包含]符号的... 查看详情